vue用了有一段时间了,开发的后台管理系统也趋于完善,如今时间比较算是有点空闲吧!这个空闲时间我在研究vue的另外的一些玩法,好比组件,插件等。今天,我就分享一个组件的练手项目--焦点图切换组件。这个项目是我用于vue组件练习的一个项目,固然了,代码也会提交到github(ec-slider),有空也会维护。我也想我开发的东西好用一点!如今,就是建议有须要的伙伴,能够来玩下这个项目,当练习的做用!另外,若是你们有什么建议,欢迎指点!javascript
建议
1.下面的步骤,最好在本身本地上跑起来,根据文章的步骤,逐步完成,若是只看代码,很容易懵逼的。
2.若是不清楚哪一个代码有什么做用,可能本身调试下,把代码去掉后,看下有什么影响,就很容易想出代码有什么做用了!
很普通,很好理解的一个目录,但仍是简单的解释一下吧css
node_modules
:文件依赖模块(自动生成)dist
:打包文件产出目录(自动生成)src
:开发文件目录src/components
:组件文件目录.babelrc
:babel编译es6的配置文件.gitnore
:不提交到git的文件(目录)的配置文件fontSize
:设置rem算法的文件(如今没用到,忽略)index.html
:模板文件index.js
:入口文件package.json
:配置文件README.md
:说明文档webpack.config.babel.js
:webpack配置文件html
这是项目的第一步(项目搭建这个,我很少说,以前的文章已经说了几回了!),如今src/components/ec-slider.vue
这里输出一个‘守候’
1.首先,在src/components/ec-slider.vue
里面输出‘守候’,代码以下vue
<template> <div> 守候 </div> </template> <script type="text/javascript"> export default { data () { return { } }, computed: { }, mounted(){ }, props: [], methods: { } } </script>
2.而后,在src/components/index.js
里面设置注册组件(要带一个install方法),代码以下java
import SlideImg from './ec-slider.vue' const ecslide={ install:function (Vue) { Vue.component('ec-slide',SlideImg) } } export default ecslide;
3.在入口文件,index.js里面引入而且使用组件node
require("./index.html"); require("./src/sass/index.scss"); import Vue from 'vue' //引入而且使用组件 import ecslide from './src/js/components/index'; Vue.use(ecslide); let app6 = new Vue({ el: "#app6", data: { }, mounted(){ } });
4.在index.html(模板文件),输出组件webpack
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <title>Title</title> </head> <body> <div id="app6"> <ec-slide></ec-slide> </div> </body> </html>
5.命令行输入$ npm run dev
跑起来,结果完美!这几步的原理貌似没什么可多说的,都是固定式的步骤。git
通过上一步以后,基础就已经打好了,那么接下来就是一个开发的过程,大部分都是修改src/components/ec-slider.vue
这个文件。
开发以前,你们不要急着写代码,先分析下当中的运行流程!
首先,一个焦点图切换,须要什么参数?根据下面的一个淘宝栗子,我简单分析下,就是下面这几个!es6
list
-图片列表[{src:'url',href:'https://www.baidu.com'},{src:'url',href:'http://www.163.com'}](src:图片的src,href:跳转链接,点击图片的时候)autoplay
-是否自动播放 布尔 (默认false)type
-轮播方式‘transparent’(透明度切换), 'slide'(滑动切换) (默认slide)option
-对应切换 (默认false,不显示)time
-轮播间隔时间,毫秒 (默认4000)sildetype
-过渡效果 (默认'ease'慢速开始,而后变快,而后慢速结束的过渡效果,参考:transition-timing-function)arrowurl
-箭头图片连接arrowsize
-箭头尺寸‘width,height’direction
-切换方向'left'(左右) 'top'(上下) (默认:左右)github
分析完了以后,就知道暂时须要这么多参数,那么接下来就是在ec-slider.vue
里面,接收这些参数。父子组件传参方式,我想你们知道--props
。代码以下
<template> <div> 守候 </div> </template> <script type="text/javascript"> export default { data () { return { } }, computed: { }, mounted(){ }, props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl','arrowsize','option','direction'], methods: { } } </script>
有地方接收参数,确定要有地方传参数,就是index.html
模板文件里面传
<div class="slider-left"> <ec-slide :list='list' :autoplay="true" :type="'slide'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i1.buimg.com/1949/4d860a3067fab23b.jpg'" :arrowsize="'20,40'" :direction="'left'"></ec-slide> </div>
既然知道了,会接收什么参数,那下面先把样式布局,给弄好先,这个很少说,代码以下!(有些解释我也是直接打到代码上)
<template> <div class="switch-img-box" id="ec-slide-box"> <div class="switch-img-type switch-img-left"> <ul :style="{'width':ulWidth,'transition-timing-function':slideChange}"> <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> </ul> </div> <!--若是须要显示对应的点--> <div class="switch-option" v-if="option"> <div> <span v-for="(li,index) in list"></span> </div> </div> <!--若是须要显示箭头--> <div class="switch-arrow" v-if="arrowurl&&arrowsize"> <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"></div> <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}"></div> </div> </div> </template> <script type="text/javascript"> export default { data () { return { slideChange: '', arrowWidth: '', arrowHeight: '', } }, computed: { //ul宽度 ulWidth: function () { return (this.list.length) + "00%"; }, //li宽度 listWidth: function () { return 100 / (this.list.length) } }, mounted(){ //设置各个数据初始值 this.slideChange = this.sildetype || 'ease'; if (this.arrowsize && this.arrowurl) { this.arrowWidth = this.arrowsize.split(',')[0]; this.arrowHeight = this.arrowsize.split(',')[1]; } }, props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'], methods: { } } </script> <style lang="scss"> .ec-slide-img-box { width: 100%; height: 100%; position: relative; touch-action: none; } .ec-slide-img-type { position: relative; overflow: hidden; width: 100%; height: 100%; &.ec-slide-img-top { } &.ec-slide-img-left { li { display: inline-block; font-size: 0; } } &.ec-slide-img-transparent { li { opacity: 0; transition: opacity 1s; width: 0; &.cur { width: auto; } &.show { opacity: 1; } } } ul { font-size: 0; &.tran { transition: all .4s; } li { text-align: center; } img { vertical-align: middle; max-width: 100%; max-height: 100%; } } } .ec-slide-arrow { div { position: absolute; z-index: 2; margin: auto; top: 0; bottom: 0; right: 0; left: 0; opacity: .5; &:hover { opacity: 1; } &.arrow-left { left: 10px; right: auto; } &.arrow-right { right: 10px; left: auto; transform: rotate(180deg); } &.arrow-top { top: 10px; bottom: auto; } &.arrow-bottom { bottom: 10px; top: auto; transform: rotate(180deg); } } } .ec-slide-option { position: absolute; font-size: 0; bottom: 10px; text-align: center; width: 100%; z-index: 5; &.isFirst { span:first-child { display: none; } } &.isLast { span:last-child { display: none; } } span { border-radius: 100%; margin: 0 5px; background: #fff; display: inline-block; width: 10px; height: 10px; &.active { background: #09f; } } &.ec-slide-option-top { display: table; width: 10px; height: 100%; top: 0; right: 10px; margin: auto; bottom: 0; span { margin: 5px 0; } div { display: table-cell; vertical-align: middle; } } } </style>
运行结果,就是下面这样
布局搞定了,下面就能够写动画,让轮播动起来!这里也须要增长几个变量,一个是nowIndex,记录当前索引。一个是timer定时器!
首先,我用transform:translate3d()
这个方式控制ul
的滑动。
<ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex))+'%,0,0)','transition-timing-function':slideChange,'transition': 'all .4s'}"> <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> </ul>
而后,根据nowIndex,设置对应点的class。
<div class="switch-option" v-if="option"> <div> <!--若是当前索引index等于nowIndex。则添加active这个class,点就会变成蓝色--> <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span> </div> </div>
js代码以下
<script type="text/javascript"> export default { data () { return { nowIndex: 0, timer: null, slideChange: '', arrowWidth: '', arrowHeight: '', } }, computed: { //ul宽度 ulWidth: function () { return (this.list.length) + "00%"; }, //li宽度 listWidth: function () { return 100 / (this.list.length) } }, mounted(){ //是否自动播放 if (this.autoplay) { this.autoSwitch(); } //设置初始值 this.slideChange = this.sildetype || 'ease'; if (this.arrowsize && this.arrowurl) { this.arrowWidth = this.arrowsize.split(',')[0]; this.arrowHeight = this.arrowsize.split(',')[1]; } }, props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'], methods: { //滑动操做 switchDo(reduce){ clearInterval(this.timer); //根据reduce判断this.nowIndex的增长或者减小! //若是是减小模式reduce=‘reduce’ if (reduce === 'reduce') { //若是nowIndex等于0,已是第一个了,就回到最后一个 if (this.nowIndex === 0) { this.nowIndex = this.list.length - 1; } else { this.nowIndex--; } } //若是是增长模式reduce=undefined else { //若是nowIndex等于this.list.length-1,已是最后一个了,就回到第一个 if (this.nowIndex === this.list.length-1) { this.nowIndex = 0; } else{ this.nowIndex++; } } //若是须要自动播放 if (this.autoplay) { this.autoSwitch(); } }, //自动播放函数 autoSwitch(){ let time = this.time || 4000; this.timer = setInterval(() => { this.switchDo(); }, time); } } } </script>
到了这里,剩下的就只有点击两个箭头,执行相应动画,这个就相对简单,无非就是调用switchDo函数,惟一区别在于,点击左边的箭头,是减小模式,右边箭头的增长模式。代码以下,很好理解。
<!--判断是否须要显示箭头--> <div class="switch-arrow" v-if="arrowurl&&arrowsize"> <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo('reduce')"></div> <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo"></div> </div>
到了这里,对交互有强迫症的开发者就受不了了,到了最后一张,再点击右边箭头,就会出现下面的状况!
到了第一张,再点击左边箭头也是相似的状况,这样就很很差。理想状况是下面这样
要想作上面的效果,改的地方会比较多,先说下原理吧,到了最后一张,这个时候,再点击右边箭头,像淘宝那样,回到第一张。到了第一张,再点击左边箭头相似效果回到最后一张。那么最后的布局是这样
这样布局能实现效果,到了最后一张,这个时候,再点击右边箭头,像淘宝那样,回到第一张。就像下面
这个时候,就须要多作一步,滚动到这里的时候,瞬间拉回去。并且这个拉回去,要把ul的过渡效果transition
去掉,否则就会看到拉回去的过渡效果!同时要改变nowIndex。
1.首先,ul布局方面
<div class="switch-img-type switch-img-left" v-if="type==='slide'&&direction==='left'"> <!--用tran这个class控制ul是否含有过渡效果,样式已经写好--> <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex+1))+'%,0,0)','transition-timing-function':slideChange}" :class="{'tran':noLast}"> <!--最后一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'"> <img :src="list[list.length-1].src" class="slider-img"/> </a> </li> <!--遍历出来的图片--> <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> <!--第一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[0].href?list[0].href:'javascript:;'"> <img :src="list[0].src" class="slider-img"/> </a> </li> </ul> </div>
2.而后,对应的点修改
<!--isLast:隐藏最后一个span,isFirst隐藏第一个span--> <div class="switch-option" v-if="option" :class="{'isLast':nowIndex===list.length, 'isFirst':nowIndex===-1,'switch-option-top':direction==='top'}"> <div> <span class="active span1" v-if="nowIndex===list.length"></span> <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span> <span class="active span2" v-if="nowIndex===-1"></span> </div> </div>
这个可能会有点绕,我解释下,好比滚动最后一张了,再点击右边箭头,向右滑动到第一张的时候,以下图
这个时候又要把第一个点变成蓝色,可是对应点的索引和nowIndex对不上,这个时候用一个技巧。把第一个(.span1)点显示出来,而后把最后一个点隐藏。这样仍是用户看到仍是看到4个点在屏幕!等动画执行完了,拉回去第一张的时候。把.span1隐藏,正常显示对应的点!这个你们细想一下就知道了。到了第一张,再点击左边箭头相似效果回到最后一张也是相同的处理方式!
到这里,功能就基本完成了,下面给出这部分代码!
<template> <div class="ec-slide-img-box" id="ec-slide-box"> <div class="ec-slide-img-type ec-slide-img-left" v-if="type==='slide'&&direction==='left'"> <!--用tran这个class控制ul是否含有过渡效果,样式已经写好--> <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex+1))+'%,0,0)','transition-timing-function':slideChange}" :class="{'tran':noLast}"> <!--最后一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'"> <img :src="list[list.length-1].src" class="slider-img"/> </a> </li> <!--遍历出来的图片--> <li v-for="(li,index) in list" :style="{'width':listWidth+'%'}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> <!--第一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[0].href?list[0].href:'javascript:;'"> <img :src="list[0].src" class="slider-img"/> </a> </li> </ul> </div> <!--isLast:隐藏最后一个span,isFirst隐藏第一个span--> <div class="ec-slide-option" v-if="option" :class="{'isLast':nowIndex===list.length, 'isFirst':nowIndex===-1,'ec-slide-option-top':direction==='top'}"> <div> <span class="active" v-if="nowIndex===list.length"></span> <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span> <span class="active" v-if="nowIndex===-1"></span> </div> </div> <div class="ec-slide-arrow" v-if="arrowurl&&arrowsize"> <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo('reduce')"></div> <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo"></div> </div> </div> </template> <script type="text/javascript"> export default { data () { return { nowIndex: 0, noLast: true, timer: null, slideChange: '', arrowWidth: '', arrowHeight: '' } }, computed: { ulWidth: function () { return (this.list.length + 2) + "00%"; }, listWidth: function () { return 100 / (this.list.length + 2) } }, mounted(){ if (this.autoplay) { this.autoSwitch(); } this.slideChange = this.sildetype || 'ease'; if (this.arrowsize && this.arrowurl) { this.arrowWidth = this.arrowsize.split(',')[0]; this.arrowHeight = this.arrowsize.split(',')[1]; } }, props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl', 'arrowsize', 'option', 'direction'], methods: { //滑动操做 switchDo(reduce){ clearInterval(this.timer); //根据reduce判断this.nowIndex的增长或者减小! if (reduce === 'reduce') { if (this.nowIndex === 0) { //若是是滑动切换 this.nowIndex--; //执行完了此次动画以后,去除过渡效果 setTimeout(() => { this.nowIndex = this.list.length - 1; this.noLast = false; }, 400) } else { this.nowIndex--; } } else { this.nowIndex++; } if (this.nowIndex === this.list.length) { //执行完了此次动画以后,去除过渡效果 setTimeout(() => { this.nowIndex = 0; this.noLast = false; }, 400) } //若是须要自动播放 if (this.autoplay) { this.autoSwitch(); } //若是是滑动切换,设置this.noLast,增长过渡效果 this.noLast = true; }, //自动播放函数 autoSwitch(){ let time = this.time || 4000; this.timer = setInterval(() => { this.switchDo(); }, time); } } } </script> <style lang="scss"> .ec-slide-img-box { width: 100%; height: 100%; position: relative; touch-action: none; } .ec-slide-img-type { position: relative; overflow: hidden; width: 100%; height: 100%; &.ec-slide-img-top { } &.ec-slide-img-left { li { display: inline-block; font-size: 0; } } &.ec-slide-img-transparent { li { opacity: 0; transition: opacity 1s; width: 0; &.cur { width: auto; } &.show { opacity: 1; } } } ul { font-size: 0; &.tran { transition: all .4s; } li { text-align: center; } img { vertical-align: middle; max-width: 100%; max-height: 100%; } } } .ec-slide-arrow { div { position: absolute; z-index: 2; margin: auto; top: 0; bottom: 0; right: 0; left: 0; opacity: .5; &:hover { opacity: 1; } &.arrow-left { left: 10px; right: auto; } &.arrow-right { right: 10px; left: auto; transform: rotate(180deg); } &.arrow-top { top: 10px; bottom: auto; } &.arrow-bottom { bottom: 10px; top: auto; transform: rotate(180deg); } } } .ec-slide-option { position: absolute; font-size: 0; bottom: 10px; text-align: center; width: 100%; z-index: 5; &.isFirst { span:first-child { display: none; } } &.isLast { span:last-child { display: none; } } span { border-radius: 100%; margin: 0 5px; background: #fff; display: inline-block; width: 10px; height: 10px; &.active { background: #09f; } } &.ec-slide-option-top { display: table; width: 10px; height: 100%; top: 0; right: 10px; margin: auto; bottom: 0; span { margin: 5px 0; } div { display: table-cell; vertical-align: middle; } } } </style>
码农怎么会知足于现状,只有一种切换方式,怎么行,因此我又完善了些,1.一个透明度的切换方式。2.当传进的list长度为1的时候只显示图片,不进行任何动画。3.左右滑动事件的处理(不规范处理)!虽然也是不多功能,可是我在平常开发能够知足!
完整代码以下,你们也能够去github上面看代码ec-slider
<template> <div class="ec-slide-img-box" id="ec-slide-box"> <!--只有一张图片的时候,只显示,不作任何操做--> <div class="ec-slide-img" v-if="list.length===1"> <a :href="list[0].href?list[0].href:'javascript:;'"> <img :src="list[0].src"/> </a> </div> <!--左右滑动方式--> <div class="ec-slide-img-type ec-slide-img-left" v-if="type==='slide'&&direction==='left'&&list.length>1"> <!--用tran这个class控制ul是否含有过渡效果,样式已经写好--> <ul :style="{'width':ulWidth,'transform':'translate3d(-'+(listWidth*(nowIndex+1))+'%,0,0)','transition-timing-function':slideChange}" :class="{'tran':noLast}" @touchstart="touchStar" @touchend="touchEnd"> <!--最后一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'"> <img :src="list[list.length-1].src" class="slider-img"/> </a> </li> <!--遍历出来的图片--> <li v-for="(li,index) in list":style="{'width':listWidth+'%'}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> <!--第一张图片--> <li :style="{'width':listWidth+'%'}"> <a :href="list[0].href?list[0].href:'javascript:;'"> <img :src="list[0].src" class="slider-img"/> </a> </li> </ul> </div> <!--上下滑动方式--> <div class="ec-slide-img-type ec-slide-img-top" v-if="type==='slide'&&direction==='top'&&list.length>1" :style="{'height':boxHeight}"> <ul :style="{'transform':'translate3d(0,-'+(listWidth*(nowIndex+1))+'%,0)','transition-timing-function':slideChange}" :class="{'tran':noLast}" @touchstart="touchStar" @touchend="touchEnd"> <li> <a :href="list[list.length-1].href?list[list.length-1].href:'javascript:;'"> <img :src="list[list.length-1].src" class="slider-img" @load="imgLoad"/> </a> </li> <li v-for="(li,index) in list"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img" @load="imgLoad"/> </a> </li> <li> <a :href="list[0].href?list[0].href:'javascript:;'"> <img :src="list[0].src" class="slider-img" @load="imgLoad"/> </a> </li> </ul> </div> <!--透明度滑动方式--> <div class="ec-slide-img-type ec-slide-img-transparent" v-if="type==='transparent'&&list.length>1"> <ul @touchstart="touchStar" @touchend="touchEnd"> <li v-for="(li,index) in list" :class="{'cur':index===nowIndex,'show':index===nowIndexShow}"> <a :href="li.href?li.href:'javascript:;'"> <img :src="li.src" class="slider-img"/> </a> </li> </ul> </div> <!--isLast:隐藏最后一个span,isFirst隐藏第一个span--> <div class="ec-slide-option" v-if="option&&list.length>1" :class="{'isLast':nowIndex===list.length, 'isFirst':nowIndex===-1,'ec-slide-option-top':direction==='top'}"> <div> <span class="active span1" v-if="nowIndex===list.length"></span> <span v-for="(li,index) in list" :class="{'active':index===nowIndex}"></span> <span class="active span2" v-if="nowIndex===-1"></span> </div> </div> <div class="ec-slide-arrow" v-if="arrowurl&&arrowsize&&list.length>1"> <div :class="{'arrow-left':direction==='left','arrow-top':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo('reduce')"></div> <div :class="{'arrow-right':direction==='left','arrow-bottom':direction==='top'}" :style="{'width':arrowWidth+'px','height':arrowHeight+'px','background':'url('+arrowurl+') no-repeat','background-size':'100%'}" @click.stop="switchDo"></div> </div> </div> </template> <script type="text/javascript"> export default { data () { return { nowIndex: 0, nowIndexShow:0, noLast: true, timer: null, slideChange: '', arrowWidth:'', arrowHeight:'', startX:0, startY:0, boxHeight:0 } }, computed: { ulWidth: function () { return (this.list.length + 2) + "00%"; }, listWidth:function () { return 100/(this.list.length+2) } }, mounted(){ if (this.autoplay) { this.autoSwitch(); } this.slideChange = this.sildetype || 'ease'; if(this.arrowsize&&this.arrowurl){ this.arrowWidth=this.arrowsize.split(',')[0]; this.arrowHeight=this.arrowsize.split(',')[1]; } }, props: ['list', 'autoplay', 'type', 'time', 'sildetype', 'arrowurl','arrowsize','option','direction'], methods: { //开始滑动 touchStar(e){ //e.preventDefault(); this.startX=e.changedTouches[0].clientX; this.startY=e.changedTouches[0].clientY; }, //滑动结束 touchEnd(e){ //e.preventDefault(); if(this.direction==='left'){ if(e.changedTouches[0].clientX-this.startX>50){ this.switchDo('reduce') } else if(e.changedTouches[0].clientX-this.startX<-50){ this.switchDo() } } else if(this.direction==='top'){ if(e.changedTouches[0].clientY-this.startY>50){ this.switchDo('reduce') } else if(e.changedTouches[0].clientY-this.startY<-50){ this.switchDo() } } }, //滑动操做 switchDo(reduce){ clearInterval(this.timer); //根据reduce判断this.nowIndex的增长或者减小! if(reduce==='reduce'){ if(this.nowIndex===0){ //若是是滑动切换 if(this.type==='slide'){ this.nowIndex--; //执行完了此次动画以后,去除过渡效果 setTimeout(() => { this.nowIndex = this.list.length-1; this.noLast = false; }, 400) } else{ this.nowIndex = this.list.length-1; } } else{ this.nowIndex--; } } else{ this.nowIndex++; } if (this.nowIndex === this.list.length) { if(this.type==='slide') { //执行完了此次动画以后,去除过渡效果 setTimeout(() => { this.nowIndex = 0; this.noLast = false; }, 400) } else{ this.nowIndex = 0; } } //是否显示图片,只针对透明度切换的状况! setTimeout(()=>{ this.nowIndexShow=this.nowIndex; },1) //若是须要自动播放 if (this.autoplay) { this.autoSwitch(); } //若是是滑动切换,设置this.noLast,增长过渡效果 if(this.type==='slide') { this.noLast = true; } }, //自动播放函数 autoSwitch(){ let time = this.time || 4000; this.timer = setInterval(() => { this.switchDo(); }, time); }, //获取最大的高度,针对上下方向,滑动切换方式的处理 imgLoad(e){ if(parseInt(this.boxHeight)<e.path[0].offsetHeight){ this.boxHeight=e.path[0].offsetHeight+'px'; } } } } </script> <style lang="scss"> .ec-slide-img-box { width: 100%; height: 100%; position: relative; touch-action: none; } .ec-slide-img{ width: 100%; height: 100%; img{ max-width: 100%; max-height: 100%; } } .ec-slide-img-type{ position: relative; overflow: hidden; width: 100%; height: 100%; &.ec-slide-img-top{ } &.ec-slide-img-left{ li { display: inline-block; font-size: 0; } } &.ec-slide-img-transparent { li { opacity: 0; transition: opacity 1s; width: 0; &.cur { width: auto; } &.show{ opacity: 1; } } } ul { font-size: 0; &.tran { transition: all .4s; } li{ text-align: center; } img { vertical-align: middle; max-width: 100%; max-height: 100%; } } } .ec-slide-arrow { div { position: absolute; z-index: 2; margin: auto; top: 0; bottom: 0; right: 0; left: 0; opacity: .5; &:hover{ opacity: 1; } &.arrow-left { left: 10px; right: auto; } &.arrow-right { right: 10px; left: auto; transform: rotate(180deg); } &.arrow-top { top: 10px; bottom: auto; } &.arrow-bottom { bottom: 10px; top: auto; transform: rotate(180deg); } } } .ec-slide-option { position: absolute; font-size: 0; bottom: 10px; text-align: center; width: 100%; z-index: 5; &.isFirst { span:first-child { display: none; } } &.isLast { span:last-child { display: none; } } span { border-radius: 100%; margin: 0 5px; background: #fff; display: inline-block; width: 10px; height: 10px; &.active { background: #09f; } } &.ec-slide-option-top{ display: table; width: 10px; height: 100%; top: 0; right: 10px; margin: auto; bottom: 0; span{ margin:5px 0; } div{display: table-cell;vertical-align: middle;} } } </style>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <title>Title</title> <style> body{ } .transparent-left{ margin-bottom: 20px; width: 500px; } .transparent-top{ max-width: 1000px; margin-bottom: 20px; } .slider-left{ width: 80%; margin: 20px auto; max-width: 1000px; } .slider-top{ width: 1000px; height: 500px; } .slider-one{ margin: 20px auto; width: 500px; } </style> </head> <body> <div id="app6"> <!--http://i2.kiimg.com/1949/098c291e8db16ab5.jpg http://i1.buimg.com/1949/4d860a3067fab23b.jpg--> <div class="transparent-top"> <ec-slide :list='list' :autoplay="true" :type="'transparent'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i2.kiimg.com/1949/098c291e8db16ab5.jpg'" :arrowsize="'40,20'" :direction="'top'"></ec-slide> </div> <div class="transparent-left"> <ec-slide :list='list' :autoplay="true" :type="'transparent'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i1.buimg.com/1949/4d860a3067fab23b.jpg'" :arrowsize="'20,40'" :direction="'left'"></ec-slide> </div> <div class="slider-left"> <ec-slide :list='list' :autoplay="true" :type="'slide'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i1.buimg.com/1949/4d860a3067fab23b.jpg'" :arrowsize="'20,40'" :direction="'left'"></ec-slide> </div> <div class="slider-top"> <ec-slide :list='list' :autoplay="true" :type="'slide'" :option="true" :time="4000" :sildetype="'ease'" :arrowurl="'http://i2.kiimg.com/1949/098c291e8db16ab5.jpg'" :arrowsize="'40,20'" :direction="'top'"></ec-slide> </div> <div class="slider-one"> <ec-slide :list='list2'></ec-slide> </div> </div> </body> </html>
好了,今天的开发就到此为止了。起初这个项目我是打算当练手用的,可是后来在项目上使用了,虽然这个写得比较简单,可是效果还不错。如今状况还不是很好,之后有须要也会维护。目前来讲,也是建议你们能够玩下这个项目,虽然文章有点长,可是直接看下,边动手写代码,边看文章,会发现。一会儿就看完了!这个应该是不错的练手项目,能够熟悉使用vue开发组件!最后,若是你们以为有哪里写错了,写得很差,欢迎指点!
-------------------------华丽的分割线--------------------
想了解更多,关注关注个人微信公众号:守候书阁