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 香草旋转木马与无限循环的主要内容,如果未能解决你的问题,请参考以下文章

javascript 重构香草旋转木马

html 无限循环旋转木马(垂直或水平)

html 无限循环旋转木马(垂直或水平)

javascript 两个类之间的无限旋转木马具有淡入淡出效果

javascript 无限卷轴香草JS

php woocommerce流行品牌旋转木马与光滑和自定义分类循环