为什么滑块中的某些幻灯片不移动?

时间:2018-10-12 11:38:43

标签: javascript css

我正在尝试创建vanila js动态滑块。我完成了大小调整,现在开始制作动画,向左滑动以供初学者使用。这是一个问题。已经存在且可见的幻灯片可以完美向左移动。但是我在动画之前创建的新幻灯片不会移动,它们只会显示在最终位置。我在做什么错了?

function Slider(options) {
  const slider = document.querySelector("#" + options.id);
  const blocks = {};
  ["left", "main", "right"].forEach(name => addBlock(name));
  const iWidth = options.itemWidth;
  const items = [];
  let currentPosition = 0;
  insertItems();
  function addBlock(name) {
    blocks[name] = document.createElement('div');
    blocks[name].className = name;
    slider.appendChild(blocks[name]);
  }
  function insertItems() {
    const slider = {items: blocks.main, position: currentPosition};
    slider.width = blocks.main.clientWidth;
    slider.canFit = Math.floor(slider.width / iWidth);
    slider.gap = (slider.width - slider.canFit  * iWidth) / (slider.canFit > 1 ? slider.canFit - 1 : 1);
    for (let i = 0; i < options.max; i++) {
      items.push(new Item({slider: slider, item: {width: iWidth, index: i}}))
    }
  }
  function updateItems() {
    const slider = {position: currentPosition};
    slider.width = blocks.main.clientWidth;
    slider.canFit = Math.floor(slider.width / iWidth);
    slider.gap =  (slider.width - slider.canFit  * iWidth) / (slider.canFit > 1 ? slider.canFit - 1 : 1);
    for (let i = 0; i < options.max; i++) {
      items[i].update(slider);
    }
  }
  function slideLeft() {
    const width = blocks.main.clientWidth;
    const canFit = Math.floor(width / iWidth);
    const gap =  (width - canFit  * iWidth) / (canFit > 1 ? canFit - 1 : 1);
    currentPosition -= canFit * (gap + iWidth);
    for (let i = 0; i < options.max; i++) {
      items[i].slide(currentPosition);
    }
  }
  window.addEventListener("resize", updateItems);
  blocks.left.addEventListener("click", slideLeft);
}
const sld = new Slider({
  id: "wrapper",
  itemWidth: 250,
  max: 20,
})
function Item(opt) {
    let item = null;
    let curSliderPos = opt.slider.position;
    showIn(calculateLeft(curSliderPos));
    function calculateLeft(sliderPosition) {
      let position = opt.item.index * (opt.item.width + opt.slider.gap);
      position += sliderPosition;
      if (opt.slider.canFit == 1) position += 0.5 * opt.slider.gap;
      return position;
    }
    function isVisibleIn(pos) {
      if (pos >= opt.slider.width) return false;
      if (pos + opt.item.width <= 0) return false;
      return true;
    }
    function showIn(pos, force = false) {
      if ((force || isVisibleIn(pos)) && !item) {
        item = document.createElement('div');
        item.className = "item";
        item.innerText = opt.item.index;
        item.style.position = "absolute";
        item.style.display="inline-block";
        opt.slider.items.appendChild(item);
      }
      if (item) {
        item.style.left =  pos + "px";
      }
    }
    this.update = function(slider) {
      curSliderPos = slider.position;
      opt.slider.width = slider.width;
      opt.slider.gap = slider.gap;
      opt.slider.canFit = slider.canFit;
      showIn(calculateLeft(opt.slider.position));
    }
    this.slide = function(newPos) {
      const oldElementPos = calculateLeft(curSliderPos);
      const newElementPos = calculateLeft(newPos);
      if(isVisibleIn(oldElementPos) || isVisibleIn(newElementPos)) {
        showIn(oldElementPos, true);
        item.style.transition = "left 2s";
        showIn(newElementPos, true);
        curSliderPos = newPos;        
      }
    }
}

https://codepen.io/TogusaRusso/pen/OBJrGW

2 个答案:

答案 0 :(得分:1)

下面是一个简短的例子,说明我之前的评论是什么意思。

/* reference to div where items are added */
const innerMain = document.querySelector("#innerMain");
/* reference to left navigation */
const leftButton = document.querySelector("#left");
leftButton.addEventListener("click", addItems);
/* determine the position of items container */
const computedStyle = window.getComputedStyle(innerMain)
let marginLeft = parseInt(computedStyle.getPropertyValue('left'));
/* set new position items container */
let newTarget = marginLeft - 1000;
/* set next number for items */
let counter = 5;
/* slide the items to the left */
let moveMain = setInterval(moveLeft, 5);

function moveLeft() {
  if (marginLeft === newTarget) {
    clearInterval(moveMain);
  } else {
    marginLeft -= 5;
    innerMain.style.left = marginLeft + "px";
  }
}

function addItems() {
  for (let i = 0; i < 4; i++) {
    const node = document.createElement("div");
    node.innerHTML = counter++;
    node.classList = "item";
    innerMain.appendChild(node);
  }
  newTarget = marginLeft - 1000;
  moveMain = setInterval(moveLeft, 5);
}
#wrapper {
  background-color: yellow;
  display: grid;
  grid-template-columns: 20px 1fr 20px;
  height: 250px;
}

#main {
  background-color: blue;
  min-width: calc(100vw - 40px);
  width: calc(100vw - 40px);
  overflow: hidden;
}

#innerMain {
  position: relative;
  display: flex;
  justify-content: space-between;
  left: 100%;
}

#left, #right {
background-color: red;
}

.item {
  width: 250px;
  min-width: 250px;
  height: 250px;
  background-color: green;
  color: white;
  font-size: 100px;
  font-family: "Lucida Console", Monaco, monospace;
  text-align: center;
}
<div id="wrapper">
  <div id="left"></div>
  <div id="main">
    <div id="innerMain">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
    </div>
  </div>
  <div id="right"></div>
</div>

答案 1 :(得分:0)

好的。我找到了解决方案。如果创建元素,同时设置属性,过渡和新属性,则CSS无需设置动画。只是设置了最新的属性而已。我使用了最小的超时,它就像一个魅力。 这样。

  const block = document.createElement("div");
  block.classList.add("block");
  block.style.left = "2000px";
  slider.appendChild(block);
  setTimeout(() => {block.style.left = "20px";}, 0);

这里是演示。 https://codepen.io/TogusaRusso/pen/XxzMdL