【Animejs】——Anime.js照片墙案例实现

目录

一、实现的效果:

二、实现js的具体步骤

1、需要实现的逻辑梳理

2、切换风格的逻辑

三、完整代码:


用js编写使用animejs实现图片复杂的切换效果

一、实现的效果:

点击——> <——箭头,实现不同动画效果的炫酷切换 。

代码可以通过我下面分享的码云链接进行下载,或者结尾我会附上完整的代码:

animejs_1照片墙: 使用animejs实现照片墙的炫酷切换效果

我们主要来实现js部分的编写,所以建议大家去我的码云把源码下载下来,方便学习。 

二、实现js的具体步骤

创建如下的目录:

目录组成部分: 

 现在的状态是,画面在第一页上,点击两个箭头页面是不动的:

我们可以看到在index.html文件中,这7个风格都在里面,每一个风格我们用类名slide--layout-n中的数字来做区分:

如slide--layout-4代表第4种风格。

 这些风格都在页面中显示,为什么我们看不到?是因为透明度改成0。

我们需要做的是给按钮添加点击事件,使之能够切换风格: 

1、需要实现的逻辑梳理

点击箭头,会有两个效果:一个显示的图片出去,将要显示的图片进来的效果。

每次切换,标题也是不同的动画效果

总结我们需要完成的业务逻辑就是:

1、 我们切换风格的逻辑是通过改变每个风格的透明度来实现。

2、实现两个动画风格:图片的和标题的。——图片又分为进入和出去两个动画风格;标题每个风格都一样,我们写一个就可以了。

2、切换风格的逻辑

展示页面的逻辑:通过添加'slide--current'类名来实现透明度变为1,展示在页面上。

1、所有代码都是自执行函数,先实现两个方法,方便之后使用。

; (function (window) {
    // 严格模式下
	'use strict';
	// extend:把某一个对象的属性复制给另一个对象,把b的属性给a
	function extend(a, b) {
		for (var key in b) {
			if (b.hasOwnProperty(key)) {
				a[key] = b[key];
			}
		}
		return a;
	}
    // 防抖:我们不希望当快速点击的时候我们就一直在执行。想要间隔一定的时间在去触发 
	function debounce(func, wait) {
		var timeout;
		return function () {
			var context = this, args = arguments;
			var later = function () {
				timeout = null;
				func.apply(context, args);
			};
			clearTimeout(timeout);
			timeout = setTimeout(later, wait);
		};
	};
})(window)

2、实现风格切换的方法: 

function MLSlideshow(el, options) {
		// 1. 元素属性
        // 拿到元素,就把元素挂载到对象下
		this.el = el;
		// 2. 相关参数
		this.options = extend({}, this.options);
		extend(this.options, options);
		// 3. 所有照片的风格
        // 最外层盒子取到所有风格的类名
		this.slides = [].slice.call(this.el.querySelectorAll('.slide'));

		// 判断:如果当前照片风格少于2,不创建实例————也就是只有1种风格
		this.slidesTotal = this.slides.length;
		if (this.slidesTotal <= 1) {
			return;
		}
		// 4. 当前展示的风格的下标
		this.current = this.options.startIdx || 0;
		// 5. 当前窗口大小————因为图片的宽高是由窗口大小决定的
		this.dimentions = {
			width: this.el.offsetWidth,
			height: this.el.offsetHeight
		}
		// 6. 照片风格初始化
        // 需要一个_init方法————下面会写
		this._init();
	}

解释: 

this.slides = [].slice.call(this.el.querySelectorAll('.slide'));

如下图index.html中知道每个风格的类名都叫 slide ,this.el.querySelectorAll('.slide')返回的是一个伪数组数据,所以我们需要转化为正常的数组来方便之后处理,通过slice


3、风格初始化——_init

// 照片墙初始化
	MLSlideshow.prototype._init = function () {
		var self = this, // self保存一下当前的this
			// 1. 当图片加载完成,展示当前第一个风格————由current决定是第几个风格
			// onPreload:图片加载完成要做的事情
			onPreload = function () {
				// 给当前的图片添加一个类名
				self.el.classList.add('slideshow--loaded');
				// 让第一个风格展示
				self.slides[self.current].classList.add('slide--current');
			};
		// 在图片加载完成的时候调用
		this._preload(onPreload);
		// 2. 添加事件:
                // 2.1 窗口大小事件
                // 2.2 键盘触发切换风格事件
		// _initEvents独立出一个方法
		this._initEvents();

	}

解释:

 当图片加载完成之后,才会展示当前第一个风格,那么我们会用到一个插件:

这个插件里面通提供了一个方法imagesLoaded,来判断我们的图片是否加载完成。

// 判断图片是否加载完成
	MLSlideshow.prototype._preload = function (callback) {
		// imagesLoaded直接调用,因为我们已经引入了这个包
		imagesLoaded(this.el, { background: true }, function () {
			// 如果传入的回调是一个函数,我们就去调用它
			if (typeof callback === 'function') {
				callback();
			}
		});
	};

4、添加事件——_initEvents:

MLSlideshow.prototype._initEvents = function () {
		var self = this;
		// 2.1 窗口大小事件
		// 用到防抖debounce
		this.debounceResize = debounce(function (ev) {
			self.dimentions = {
				width: self.el.offsetWidth,
				height: self.el.offsetHeight
			};
		}, 10)
		// 添加事件,当窗口的大小发送改变: 
		window.addEventListener('resize', this.debounceResize);
		// 2.2 键盘触发切换风格事件
		// 按下左右键的键盘按键,触发切换的按钮
		this.keyboardFn = function (ev) {
			var keyCode = ev.keyCode || ev.which;
			switch (keyCode) {
				case 37:
					// _navigate('prev'):往前切换————一会完成前后切换的函数实现
					self._navigate('prev');
					break;
				case 39:
					// _navigate('next'):往后切换
					self._navigate('next');
					break;
			}
		};
		this.el.addEventListener('keydown', this.keyboardFn);
	}

5、前后切换——_navigate

// _navigate:参数接收prev和next
	MLSlideshow.prototype._navigate = function (direction) {
		// isAnimating:判断当前动画是否在运动
		if (this.isAnimating) {
			return false;
		}
		this.isAnimating = true;
		// 1. 获取当前展示风格的信息: 当前元素,唯一标识,相关标题
		var self = this,
			// 知道当前展示的下标是什么,当点击前后切换的时候,改变下标的值来完成
			currentSlide = this.slides[this.current],
			// 获取当前风格标识
			currentLayout = currentSlide.getAttribute('data-layout') || 'layout1',
			// 获取当前展示风格的标题
			currentTitle = currentSlide.querySelector('.slide__title');

		// 2. 获取下一个要展示风格的信息: 当前元素,唯一标识,相关标题
		if (direction === 'next') {
			this.current = this.current < this.slidesTotal - 1 ? this.current + 1 : 0;
		}
		else {
			this.current = this.current > 0 ? this.current - 1 : this.slidesTotal - 1;
		}
		// 获取元素信息
		var nextSlide = this.slides[this.current],
			nextLayout = nextSlide.getAttribute('data-layout'),
			nextTitle = nextSlide.querySelector('.slide__title');
        // 3. 针对要出去的元素的动画
		// currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner'):动画中要出去的所有的图片
		// currentSlide:当前要出去的元素
		var outItems = [].slice.call(currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner')),
			// 获取相关配置参数
			outconfig = this.options.layoutConfig[currentLayout] !== undefined ? this.options.layoutConfig[currentLayout].out : this.options.layoutConfig['layout1'].out,
			animeOutProps = {
				targets: outItems,
				duration: outconfig.duration,
				easing: outconfig.easing,
				// 延迟是一个方法
				delay: function (el, index) {
					return direction === 'next' ? index * outconfig.itemsDelay : (outItems.length - 1 - index) * outconfig.itemsDelay;
				},
				// 走的这个元素之前是添加了一个类名,现在走了要把类名拿掉
				complete: function () {
					currentSlide.classList.remove('slide--current');
				}
			};
		this._setAnimationProperties(animeOutProps, outconfig, direction)
		// 参数传入,直接进行动画
		anime(animeOutProps);
		// 标题
		this._anmateTitle(currentTitle, 'out');
		// 创建定时器:当前风格出去了,再让下一个风格进来
		clearTimeout(this.navtime);
		// animateIn:让动画进来  
		this.navtime = setTimeout(animateIn, this.options.layoutConfig[nextLayout] !== undefined && this.options.layoutConfig[nextLayout].in.delay !== undefined ? this.options.layoutConfig[nextLayout].in.delay : 150);
	}

针对要显示的风格创建方法:

// _navigate:参数接收prev和next
	MLSlideshow.prototype._navigate = function (direction) {
		// isAnimating:判断当前动画是否在运动
		if (this.isAnimating) {
			return false;
		}
		this.isAnimating = true;
		// 1. 获取当前展示风格的信息: 当前元素,唯一标识,相关标题
		var self = this,
			// 知道当前展示的下标是什么也就是要出去的元素,当点击前后切换的时候,改变下标的值来完成
			currentSlide = this.slides[this.current],
			// 获取当前风格标识
			currentLayout = currentSlide.getAttribute('data-layout') || 'layout1',
			// 获取当前展示风格的标题
			currentTitle = currentSlide.querySelector('.slide__title');

		// 2. 获取下一个要展示风格的信息: 当前元素,唯一标识,相关标题
		if (direction === 'next') {
			this.current = this.current < this.slidesTotal - 1 ? this.current + 1 : 0;
		}
		else {
			this.current = this.current > 0 ? this.current - 1 : this.slidesTotal - 1;
		}
		// 获取元素信息
		var nextSlide = this.slides[this.current],
			nextLayout = nextSlide.getAttribute('data-layout'),
			nextTitle = nextSlide.querySelector('.slide__title');
		// 4. 针对要显示的风格创建方法
		var animateIn = function () {

			// 开启动画之前把其他动画停掉
			clearTimeout(self.navtime);

			// 获取计算的要进入的风格的照片元素
			var inItems = [].slice.call(nextSlide.querySelectorAll('.slide-imgwrap .slide__img-inner')),
				// 设置计算的下一个的下标元素动画,如果不存在就设置第一个元素动画,标识区分
				// 获取即将进入的风格的动画参数
				inconfig = self.options.layoutConfig[nextLayout] !== undefined ? self.options.layoutConfig[nextLayout].in : self.options.layoutConfig['layout1'].in,
				// 进入时,初始化设置赋值给inresetconfig
				inresetconfig = inconfig.resetProps,
				// 设置动画参数
				animeInProps = {
					targets: inItems,
					duration: inconfig.duration,
					easing: inconfig.easing,
					delay: function (el, index) {
						return direction === 'next' ? index * inconfig.itemsDelay : (inItems.length - 1 - index) * inconfig.itemsDelay;
					},
					// 动画完成设置动画运动标识是false
					complete: function () {
						self.isAnimating = false;
					}
				};

			// Configure the animation in properties.
			// 将动画参数,当前动画元素相关信息,前后传入设置动画属性的方法中
			self._setAnimationProperties(animeInProps, inconfig, direction);
			// Reset before animating in:
			// 在动画之前重置即将进入的风格的图片
			// 需要重置的原因:因为图片的宽高是相对窗口的 ,但是图片的宽高又是根据浏览器窗口的,所以每一次我们都要重置一下图片的宽高,避免窗口发生改变之后,盒子小了图片还很大这种不好的效果
			inItems.forEach(function (item, pos) {
				var transformStr = '';
				// 将属性中的translateX、translateY、rotateZ、scale、opacity进行重置
				if (inresetconfig.translateX !== undefined) {
					var tx = typeof inresetconfig.translateX === 'object' ?
						function () {
							return typeof inresetconfig.translateX[direction] === 'function' ?
								self._getValuePercentage(inresetconfig.translateX[direction](item, pos), 'width') :
								self._getValuePercentage(inresetconfig.translateX[direction], 'width');
						} : self._getValuePercentage(inresetconfig.translateX, 'width');

					transformStr += ' translateX(' + (typeof tx === 'function' ? tx() : tx) + 'px)';
				}
				if (inresetconfig.translateY !== undefined) {
					var ty = typeof inresetconfig.translateY === 'object' ? function () {
						return typeof inresetconfig.translateY[direction] === 'function' ? self._getValuePercentage(inresetconfig.translateY[direction](item, pos), 'height') : self._getValuePercentage(inresetconfig.translateY[direction], 'height');
					} : self._getValuePercentage(inresetconfig.translateY, 'height');
					transformStr += ' translateY(' + (typeof ty === 'function' ? ty() : ty) + 'px)';
				}
				if (inresetconfig.rotateZ !== undefined) {
					var rot = typeof inresetconfig.rotateZ === 'object' ? function () {
						return typeof inresetconfig.rotateZ[direction] === 'function' ? inresetconfig.rotateZ[direction](item, pos) : inresetconfig.rotateZ[direction];
					} : inresetconfig.rotateZ;

					transformStr += ' rotateZ(' + (typeof rot === 'function' ? rot() : rot) + 'deg)';
				}
				if (inresetconfig.scale !== undefined) {
					var s = typeof inresetconfig.scale === 'object' ? function () {
						return typeof inresetconfig.scale[direction] === 'function' ? inresetconfig.scale[direction](item, pos) : inresetconfig.scale[direction];
					} : inresetconfig.scale;

					transformStr += ' scale(' + (typeof s === 'function' ? s() : s) + ')';
				}
				if (transformStr !== '') {
					item.style.transform = item.style.WebkitTransform = transformStr;
				}
				if (inresetconfig.opacity !== undefined) {
					item.style.opacity = inresetconfig.opacity;
				}
			});
			// 设置即将进入的风格的title是透明的
			// Reset next title.
			nextTitle.style.opacity = 0;
			// Switch current class.
			// 设置即将进入的元素类名是当前风格的
			nextSlide.classList.add('slide--current');
			// Animate next slide in.
			// 动画让其进入
			anime(animeInProps);
			// Animate next title in.
			// 让标题进入
			self._animateTitle(nextTitle, 'in');
		};

		// 3. 针对要出去的元素的动画
		// currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner'):动画中要出去的所有的图片
		// currentSlide:当前要出去的元素
		var outItems = [].slice.call(currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner')),
			// 获取相关配置参数
			outconfig = this.options.layoutConfig[currentLayout] !== undefined ? this.options.layoutConfig[currentLayout].out : this.options.layoutConfig['layout1'].out,
			animeOutProps = {
				targets: outItems,
				duration: outconfig.duration,
				easing: outconfig.easing,
				// 延迟是一个方法
				delay: function (el, index) {
					return direction === 'next' ? index * outconfig.itemsDelay : (outItems.length - 1 - index) * outconfig.itemsDelay;
				},
				// 走的这个元素之前是添加了一个类名,现在走了要把类名拿掉
				complete: function () {
					currentSlide.classList.remove('slide--current');
				}
			};
		this._setAnimationProperties(animeOutProps, outconfig, direction)
		// 参数传入,直接进行动画
		anime(animeOutProps);
		// 标题
		this._anmateTitle(currentTitle, 'out');
		// 创建定时器:当前风格出去了,再让下一个风格进来
		clearTimeout(this.navtime);
		// animateIn:让动画进来  
		this.navtime = setTimeout(animateIn, this.options.layoutConfig[nextLayout] !== undefined && this.options.layoutConfig[nextLayout].in.delay !== undefined ? this.options.layoutConfig[nextLayout].in.delay : 150);
	}

6、图片进入和出去相关的动画参数——options

这里有7个动画效果,我们只分析一个,其他7个是完全一样的,详细看源码。

	// 图片进入和出去相关的动画参数
	// 设计风格动画参数
	MLSlideshow.prototype.options = {
		// 起始的下标设置成0
		startIdx: 0,
		// layoutConfig:7个风格会放在一个对象下 
		layoutConfig: {
			layout1: {
				// 退出时
				out: {
					// 点击next还是点击prev,方向是不一样的
					translateX: {
						next: '-100%',
						prev: '100%'
					},
					rotateZ: {
						next: function (el, index) {
							return anime.random(-15, 0);
						},
						prev: function (el, index) {
							return anime.random(0, 15);
						}
					},
					opacity: 0,
					duration: 1200,
					easing: 'easeOutQuint',
					itemsDelay: 80
				},
				// 进入时
				in: {
					// resetProps:在进入时需要重置一下动画的参数
					resetProps: {
						translateX: {
							next: '100%',
							prev: '-100%'
						},
						rotateZ: {
							next: function (el, index) {
								return anime.random(0, 15);
							},
							prev: function (el, index) {
								return anime.random(-15, 0);
							}
						},
						opacity: 0,
					},
					translateX: '0%',
					rotateZ: 0,
					opacity: 1,
					duration: 700,
					easing: 'easeOutQuint',
					itemsDelay: 80
				}
			},
            layout12: {
            }
            ...
        }
    }

7、进入和出去两个动画之前都是处理一下参数,把config的参数传递给当前动画的参数,思路和初始化的思路是一样的。

// 处理参数
	MLSlideshow.prototype._setAnimationProperties = function (props, config, direction) {
		var self = this;
		if (config.translateX !== undefined) {
			props.translateX = typeof config.translateX === 'object' ?
				function (el, index) {
					return typeof config.translateX[direction] === 'function' ?
						self._getValuePercentage(config.translateX[direction](el, index), 'width')
						: self._getValuePercentage(config.translateX[direction], 'width');
				} : this._getValuePercentage(config.translateX, 'width');
		}
		if (config.translateY !== undefined) {
			props.translateY = typeof config.translateY === 'object' ? function (el, index) {
				return typeof config.translateY[direction] === 'function' ? self._getValuePercentage(config.translateY[direction](el, index), 'width') : self._getValuePercentage(config.translateY[direction], 'height');
			} : this._getValuePercentage(config.translateY, 'height');
		}
		if (config.rotateZ !== undefined) {
			props.rotateZ = typeof config.rotateZ === 'object' ? function (el, index) {
				return typeof config.rotateZ[direction] === 'function' ? config.rotateZ[direction](el, index) : config.rotateZ[direction];
			} : config.rotateZ;
		}
		if (config.scale !== undefined) {
			props.scale = typeof config.scale === 'object' ? function (el, index) {
				return typeof config.scale[direction] === 'function' ? config.scale[direction](el, index) : config.scale[direction];
			} : config.scale;
		}
		if (config.opacity !== undefined) {
			props.opacity = config.opacity;
		}
	};
    // _getValuePercentage :获取百分比,改为值
	MLSlideshow.prototype._getValuePercentage = function (str, axis) {
		return typeof str === 'string' && str.indexOf('%') !== -1 ? parseFloat(str) / 100 * this.dimentions[axis] : str;
	}

8、设置title动画

// 设置title动画
	MLSlideshow.prototype._anmateTitle = function (titleEl, dir) {
		anime({
			targets: titleEl,
			opacity: dir === 'out' ? 0 : 1,
			duration: dir === 'out' ? 200 : 500,
			easing: 'easeOutExpo'
		})
	}
	MLSlideshow.prototype.next = function () {
		this._navigate('next');
	}
	MLSlideshow.prototype.prev = function () {
		this._navigate('prev');
	}
	window.MLSlideshow = MLSlideshow;

代码就完成了,我们去index.html调用我们写的方法:

<script src="js/imagesloaded.pkgd.min.js"></script>
<script src="js/anime.min.js"></script>
<script src="js/main.js"></script>
<script>
        (function () {
            var slideshow = new MLSlideshow(document.querySelector('.slideshow'));
            document.querySelector('#prev-slide').addEventListener('click', function () {
                slideshow.prev();
            })
            document.querySelector('#next-slide').addEventListener('click', function () {
                slideshow.next();
            })
        })()

</script>

三、完整代码:

// ▷main.js

// 所有代码都是自执行函数
; (function (window) {
	// 严格模式下
	'use strict';
	// extend:把某一个对象的属性复制给另一个对象,把b的属性给a
	function extend(a, b) {
		for (var key in b) {
			if (b.hasOwnProperty(key)) {
				a[key] = b[key];
			}
		}
		return a;
	}
	// 防抖:我们不希望当快速点击的时候我们就一直在执行。想要间隔一定的时间在去触发 
	function debounce(func, wait) {
		var timeout;
		return function () {
			var context = this, args = arguments;
			var later = function () {
				timeout = null;
				func.apply(context, args);
			};
			clearTimeout(timeout);
			timeout = setTimeout(later, wait);
		};
	};

	function MLSlideshow(el, options) {
		// 1. 元素属性
		// 拿到元素,就把元素挂载到对象下
		this.el = el;
		// 2. 相关参数
		this.options = extend({}, this.options);
		extend(this.options, options);
		// 3. 所有照片的风格
		// 最外层盒子取到所有风格的类名
		this.slides = [].slice.call(this.el.querySelectorAll('.slide'));

		// 判断:如果当前照片风格少于2,不创建实例
		this.slidesTotal = this.slides.length;
		if (this.slidesTotal <= 1) {
			return;
		}
		// 4. 当前展示的风格的下标
		this.current = this.options.startIdx || 0;
		// 5. 当前窗口
		this.dimentions = {
			width: this.el.offsetWidth,
			height: this.el.offsetHeight
		}
		// 6. 照片风格初始化
		this._init();
	}

	// 照片墙初始化
	MLSlideshow.prototype._init = function () {
		var self = this, // self保存一下当前的this
			// 1. 当图片加载完成,展示当前第一个风格————由current决定是第几个风格
			// onPreload:图片加载完成要做的事情
			onPreload = function () {
				// 给当前的图片添加一个类名
				self.el.classList.add('slideshow--loaded');
				// 让第一个风格展示
				self.slides[self.current].classList.add('slide--current');
			};
		// 在图片加载完成的时候调用
		this._preload(onPreload);
		// 2. 添加事件:
		// _initEvents独立出一个方法
		this._initEvents();

	}

	// 判断图片是否加载完成
	MLSlideshow.prototype._preload = function (callback) {
		// imagesLoaded直接调用,因为我们已经引入了这个包
		imagesLoaded(this.el, { background: true }, function () {
			// 如果传入的回调是一个函数,我们就去调用它
			if (typeof callback === 'function') {
				callback();
			}
		});
	};

	MLSlideshow.prototype._initEvents = function () {
		var self = this;
		// 2.1 窗口大小事件
		// 用到防抖debounce
		this.debounceResize = debounce(function (ev) {
			self.dimentions = {
				width: self.el.offsetWidth,
				height: self.el.offsetHeight
			};
		}, 10)
		// 添加事件,当窗口的大小发送改变: 
		window.addEventListener('resize', this.debounceResize);
		// 2.2 键盘触发切换风格事件
		// 按下左右键的键盘按键,触发切换的按钮
		this.keyboardFn = function (ev) {
			var keyCode = ev.keyCode || ev.which;
			switch (keyCode) {
				case 37:
					// _navigate('prev'):往前切换
					self._navigate('prev');
					break;
				case 39:
					// _navigate('next'):往后切换
					self._navigate('next');
					break;
			}
		};
		this.el.addEventListener('keydown', this.keyboardFn);
	}
	
	// 图片进入和出去相关的动画参数
	// 设计风格动画参数
	MLSlideshow.prototype.options = {
		// 起始的下标设置成0
		startIdx: 0,
		// layoutConfig:7个风格会放在一个对象下 
		layoutConfig: {
			layout1: {
				// 退出时
				out: {
					// 点击next还是点击prev,方向是不一样的
					translateX: {
						next: '-100%',
						prev: '100%'
					},
					rotateZ: {
						next: function (el, index) {
							return anime.random(-15, 0);
						},
						prev: function (el, index) {
							return anime.random(0, 15);
						}
					},
					opacity: 0,
					duration: 1200,
					easing: 'easeOutQuint',
					itemsDelay: 80
				},
				// 进入时
				in: {
					// resetProps:在进入时需要重置一下动画的参数
					resetProps: {
						translateX: {
							next: '100%',
							prev: '-100%'
						},
						rotateZ: {
							next: function (el, index) {
								return anime.random(0, 15);
							},
							prev: function (el, index) {
								return anime.random(-15, 0);
							}
						},
						opacity: 0,
					},
					translateX: '0%',
					rotateZ: 0,
					opacity: 1,
					duration: 700,
					easing: 'easeOutQuint',
					itemsDelay: 80
				}
			},
			layout2: {
				out: {
					translateX: {
						next: function (el, index) {
							return anime.random(-50, 50) + '%';
						},
						prev: function (el, index) {
							return anime.random(-50, 50) + '%';
						}
					},
					translateY: {
						next: function (el, index) {
							return anime.random(-50, 50) + '%';
						},
						prev: function (el, index) {
							return anime.random(-50, 50) + '%';
						}
					},
					opacity: 0,
					duration: 1200,
					easing: 'easeOutQuint',
					itemsDelay: 10
				},
				in: {
					resetProps: {
						translateX: {
							next: '100%',
							prev: '-100%'
						},
						rotateZ: {
							next: function (el, index) {
								return anime.random(0, 90);
							},
							prev: function (el, index) {
								return anime.random(-90, 0);
							}
						},
						opacity: 0,
					},
					translateX: '0%',
					rotateZ: 0,
					opacity: 1,
					duration: 900,
					easing: 'easeOutExpo',
					itemsDelay: 30
				}
			},
			layout3: {
				out: {
					translateX: '-10%',
					rotateZ: 0,
					opacity: 0,
					duration: 500,
					easing: 'easeOutExpo',
					itemsDelay: 0
				},
				in: {
					resetProps: {
						translateX: '-10%',
						rotateZ: 0,
						opacity: 0
					},
					translateX: 0,
					opacity: 1,
					rotateZ: {
						next: function (el, index) {
							return index * 6;
						},
						prev: function (el, index) {
							return index * 6;
						}
					},
					duration: 1200,
					easing: 'easeOutElastic',
					itemsDelay: 0
				}
			},
			layout4: {
				out: {
					translateY: {
						next: '60%',
						prev: '-60%'
					},
					opacity: 0,
					duration: 700,
					easing: 'easeOutQuint',
					itemsDelay: 50
				},
				in: {
					resetProps: {
						translateY: {
							next: '-60%',
							prev: '60%'
						},
						opacity: 0,
					},
					translateY: '0%',
					opacity: 1,
					duration: 700,
					easing: 'easeOutQuint',
					itemsDelay: 50,
					delay: 250
				}
			},
			layout5: {
				out: {
					scale: 0.5,
					opacity: 0,
					duration: 500,
					easing: 'easeOutExpo',
					itemsDelay: 20
				},
				in: {
					resetProps: {
						scale: 0.5,
						opacity: 0
					},
					opacity: 1,
					scale: 1,
					duration: 500,
					easing: 'easeOutExpo',
					itemsDelay: 20,
					delay: 300
				}
			},
			layout6: {
				out: {
					scale: 0.5,
					opacity: 0,
					duration: 300,
					easing: 'easeInBack',
					itemsDelay: 20
				},
				in: {
					resetProps: {
						scale: 0.5,
						opacity: 0
					},
					opacity: 1,
					scale: 1,
					duration: 1000,
					easing: 'easeOutElastic',
					itemsDelay: 50,
					delay: 400
				}
			},
			layout7: {
				out: {
					translateX: {
						next: '-100%',
						prev: '100%'
					},
					opacity: 0,
					duration: 1200,
					easing: 'easeOutQuint',
					itemsDelay: 40
				},
				in: {
					resetProps: {
						translateX: {
							next: '100%',
							prev: '-100%'
						},
						rotateZ: {
							next: function (el, index) {
								return anime.random(0, 25);
							},
							prev: function (el, index) {
								return anime.random(-25, 0);
							}
						},
						opacity: 0,
					},
					translateX: '0%',
					rotateZ: 0,
					opacity: 1,
					duration: 700,
					easing: 'easeOutQuint',
					itemsDelay: 40,
					delay: 250
				}
			}
		}
	};

	// _navigate:参数接收prev和next
	MLSlideshow.prototype._navigate = function (direction) {
		// isAnimating:判断当前动画是否在运动
		if (this.isAnimating) {
			return false;
		}
		this.isAnimating = true;
		// 1. 获取当前展示风格的信息: 当前元素,唯一标识,相关标题
		var self = this,
			// 知道当前展示的下标是什么也就是要出去的元素,当点击前后切换的时候,改变下标的值来完成
			currentSlide = this.slides[this.current],
			// 获取当前风格标识
			currentLayout = currentSlide.getAttribute('data-layout') || 'layout1',
			// 获取当前展示风格的标题
			currentTitle = currentSlide.querySelector('.slide__title');

		// 2. 获取下一个要展示风格的信息: 当前元素,唯一标识,相关标题
		if (direction === 'next') {
			this.current = this.current < this.slidesTotal - 1 ? this.current + 1 : 0;
		}
		else {
			this.current = this.current > 0 ? this.current - 1 : this.slidesTotal - 1;
		}
		// 获取元素信息
		var nextSlide = this.slides[this.current],
			nextLayout = nextSlide.getAttribute('data-layout'),
			nextTitle = nextSlide.querySelector('.slide__title');
		// 4. 针对要显示的风格创建方法
		var animateIn = function () {

			// 开启动画之前把其他动画停掉
			clearTimeout(self.navtime);

			// 获取计算的要进入的风格的照片元素
			var inItems = [].slice.call(nextSlide.querySelectorAll('.slide-imgwrap .slide__img-inner')),
				// 设置计算的下一个的下标元素动画,如果不存在就设置第一个元素动画,标识区分
				// 获取即将进入的风格的动画参数
				inconfig = self.options.layoutConfig[nextLayout] !== undefined ? self.options.layoutConfig[nextLayout].in : self.options.layoutConfig['layout1'].in,
				// 进入时,初始化设置赋值给inresetconfig
				inresetconfig = inconfig.resetProps,
				// 设置动画参数
				animeInProps = {
					targets: inItems,
					duration: inconfig.duration,
					easing: inconfig.easing,
					delay: function (el, index) {
						return direction === 'next' ? index * inconfig.itemsDelay : (inItems.length - 1 - index) * inconfig.itemsDelay;
					},
					// 动画完成设置动画运动标识是false
					complete: function () {
						self.isAnimating = false;
					}
				};

			// Configure the animation in properties.
			// 将动画参数,当前动画元素相关信息,前后传入设置动画属性的方法中
			self._setAnimationProperties(animeInProps, inconfig, direction);
			// Reset before animating in:
			// 在动画之前重置即将进入的风格的图片
			// 需要重置的原因:因为图片的宽高是相对窗口的 ,但是图片的宽高又是根据浏览器窗口的,所以每一次我们都要重置一下图片的宽高,避免窗口发生改变之后,盒子小了图片还很大这种不好的效果
			inItems.forEach(function (item, pos) {
				var transformStr = '';
				// 将属性中的translateX、translateY、rotateZ、scale、opacity进行重置
				if (inresetconfig.translateX !== undefined) {
					var tx = typeof inresetconfig.translateX === 'object' ?
						function () {
							return typeof inresetconfig.translateX[direction] === 'function' ?
								self._getValuePercentage(inresetconfig.translateX[direction](item, pos), 'width') :
								self._getValuePercentage(inresetconfig.translateX[direction], 'width');
						} : self._getValuePercentage(inresetconfig.translateX, 'width');

					transformStr += ' translateX(' + (typeof tx === 'function' ? tx() : tx) + 'px)';
				}
				if (inresetconfig.translateY !== undefined) {
					var ty = typeof inresetconfig.translateY === 'object' ? function () {
						return typeof inresetconfig.translateY[direction] === 'function' ? self._getValuePercentage(inresetconfig.translateY[direction](item, pos), 'height') : self._getValuePercentage(inresetconfig.translateY[direction], 'height');
					} : self._getValuePercentage(inresetconfig.translateY, 'height');
					transformStr += ' translateY(' + (typeof ty === 'function' ? ty() : ty) + 'px)';
				}
				if (inresetconfig.rotateZ !== undefined) {
					var rot = typeof inresetconfig.rotateZ === 'object' ? function () {
						return typeof inresetconfig.rotateZ[direction] === 'function' ? inresetconfig.rotateZ[direction](item, pos) : inresetconfig.rotateZ[direction];
					} : inresetconfig.rotateZ;

					transformStr += ' rotateZ(' + (typeof rot === 'function' ? rot() : rot) + 'deg)';
				}
				if (inresetconfig.scale !== undefined) {
					var s = typeof inresetconfig.scale === 'object' ? function () {
						return typeof inresetconfig.scale[direction] === 'function' ? inresetconfig.scale[direction](item, pos) : inresetconfig.scale[direction];
					} : inresetconfig.scale;

					transformStr += ' scale(' + (typeof s === 'function' ? s() : s) + ')';
				}
				if (transformStr !== '') {
					item.style.transform = item.style.WebkitTransform = transformStr;
				}
				if (inresetconfig.opacity !== undefined) {
					item.style.opacity = inresetconfig.opacity;
				}
			});
			// 设置即将进入的风格的title是透明的
			// Reset next title.
			nextTitle.style.opacity = 0;
			// Switch current class.
			// 设置即将进入的元素类名是当前风格的
			nextSlide.classList.add('slide--current');
			// Animate next slide in.
			// 动画让其进入
			anime(animeInProps);
			// Animate next title in.
			// 让标题进入
			self._anmateTitle(nextTitle, 'in');
		};

		// 3. 针对要出去的元素的动画
		// currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner'):动画中要出去的所有的图片
		// currentSlide:当前要出去的元素
		var outItems = [].slice.call(currentSlide.querySelectorAll('.slide-imgwrap .slide__img-inner')),
			// 获取相关配置参数
			outconfig = this.options.layoutConfig[currentLayout] !== undefined ? this.options.layoutConfig[currentLayout].out : this.options.layoutConfig['layout1'].out,
			animeOutProps = {
				targets: outItems,
				duration: outconfig.duration,
				easing: outconfig.easing,
				// 延迟是一个方法
				delay: function (el, index) {
					return direction === 'next' ? index * outconfig.itemsDelay : (outItems.length - 1 - index) * outconfig.itemsDelay;
				},
				// 走的这个元素之前是添加了一个类名,现在走了要把类名拿掉
				complete: function () {
					currentSlide.classList.remove('slide--current');
				}
			};
		this._setAnimationProperties(animeOutProps, outconfig, direction)
		// 参数传入,直接进行动画
		anime(animeOutProps);
		// 标题
		this._anmateTitle(currentTitle, 'out');
		// 创建定时器:当前风格出去了,再让下一个风格进来
		clearTimeout(this.navtime);
		// animateIn:让动画进来  
		this.navtime = setTimeout(animateIn, this.options.layoutConfig[nextLayout] !== undefined && this.options.layoutConfig[nextLayout].in.delay !== undefined ? this.options.layoutConfig[nextLayout].in.delay : 150);
	}

	// 处理参数
	MLSlideshow.prototype._setAnimationProperties = function (props, config, direction) {
		var self = this;
		if (config.translateX !== undefined) {
			props.translateX = typeof config.translateX === 'object' ?
				function (el, index) {
					return typeof config.translateX[direction] === 'function' ?
						self._getValuePercentage(config.translateX[direction](el, index), 'width')
						: self._getValuePercentage(config.translateX[direction], 'width');
				} : this._getValuePercentage(config.translateX, 'width');
		}
		if (config.translateY !== undefined) {
			props.translateY = typeof config.translateY === 'object' ? function (el, index) {
				return typeof config.translateY[direction] === 'function' ? self._getValuePercentage(config.translateY[direction](el, index), 'width') : self._getValuePercentage(config.translateY[direction], 'height');
			} : this._getValuePercentage(config.translateY, 'height');
		}
		if (config.rotateZ !== undefined) {
			props.rotateZ = typeof config.rotateZ === 'object' ? function (el, index) {
				return typeof config.rotateZ[direction] === 'function' ? config.rotateZ[direction](el, index) : config.rotateZ[direction];
			} : config.rotateZ;
		}
		if (config.scale !== undefined) {
			props.scale = typeof config.scale === 'object' ? function (el, index) {
				return typeof config.scale[direction] === 'function' ? config.scale[direction](el, index) : config.scale[direction];
			} : config.scale;
		}
		if (config.opacity !== undefined) {
			props.opacity = config.opacity;
		}
	};

	
	MLSlideshow.prototype._getValuePercentage = function (str, axis) {
		return typeof str === 'string' && str.indexOf('%') !== -1 ? parseFloat(str) / 100 * this.dimentions[axis] : str;
	}

	// 设置title动画
	MLSlideshow.prototype._anmateTitle = function (titleEl, dir) {
		anime({
			targets: titleEl,
			opacity: dir === 'out' ? 0 : 1,
			duration: dir === 'out' ? 200 : 500,
			easing: 'easeOutExpo'
		})
	}
	MLSlideshow.prototype.next = function () {
		this._navigate('next');
	}
	MLSlideshow.prototype.prev = function () {
		this._navigate('prev');
	}
	window.MLSlideshow = MLSlideshow;
})(window)
// ▷index.html

<!DOCTYPE html>
<html lang="en" class="no-js">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>照片墙</title>
    <link rel="stylesheet" type="text/css" href="css/normalize.css" />
    <link rel="stylesheet" type="text/css" href="css/demo.css" />
    <link rel="stylesheet" type="text/css" href="css/slideshow.css" />
    <link rel="stylesheet" type="text/css" href="css/slideshow_layouts.css" />
    <!--[if IE]>
  		<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  		<style>
			.ie-message { display: inline-block; }
  		</style>
		<![endif]-->
    <script>document.documentElement.className = 'js';</script>
</head>

<body>
    <svg class="hidden">
        <defs>
            <symbol id="icon-arrow" viewBox="0 0 24 24">
                <title>arrow</title>
                <polygon points="6.3,12.8 20.9,12.8 20.9,11.2 6.3,11.2 10.2,7.2 9,6 3.1,12 9,18 10.2,16.8 " />
            </symbol>
            <symbol id="icon-drop" viewBox="0 0 24 24">
                <title>drop</title>
                <path
                    d="M12,21c-3.6,0-6.6-3-6.6-6.6C5.4,11,10.8,4,11.4,3.2C11.6,3.1,11.8,3,12,3s0.4,0.1,0.6,0.3c0.6,0.8,6.1,7.8,6.1,11.2C18.6,18.1,15.6,21,12,21zM12,4.8c-1.8,2.4-5.2,7.4-5.2,9.6c0,2.9,2.3,5.2,5.2,5.2s5.2-2.3,5.2-5.2C17.2,12.2,13.8,7.3,12,4.8z" />
                <path
                    d="M12,18.2c-0.4,0-0.7-0.3-0.7-0.7s0.3-0.7,0.7-0.7c1.3,0,2.4-1.1,2.4-2.4c0-0.4,0.3-0.7,0.7-0.7c0.4,0,0.7,0.3,0.7,0.7C15.8,16.5,14.1,18.2,12,18.2z" />
            </symbol>
            <symbol id="icon-prev" viewBox="0 0 100 50">
                <title>prev</title>
                <polygon
                    points="5.4,25 18.7,38.2 22.6,34.2 16.2,27.8 94.6,27.8 94.6,22.2 16.2,22.2 22.6,15.8 18.7,11.8" />
            </symbol>
            <symbol id="icon-next" viewBox="0 0 100 50">
                <title>next</title>
                <polygon
                    points="81.3,11.8 77.4,15.8 83.8,22.2 5.4,22.2 5.4,27.8 83.8,27.8 77.4,34.2 81.3,38.2 94.6,25 " />
            </symbol>
            <symbol id="icon-octicon" viewBox="0 0 24 24">
                <title>octicon</title>
                <path
                    d="M12,2.2C6.4,2.2,1.9,6.7,1.9,12.2c0,4.4,2.9,8.2,6.9,9.6c0.5,0.1,0.7-0.2,0.7-0.5c0-0.2,0-0.9,0-1.7c-2.8,0.6-3.4-1.4-3.4-1.4C5.6,17.1,5,16.8,5,16.8C4.1,16.2,5,16.2,5,16.2c1,0.1,1.5,1,1.5,1c0.9,1.5,2.4,1.1,2.9,0.8c0.1-0.7,0.4-1.1,0.6-1.3c-2.2-0.3-4.6-1.1-4.6-5c0-1.1,0.4-2,1-2.7C6.5,8.8,6.2,7.7,6.7,6.4c0,0,0.8-0.3,2.8,1C10.3,7.2,11.1,7.1,12,7c0.9,0,1.7,0.1,2.5,0.3c1.9-1.3,2.8-1,2.8-1c0.5,1.4,0.2,2.4,0.1,2.7c0.6,0.7,1,1.6,1,2.7c0,3.9-2.4,4.7-4.6,5c0.4,0.3,0.7,0.9,0.7,1.9c0,1.3,0,2.4,0,2.8c0,0.3,0.2,0.6,0.7,0.5c4-1.3,6.9-5.1,6.9-9.6C22.1,6.7,17.6,2.2,12,2.2z" />
            </symbol>

            <clipPath id="polygon-clip-rhomboid" clipPathUnits="objectBoundingBox">
                <polygon points="0 1, 0.3 0, 1 0, 0.7 1" />
            </clipPath>
        </defs>
    </svg>
    <main>
        <div class="slideshow" tabindex="0">
            <div class="slide slide--layout-1" data-layout="layout1">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/1.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/2.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/3.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Now or Never</h3>
                    <p class="slide__title-sub">Our battered suitcases were piled on the sidewalk again; we had longer
                        ways to go. But no matter, the road is life. <a href="#">Read more</a></p>
                </div>
            </div>
            <div class="slide slide--layout-2" data-layout="layout2">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/6.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/5.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/6.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/7.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/9.jpg);">
                            <h4 class="slide__img-caption">Today is someday</h4>
                        </div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Crazy Breed</h3>
                    <p class="slide__title-sub">There's those thinking more or less less is more. But if less is more
                        how you're keeping score?</p>
                </div>
            </div>

            <div class="slide slide--layout-3" data-layout="layout3">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/9.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/10.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/11.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/15.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/13.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/14.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/12.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Safe Harbor</h3>
                    <p class="slide__title-sub">Twenty years from now you will be more disappointed by the things you
                        didn’t do than by the ones you did do.</p>
                </div>
            </div>

            <div class="slide slide--layout-4" data-layout="layout4">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/10.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/8.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/11.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/13.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Our Freedom</h3>
                    <p class="slide__title-sub">For to be free is not merely to cast off one's chains, but to live in a
                        way that respects and enhances the freedom of others.</p>
                </div>
            </div>

            <div class="slide slide--layout-5" data-layout="layout5">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/1.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/2.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/3.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/4.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/5.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/6.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/7.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/8.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/9.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/10.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/11.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/12.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/13.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/14.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/15.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/16.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/17.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/small/18.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Stopping Time</h3>
                    <p class="slide__title-sub">Emancipate yourselves from mental slavery, none but ourselves can free
                        our minds.</p>
                </div>
            </div>

            <div class="slide slide--layout-6" data-layout="layout6">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/14.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/11.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/3.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Walk the Walk</h3>
                    <p class="slide__title-sub">The trouble with being in the rat race is that even if you win, you're
                        still a rat.</p>
                </div>
            </div>

            <div class="slide slide--layout-7" data-layout="layout7">
                <div class="slide-imgwrap">
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/16.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/1.jpg);"></div>
                    </div>
                    <div class="slide__img">
                        <div class="slide__img-inner" style="background-image: url(img/4.jpg);"></div>
                    </div>
                </div>
                <div class="slide__title">
                    <h3 class="slide__title-main">Caged Birds</h3>
                    <p class="slide__title-sub">They told me to grow roots, instead I grew wings. Birds born in a cage
                        think flying is an illness. </p>
                </div>
            </div>

            <nav class="slideshow__nav slideshow__nav--arrows">
                <button id="prev-slide" class="btn btn--arrow" aria-label="Previous slide"><svg class="icon icon--prev">
                        <use xlink:href="#icon-prev"></use>
                    </svg></button>
                <button id="next-slide" class="btn btn--arrow" aria-label="Next slide"><svg class="icon icon--next">
                        <use xlink:href="#icon-next"></use>
                    </svg></button>
            </nav>
        </div>

    </main>
    <!-- 引入js中的三个包 -->
    <script src="js/imagesloaded.pkgd.min.js"></script>
    <script src="js/anime.min.js"></script>
    <script src="js/main.js"></script>
    <script>
        (function () {
            var slideshow = new MLSlideshow(document.querySelector('.slideshow'));
            document.querySelector('#prev-slide').addEventListener('click', function () {
                slideshow.prev();
            })
            document.querySelector('#next-slide').addEventListener('click', function () {
                slideshow.next();
            })
        })()

    </script>
</body>

</html>
当然,我可以使用Anime.js来为你创建一个具有连续动作的动态火柴人动画。请确保已经在HTML文件中引入了Anime.js库,然后可以使用以下代码: ```html <!DOCTYPE html> <html> <head> <title>火柴人动画</title> <style> #canvas { width: 400px; height: 400px; border: 1px solid black; } </style> </head> <body> <div id="canvas"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script> <script> const canvas = document.getElementById('canvas'); const animation = anime.timeline({ autoplay: true, loop: true, }); const drawStickMan = () => { const stickMan = document.createElement('div'); stickMan.classList.add('stickman'); canvas.appendChild(stickMan); }; drawStickMan(); animation .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -80, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: 360, duration: 1000 }, ], easing: 'linear', }) .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -40, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: -360, duration: 1000 }, ], easing: 'linear', }) .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -80, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: 360, duration: 1000 }, ], easing: 'linear', }); </script> </body> </html> ``` 在上述代码中,我们使用了Anime.js来创建一个时间轴(timeline),并为火柴人动画添加了一系列连续的动作。在`drawStickMan`函数中,我们创建了一个`div`元素,添加了`stickman`类,并将其附加到Canvas容器中。然后,我们使用Anime.js的时间轴来定义火柴人的动作序列。每个动作都使用`targets`属性指定要应用动画的元素,这里是具有`stickman`类的div元素。通过指定`translateY`和`rotateZ`属性,我们定义了火柴人在垂直和水平方向上的移动和旋转动画效果。我们还设置了持续时间和缓动效果。 你可以根据需要调整动画效果,例如修改持续时间、添加更多动作等。同时,你也可以通过添加CSS样式来美化火柴人的外观。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值