我正在尝试创建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;
}
}
}
答案 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);