Карусель фотографий

Для одной своей идеи, использовал карусель фотографий, взятую из интернета и переписанную под себя. Выложу, как было у меня. Карусель использует библиотеку jQuery, так что придется подключать её, хотя, переписать на чистый JavaScript не составит особого труда.

jQuery:
var carouselID = 1, change = 8000;

function carouselStart() {
	if ($('div[data-carousel="carousel"]').length < 1) {
		return false;
	};

	$('div[data-carousel="carousel"]').each(function() {
		$(this).removeAttr('data-carousel').attr('id', 'carousel_' + carouselID);
		carousel('#carousel_' + carouselID);
		carouselID++;
	});
};

$(() => {
	carouselStart();
	window.setInterval(carouselStart, 3000);
});

function carousel(carouselID) {
	var $slr, $sls, interval, $selectors, $btns, currentIndex, nextIndex;
	var cycle = index => {
		var $currentSlide, $nextSlide, $currentSelector, $nextSelector;
		nextIndex        = index !== undefined ? index : nextIndex;
		$currentSlide    = $($sls.get(currentIndex));
		$currentSelector = $($selectors.get(currentIndex));
		$nextSlide       = $($sls.get(nextIndex));
		$nextSelector    = $($selectors.get(nextIndex));

		$currentSlide.removeClass('sl-active').css('z-index', '0');
		$nextSlide.addClass('sl-active').css('z-index', '1');
		$currentSelector.removeClass('sl-current');

		$nextSelector.addClass('sl-current');
		currentIndex = index !== undefined ? nextIndex : currentIndex < $sls.length - 1 ? currentIndex + 1 : 0;
		nextIndex    = currentIndex + 1 < $sls.length ? currentIndex + 1 : 0;
	};

	currentIndex = 0;
	nextIndex    = 1;
	$slr         = $(carouselID);
	$sls         = $(carouselID + ' .sl');
	$selectors   = $(carouselID + ' .selector');
	$btns        = $(carouselID + ' .sl-btn');

	$sls.first().addClass('sl-active');
	$selectors.first().addClass('sl-current');
	interval = window.setInterval(cycle, change);

	$selectors.on('click', e => {
		var target = $selectors.index(e.target);
		if (target !== currentIndex) {
			window.clearInterval(interval);
			cycle(target);
			interval = window.setInterval(cycle, change);
		};
	});

	$btns.on('click', e => {
		window.clearInterval(interval);
		if ($(e.target).hasClass('sl-prev')) {
			var target = currentIndex > 0 ? currentIndex - 1 : $sls.length - 1;
			cycle(target);
		}
		else if ($(e.target).hasClass('sl-next')) {
			cycle();
		};

		interval = window.setInterval(cycle, change);
	});
};

CSS:
.slr {
    position: relative;
    width: 100%;
    height: 400px;
    overflow: hidden;
    background-color: #3178b5;
    background-position: center center;
    background-repeat: no-repeat;
    margin: 5px 0 15px 0;
}

.slr ul {
    list-style: none;
    margin: 0;
    padding-left:0;
}

#sls .sl {
    position: absolute;
    display: flex;
    width: 100%;
    height: 100%;
}

#sls .sl .sl-text {
    position: absolute;
    margin: 5px;
    bottom: 0;
    z-index: 2;
    padding: 12px 10px 12px 10px;
    background: rgba(0, 0, 0, 0.6);
    transform: translateY(200%);
    transition: all 1000ms ease-in-out;
}

#sls .sl .sl-text a {
	color: #BBBBBB;
}

#sls .sl .sl-text a:hover {
	text-decoration: underline;
}

#sls .sl.sl-active .sl-text {
    transform: translateY(0);
    transition-delay: 0.3s;
}

#sls .sl .sl-text .sl-title {
    font-size: 20px;
    color: #FFFFFF;
    font-family: 'Roboto', sans-serif;    
    margin-bottom: 5px;
}

#sls .sl .sl-text .sl-data {
    font-size: 15px;
    color: #FFFFFF;   
}

#sls .sl .sl-text .sl-link {
	margin: 15px 0 2px 0;
}

#sls .sl .sl-text .sl-read {
    text-decoration: none;
    position: relative;
    font-size: 12px;
    padding: 5px 10px;
    color: #FFFFFF;
    font-weight: bold; 
    font-family: 'Roboto', sans-serif;
    background: #337AB7;
    cursor: pointer; 
}

#sls .sl .sl-text .sl-read:hover,
#sls .sl .sl-text .sl-read:active,
#sls .sl .sl-text .sl-read:focus {
    color: #FFFFFF;
}

#sls .sl .sl-text .sl-read:after,
#sls .sl .sl-text .sl-read:before {
    position: absolute;
    height: 4px;
    left: 50%;
    background: #337AB7;
    bottom: -8px;
    content: "";
    transition: all 280ms ease-in-out;
    width: 0;
}

#sls .sl .sl-text .sl-read:before {
    top: -8px;
}

#sls .sl .sl-text .sl-read:hover:after,
#sls .sl .sl-text .sl-read:hover:before,
#sls .sl .sl-text .sl-read:active:after,
#sls .sl .sl-text .sl-read:active:before,
#sls .sl .sl-text .sl-read:focus:after,
#sls .sl .sl-text .sl-read:focus:before {
    width: 100%;
    left: 0;
}

#sls .sl .sl-partial {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    transition: transform 1s ease-in-out;
}

#sls .sl .sl-partial img {
    position: absolute;
    z-index: 1;
    width: 100%;
    height: 100%;
    transition: transform 1s ease-in-out;
}

#sls .sl .sl-left {
    top: 0;
    left: 0;
    transform: translateX(-100%);
    clip-path: polygon(0 0, 2% 0, 100% 98%, 100% 100%, 0 100%);
}

#sls .sl .sl-left img {
    top: 0;
    right: 0;
}

#sls .sl .sl-right {
    top: 0;
    right: 0;
    transform: translateX(100%);
    clip-path: polygon(0 2%, 0 0, 100% 0, 100% 100%, 98% 100%);
}

#sls .sl .sl-right img {
    top: 0;
    left: 0;
}

#sls .sl.sl-active .sl-partial, 
#sls .sl.sl-active .sl-partial img {
    transform: translateX(0);
}

.slr .sl-btn {
    position: absolute;
    top: 20px;
    right: 130px;
    z-index: 100;
    height: 50px;
    width: 50px;
    z-index: 100;
    cursor: pointer;
    overflow: visible;
}

.slr .sl-btn.sl-next {
    right: 40px;    
}

.slr .sl-btn polygon, 
.slr .sl-btn path {
    transition: all 0.5s cubic-bezier(0.2, 1, 0.3, 1);
    fill: #FFFFFF;
}

.slr .sl-btn:hover polygon, 
.slr .sl-btn:hover path {
    transition: all 1s cubic-bezier(0.2, 1, 0.3, 1);
    fill: #FFFFFF;
}

.slr .sl-btn:hover .sl-btn-pl {
    animation: sl-btn-anim 1s cubic-bezier(0.2, 1, 0.3, 1) infinite;
}

.slr .sl-btn:hover .sl-btn-pl-fixed {
    animation: sl-btn-fixed-anim 1s cubic-bezier(0.2, 1, 0.3, 1) infinite;
}

.sl-select {
    position: absolute;
    left: 8px;
    top: 10px;
    z-index: 100;
}

.sl-select li {
    cursor: pointer;
    margin: 0 0 4px 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 14px;
	font-weight: bold;
}

.sl-select .selector {
    height: 28px;
    width: 28px;
	border-radius: 50%;
    background-color: #FFFFFF;
	opacity: 0.5;
    transition: background-color 0.5s ease-in-out;
}

.sl-select .selector.sl-current {
    opacity: 1;
}

@keyframes sl-btn-anim {
    0% {
        opacity: 1;
        transform: translateX(0);
    }

    5% {
        transform: translateX(-0.1rem);
    }

    100% {
        transform: translateX(1rem);
        opacity: 0;
    }
}

@keyframes sl-btn-fixed-anim {
    5% {
        opacity: 0;
    }

    20% {
        opacity: 0.4;
    }

    100% {
        opacity: 1;
    }
}
   
@media screen and (max-width:767px) {
    #sls .sl .sl-text {
        position: absolute;
        margin: 5px;
        bottom: 0;
        z-index: 2;
        padding: 10px;
    }

    #sls .sl .sl-text .sl-title {
        font-size: 20px;
        line-height: 25px;
        margin-bottom: 2px;
    }

    #sls .sl .sl-text .sl-data {
        font-size: 13px;
        line-height: 18px;   
    }

	#sls .sl .sl-text .sl-link {
		margin: 12px 0 2px 0;
	}
}

HTML:
<div class="slr" data-carousel="carousel">    
    <ul id="sls">
		{foreach from=$carousel item=block}
        <li class="sl">
            <div class="sl-partial sl-left"><img src="{$block.img}"/></div>
            <div class="sl-partial sl-right"><img src="{$block.img}"/></div>
            <div class="sl-text">
                <div class="sl-title">{$block.title|shorten:70:'...'}</div> 
				{if isset($block.text)}
				<div class="sl-data">{$block.text|parse|shorten:180:'...'}</div>
				{/if}
				{if isset($block.links)}
				<div class="sl-link">
					{foreach from=$block.links item=link}
					<a href="{$link.url}" class="sl-read">{$link.title}</a>
					{/foreach}
				</div>
				{/if}				
            </div>   
        </li>
		{/foreach}
    </ul>
    <svg class="sl-btn sl-prev" viewBox="0 0 18 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g transform="translate(8.500000, 8.500000) scale(-1, 1) translate(-8.500000, -8.500000)">
            <polygon class="sl-btn-pl" points="16.3746667 8.33860465 7.76133333 15.3067621 6.904 14.3175671 14.2906667 8.34246869 6.908 2.42790698 7.76 1.43613596"></polygon>
            <polygon class="sl-btn-pl-fixed" points="16.3746667 8.33860465 7.76133333 15.3067621 6.904 14.3175671 14.2906667 8.34246869 6.908 2.42790698 7.76 1.43613596"></polygon>
            <path d="M-1.48029737e-15,0.56157424 L-1.48029737e-15,16.1929159 L9.708,8.33860465 L-2.66453526e-15,0.56157424 L-1.48029737e-15,0.56157424 Z M1.33333333,3.30246869 L7.62533333,8.34246869 L1.33333333,13.4327013 L1.33333333,3.30246869 L1.33333333,3.30246869 Z"></path>
        </g>
    </svg>
    <svg class="sl-btn sl-next" viewBox="-1 0 18 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g>
            <polygon class="sl-btn-pl" points="16.3746667 8.33860465 7.76133333 15.3067621 6.904 14.3175671 14.2906667 8.34246869 6.908 2.42790698 7.76 1.43613596"></polygon>
            <polygon class="sl-btn-pl-fixed" points="16.3746667 8.33860465 7.76133333 15.3067621 6.904 14.3175671 14.2906667 8.34246869 6.908 2.42790698 7.76 1.43613596"></polygon>
            <path d="M-4.58892184e-16,0.56157424 L-4.58892184e-16,16.1929159 L9.708,8.33860465 L-1.64313008e-15,0.56157424 L-4.58892184e-16,0.56157424 Z M1.33333333,3.30246869 L7.62533333,8.34246869 L1.33333333,13.4327013 L1.33333333,3.30246869 L1.33333333,3.30246869 Z"></path>
        </g>
    </svg>
    <ul class="sl-select">
	{for $i = 1; $i <= count($carousel); $i++}
        <li class="selector">{$i}</li>
	{/for}
    </ul>
</div>

Собирать массив для карусели, можно так:
		$carousel = [];
		foreach ($photos as $photo)
		{
			$carousel[] = [
				'img'    => 'imgURL',
				'title'  => 'imgTitle',
				'text'   => 'imgDescription',
				'links'  => [
					[
						'url'   => 'link', // Ссылка с фотографии 1
						'title' => 'title' // Анкор ссылки 1
					],
					[
						'url'   => 'link', // Ссылка с фотографии 2
						'title' => 'title' // Анкор ссылки 2
					]
				]
			];
		}

Пример, к сожалению, показать не могу.
Автор:  16.02.2025 04:30:11 pm