我正在锻炼,我试图在纯JS上写自己的旋转木马。
window.onload = function () {
var slider = document.getElementById('slide-list');
var left = document.getElementById('rewind');
var right = document.getElementById('forward');
var clickDisabled = false;
function spin() {
slider.firstChild.style.marginLeft = -800 + 'px';
setTimeout(function () {
slider.appendChild(slider.removeChild(slider.firstChild));
slider.lastChild.style.marginLeft = '0px';
}, 2000);
}
var slideShow = setInterval(spin, 4000);
left.onclick = function () {
if (clickDisabled) {return;}
else {
clickDisabled = true;
clearInterval(slideShow);
slider.lastChild.style.marginLeft = -800 + 'px';
slider.insertBefore(slider.lastChild, slider.firstChild);
// the crutch - try to unwrap content from timeout and see that image changes instantly, with no transition
setTimeout(function () { slider.firstChild.style.marginLeft = '0px'; }, 1);
slideShow = setInterval(spin, 4000);
setTimeout(function() {clickDisabled = false;}, 2000);
}
}
right.onclick = function () {
// fix of fast sliding after multiple clicks
if (clickDisabled) {return;}
else {
clickDisabled = true;
clearInterval(slideShow);
spin();
slideShow = setInterval(spin, 4000);
setTimeout(function() {clickDisabled = false;}, 2000);
}
}
}
我的想法是我有一个带旋转木马幻灯片的列表,我用setInterval重新排列这些幻灯片。通过在CSS中传输并改变滑块的边缘来实现平滑的滑动过渡 - 因此过渡使其平滑滑动。
自动旋转工作正常并没有问题,关键是要手动更改幻灯片,使用左右按钮。 问题是,如果没有一个非常奇怪的(对我来说)拐杖,它就不会工作。它在代码中标记(第28行)。似乎有些事情阻止了过渡到完成,没有那个拐杖图像改变而没有过渡。 我也非常感谢有关按钮的临时阻止onclick事件的想法的评论,以防止多次点击时出现乱码和即时滑动。也许这是一个糟糕的方式?哪种方式可以更好?
答案 0 :(得分:0)
你可以使用我建立的这个图像滑块......虽然它只适用于现代浏览器。
http://codepen.io/team/moderndeveloper/pen/MKgqzq
/* global Modernizr */
if (!Object.assign) {
Object.defineProperty(Object, 'assign', {
enumerable: false,
configurable: true,
writable: true,
value: function(target) {
'use strict';
if (target === undefined || target === null) {
throw new TypeError('Cannot convert first argument to object');
}
var to = Object(target);
for (var i = 1; i < arguments.length; i++) {
var nextSource = arguments[i];
if (nextSource === undefined || nextSource === null) {
continue;
}
nextSource = Object(nextSource);
var keysArray = Object.keys(nextSource);
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
var nextKey = keysArray[nextIndex];
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
if (desc !== undefined && desc.enumerable) {
to[nextKey] = nextSource[nextKey];
}
}
}
return to;
}
});
}
(function(window, document, Modernizr) {
"use strict";
var d = document;
var transform = Modernizr.prefixed('transform');
function ImageSliderIndicators(imageSlider, options) {
this.imageSlider = imageSlider;
this.options = Object.assign({}, ImageSliderIndicators.DEFAULTS, options || {});
this.el = d.querySelector('.' + this.options.indicatorsClass);
this.indicators = [].slice.call(d.querySelectorAll('.' + this.options.indicatorClass));
this.imageSlider.el.addEventListener('positionChanged', this.onPositionChanged.bind(this));
this.el.addEventListener('click', this.onIndicatorClick.bind(this), false);
this.onPositionChanged();
}
ImageSliderIndicators.DEFAULTS = {
indicatorsClass: 'ImageSlider-indicators',
indicatorClass: 'ImageSlider-indicator',
indicatorActiveClass: 'ImageSlider-indicator--is-active'
};
ImageSliderIndicators.prototype.onIndicatorClick = function onIndicatorClick(event) {
var position = this.indicators.indexOf(event.target);
if (position !== -1) {
this.imageSlider.goto(position);
}
};
ImageSliderIndicators.prototype.onPositionChanged = function onPositionChanged() {
var self = this;
this.indicators.forEach(function(element, index) {
var action = index === self.imageSlider.position ? 'add' : 'remove';
element.classList[action](self.options.indicatorActiveClass);
});
};
function ImageSlider(options) {
this.options = Object.assign({}, ImageSlider.DEFAULTS, options || {});
this.position = 0;
this.el = d.querySelector('.' + this.options.imageSliderClass);
this.items = d.querySelector('.' + this.options.itemsClass);
this.itemCount = d.querySelectorAll('.' + this.options.itemClass).length;
this.scroller = d.querySelector('.' + this.options.scrollerClass);
this.previousButton = d.querySelector('.' + this.options.previousButtonClass);
this.nextButton = d.querySelector('.' + this.options.nextButtonClass);
this.indicators = new ImageSliderIndicators(this, this.options.indicators);
window.addEventListener('resize', this.render.bind(this));
this.nextButton && this.nextButton.addEventListener('click', this.next.bind(this));
this.previousButton && this.previousButton.addEventListener('click', this.previous.bind(this));
}
ImageSlider.DEFAULTS = {
imageSliderClass: 'ImageSlider',
itemsClass: 'ImageSlider-items',
itemClass: 'ImageSlider-item',
scrollerClass: 'ImageSlider-scroller',
previousButtonClass: 'js-ImageSlider-button--previous',
nextButtonClass: 'js-ImageSlider-button--next'
};
ImageSlider.prototype.render = function render() {
this.items.style[transform] = 'translate3d(' + (-this.position * this.items.offsetWidth) + 'px,0,0)';
};
ImageSlider.prototype.goto = function goto(position) {
var event = d.createEvent('Event');
event.initEvent('positionChanged', true, true);
this.position = position;
this.el.dispatchEvent(event);
this.render();
};
ImageSlider.prototype.previous = function previous() {
this.goto((this.position + (this.itemCount - 1)) % this.itemCount);
};
ImageSlider.prototype.next = function next() {
this.goto((this.position + 1) % this.itemCount);
};
window.ImageSlider = ImageSlider;
}).call(this, window, window.document, Modernizr);
new ImageSlider();
答案 1 :(得分:0)
为简单起见……图像、css 和 javascript 都在完全相同的时间呈现。因此转换无法发生,因为在转换运行时,图像已经具有您要“更改它”的值。
它的呈现是在添加值之后进行的,因此没有过渡。在这种情况下,使用 setTimeout 是相当标准的。但是,您应该意识到,如果某人的互联网连接速度较慢,那么 1/1000 秒的超时可能并不总是足够的。
正确的解决方案是,不要使用 javascript 更改样式,而是创建一个覆盖默认值的类,并使用 javascript 来切换您的类。
希望这实际上是您问题的答案,而不仅仅是我指出您使用预先存在的解决方案。
不过,就我个人而言,我完全按照您在做的事情做,就像我自己的轮播示例中所见:
/* set each image except first to not display */
document.querySelectorAll('.imgContainer div:not(:nth-child(1))').forEach(function(el) {
el.style.display = 'none';
el.style.opacity = 0;
});
/* set onclick event for navigation dots */
var dotty = document.querySelectorAll('ul li');
for (var i = 0; i < dotty.length; i++) {
dotty[i].addEventListener("click", contentChanger);
}
/* rotate function */
function contentChanger(evt) {
var id = evt.target.id;
x = evt.target.id;
[].forEach.call(document.querySelectorAll('li'), function (el) {
el.classList.remove('active');
});
evt.target.classList.add('active');
document.querySelectorAll('.imgContainer div:not(:nth-child(' + id + '))').forEach(function(el) {
el.style.display = 'none';
el.style.opacity = '0';
});
document.querySelector('.imgContainer div:nth-child(' + id + ')').style.display = 'block';
setTimeout(function(){
document.querySelector('.imgContainer div:nth-child(' + id + ')').style.opacity = 1;
}, 50);
}
/* only required to automate rotation leave this code out if you want only a click navigation. */
function clickIt(i) {
document.querySelector('ul li:nth-child('+i+')').click();
}
var x = 0;
setInterval(function(){
x++;
if (x > dotty.length) { x = 1; }
clickIt(x);
}, 5000);