首页 > 解决方案 > 用于幻灯片 div 的 javascript

问题描述

如果您单击向右或向左箭头,它将添加一张新的白<div>卡并从另一侧删除一张。 我想制作 10 张白卡
的幻灯片。<div>我的想法是实现一个功能,它会一直点击右键,这样白色的 div 卡就会自动移动。我尝试了 W3schools 的一些功能,但没有用。有什么解决办法吗?

这是代码:

<div class="container">
  <div class="row">
      <div class="col-sm-12">
      <h2 class="text-center font-weight-bold text-white">Our Customers are Seeing Big Results</h2>
      <p></p>
     <div class="mt-5 pos-r">
        <div class="carousel-controls testimonial-carousel-controls">
          <div class="control prev"><i class="fa fa-chevron-left text-white">&nbsp;</i></div>
          <div class="control next"><i class="fa fa-chevron-right text-white">&nbsp;</i></div>
        </div>
        <div class="testimonial-carousel">
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">I have been working with Solodev for nearly 4 years and I couldn&#39;t be happier with the results!</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Florida Dairy Farmers" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-1.png" class="mx-auto"/></div>
            </div>
          </div>
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">The interface is easy for a novice user to make updates just as easily as an experienced developer.</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Florida Department of Education" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-2.png" class="mx-auto"/></div>
            </div>
          </div>
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">Solodev is a great company to partner with! We are extremely happy with the software, service, and support.</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Seminole County" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-3.png" class="mx-auto" /></div>
            </div>
          </div>
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">If you are looking for a great CMS company then Solodev is the right choice.</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Lynx" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-4.png" class="mx-auto" /></div>
            </div>
          </div>
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">Everyone on the Solodev team is very knowledgeable and they have been always been very responsive.</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Miami Beach VCA" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-5.png" class="mx-auto" /></div>
            </div>
          </div>
          <div class="one-slide white">
            <div class="testimonial w-100 h-100  p-3 text-center">
              <div class="message text-center text-gray">Solodev has been able to successfully keep us at the forefront of our industry and continually meet our ever adapting needs.</div>
              <div class="separator">&nbsp;</div>
              <div class="brand"><img alt="Oneblood" src="https://raw.githubusercontent.com/solodev/slider-boxes/master/images/img-6.png" class="mx-auto" /></div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
</section>
.orange-fade {
    background: #ff910e;
    background: linear-gradient(135deg,#ff910e 0,#ffa841 100%);
}
.pos-r {
    position: relative!important;
}
.white {
    background: #fff;
}
.text-white {
    color: #fff!important;
}
.text-gray {
    color: #363636;
}
.testimonial {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
.separator {
    width: 14%;
    height: 3px;
    margin: 1.2em auto 1em;
    background: #ffc53a;
}
.one-slide {
  border-radius: 3px;
  margin-left: 1rem;
  margin-right: 1rem;
  font-size: 1.1rem;
  height: 300px;
}
.one-slide img {
  width: 60%;
}
.carousel-controls .control {
  position: absolute;
  cursor: pointer;
  top: 56.4%;
  -webkit-transform: translateY(-50%);
  -moz-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  -o-transform: translateY(-50%);
  transform: translateY(-50%);
  c
}
.prev {
  left: -1.875rem;
}
.next {
  right: -1.875rem;
}
.testimonial-carousel { 
  &.slick-initialized { 
    display: block; 
  }
 .message {
    width: 100%;
    font-size: .9rem;
  }
  .brand {
    width: 100%;
  }
  @media (max-width: 575px) {
    .one-slide {
        height: 200px;
      }
    img {
        width: 40%;
      }
  }
}

$(document).ready(function() {
    $(".testimonial-carousel").slick({
        infinite: !0,
        slidesToShow: 4,
        slidesToScroll: 1,
        autoplay: !1,
        arrows:true,
        prevArrow: $(".testimonial-carousel-controls .prev"),
        nextArrow: $(".testimonial-carousel-controls .next"),
        responsive: [{
            breakpoint: 1200,
            settings: {
                slidesToShow: 3
            }
        }, {
            breakpoint: 992,
            settings: {
                slidesToShow: 2
            }
        }, {
            breakpoint: 600,
            settings: {
                slidesToShow: 1
            }
        }]
    });
});

标签: javascriptjqueryhtmlcss

解决方案


以下实现允许直接在 DOM 中定义任意数量的幻灯片。

每张幻灯片都映射到数组中的一个整数位置slideOrder

通过更改此数组中的值,可以控制幻灯片旋转的位置。

render函数仅在状态更改时调用。render 函数通过每张幻灯片上的数据属性将幻灯片顺序呈现给 DOM。CSS 过渡与此无关。

共有三个动作:MOVE_PREVIOUSMOVE_NEXTTOGGLE_AUTOPLAY。这些可以被分派到一个内部队列中,随着动作的完成,该队列被逐个排出。可以在动作的有效负载中指定持续时间,以确保 UI 不会在 CSS 转换的中间重新渲染。

const $ = document.querySelector.bind(document);
const $s = document.querySelectorAll.bind(document);
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

const ACTIONS = {
  MOVE_PREVIOUS: "MOVE_PREVIOUS",
  MOVE_NEXT: "MOVE_NEXT",
  TOGGLE_AUTOPLAY: "TOGGLE_AUTOPLAY"
};

function createAutoplayer(store) {
  let timeoutId = null;
  function start() {
    function next() {
      const { autoplay, slideChangeTime, autoplayInterval } = store.getState();
      const now = performance.now();
      if (!autoplay) {
        timeoutId = setTimeout(next, autoplayInterval);
        return;
      }
      if ((now - slideChangeTime) >= autoplayInterval) {
        movePrevious(store);
        timeoutId = setTimeout(next, autoplayInterval);
        return;
      }
      timeoutId = setTimeout(
        next,
        autoplayInterval - (now - slideChangeTime)
      );
    }
    const { autoplayInterval } = store.getState();
    timeoutId = setTimeout(next, autoplayInterval);
  }
  function stop() {
    clearTimeout(timeoutId);
  }
  return { start, stop };
}

const initialState = {
  selector: ".slideshow",
  slideSelector: ".slide",
  autoplayButtonSelector: ".toggle-autoplay",
  autoplay: false,
  autoplayInterval: 5000,
  slideChangeTime: null
};

function createShow(state = initialState) {
  const slides = $s(state.slideSelector);
  state = { ...initialState, slides, slideOrder: [...Object.keys(slides)] };
  const store = createStore({ initialState: state, reducers });
  createAutoplayer(store).start();
  return {
    start: start.bind(null, store),
    moveNext: moveNext.bind(null, store),
    movePrevious: movePrevious.bind(null, store),
    toggleAutoplay: toggleAutoplay.bind(null, store)
  };
}

function moveNext(store) {
  const actions = [
    createAction(ACTIONS.MOVE_NEXT, {
      duration: 500
    })
  ];
  store.dispatch(...actions);
}

function movePrevious(store) {
  store.dispatch(createAction(ACTIONS.MOVE_PREVIOUS, { duration: 500 }));
}

function rotateForward([first, ...rest]) {
  return [...rest, first];
}

function rotateBackward(arr) {
  return [arr[arr.length - 1], ...arr.slice(0, arr.length - 1)];
}

const reducers = {
  [ACTIONS.MOVE_NEXT]: (state, payload) => ({
    ...state,
    slideOrder: rotateForward(state.slideOrder),
    slideChangeTime: performance.now()
  }),
  [ACTIONS.MOVE_PREVIOUS]: (state, payload) => ({
    ...state,
    slideOrder: rotateBackward(state.slideOrder),
    slideChangeTime: performance.now()
  }),
  [ACTIONS.TOGGLE_AUTOPLAY]: (state, payload) => ({
    ...state,
    autoplay: !state.autoplay,
    slideChangeTime: null
  })
};

function render(state) {
  const { slides, slideOrder, autoplay, autoplayButtonSelector } = state;
  for (let x = 0; x < slides.length; x++) {
    slides[x].dataset.index = slideOrder[x];
  }
  autoplay
    ? $(autoplayButtonSelector).classList.add('enabled')
    : $(autoplayButtonSelector).classList.remove('enabled');
}

let previousState = null;
function start(store) {
  function loop() {
    const state = store.getState();
    if (state === previousState) {
      return requestAnimationFrame(loop);
    }
    previousState = state;
    render(state);
    requestAnimationFrame(loop);
  }
  requestAnimationFrame(loop);
}

function toggleAutoplay(store) {
  const actions = [createAction(ACTIONS.TOGGLE_AUTOPLAY)];
  store.dispatch(...actions);
}

function createAction(type, payload = {}) {
  return { type, payload };
}

function createDispatcher({ getState, setState, reducers }) {
  const q = [];
  let isDraining = false;
  async function drain() {
    isDraining = true;
    while (q.length) {
      const { type, payload } = q.shift();
      setState(reducers[type](getState(), payload));
      await wait(payload.duration);
    }
    isDraining = false;
  }
  function dispatch(...actions) {
    q.push(...actions);
    if (!isDraining) {
      drain();
    }
  }
  return { dispatch };
}

function createStore({ initialState, reducers }) {
  let state = Object.freeze(initialState);
  function getState() {
    return state;
  }
  function setState(value) {
    state = Object.freeze(value);
  }
  const { dispatch } = createDispatcher({ getState, setState, reducers });
  return {
    getState,
    dispatch
  };
}

const show = createShow();

$(".next").addEventListener("click", show.moveNext);
$(".previous").addEventListener("click", show.movePrevious);
$(".toggle-autoplay").addEventListener("click", show.toggleAutoplay);
show.start();
* {
  font-size: 0;
  border: 0;
  padding: 0;
  margin: 0;
  color: #444;
  box-sizing: border-box;
  user-select: none;
  -webkit-user-select: none;
}
html {
  font-size: 12px;
}
body {
  width: 100%;
  font-family: sans-serif;
}
button {
  width: 100px;
  height: 50px;
  font-size: 2.2rem;
  background: none;
  box-shadow: 0 0 0 2px rgba(0,200,200, .5) inset;
  border-radius: 10px;
  border: 0;
  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
}
.toggle-autoplay.enabled {
  box-shadow: 0 0 55px 5px rgba(200,0,50, .3) inset;
}
.controls-container {
  clear: both;
  display: block;
  text-align: center;
  padding: 15px;
}
.container {
  padding: 0;
}
.h-spacer-container {
  display: inline-block;
  padding: 0 15px;
}
.slides-container {
  width: 100%;
  padding: 00px 0 30px calc(50% - 200px);
  height: calc(200px + 30px);
}
.slide {
  position: absolute;  
  width: 400px;
  height: 200px;
  background-size: cover;
  border-radius: 10px;
  opacity: 0;
  transition: all 0.5s ease-in-out 0s;
  font-size: 2rem;
  padding: 10px;
}
.slide[data-index = '0'] {
  z-index: 0;
  transform: perspective(20px) rotate3d(1, -2.0, -3.0, 5deg) translate(-200px, 0px); 
}
.slide[data-index = '1'] {
  z-index: 9;
  opacity: 1;
  transform: translate3d(0px, 0px, 0px)
}
.slide[data-index = '2'] {
  transform: perspective(20px) rotate3d(1, 2.0, 3.0, 5deg) translate(200px, 0px); 
}
.slide-1 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi.redd.it%2Fheyde2iaughz.jpg&f=1&nofb=1);
}
.slide-2 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fsailingheaven.com%2Fwp-content%2Fuploads%2F2015%2F03%2Fmega-yacht-3.jpg&f=1&nofb=1);
}
.slide-3 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Fcdn.boatinternational.com%2Fbi_prd%2Fbi%2Flibrary_images%2FTHUqC2wQSeVWkkilwTFw_Unfurled-Vitters-sailing-yacht-hero-credit-Stuart-Pearce-1280x720.jpg&f=1&nofb=1);
}
.slide-4 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Fmegayachtconcepts.weebly.com%2Fuploads%2F5%2F7%2F8%2F5%2F5785334%2F6248846.jpg%3F859&f=1&nofb=1);
}
.slide-5 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi.ytimg.com%2Fvi%2FmT5ZNjPqVuM%2Fmaxresdefault.jpg&f=1&nofb=1);
}
.slide-6 {
  background-image: url(https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Fgtspirit.com%2Fwp-content%2Fuploads%2F2016%2F01%2FGanesha-Sailing-Superyacht-17.jpg&f=1&nofb=1);
}
<div class="slideshow container">
 <div class="controls-container">
    <div class="h-spacer-container">
      <button class="next">⏮&lt;/button>
    </div>
    <div class="h-spacer-container">
      <button class="toggle-autoplay">⏯&lt;/button>
    </div>
    <div class="h-spacer-container">
      <button class="previous">⏭&lt;/button>
    </div>
  </div>
  <div class="slides-container">
    <div class="slide slide-6">Yacht F</div>
    <div class="slide slide-1">Yacht A</div>
    <div class="slide slide-2">Yacht B</div>
    <div class="slide slide-3">Yacht C</div>
    <div class="slide slide-4">Yacht D</div>
    <div class="slide slide-5">Yacht E</div>        
  </div>
</div>    


推荐阅读