javascript 香草旋转木马与无限循环
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript 香草旋转木马与无限循环相关的知识,希望对你有一定的参考价值。
@import "../../core/fonts";
@import "../../core/colors";
@import "../../core/mixins";
$number-of-slides-carousel: 4;
$number-of-slides-content-images: 3;
@mixin activeSlide() {
.refresh-content-images__info-cta {
a {
color: $gold-refresh;
}
}
img {
@include breakpoint(xp) {
opacity: 0.8;
}
}
}
.refresh-content-images {
margin-bottom: 20px;
@include breakpoint(xp) {
margin-bottom: 80px;
}
&__carousel-wrapper, &__list-wrapper {
position: relative;
overflow: hidden;
}
&__container {
position: relative;
}
&__arrow {
position: absolute;
top: 45%;
transform: translateY(-100%);
width: 35px;
height: 35px;
background: $white-dark;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
cursor: pointer;
z-index: 10;
&--left {
left: 0;
}
&--right {
right: 0;
}
&--disabled {
display: none;
}
@at-root .touchevents & {
display: none;
}
}
&__title {
font-family: $avantgarde-gothic;
font-size: 46px;
font-weight: 300;
text-transform: uppercase;
text-align: center;
margin-bottom: 40px;
@include breakpoint(xp) {
font-size: 82px;
}
}
&__list, &__carousel {
position: relative;
left: 0;
display: flex;
transition: all .3s ease-in-out;
}
&__list-item {
display: flex;
flex-direction: column;
box-sizing: border-box;
@at-root .touchevents &.active {
@include activeSlide
}
@at-root .no-touchevents &:hover {
@include activeSlide
}
img {
display: block;
height: auto;
pointer-events: none;
}
}
&__info {
font-family: $avantgarde-gothic;
text-transform: uppercase;
color: $gray-refresh;
padding: 25px;
box-sizing: border-box;
@include breakpoint(xp) {
padding: 35px;
}
}
&__info-title {
font-size: 16px;
@include breakpoint(xp) {
line-height: 24px;
font-size: 24px;
}
}
&__info-cta {
font-size: 12px;
margin-top: 20px;
@include breakpoint(xp) {
font-size: 13px;
margin-top: 25px;
}
a {
color: lighten($gray-refresh, 20%);
&,
&:hover {
@include breakpoint(xp) {
text-decoration: underline;
}
}
}
}
&__list {
.refresh-content-images__list-item {
.refresh-content-images__info,
img {
width: 1024px/$number-of-slides-carousel;
@include breakpoint(sm) {
width: 1024px/$number-of-slides-content-images;
}
@include breakpoint(xp) {
width: (100vw/$number-of-slides-content-images);
}
}
}
}
&__list {
text-align: center;
}
&__carousel {
.refresh-content-images__list-item {
&:nth-child(odd) {
background-color: $white-dark;
}
.refresh-content-images__info,
img {
width: 1024px/$number-of-slides-carousel;
@include breakpoint(xp) {
width: (100vw/$number-of-slides-carousel);
}
}
.refresh-content-images__info-title {
font-size: 13px;
@include breakpoint(xp) {
font-size: 16px;
}
}
.refresh-content-images__info-copy {
margin-top: 20px;
font-family: $helvetica-light;
font-size: 12px;
text-transform: none;
font-weight: 300;
@include breakpoint(xp) {
font-size: 14px;
margin-top: 25px;
}
}
}
}
}
export default element => {
const wrapper = element.parentElement.parentElement;
const position = 0;
const numberOfSlides = parseInt(element.dataset.numberOfSlides);
const slideWidth = window.innerWidth / numberOfSlides;
const loadedSlides = [numberOfSlides];
const com = {
carousel: element,
titleList: element.querySelectorAll('.refresh-content-images__info-title'),
leftArrow: wrapper.querySelector('.refresh-content-images__arrow--left'),
rightArrow: wrapper.querySelector('.refresh-content-images__arrow--right')
};
const gallery = Array
.from(com.carousel.children || [])
.filter(e => e.classList.contains('refresh-content-images__list-item'));
const active = 0;
const stepPos = 0;
const increment = 1;
return {
wrapper,
position,
numberOfSlides,
slideWidth,
loadedSlides,
com,
gallery,
active,
stepPos,
increment
};
};
import Hammer from 'hammerjs';
import {slide, activePrev, activeNext} from './moves';
export default metadata => {
const {com, wrapper} = metadata;
const sliderManager = new Hammer.Manager(wrapper);
const reposition = e => metadata.position + e.deltaX;
sliderManager.add(new Hammer.Pan({
threshold: 10,
pointers: 1,
direction: Hammer.DIRECTION_HORIZONTAL
}));
sliderManager.on('panstart', e => {
if (e.pointerType !== 'touch') {
return;
}
com.carousel.style.transition = 'none';
});
sliderManager.on('panleft panright', e => {
const isHorizontalPos = Math.abs(e.deltaX) > Math.abs(e.deltaY);
if (e.pointerType !== 'touch' || !isHorizontalPos) {
return;
}
slide({com, position: reposition(e)});
});
sliderManager.on('panend', e => {
let increment = Math.round(Math.abs(e.deltaX / metadata.slideWidth));
metadata.increment = increment === 0 ? 1 : increment;
const isHorizontal = Math.abs(e.deltaX) > Math.abs(e.deltaY);
if (e.pointerType !== 'touch' || !isHorizontal) {
return;
}
metadata.position = reposition(e);
com.carousel.style.transition = 'all .3s ease-in-out';
if (e.direction === Hammer.DIRECTION_LEFT || e.deltaX * 1 < 0) {
metadata.position -= (metadata.slideWidth * metadata.increment - Math.abs(e.deltaX));
activeNext(metadata);
} else if (e.direction === Hammer.DIRECTION_RIGHT || e.deltaX * 1 > 0) {
metadata.position += (metadata.slideWidth * metadata.increment - Math.abs(e.deltaX));
activePrev(metadata);
}
slide(metadata);
metadata.increment = 1;
});
}
import lazyLoad from './lazyLoad';
export const slide = ({com, position}) => {
com.carousel.style.left = position + 'px';
};
export const step = (metadata, time) => {
setTimeout(() => {
for (let i = 0; i < metadata.gallery.length; i++) {
const index = (metadata.active + i) % metadata.gallery.length;
const slide = metadata.com.carousel.children[index];
slide.style.position = 'absolute';
slide.style.left = `${metadata.slideWidth * i + metadata.stepPos}px`;
}
}, time || 0);
};
export const activeNext = metadata => {
metadata.stepPos += metadata.slideWidth * metadata.increment;
metadata.com.carousel.children[metadata.active].classList.remove('active');
metadata.active = metadata.active + metadata.increment > metadata.com.carousel.children.length - 1 ? 0 : metadata.active + metadata.increment;
metadata.com.carousel.children[metadata.active].classList.add('active');
step(metadata, 300);
lazyLoad(metadata.active + metadata.numberOfSlides - 1, metadata);
};
export const activePrev = metadata => {
metadata.stepPos -= metadata.slideWidth * metadata.increment;
metadata.com.carousel.children[metadata.active].classList.remove('active');
metadata.active = metadata.active - metadata.increment < 0 ? metadata.com.carousel.children.length - 1 : metadata.active - metadata.increment;
metadata.com.carousel.children[metadata.active].classList.add('active');
step(metadata, 0);
lazyLoad(metadata.active, metadata);
};
export const nextHandler = metadata => {
const {com, slideWidth} = metadata;
activeNext(metadata);
metadata.position -= slideWidth * metadata.increment;
slide({com, position: metadata.position});
};
export const previousHandler = metadata => {
const {com, slideWidth} = metadata;
activePrev(metadata);
metadata.position += slideWidth * metadata.increment;
slide({com, position: metadata.position});
};
const getSrcSet = image => {
if (!image || !image.srcset) {
return [];
}
return image.srcset.split(',').map(link => {
const [url, ratio] = link.trim().split` `;
const splitLink = url.split`/`;
return {
ratio,
width: splitLink[splitLink.length - 1]
};
});
};
export default (slide, metadata) => {
const {gallery} = metadata;
const lastLoadedSlide = metadata.loadedSlides[metadata.loadedSlides.length - 1];
const [gallerySample] = gallery[0].children[0].children;
if (slide > gallery.length - 1) {
return;
}
for (let i = lastLoadedSlide; i <= slide; i++) {
const [slideElement] = gallery[i].children,
[slideImage] = slideElement.children,
kalturaEntry = slideImage.dataset.kalturaEntry;
const sampleSrc = gallerySample.src.trim().split`/`,
sampleSrcWidth = sampleSrc[sampleSrc.length - 1];
if (!slideImage.src) {
slideImage.src = `${window.GHD.config.kalturaThumbnailURL}/${kalturaEntry}/width/${sampleSrcWidth}`;
slideImage.srcset = getSrcSet(gallerySample).map(v =>
`${window.GHD.config.kalturaThumbnailURL}/${kalturaEntry}/quality/75/width/${v.width} ${v.ratio}`
);
slideImage.sizes = gallerySample.sizes;
metadata.loadedSlides.push(i);
}
}
};
import metadata from './utils/metadata';
import hammer from './utils/hammer';
import debounce from '../tools/debounce';
import {nextHandler, previousHandler, step} from './utils/moves';
import {onResizeThrottler} from '../tools/throttler';
const initializeDimensions = metadata => {
resizeTitleHeights(metadata.com.titleList);
adjustSlideWidth(metadata);
metadata.wrapper.style.height = `${metadata.com.carousel.children[0].offsetHeight}px`;
resizeSlidesHeight(metadata);
};
const resizeSlidesHeight = ({gallery, wrapper}) => {
gallery.forEach(slide => slide.style.height = wrapper.style.height)
};
const resizeTitleHeights = titleList => {
const titleArray = Array.from(titleList);
const titleHeights = titleArray.map(title => title.offsetHeight);
const greatestTitleHeight = titleHeights.sort()[titleHeights.length - 1];
titleArray.forEach(title => title.style.height = greatestTitleHeight + 'px');
};
const adjustSlideWidth = metadata => {
metadata.slideWidth = window.innerWidth <= 1024
? metadata.gallery[0].children[0].children[0].width
: window.innerWidth / metadata.numberOfSlides;
step(metadata, 0);
};
const addEventListeners = carouselData => {
const {com} = carouselData;
com.leftArrow.addEventListener('click', debounce(150, () => previousHandler(carouselData)));
com.rightArrow.addEventListener('click', debounce(150, () => nextHandler(carouselData)));
};
const initialize = metadata => {
metadata.com.carousel.children[metadata.active].classList.add('active');
addEventListeners(metadata);
hammer(metadata);
initializeDimensions(metadata);
onResizeThrottler(() => initializeDimensions(metadata), 500);
};
export default element => initialize(metadata(element));
export default {
lazyLoad: async () => {
const elList = document.querySelectorAll('.refresh-carousel');
if (elList.length > 0) {
const {default: carousel} = await import('./carousel');
elList.forEach(el => carousel(el));
}
}
};
以上是关于javascript 香草旋转木马与无限循环的主要内容,如果未能解决你的问题,请参考以下文章