【Animejs】—Anime.js Photo Wall Case Implementation

Table of contents

1. The effect achieved:

Two, the specific steps to realize js

1. Logical combing that needs to be implemented

2. The logic of switching styles

3. Complete code:


Written in js and using animejs to achieve complex switching effects of pictures

1. The effect achieved:

Click ——> <——arrows to achieve cool switching of different animation effects.

The code can be downloaded through the code cloud link I shared below, or I will attach the complete code at the end:

animejs_1 photo wall: Use animejs to achieve cool switching effects on the photo wall

We mainly implement the writing of the js part, so I suggest that you go to my code cloud to download the source code for easy learning. 

Two, the specific steps to realize js

Create the following directories:

Directory components: 

 The current state is that the screen is on the first page, and the page does not move when the two arrows are clicked:

We can see that in the index.html file, these 7 styles are in it, and we use the number in the class name slide--layout-n to distinguish each style:

For example, slide--layout-4 represents the fourth style.

 These styles are displayed on the page, why can't we see them? It is because the transparency is changed to 0.

What we need to do is to add a click event to the button so that it can switch styles: 

1. Logical combing that needs to be implemented

Click the arrow, there will be two effects: a displayed picture goes out, and the picture to be displayed comes in.

Every time you switch, the title is also a different animation effect

To sum up the business logic we need to complete is:

1. Our logic of switching styles is realized by changing the transparency of each style.

2. Implement two animation styles: picture and title. ——The picture is divided into two animation styles: entry and exit; each style of the title is the same, we can write one.

2. The logic of switching styles

The logic of displaying the page: by adding the class name of ' slide--current ', the transparency becomes 1 and displayed on the page.

1. All codes are self-executing functions. First implement two methods for later use.

; (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. The method of realizing style switching: 

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();
	}

explain: 

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

As shown in the index.html shown in the figure below, we know that the class name of each style is called slide, and this.el.querySelectorAll('.slide') returns a pseudo-array data, so we need to convert it into a normal array for later processing. slice


3. Style initialization - _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();

	}

explain:

 When the picture is loaded, the current first style will be displayed, then we will use a plug-in:

This plug-in generally provides a method imagesLoaded to determine whether our images have been loaded.

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

4. Add event - _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. Switching back and forth——_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);
	}

Create a method for the style to display:

// _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. Animation parameters related to picture entry and exit—options

There are 7 animation effects here, we only analyze one, the other 7 are exactly the same, see the source code for details.

	// 图片进入和出去相关的动画参数
	// 设计风格动画参数
	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. Before entering and exiting the two animations, the parameters are processed, and the parameters of the config are passed to the parameters of the current animation. The idea is the same as that of initialization.

// 处理参数
	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. Set title animation

// 设置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;

The code is complete, we go to index.html to call the method we wrote:

<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>

3. Complete code:

// ▷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>

Guess you like

Origin blog.csdn.net/qq_50497708/article/details/128425929