├── example
├── card
│ ├── card.json
│ ├── card.wxml
│ ├── card.wxss
│ └── card.js
├── general
│ ├── general.json
│ ├── general.wxml
│ ├── general.wxss
│ └── general.js
└── dashboard
│ ├── dashboard.js
│ ├── dashboard.json
│ ├── dashboard.wxss
│ └── dashboard.wxml
├── .babelrc
├── .gitignore
├── screenshots
├── Gif_20170401_013701.gif
└── Gif_20170401_013729.gif
├── app.wxss
├── src
├── syncView.js
├── exception.js
├── animate.js
├── controller.js
├── default.js
├── handle.js
├── main.js
└── methods.js
├── package.json
├── app.json
├── app.js
├── LICENSE
├── dist
├── weSwiper.wxss
└── weSwiper.js
└── README.md
/example/card/card.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/example/general/general.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/example/dashboard/dashboard.js:
--------------------------------------------------------------------------------
1 | Page({})
2 |
--------------------------------------------------------------------------------
/example/dashboard/dashboard.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | { "presets": ["es2015-rollup"] }
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | node_modules/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
--------------------------------------------------------------------------------
/screenshots/Gif_20170401_013701.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/we-plugin/we-swiper/HEAD/screenshots/Gif_20170401_013701.gif
--------------------------------------------------------------------------------
/screenshots/Gif_20170401_013729.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/we-plugin/we-swiper/HEAD/screenshots/Gif_20170401_013729.gif
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .container {
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: center;
7 | justify-content: space-between;
8 | padding: 200rpx 0;
9 | box-sizing: border-box;
10 | }
11 |
--------------------------------------------------------------------------------
/src/syncView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by sail on 2017/4/1.
3 | */
4 | export default {
5 | /**
6 | * 同步设置到视图
7 | * @param DEFAULT:默认参数
8 | * @param param:构造参数
9 | */
10 | syncView (viewName, prop) {
11 | this.pageContext.setData({
12 | [`${viewName}`]: prop
13 | })
14 | }
15 | }
--------------------------------------------------------------------------------
/src/exception.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by sail on 2017/4/1.
3 | */
4 | const ERROR = {
5 | 'paramType': '参数类型错误',
6 | 'bound': '参数越界'
7 | }
8 |
9 | export default {
10 | /**
11 | * 错误对照
12 | */
13 | consoleException (type, place) {
14 | console.error(`%c${place}:${ERROR[type]}`, 'color: red')
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "we-swiper",
3 | "version": "0.1.0",
4 | "main": "dist/weSwiper.js",
5 | "scripts": {
6 | "build": "node build/build.js"
7 | },
8 | "devDependencies": {
9 | "babel-preset-es2015-rollup": "^3.0.0",
10 | "rollup": "^0.41.6",
11 | "rollup-plugin-babel": "^2.7.1"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "example/dashboard/dashboard",
4 | "example/general/general",
5 | "example/card/card",
6 | "example/flip/flip"
7 | ],
8 | "window":{
9 | "backgroundTextStyle":"light",
10 | "navigationBarBackgroundColor": "#fff",
11 | "navigationBarTitleText": "WeChat",
12 | "navigationBarTextStyle":"black"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/example/card/card.wxml:
--------------------------------------------------------------------------------
1 |
2 |
7 | slide 1
8 | slide 2
9 | slide 3
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/general/general.wxml:
--------------------------------------------------------------------------------
1 |
2 |
7 | slide 1
8 | slide 2
9 | slide 3
10 |
11 |
--------------------------------------------------------------------------------
/example/general/general.wxss:
--------------------------------------------------------------------------------
1 | @import "../../dist/weSwiper.wxss";
2 |
3 | /************* 个人样式 *************/
4 | .we-slide{
5 | display: flex;
6 | align-items: center;
7 | justify-content: center;
8 | color: #fff;
9 | font-size: 2rem;
10 | }
11 |
12 | .we-slide:nth-child(1){
13 | background-color: #4390EE
14 | }
15 | .we-slide:nth-child(2){
16 | background-color: #CA4040
17 | }
18 | .we-slide:nth-child(3){
19 | background-color: #FF8604
20 | }
21 |
--------------------------------------------------------------------------------
/example/card/card.wxss:
--------------------------------------------------------------------------------
1 | @import "../../dist/weSwiper.wxss";
2 |
3 | /************* 个人样式 *************/
4 | .we-wrapper{
5 | width: 100%;
6 | height: 100%;
7 | padding: 75rpx 0 100rpx 100rpx;
8 | box-sizing: border-box;
9 | }
10 | .we-slide{
11 | display: flex;
12 | align-items: center;
13 | justify-content: center;
14 | width: 500rpx;
15 | margin: 25rpx;
16 | box-sizing: border-box;
17 | color: #fff;
18 | font-size: 2rem;
19 | }
20 |
21 | .we-slide:nth-child(1){
22 | background-color: #4390EE
23 | }
24 | .we-slide:nth-child(2){
25 | background-color: #CA4040
26 | }
27 | .we-slide:nth-child(3){
28 | background-color: #FF8604
29 | }
30 |
--------------------------------------------------------------------------------
/example/dashboard/dashboard.wxss:
--------------------------------------------------------------------------------
1 | Page{
2 | background-color: #f8f8f8;
3 | }
4 |
5 | .lists{
6 | margin: 25rpx 0;
7 | border-top: 1rpx solid #d7d7d7;
8 | border-bottom: 1rpx solid #d7d7d7;
9 | background-color: #fff;
10 | }
11 |
12 | .list-item{
13 | position: relative;
14 | width: 100%;
15 | height: 100rpx;
16 | margin-left: 25rpx;
17 | line-height: 100rpx;
18 | font-size: 32rpx;
19 | border-bottom: 1rpx solid #d7d7d7;
20 | }
21 |
22 | .list-item:after{
23 | position: absolute;
24 | top: 50%;
25 | right: 50rpx;
26 | content: '>';
27 | transform: translateY(-50%);
28 | color: #666;
29 | }
30 |
31 | .list-item:last-child{
32 | border: 0;
33 | }
34 |
--------------------------------------------------------------------------------
/example/dashboard/dashboard.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | we-swiper
4 |
5 |
6 | 常规
7 | 卡片
8 | flip
9 | 2D翻转
10 |
11 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | //调用API从本地缓存中获取数据
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 | },
9 | getUserInfo:function(cb){
10 | var that = this
11 | if(this.globalData.userInfo){
12 | typeof cb == "function" && cb(this.globalData.userInfo)
13 | }else{
14 | //调用登录接口
15 | wx.login({
16 | success: function () {
17 | wx.getUserInfo({
18 | success: function (res) {
19 | that.globalData.userInfo = res.userInfo
20 | typeof cb == "function" && cb(that.globalData.userInfo)
21 | }
22 | })
23 | }
24 | })
25 | }
26 | },
27 | globalData:{
28 | userInfo:null
29 | }
30 | })
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Sail
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/animate.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by sail on 2017/4/1.
3 | */
4 | const REG = {
5 | SPEED: /^(0|[1-9][0-9]*|-[1-9][0-9]*)$/,
6 | TIMINGFUNCTION: /linear|ease|ease-in|ease-in-out|ease-out|step-start|step-end/
7 | }
8 |
9 | export default {
10 | /**
11 | * 平移动画
12 | * @param translate:平移位置
13 | * @param speed:过渡时长
14 | * @param timingFunction:过渡类型
15 | */
16 | slideAnimation (translate = 0, speed = 300, timingFunction = 'ease') {
17 | const { XORY, animationViewName, consoleException } = this
18 | try {
19 | /**
20 | * 异常处理
21 | */
22 | if(!REG.SPEED.test(speed)) throw 'paramType'
23 | if(!REG.TIMINGFUNCTION.test(timingFunction)) throw 'paramType'
24 | /**
25 | * 创建一个动画实例
26 | */
27 | const animation = wx.createAnimation({
28 | transformOrigin: '50% 50%',
29 | duration: speed,
30 | timingFunction,
31 | delay: 0
32 | })
33 |
34 | animation[`translate${XORY}`](translate).step() // 动画描述
35 |
36 | this.syncView(animationViewName, animation.export()) // 同步动画到视图
37 |
38 | } catch (err) {
39 | consoleException(err, 'slideAnimation[Function]')
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/controller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by sail on 2017/4/1.
3 | */
4 |
5 | export default {
6 | /**
7 | * 切换控制器
8 | * @param touchStartTime: 手指触碰slide时的时间戳
9 | * @param et: 手指离开slide时的时间戳
10 | * @param from: 手指触碰slide时的屏幕位置
11 | * @param to: 手指离开slide时的屏幕位置
12 | * @param wrapperDistance: slide滑动方向上的容器长度
13 | * @returns {*}
14 | */
15 | action (touchStartTime, touchEndTime, from, to, wrapperDistance) {
16 | const {
17 | activeIndex,
18 | slideLength,
19 | onTransitionStart } = this
20 | const deltaTime = touchEndTime - touchStartTime // 手指触摸时长
21 | const distance = Math.abs(to - from) // 滑动距离
22 |
23 | const k = distance / deltaTime
24 |
25 | if (to > from) {
26 | typeof onTransitionStart === 'function' && onTransitionStart(this) // slide达到过渡条件时执行
27 | return (k > 0.3 || distance > wrapperDistance / 2) ? (activeIndex === 0 ? 'slideBack' : 'slidePrev') : 'slideBack'
28 | }
29 |
30 | if (to < from) {
31 | typeof onTransitionStart === 'function' && onTransitionStart(this) // slide达到过渡条件时执行
32 | return (k > 0.3 || distance > wrapperDistance / 2) ? (activeIndex === slideLength - 1 ? 'slideBack' : 'slideNext') : 'slideBack'
33 | }
34 |
35 | if (to = from) {
36 | return 'slideBack'
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/dist/weSwiper.wxss:
--------------------------------------------------------------------------------
1 | Page{
2 | width: 100%;
3 | height: 100%;
4 | }
5 |
6 | .we-container{
7 | width: 100%;
8 | height: 100%;
9 | }
10 |
11 | .we-container {
12 | margin-left: auto;
13 | margin-right: auto;
14 | position: relative;
15 | overflow: hidden;
16 | z-index: 1;
17 | }
18 |
19 | .we-wrapper{
20 | position: relative;
21 | width: 100%;
22 | height: 100%;
23 | z-index: 1;
24 | display: -webkit-box;
25 | display: -moz-box;
26 | display: -ms-flexbox;
27 | display: -webkit-flex;
28 | display: flex;
29 | -webkit-transition-property: -webkit-transform;
30 | -moz-transition-property: -moz-transform;
31 | -o-transition-property: -o-transform;
32 | -ms-transition-property: -ms-transform;
33 | transition-property: transform;
34 | -webkit-box-sizing: content-box;
35 | -moz-box-sizing: content-box;
36 | box-sizing: content-box;
37 | }
38 |
39 | .we-container-vertical>.we-wrapper {
40 | -webkit-box-orient: vertical;
41 | -moz-box-orient: vertical;
42 | -ms-flex-direction: column;
43 | -webkit-flex-direction: column;
44 | flex-direction: column;
45 | }
46 |
47 | .we-slide {
48 | -webkit-flex-shrink: 0;
49 | -ms-flex: 0 0 auto;
50 | flex-shrink: 0;
51 | width: 100%;
52 | height: 100%;
53 | position: relative;
54 | }
--------------------------------------------------------------------------------
/src/default.js:
--------------------------------------------------------------------------------
1 | const device = wx.getSystemInfoSync() // 获取设备信息
2 |
3 | export default {
4 | /**
5 | * 必填项
6 | */
7 | slideLength: 0, // 由于目前无法直接获取slide页数,目前只能通过参数写入
8 | /**
9 | * 可选参数
10 | */
11 | width: device.windowWidth,
12 | height: device.windowHeight,
13 | direction: 'horizontal',
14 | initialSlide: 0,
15 | speed: 300,
16 | effect: 'slide', // 过渡效果
17 | timingFunction: 'ease', // 过渡动画速度曲线
18 | autoplay: 0, // 自动播放间隔,设置为0时不自动播放
19 | animationViewName: 'animationData', // 对应视图wrapper中animation属性名
20 | /**
21 | * 事件回调
22 | * @type {[type]}
23 | */
24 | onInit: null, // swiper初始化时执行
25 | onTouchStart: null, // 手指碰触slide时执行
26 | onTouchMove: null, // 手指碰触slide并且滑动时执行
27 | onTouchEnd: null, // 手指离开slide时执行
28 | onSlideChangeStart: null, // slide达到过渡条件时执行
29 | onSlideChangeEnd: null, // swiper从一个slide过渡到另一个slide结束时执行
30 | onTransitionStart: null, // 过渡时触发
31 | onTransitionEnd: null, // 过渡结束时执行
32 | onSlideMove: null, // 手指触碰swiper并且拖动slide时执行
33 | onSlideNextStart: null, // slide达到过渡条件 且规定了方向 向前(右、下)切换时执行
34 | onSlideNextEnd: null, // slide达到过渡条件 且规定了方向 向前(右、下)切换结束时执行
35 | onSlidePrevStart: null, // slide达到过渡条件 且规定了方向 向前(左、上)切换时执行
36 | onSlidePrevEnd: null // slide达到过渡条件 且规定了方向 向前(左、上)切换结束时执行
37 | }
38 |
--------------------------------------------------------------------------------
/src/handle.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | touchstart (e) {
4 | if (this.noSwiper) return
5 | const { onTouchStart, XORY, activeIndex, rectDistance } = this
6 | const touch = e.changedTouches[0]
7 | const distance = touch[`client${XORY}`]
8 | const translate = - activeIndex * rectDistance
9 |
10 | this[`touchStart${XORY}`] = distance
11 | this[`translate${XORY}`] = translate
12 | this.touchStartTime = new Date().getTime()
13 |
14 | typeof onTouchStart === 'function' && onTouchStart(this, e) // 当手指碰触到slide时执行
15 |
16 | this.slideAnimation(translate, 0)
17 | },
18 |
19 | touchmove (e) {
20 | if (this.noSwiper) return
21 | const { onTouchMove, XORY, onSlideMove } = this
22 | const touch = e.changedTouches[0]
23 | const distance = touch[`client${XORY}`]
24 | const tmpMove = this[`translate${XORY}`] + distance - this[`touchStart${XORY}`]
25 |
26 |
27 | typeof onTouchMove === 'function' && onTouchMove(this, e) // 手指碰触slide并且滑动时执行
28 |
29 | this.slideAnimation(tmpMove, 0)
30 |
31 | typeof onSlideMove === 'function' && onSlideMove(this)
32 | },
33 |
34 | touchend (e) {
35 | if (this.noSwiper) return
36 | const { onTouchEnd, XORY, speed, touchStartTime, rectDistance } = this
37 | const touch = e.changedTouches[0]
38 | const distance = touch[`client${XORY}`]
39 | const touchEndTime = new Date().getTime()
40 |
41 | const action = this.action(touchStartTime, touchEndTime, this[`touchStart${XORY}`], distance, rectDistance)
42 |
43 | typeof onTouchEnd === 'function' && onTouchEnd(this, e) // 手指离开slide时执行
44 |
45 | this[action](true, speed)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import DEFAULT from './default'
2 | import handle from './handle'
3 | import controller from './controller'
4 | import methods from './methods'
5 | import animate from './animate'
6 | import sync from './syncView'
7 | import exception from './exception'
8 |
9 | class weSwiper {
10 |
11 | constructor (param) {
12 |
13 | const pages = getCurrentPages()
14 |
15 | // 获取到当前page上下文
16 | this.pageContext = pages[pages.length - 1]
17 | // 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
18 | this.pageContext.weswiper = this
19 |
20 | const all = Object.assign(this, DEFAULT, param || {})
21 |
22 | this.init(all)
23 | }
24 |
25 | /**
26 | * 初始化配置
27 | */
28 | init (param) {
29 | const {
30 | speed,
31 | initialSlide,
32 | direction,
33 | autoplay,
34 | directionViewName
35 | } = param
36 |
37 | const directionClass = direction === 'horizontal' ? 'we-container-horizontal' : 'we-container-vertical'
38 | this.syncView(directionViewName, directionClass)
39 | this.rectDistance = direction === 'horizontal' ? this.width : this.height
40 | this.XORY = direction === 'horizontal' ? 'X' : 'Y'
41 | this.activeIndex = initialSlide // 将初始页码赋给activeIndex
42 | this.noSwiper = false // 阻止手势滑动
43 | this.previousIndex = initialSlide // 返回上一个活动块的索引,切换前的索引
44 | this.slideTo(initialSlide, 0)
45 | typeof autoplay === 'number' && autoplay > 0 && setInterval(() => {
46 | if (this.isEnd) {
47 | this.slideTo(0, speed)
48 | } else {
49 | this.slideTo(this.activeIndex + 1, speed)
50 | }
51 | }, autoplay)
52 | /**
53 | * 处理callback
54 | */
55 | const { onInit } = this
56 | typeof onInit === 'function' && onInit(this)
57 | }
58 | }
59 |
60 | Object.assign(weSwiper.prototype, controller)
61 | Object.assign(weSwiper.prototype, handle)
62 | Object.assign(weSwiper.prototype, methods)
63 | Object.assign(weSwiper.prototype, animate)
64 | Object.assign(weSwiper.prototype, sync)
65 | Object.assign(weSwiper.prototype, exception)
66 |
67 | export default weSwiper
68 |
--------------------------------------------------------------------------------
/example/general/general.js:
--------------------------------------------------------------------------------
1 | import weSwiper from '../../src/main'
2 |
3 | const option = {
4 | touchstart (e) {
5 | this.weswiper.touchstart(e)
6 | },
7 | touchmove (e) {
8 | this.weswiper.touchmove(e)
9 | },
10 | touchend (e) {
11 | this.weswiper.touchend(e)
12 | },
13 | onLoad () {
14 | const device = wx.getSystemInfoSync()
15 | new weSwiper({
16 | animationViewName: 'animationData',
17 | slideLength: 3,
18 | initialSlide: 0,
19 | /**
20 | * swiper初始化后执行
21 | * @param swiper
22 | */
23 | onInit (weswiper) {
24 |
25 | },
26 | /**
27 | * 手指碰触slide时执行
28 | * @param swiper
29 | * @param event
30 | */
31 | onTouchStart (weswiper, event) {
32 |
33 | },
34 | /**
35 | * 手指碰触slide并且滑动时执行
36 | * @param swiper
37 | * @param event
38 | */
39 | onTouchMove (weswiper, event) {
40 |
41 | },
42 | /**
43 | * 手指离开slide时执行
44 | * @param swiper
45 | * @param event
46 | */
47 | onTouchEnd (weswiper, event) {
48 |
49 | },
50 | /**
51 | * slide达到过渡条件时执行
52 | */
53 | onSlideChangeStart (weswiper) {
54 |
55 | },
56 | /**
57 | * swiper从一个slide过渡到另一个slide结束时执行
58 | */
59 | onSlideChangeEnd (weswiper) {
60 |
61 | },
62 | /**
63 | * 过渡时触发
64 | */
65 | onTransitionStart (weswiper) {
66 |
67 | },
68 | /**
69 | * 过渡结束时执行
70 | */
71 | onTransitionEnd (weswiper) {
72 |
73 | },
74 | /**
75 | * 手指触碰swiper并且拖动slide时执行
76 | */
77 | onSlideMove (weswiper) {
78 |
79 | },
80 | /**
81 | * slide达到过渡条件 且规定了方向 向前(右、下)切换时执行
82 | */
83 | onSlideNextStart (weswiper) {
84 |
85 | },
86 | /**
87 | * slide达到过渡条件 且规定了方向 向前(右、下)切换结束时执行
88 | */
89 | onSlideNextEnd (weswiper) {
90 |
91 | },
92 | /**
93 | * slide达到过渡条件 且规定了方向 向前(左、上)切换时执行
94 | */
95 | onSlidePrevStart (swiper) {
96 |
97 | },
98 | /**
99 | * slide达到过渡条件 且规定了方向 向前(左、上)切换结束时执行
100 | */
101 | onSlidePrevEnd (weswiper) {
102 |
103 | }
104 | })
105 | }
106 | }
107 | Page(option)
108 |
--------------------------------------------------------------------------------
/example/card/card.js:
--------------------------------------------------------------------------------
1 | import weSwiper from '../../src/main'
2 |
3 | const option = {
4 | touchstart (e) {
5 | this.weswiper.touchstart(e)
6 | },
7 | touchmove (e) {
8 | this.weswiper.touchmove(e)
9 | },
10 | touchend (e) {
11 | this.weswiper.touchend(e)
12 | },
13 | onLoad () {
14 | const device = wx.getSystemInfoSync()
15 | new weSwiper({
16 | animationViewName: 'animationData',
17 | slideLength: 3,
18 | initialSlide: 0,
19 | width: 550 * device.windowWidth / 750,
20 | height: 500 * device.windowWidth / 750,
21 | /**
22 | * swiper初始化后执行
23 | * @param swiper
24 | */
25 | onInit (weswiper) {
26 |
27 | },
28 | /**
29 | * 手指碰触slide时执行
30 | * @param swiper
31 | * @param event
32 | */
33 | onTouchStart (weswiper, event) {
34 |
35 | },
36 | /**
37 | * 手指碰触slide并且滑动时执行
38 | * @param swiper
39 | * @param event
40 | */
41 | onTouchMove (weswiper, event) {
42 |
43 | },
44 | /**
45 | * 手指离开slide时执行
46 | * @param swiper
47 | * @param event
48 | */
49 | onTouchEnd (weswiper, event) {
50 |
51 | },
52 | /**
53 | * slide达到过渡条件时执行
54 | */
55 | onSlideChangeStart (weswiper) {
56 |
57 | },
58 | /**
59 | * swiper从一个slide过渡到另一个slide结束时执行
60 | */
61 | onSlideChangeEnd (weswiper) {
62 |
63 | },
64 | /**
65 | * 过渡时触发
66 | */
67 | onTransitionStart (weswiper) {
68 |
69 | },
70 | /**
71 | * 过渡结束时执行
72 | */
73 | onTransitionEnd (weswiper) {
74 |
75 | },
76 | /**
77 | * 手指触碰swiper并且拖动slide时执行
78 | */
79 | onSlideMove (weswiper) {
80 |
81 | },
82 | /**
83 | * slide达到过渡条件 且规定了方向 向前(右、下)切换时执行
84 | */
85 | onSlideNextStart (weswiper) {
86 |
87 | },
88 | /**
89 | * slide达到过渡条件 且规定了方向 向前(右、下)切换结束时执行
90 | */
91 | onSlideNextEnd (weswiper) {
92 |
93 | },
94 | /**
95 | * slide达到过渡条件 且规定了方向 向前(左、上)切换时执行
96 | */
97 | onSlidePrevStart (swiper) {
98 |
99 | },
100 | /**
101 | * slide达到过渡条件 且规定了方向 向前(左、上)切换结束时执行
102 | */
103 | onSlidePrevEnd (weswiper) {
104 |
105 | }
106 | })
107 | }
108 | }
109 | Page(option)
110 |
--------------------------------------------------------------------------------
/src/methods.js:
--------------------------------------------------------------------------------
1 | export default {
2 | /**
3 | * 切换至下一个slide
4 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
5 | * @param speed: 可选,num(单位ms),切换速度
6 | */
7 | slideNext (runCallbacks = false, speed = 300) {
8 | const self = this
9 | const {
10 | onSlideNextStart,
11 | onSlideNextEnd
12 | } = self
13 |
14 | typeof onSlideNextStart === 'function' && onSlideNextStart(self) // slide达到过渡条件时执行
15 |
16 | self.slideTo(self.activeIndex + 1, speed, runCallbacks)
17 |
18 | typeof onSlideNextEnd === 'function' && setTimeout(() => { onSlideNextEnd(self) }, speed) // slide过渡结束后执行
19 | },
20 | /**
21 | * 切换至上一个slide
22 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
23 | * @param speed: 可选,num(单位ms),切换速度
24 | */
25 | slidePrev (runCallbacks = false, speed = 300) {
26 | const self = this
27 | const {
28 | onSlidePrevStart,
29 | onSlidePrevEnd
30 | } = self
31 |
32 | typeof onSlidePrevStart === 'function' && onSlidePrevStart(self) // slide达到过渡条件时执行
33 |
34 | self.slideTo(self.activeIndex - 1, speed, runCallbacks)
35 |
36 | typeof onSlidePrevEnd === 'function' && setTimeout(() => { onSlidePrevEnd(self) }, speed) // slide过渡结束后执行
37 | },
38 | /**
39 | * 回弹
40 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
41 | * @param speed: 可选,num(单位ms),切换速度
42 | */
43 | slideBack (runCallbacks = false, speed = 300) {
44 | const self = this
45 | const {
46 | XORY,
47 | activeIndex,
48 | rectDistance,
49 | onTransitionEnd
50 | } = self
51 |
52 | const translate = - activeIndex * rectDistance
53 |
54 | self.slideAnimation(translate, speed)
55 |
56 | typeof onTransitionEnd === 'function' && setTimeout(() => { onTransitionEnd(self) }, speed) // slide过渡结束后执行
57 | },
58 | /**
59 | * 切换到指定slide
60 | * @param index:必选,num,指定将要切换到的slide的索引
61 | * @param speed:可选,num(单位ms),切换速度
62 | * @param runCallbacks:可选,boolean,设置为false时不会触发onSlideChange回调函数
63 | */
64 | slideTo (index, speed = 300, runCallbacks = false) {
65 | const self = this
66 | const {
67 | slideLength,
68 | activeIndex,
69 | rectDistance,
70 | onSlideChangeStart,
71 | onSlideChangeEnd,
72 | onTransitionEnd,
73 | consoleException
74 | } = self
75 |
76 | try {
77 | if (typeof index !== 'number') throw 'paramType' // 参数类型错误
78 | if (index < 0 || index > slideLength - 1) throw 'bound' // 越界
79 |
80 | const translate = - index * rectDistance
81 | self.previousIndex = activeIndex
82 | self.activeIndex = index
83 | self.isBeginning = self.activeIndex === self.initialSlide
84 | self.isEnd = self.activeIndex === self.slideLength - 1
85 |
86 | runCallbacks && typeof onSlideChangeStart === 'function' && onSlideChangeStart(self) // slide达到过渡条件时执行
87 |
88 | self.slideAnimation(translate, speed)
89 |
90 | runCallbacks && typeof onSlideChangeEnd === 'function' && setTimeout(() => { onSlideChangeEnd(self) }, speed) // swiper从一个slide过渡到另一个slide结束后执行
91 | typeof onTransitionEnd === 'function' && setTimeout(() => { onTransitionEnd(self) }, speed) // slide过渡结束后执行
92 | } catch (err) {
93 | consoleException(err, 'slideTo[Function]')
94 | }
95 |
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # we-swiper
2 | 微信小程序触摸内容滑动解决方案,API设计细节及命名参考于[swiper.js](http://www.swiper.com.cn/).
3 | ### 为什么要开发这款插件
4 | #### 官方swiper组件:
5 | * 支持的事件回调很单一
6 | * ~~从文档上看只是能支持横向滑动~~(官方swiper组件实际是支持纵向滚动的,设置属性vertical="true"即可,但并未在官方文档提及,感谢[@pangz1](https://github.com/pangz1)指正)
7 | * 拓展性不强
8 |
9 | #### we-swiper插件:
10 | * 丰富的事件回调
11 | * 丰富的属性
12 | * 支持横、纵向滑动
13 | * 强拓展(可在原插件基础上二次开发)
14 |
15 | ## ScreenShots
16 | #### 横向滚动
17 | 
18 | #### 纵向滚动
19 | 
20 |
21 | ## 使用方式
22 | #### 克隆项目至你的目录
23 | ```bash
24 | cd my-project
25 |
26 | git clone https://github.com/dlhandsome/we-swiper.git
27 | ```
28 |
29 | #### 在项目文件引入``` dist/weSwiper.js```进行开发
30 |
31 | ##### es6 module
32 | ``` javascript
33 | import weSwiper from 'dist/weSwiper'
34 | ```
35 | ##### commonjs
36 | ```javascript
37 | var weSwiper = require('dist/weSwiper')
38 | ```
39 |
40 | ## 示例
41 | #### example.wxml
42 | ``` html
43 |
44 |
49 | slide 1
50 | slide 2
51 | slide 3
52 |
53 |
54 | ```
55 | #### example.js
56 | ``` javascript
57 | import weSwiper from '../dist/weSwiper'
58 |
59 | const option = {
60 | touchstart (e) {
61 | this.weswiper.touchstart(e)
62 | },
63 | touchmove (e) {
64 | this.weswiper.touchmove(e)
65 | },
66 | touchend (e) {
67 | this.weswiper.touchend(e)
68 | },
69 | onLoad () {
70 | new weSwiper({
71 | animationViewName: 'animationData',
72 | slideLength: 3,
73 | initialSlide: 0,
74 | /**
75 | * swiper初始化后执行
76 | * @param weswiper
77 | */
78 | onInit (weswiper) {
79 |
80 | },
81 | /**
82 | * 手指碰触slide时执行
83 | * @param weswiper
84 | * @param event
85 | */
86 | onTouchStart (weswiper, event) {
87 |
88 | },
89 | /**
90 | * 手指碰触slide并且滑动时执行
91 | * @param weswiper
92 | * @param event
93 | */
94 | onTouchMove (weswiper, event) {
95 |
96 | },
97 | /**
98 | * 手指离开slide时执行
99 | * @param weswiper
100 | * @param event
101 | */
102 | onTouchEnd (weswiper, event) {
103 |
104 | },
105 | /**
106 | * slide达到过渡条件时执行
107 | */
108 | onSlideChangeStart (weswiper) {
109 |
110 | },
111 | /**
112 | * weswiper从一个slide过渡到另一个slide结束时执行
113 | */
114 | onSlideChangeEnd (weswiper) {
115 |
116 | },
117 | /**
118 | * 过渡时触发
119 | */
120 | onTransitionStart (weswiper) {
121 |
122 | },
123 | /**
124 | * 过渡结束时执行
125 | */
126 | onTransitionEnd (weswiper) {
127 |
128 | },
129 | /**
130 | * 手指触碰weswiper并且拖动slide时执行
131 | */
132 | onSlideMove (weswiper) {
133 |
134 | },
135 | /**
136 | * slide达到过渡条件 且规定了方向 向前(右、下)切换时执行
137 | */
138 | onSlideNextStart (weswiper) {
139 |
140 | },
141 | /**
142 | * slide达到过渡条件 且规定了方向 向前(右、下)切换结束时执行
143 | */
144 | onSlideNextEnd (weswiper) {
145 |
146 | },
147 | /**
148 | * slide达到过渡条件 且规定了方向 向前(左、上)切换时执行
149 | */
150 | onSlidePrevStart (swiper) {
151 |
152 | },
153 | /**
154 | * slide达到过渡条件 且规定了方向 向前(左、上)切换结束时执行
155 | */
156 | onSlidePrevEnd (weswiper) {
157 |
158 | }
159 | })
160 | }
161 | }
162 | Page(option)
163 |
164 | ```
165 |
166 | ## we-swiper初始化
167 |
168 | #### weSwiper在onLoad方法中实例化
169 |
170 | ```javascript
171 | onLoad () {
172 | new weSwiper({
173 | slideLength: 3 // 必填,由于目前无法直接获取slide页数,目前只能通过参数写入
174 | })
175 | }
176 | ```
177 |
178 | #### 可通过this.weswiper在Page的钩子函数中访问实例
179 |
180 | ```javascript
181 | touchstart (e) {
182 | this.weswiper.touchstart(e)
183 | }
184 | ```
185 |
186 | #### WXML结构配置
187 |
188 | ```html
189 |
190 |
195 | slide 1
196 | slide 2
197 | slide 3
198 |
199 |
200 | ```
201 | 小提示:WXML中的字段不需要在Page的data中给出默认值,we-swiper内部有同步视图机制。
202 |
203 | ## 构造器参数
204 |
205 | ### 必填项
206 |
207 |
208 | #### slideLength
209 |
210 | - Type: `Number`
211 | - Default: `0`
212 |
213 | 表示slide的页数
214 |
215 | ### 可选项
216 |
217 |
218 | #### width
219 |
220 | - Type: `Number`
221 | - Default: `device.windowWidth`
222 |
223 | 设定slide的宽度(横向滑动时slide滑动间隔距离会根据其值计算)
224 |
225 |
226 | #### height
227 |
228 | - Type: `Number`
229 | - Default: `device.windowHeight`
230 |
231 | 设定slide的高度(纵向滑动时slide滑动间隔距离会根据其值计算)
232 |
233 |
234 | #### direction
235 |
236 | - Type: `String`
237 | - Default: `horizontal`
238 | - Option:
239 | - `horizontal`: slide水平方向滑动
240 | - `vertical`: slide垂直方向滑动
241 |
242 | 设定slide滑动方向
243 |
244 |
245 | #### initialSlide
246 |
247 | - Type: `Number`
248 | - Default: `0`
249 |
250 | 设定初始化时slide的索引
251 |
252 |
253 | #### speed
254 |
255 | - Type: `Number`
256 | - Default: `300`
257 |
258 | 设定slide过渡时长
259 |
260 |
261 | #### timingFunction
262 |
263 | - Type: `String`
264 | - Default: `ease`
265 | - Option:
266 | - `linear`: slide水平方向滑动
267 | - `ease`: slide垂直方向滑动
268 | - `ease-in`: slide垂直方向滑动
269 | - `ease-in-out`: slide垂直方向滑动
270 | - `ease-out`: slide垂直方向滑动
271 | - `step-start`: slide垂直方向滑动
272 | - `step-end`: slide垂直方向滑动
273 |
274 | 设定slide过渡动画速度曲线
275 |
276 |
277 | #### autoplay
278 |
279 | - Type: `Number`
280 | - Default: `0`
281 |
282 | 设定slide自动播放间隔时长,设置为0时不自动播放
283 |
284 |
285 | #### directionViewName
286 |
287 | - Type: `String`
288 | - Default: `directionClass`
289 |
290 | 对应视图中direction类名
291 |
292 |
293 | #### animationViewName
294 |
295 | - Type: `String`
296 | - Default: `animationData`
297 |
298 | 对应视图中animation属性名
299 |
300 |
301 | ## 属性
302 |
303 |
304 | #### weswiper.activeIndex
305 |
306 | 返回当前活动块(激活块)的索引
307 |
308 |
309 | #### weswiper.previousIndex
310 |
311 | 返回上一个活动块的索引
312 |
313 |
314 | #### weswiper.width
315 |
316 | 返回swiper容器的宽度
317 |
318 |
319 | #### weswiper.height
320 |
321 | 返回swiper容器的高度
322 |
323 |
324 | #### weswiper.isBeginning
325 |
326 | 如果swiper处于最初始位置,返回true
327 |
328 |
329 | #### weswiper.isEnd
330 |
331 | 如果swiper处于最末尾位置,返回true
332 |
333 |
334 | #### weswiper.speed
335 |
336 | 返回当前swiper的过渡时长
337 |
338 |
339 | ## 方法
340 |
341 |
342 | #### weswiper.slideNext(runCallbacks, speed)
343 |
344 | 滑动到后一个slide
345 |
346 | - Params:
347 | - `runCallbacks`: 可选,设为false不触发onSlideChange回调函数
348 | - `speed`: 可选,切换速度
349 |
350 |
351 | #### weswiper.slidePrev(runCallbacks, speed)
352 |
353 | 滑动到前一个slide。
354 |
355 | - Params:
356 | - `runCallbacks`: 可选,设为false不触发onSlideChange回调函数
357 | - `speed`: 可选,切换速度
358 |
359 |
360 | #### weswiper.slideTo(index, speed, runCallbacks)
361 |
362 | 切换到指定slide。
363 |
364 | - Params:
365 | - `index`: 必选,num,指定将要切换到的slide的索引
366 | - `speed`: 可选,切换速度
367 | - `runCallbacks`: 可选,设为false不触发onSlideChange回调函数
368 |
369 |
370 | ## 事件回调
371 |
372 |
373 | #### onInit (weswiper)
374 |
375 | 回调函数,初始化后执行。
376 | 可选weswiper实例作为参数。
377 |
378 |
379 | #### onTouchStart (weswiper, event)
380 |
381 | 回调函数,当碰触到slider时执行。可选weswiper和touchstart事件作为参数
382 |
383 |
384 | #### onTouchMove (weswiper, event)
385 |
386 | 回调函数,手指触碰weswiper并滑动(手指)时执行。此时slide不一定会发生移动,比如你手指的移动方向和weswiper的切换方向垂直时
387 |
388 |
389 | #### onTouchEnd (weswiper, event)
390 |
391 | 回调函数,当释放slider时执行。(释放即执行)
392 |
393 |
394 | #### onSlideChangeStart (weswiper)
395 |
396 | 回调函数,weswiper从当前slide开始过渡到另一个slide时执行。触摸情况下,如果释放slide时没有达到过渡条件而回弹时不会触发这个函数,此时可用onTransitionStart。
397 |
398 | 可接受weswiper实例作为参数,输出的activeIndex是过渡后的slide索引
399 |
400 |
401 | #### onSlideChangeEnd (weswiper)
402 |
403 | 回调函数,weswiper从一个slide过渡到另一个slide结束时执行。
404 |
405 | 可接受swiper实例作为参数。
406 |
407 |
408 | #### onTransitionStart (weswiper)
409 |
410 | 回调函数,过渡开始时触发,接受weswiper实例作为参数。
411 |
412 |
413 | #### onTransitionEnd (weswiper)
414 |
415 | 回调函数,过渡结束时触发,接收weswiper实例作为参数。
416 |
417 |
418 | #### onSlideMove (weswiper)
419 |
420 | 回调函数,手指触碰weswiper并拖动slide时执行。
421 |
422 |
423 | #### onSlideNextStart (weswiper)
424 |
425 | 回调函数,滑块释放时如果触发slider向前(右、下)切换则执行。类似于onSlideChangeStart,但规定了方向。
426 |
427 |
428 | #### onSlideNextEnd (weswiper)
429 |
430 | 回调函数,slider向前(右、下)切换结束时执行。类似于onSlideChangeEnd,但规定了方向。
431 |
432 |
433 | #### onSlidePrevStart (weswiper)
434 |
435 | 回调函数,滑块释放时如果触发slider向后(左、上)切换则执行。类似于onSlideChangeStart,但规定了方向。
436 |
437 | #### onSlidePrevEnd (weswiper)
438 |
439 | 回调函数,slider向后(左、上)切换结束时执行。类似于onSlideChangeEnd,但规定了方向。
440 |
441 |
442 | ## TODO
443 |
444 | - 增加切换效果:fade,flip等
445 |
446 | ## License
447 | The MIT License(http://opensource.org/licenses/MIT)
448 |
449 | 请自由地享受和参与开源
450 |
451 | ## 贡献
452 |
453 | 如果你有好的意见或建议,欢迎给我提issue或pull request。
454 |
455 |
456 |
457 |
458 |
--------------------------------------------------------------------------------
/dist/weSwiper.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (global.weSwiper = factory());
5 | }(this, (function () { 'use strict';
6 |
7 | var device = wx.getSystemInfoSync(); // 获取设备信息
8 |
9 | var DEFAULT = {
10 | /**
11 | * 必填项
12 | */
13 | slideLength: 0, // 由于目前无法直接获取slide页数,目前只能通过参数写入
14 | /**
15 | * 可选参数
16 | */
17 | width: device.windowWidth,
18 | height: device.windowHeight,
19 | direction: 'horizontal',
20 | initialSlide: 0,
21 | speed: 300,
22 | effect: 'slide', // 过渡效果
23 | timingFunction: 'ease', // 过渡动画速度曲线
24 | autoplay: 0, // 自动播放间隔,设置为0时不自动播放
25 | animationViewName: 'animationData', // 对应视图wrapper中animation属性名
26 | /**
27 | * 事件回调
28 | * @type {[type]}
29 | */
30 | onInit: null, // swiper初始化时执行
31 | onTouchStart: null, // 手指碰触slide时执行
32 | onTouchMove: null, // 手指碰触slide并且滑动时执行
33 | onTouchEnd: null, // 手指离开slide时执行
34 | onSlideChangeStart: null, // slide达到过渡条件时执行
35 | onSlideChangeEnd: null, // swiper从一个slide过渡到另一个slide结束时执行
36 | onTransitionStart: null, // 过渡时触发
37 | onTransitionEnd: null, // 过渡结束时执行
38 | onSlideMove: null, // 手指触碰swiper并且拖动slide时执行
39 | onSlideNextStart: null, // slide达到过渡条件 且规定了方向 向前(右、下)切换时执行
40 | onSlideNextEnd: null, // slide达到过渡条件 且规定了方向 向前(右、下)切换结束时执行
41 | onSlidePrevStart: null, // slide达到过渡条件 且规定了方向 向前(左、上)切换时执行
42 | onSlidePrevEnd: null // slide达到过渡条件 且规定了方向 向前(左、上)切换结束时执行
43 | };
44 |
45 | var handle = {
46 | touchstart: function touchstart(e) {
47 | if (this.noSwiper) return;
48 | var onTouchStart = this.onTouchStart,
49 | XORY = this.XORY,
50 | activeIndex = this.activeIndex,
51 | rectDistance = this.rectDistance;
52 |
53 | var touch = e.changedTouches[0];
54 | var distance = touch['client' + XORY];
55 | var translate = -activeIndex * rectDistance;
56 |
57 | this['touchStart' + XORY] = distance;
58 | this['translate' + XORY] = translate;
59 | this.touchStartTime = new Date().getTime();
60 |
61 | typeof onTouchStart === 'function' && onTouchStart(this, e); // 当手指碰触到slide时执行
62 |
63 | this.slideAnimation(translate, 0);
64 | },
65 | touchmove: function touchmove(e) {
66 | if (this.noSwiper) return;
67 | var onTouchMove = this.onTouchMove,
68 | XORY = this.XORY,
69 | onSlideMove = this.onSlideMove;
70 |
71 | var touch = e.changedTouches[0];
72 | var distance = touch['client' + XORY];
73 | var tmpMove = this['translate' + XORY] + distance - this['touchStart' + XORY];
74 |
75 | typeof onTouchMove === 'function' && onTouchMove(this, e); // 手指碰触slide并且滑动时执行
76 |
77 | this.slideAnimation(tmpMove, 0);
78 |
79 | typeof onSlideMove === 'function' && onSlideMove(this);
80 | },
81 | touchend: function touchend(e) {
82 | if (this.noSwiper) return;
83 | var onTouchEnd = this.onTouchEnd,
84 | XORY = this.XORY,
85 | speed = this.speed,
86 | touchStartTime = this.touchStartTime,
87 | rectDistance = this.rectDistance;
88 |
89 | var touch = e.changedTouches[0];
90 | var distance = touch['client' + XORY];
91 | var touchEndTime = new Date().getTime();
92 |
93 | var action = this.action(touchStartTime, touchEndTime, this['touchStart' + XORY], distance, rectDistance);
94 |
95 | typeof onTouchEnd === 'function' && onTouchEnd(this, e); // 手指离开slide时执行
96 |
97 | this[action](true, speed);
98 | }
99 | };
100 |
101 | /**
102 | * Created by sail on 2017/4/1.
103 | */
104 |
105 | var controller = {
106 | /**
107 | * 切换控制器
108 | * @param touchStartTime: 手指触碰slide时的时间戳
109 | * @param et: 手指离开slide时的时间戳
110 | * @param from: 手指触碰slide时的屏幕位置
111 | * @param to: 手指离开slide时的屏幕位置
112 | * @param wrapperDistance: slide滑动方向上的容器长度
113 | * @returns {*}
114 | */
115 | action: function action(touchStartTime, touchEndTime, from, to, wrapperDistance) {
116 | var activeIndex = this.activeIndex,
117 | slideLength = this.slideLength,
118 | onTransitionStart = this.onTransitionStart;
119 |
120 | var deltaTime = touchEndTime - touchStartTime; // 手指触摸时长
121 | var distance = Math.abs(to - from); // 滑动距离
122 |
123 | var k = distance / deltaTime;
124 |
125 | if (to > from) {
126 | typeof onTransitionStart === 'function' && onTransitionStart(this); // slide达到过渡条件时执行
127 | return k > 0.3 || distance > wrapperDistance / 2 ? activeIndex === 0 ? 'slideBack' : 'slidePrev' : 'slideBack';
128 | }
129 |
130 | if (to < from) {
131 | typeof onTransitionStart === 'function' && onTransitionStart(this); // slide达到过渡条件时执行
132 | return k > 0.3 || distance > wrapperDistance / 2 ? activeIndex === slideLength - 1 ? 'slideBack' : 'slideNext' : 'slideBack';
133 | }
134 |
135 | if (to = from) {
136 | return 'slideBack';
137 | }
138 | }
139 | };
140 |
141 | var methods = {
142 | /**
143 | * 切换至下一个slide
144 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
145 | * @param speed: 可选,num(单位ms),切换速度
146 | */
147 | slideNext: function slideNext() {
148 | var runCallbacks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
149 | var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
150 |
151 | var self = this;
152 | var onSlideNextStart = self.onSlideNextStart,
153 | onSlideNextEnd = self.onSlideNextEnd;
154 |
155 |
156 | typeof onSlideNextStart === 'function' && onSlideNextStart(self); // slide达到过渡条件时执行
157 |
158 | self.slideTo(self.activeIndex + 1, speed, runCallbacks);
159 |
160 | typeof onSlideNextEnd === 'function' && setTimeout(function () {
161 | onSlideNextEnd(self);
162 | }, speed); // slide过渡结束后执行
163 | },
164 |
165 | /**
166 | * 切换至上一个slide
167 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
168 | * @param speed: 可选,num(单位ms),切换速度
169 | */
170 | slidePrev: function slidePrev() {
171 | var runCallbacks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
172 | var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
173 |
174 | var self = this;
175 | var onSlidePrevStart = self.onSlidePrevStart,
176 | onSlidePrevEnd = self.onSlidePrevEnd;
177 |
178 |
179 | typeof onSlidePrevStart === 'function' && onSlidePrevStart(self); // slide达到过渡条件时执行
180 |
181 | self.slideTo(self.activeIndex - 1, speed, runCallbacks);
182 |
183 | typeof onSlidePrevEnd === 'function' && setTimeout(function () {
184 | onSlidePrevEnd(self);
185 | }, speed); // slide过渡结束后执行
186 | },
187 |
188 | /**
189 | * 回弹
190 | * @param runCallbacks: 可选,boolean,设置为false时不会触发onSlideChange回调函数
191 | * @param speed: 可选,num(单位ms),切换速度
192 | */
193 | slideBack: function slideBack() {
194 | var runCallbacks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
195 | var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
196 |
197 | var self = this;
198 | var XORY = self.XORY,
199 | activeIndex = self.activeIndex,
200 | rectDistance = self.rectDistance,
201 | onTransitionEnd = self.onTransitionEnd;
202 |
203 |
204 | var translate = -activeIndex * rectDistance;
205 |
206 | self.slideAnimation(translate, speed);
207 |
208 | typeof onTransitionEnd === 'function' && setTimeout(function () {
209 | onTransitionEnd(self);
210 | }, speed); // slide过渡结束后执行
211 | },
212 |
213 | /**
214 | * 切换到指定slide
215 | * @param index:必选,num,指定将要切换到的slide的索引
216 | * @param speed:可选,num(单位ms),切换速度
217 | * @param runCallbacks:可选,boolean,设置为false时不会触发onSlideChange回调函数
218 | */
219 | slideTo: function slideTo(index) {
220 | var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
221 | var runCallbacks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
222 |
223 | var self = this;
224 | var noSwiper = self.noSwiper,
225 | slideLength = self.slideLength,
226 | activeIndex = self.activeIndex,
227 | rectDistance = self.rectDistance,
228 | onSlideChangeStart = self.onSlideChangeStart,
229 | onSlideChangeEnd = self.onSlideChangeEnd,
230 | onTransitionEnd = self.onTransitionEnd,
231 | consoleException = self.consoleException;
232 |
233 |
234 | try {
235 | if (typeof index !== 'number') throw 'paramType'; // 参数类型错误
236 | if (index < 0 || index > slideLength - 1) throw 'bound'; // 越界
237 |
238 | var translate = -index * rectDistance;
239 | self.previousIndex = activeIndex;
240 | self.activeIndex = index;
241 | self.isBeginning = self.activeIndex === self.initialSlide;
242 | self.isEnd = self.activeIndex === self.slideLength - 1;
243 |
244 | runCallbacks && typeof onSlideChangeStart === 'function' && onSlideChangeStart(self); // slide达到过渡条件时执行
245 |
246 | self.slideAnimation(translate, speed);
247 |
248 | runCallbacks && typeof onSlideChangeEnd === 'function' && setTimeout(function () {
249 | onSlideChangeEnd(self);
250 | }, speed); // swiper从一个slide过渡到另一个slide结束后执行
251 | typeof onTransitionEnd === 'function' && setTimeout(function () {
252 | onTransitionEnd(self);
253 | }, speed); // slide过渡结束后执行
254 | } catch (err) {
255 | consoleException(err, 'slideTo[Function]');
256 | }
257 | }
258 | };
259 |
260 | /**
261 | * Created by sail on 2017/4/1.
262 | */
263 | var REG = {
264 | SPEED: /^(0|[1-9][0-9]*|-[1-9][0-9]*)$/,
265 | TIMINGFUNCTION: /linear|ease|ease-in|ease-in-out|ease-out|step-start|step-end/
266 | };
267 |
268 | var animate = {
269 | /**
270 | * 平移动画
271 | * @param translate:平移位置
272 | * @param speed:过渡时长
273 | * @param timingFunction:过渡类型
274 | */
275 | slideAnimation: function slideAnimation() {
276 | var translate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
277 | var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
278 | var timingFunction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'ease';
279 | var XORY = this.XORY,
280 | animationViewName = this.animationViewName,
281 | consoleException = this.consoleException;
282 |
283 | try {
284 | /**
285 | * 异常处理
286 | */
287 | if (!REG.SPEED.test(speed)) throw 'paramType';
288 | if (!REG.TIMINGFUNCTION.test(timingFunction)) throw 'paramType';
289 | /**
290 | * 创建一个动画实例
291 | */
292 | var animation = wx.createAnimation({
293 | transformOrigin: '50% 50%',
294 | duration: speed,
295 | timingFunction: timingFunction,
296 | delay: 0
297 | });
298 |
299 | animation['translate' + XORY](translate).step(); // 动画描述
300 |
301 | this.syncView(animationViewName, animation.export()); // 同步动画到视图
302 | } catch (err) {
303 | consoleException(err, 'slideAnimation[Function]');
304 | }
305 | }
306 | };
307 |
308 | var classCallCheck = function (instance, Constructor) {
309 | if (!(instance instanceof Constructor)) {
310 | throw new TypeError("Cannot call a class as a function");
311 | }
312 | };
313 |
314 | var createClass = function () {
315 | function defineProperties(target, props) {
316 | for (var i = 0; i < props.length; i++) {
317 | var descriptor = props[i];
318 | descriptor.enumerable = descriptor.enumerable || false;
319 | descriptor.configurable = true;
320 | if ("value" in descriptor) descriptor.writable = true;
321 | Object.defineProperty(target, descriptor.key, descriptor);
322 | }
323 | }
324 |
325 | return function (Constructor, protoProps, staticProps) {
326 | if (protoProps) defineProperties(Constructor.prototype, protoProps);
327 | if (staticProps) defineProperties(Constructor, staticProps);
328 | return Constructor;
329 | };
330 | }();
331 |
332 |
333 |
334 |
335 |
336 | var defineProperty = function (obj, key, value) {
337 | if (key in obj) {
338 | Object.defineProperty(obj, key, {
339 | value: value,
340 | enumerable: true,
341 | configurable: true,
342 | writable: true
343 | });
344 | } else {
345 | obj[key] = value;
346 | }
347 |
348 | return obj;
349 | };
350 |
351 | /**
352 | * Created by sail on 2017/4/1.
353 | */
354 | var sync = {
355 | /**
356 | * 同步设置到视图
357 | * @param DEFAULT:默认参数
358 | * @param param:构造参数
359 | */
360 | syncView: function syncView(viewName, prop) {
361 | this.pageContext.setData(defineProperty({}, "" + viewName, prop));
362 | }
363 | };
364 |
365 | /**
366 | * Created by sail on 2017/4/1.
367 | */
368 | var ERROR = {
369 | 'paramType': '参数类型错误',
370 | 'bound': '参数越界'
371 | };
372 |
373 | var exception = {
374 | /**
375 | * 错误对照
376 | */
377 | consoleException: function consoleException(type, place) {
378 | console.error('%c' + place + ':' + ERROR[type], 'color: red');
379 | }
380 | };
381 |
382 | var weSwiper = function () {
383 | function weSwiper(param) {
384 | classCallCheck(this, weSwiper);
385 |
386 |
387 | var pages = getCurrentPages();
388 |
389 | // 获取到当前page上下文
390 | this.pageContext = pages[pages.length - 1];
391 | // 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
392 | this.pageContext.weswiper = this;
393 |
394 | var all = Object.assign(this, DEFAULT, param || {});
395 |
396 | this.init(all);
397 | }
398 |
399 | /**
400 | * 初始化配置
401 | */
402 |
403 |
404 | createClass(weSwiper, [{
405 | key: 'init',
406 | value: function init(param) {
407 | var _this = this;
408 |
409 | var speed = param.speed,
410 | initialSlide = param.initialSlide,
411 | direction = param.direction,
412 | autoplay = param.autoplay,
413 | directionViewName = param.directionViewName;
414 |
415 |
416 | var directionClass = direction === 'horizontal' ? 'we-container-horizontal' : 'we-container-vertical';
417 | this.syncView(directionViewName, directionClass);
418 | this.rectDistance = direction === 'horizontal' ? this.width : this.height;
419 | this.XORY = direction === 'horizontal' ? 'X' : 'Y';
420 | this.activeIndex = initialSlide; // 将初始页码赋给activeIndex
421 | this.noSwiper = false; // 阻止手势滑动
422 | this.previousIndex = initialSlide; // 返回上一个活动块的索引,切换前的索引
423 | this.slideTo(initialSlide, 0);
424 | typeof autoplay === 'number' && autoplay > 0 && setInterval(function () {
425 | if (_this.isEnd) {
426 | _this.slideTo(0, speed);
427 | } else {
428 | _this.slideTo(_this.activeIndex + 1, speed);
429 | }
430 | }, autoplay);
431 | /**
432 | * 处理callback
433 | */
434 | var onInit = this.onInit;
435 |
436 | typeof onInit === 'function' && onInit(this);
437 | }
438 | }]);
439 | return weSwiper;
440 | }();
441 |
442 | Object.assign(weSwiper.prototype, controller);
443 | Object.assign(weSwiper.prototype, handle);
444 | Object.assign(weSwiper.prototype, methods);
445 | Object.assign(weSwiper.prototype, animate);
446 | Object.assign(weSwiper.prototype, sync);
447 | Object.assign(weSwiper.prototype, exception);
448 |
449 | return weSwiper;
450 |
451 | })));
452 |
--------------------------------------------------------------------------------