├── .gitignore
├── LICENSE
├── package.json
├── webpack.config.js
├── src
├── vue-swiper.less
└── vue-swiper.vue
├── README.md
├── demo
└── index.html
└── dist
└── vue-swiper.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 威老
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 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-swiper",
3 | "version": "0.5.0",
4 | "description": "Swiper component. Easy to use.",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/weilao/vue-swiper.git"
8 | },
9 | "author": "weilao",
10 | "license": "MIT",
11 | "bugs": {
12 | "url": "https://github.com/weilao/vue-swiper/issues"
13 | },
14 | "homepage": "https://github.com/weilao/vue-swiper",
15 | "main": "dist/vue-swiper.js",
16 | "scripts": {
17 | "dev": "NODE_ENV=dev webpack-dev-server --inline --hot --host 0.0.0.0 --config webpack.config.js",
18 | "build": "webpack"
19 | },
20 | "devDependencies": {
21 | "autoprefixer": "^6.3.6",
22 | "babel-core": "^6.8.0",
23 | "babel-loader": "^6.2.4",
24 | "babel-plugin-transform-runtime": "^6.8.0",
25 | "babel-preset-es2015": "^6.6.0",
26 | "babel-runtime": "^6.6.1",
27 | "css-loader": "^0.23.1",
28 | "less": "^2.7.0",
29 | "less-loader": "^2.2.3",
30 | "vue-hot-reload-api": "^1.3.2",
31 | "vue-html-loader": "^1.2.2",
32 | "vue-loader": "^8.3.1",
33 | "vue-style-loader": "^1.0.0",
34 | "webpack": "^1.13.0",
35 | "webpack-dev-server": "^1.14.1"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 | var autoprefixer = require('autoprefixer');
4 | var pkg = require('./package.json');
5 | var banner = `${pkg.name} v${pkg.version}\n${pkg.description}\n${pkg.homepage}\n@author ${pkg.author}`;
6 | module.exports = {
7 | entry: {
8 | 'vue-swiper': path.join(__dirname, 'src/vue-swiper.vue')
9 | },
10 | output: {
11 | path: path.join(__dirname, 'dist'),
12 | publicPath: '/',
13 | library: 'VueSwiper',
14 | libraryTarget: 'umd',
15 | filename: "[name].js"
16 | },
17 | module: {
18 | loaders: [
19 | {test: /\.js$/, loader: 'babel', exclude: /node_modules/},
20 | {test: /\.vue$/, loader: 'vue'},
21 | {test: /\.less$/, loader: "css?sourceMap!postcss!less?sourceMap"}
22 | ]
23 | },
24 | postcss: [autoprefixer({browsers: ['last 2 versions', 'Android 2.3']})],
25 | babel: {
26 | "presets": ["es2015"]
27 | },
28 | plugins: []
29 | };
30 |
31 | if (process.env.NODE_ENV === 'dev') {
32 | module.exports.devtool = '#eval-source-map';
33 | } else {
34 | module.exports.plugins.push(new webpack.optimize.UglifyJsPlugin());
35 | module.exports.plugins.push(new webpack.BannerPlugin(banner));
36 | }
37 |
--------------------------------------------------------------------------------
/src/vue-swiper.less:
--------------------------------------------------------------------------------
1 | .swiper {
2 | position: relative;
3 | overflow: hidden;
4 |
5 | .swiper-wrap {
6 | display: flex;
7 | width: 100%;
8 | height: 100%;
9 | transition: all 0ms ease;
10 |
11 | > div {
12 | overflow: hidden;
13 | flex-shrink: 0;
14 | width: 100%;
15 | height: 100%;
16 | }
17 | }
18 |
19 | &.horizontal .swiper-wrap {
20 | flex-direction: row;
21 | }
22 |
23 | &.vertical .swiper-wrap {
24 | flex-direction: column;
25 | }
26 |
27 | .swiper-pagination {
28 | position: absolute;
29 |
30 | .swiper-pagination-bullet {
31 | width: 8px;
32 | height: 8px;
33 | border-radius: 50%;
34 | background-color: #000000;
35 | opacity: .2;
36 | transition: all .5s ease;
37 | }
38 |
39 | .swiper-pagination-bullet.active {
40 | background: #007aff;
41 | opacity: 1;
42 | }
43 | }
44 |
45 | &.vertical .swiper-pagination {
46 | right: 10px;
47 | top: 50%;
48 | transform: translate3d(0, -50%, 0);
49 |
50 | .swiper-pagination-bullet {
51 | display: block;
52 | margin: 6px 0;
53 | }
54 | }
55 |
56 | &.horizontal .swiper-pagination {
57 | bottom: 10px;
58 | width: 100%;
59 | text-align: center;
60 |
61 | .swiper-pagination-bullet {
62 | display: inline-block;
63 | margin: 0 3px;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://raw.githubusercontent.com/weilao/vue-swiper/master/LICENSE)
2 | [](https://www.npmjs.com/package/vue-swiper)
3 | [](https://github.com/weilao/vue-swiper/releases)
4 | [](https://github.com/weilao/vue-swiper/issues)
5 | [](https://github.com/weilao/vue-swiper)
6 |
7 | [](https://nodei.co/npm/vue-swiper/)
8 |
9 | # vue-swiper
10 | Swiper component. Easy to use.
11 |
12 | ## Examples
13 | [basic demo](http://weilao.github.io/vue-swiper/demo)
14 |
15 | ## Install
16 | ```
17 | npm i vue-swiper -S
18 | ```
19 |
20 | ## Usage
21 |
22 | ```js
23 | import Vue from 'vue'
24 | import Swiper from 'vue-swiper'
25 |
26 | new Vue({
27 | el: 'body',
28 | components: {Swiper},
29 | methods: {
30 | onSlideChangeStart (currentPage) {
31 | console.log('onSlideChangeStart', currentPage);
32 | },
33 | onSlideChangeEnd (currentPage) {
34 | console.log('onSlideChangeEnd', currentPage);
35 | }
36 | }
37 | });
38 | ```
39 |
40 | ```html
41 |
50 | Page 1
51 | Page 2
52 | Page 3
53 |
54 | ```
55 |
56 | ## Api
57 | ### Properties
58 | | Name | Type | Default | Description |
59 | |----------------------|-----------|--------------|--------------------------------------------------------------------|
60 | | direction | `String` | `"vertical"` | Could be 'horizontal' or 'vertical' (for vertical slider). |
61 | | mousewheel-control | `Boolean` | `true` | Set to true to enable navigation through slides using mouse wheel. |
62 | | pagination-visible | `Boolean` | `false` | Toggle (hide/true) pagination container visibility when click on Slider's container |
63 | | pagination-clickable | `Boolean` | `false` | If true then clicking on pagination button will cause transition to appropriate slide. |
64 | | performace-mode | `Boolean` | `false` | Disable advance effect for better performance. |
65 | | loop | `Boolean` | `false` | Set to true to enable continuous loop mode |
66 | | ==================== | ========= | ============ | =================== |
67 |
68 | ### Methods
69 | | Method | Description |
70 | |-------------------|--------------------------|
71 | | next() | Go next page. |
72 | | prev() | Go previous page. |
73 | | setPage(`Number`) | Set current page number. |
74 |
75 | ### Events
76 | | Name | Parameters | Description |
77 | |--------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
78 | | slide-change-start | `pageNumber` | Fire in the beginning of animation to other slide (next or previous). |
79 | | slide-change-end | `pageNumber` | Will be fired after animation to other slide (next or previous). |
80 | | slide-revert-start | `pageNumber` | Fire in the beginning of animation to revert slide (no change). |
81 | | slide-revert-end | `pageNumber` | Will be fired after animation to revert slide (no change). |
82 | | slider-move | `offset` | Callback function, will be executed when user touch and move finger over Swiper and move it. Receives swiper instance and 'touchmove' event as an arguments. |
83 | | ================== | ================ | ============================ |
84 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-swiper DEMO
6 |
8 |
108 |
109 |
110 | vue-swiper demo
111 | Vertical
112 |
119 | ↑
o
↓
120 | Page {{n}}
121 |
122 | Horizontal
123 |
126 | {{slideText}}
127 |
128 | Loop Mode / Infinite Loop
129 |
133 | {{slideText}}
134 |
135 | Append Child
136 |
137 |
138 |
139 | Different children size
140 |
141 | ↑
o
↓
142 | Page {{n}}
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/dist/vue-swiper.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-swiper v0.5.0
3 | * Swiper component. Easy to use.
4 | * https://github.com/weilao/vue-swiper
5 | * @author weilao
6 | */
7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.VueSwiper=e():t.VueSwiper=e()}(this,function(){return function(t){function e(n){if(i[n])return i[n].exports;var s=i[n]={exports:{},id:n,loaded:!1};return t[n].call(s.exports,s,s.exports,e),s.loaded=!0,s.exports}var i={};return e.m=t,e.c=i,e.p="/",e(0)}([function(t,e,i){var n,s;i(1),n=i(5),s=i(6),t.exports=n||{},t.exports.__esModule&&(t.exports=t.exports["default"]),s&&(("function"==typeof t.exports?t.exports.options||(t.exports.options={}):t.exports).template=s)},function(t,e,i){var n=i(2);"string"==typeof n&&(n=[[t.id,n,""]]);i(4)(n,{});n.locals&&(t.exports=n.locals)},function(t,e,i){e=t.exports=i(3)(),e.push([t.id,".swiper{position:relative;overflow:hidden}.swiper .swiper-wrap{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:100%;-webkit-transition:all 0ms ease;transition:all 0ms ease}.swiper .swiper-wrap>div{overflow:hidden;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;width:100%;height:100%}.swiper.horizontal .swiper-wrap{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.swiper.vertical .swiper-wrap{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.swiper .swiper-pagination{position:absolute}.swiper .swiper-pagination .swiper-pagination-bullet{width:8px;height:8px;border-radius:50%;background-color:#000;opacity:.2;-webkit-transition:all .5s ease;transition:all .5s ease}.swiper .swiper-pagination .swiper-pagination-bullet.active{background:#007aff;opacity:1}.swiper.vertical .swiper-pagination{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper.vertical .swiper-pagination .swiper-pagination-bullet{display:block;margin:6px 0}.swiper.horizontal .swiper-pagination{bottom:10px;width:100%;text-align:center}.swiper.horizontal .swiper-pagination .swiper-pagination-bullet{display:inline-block;margin:0 3px}",""])},function(t,e){t.exports=function(){var t=[];return t.toString=function(){for(var t=[],e=0;e=0&&m.splice(e,1)}function a(t){var e=document.createElement("style");return e.type="text/css",r(t,e),e}function l(t,e){var i,n,s;if(e.singleton){var r=v++;i=g||(g=a(e)),n=h.bind(null,i,r,!1),s=h.bind(null,i,r,!0)}else i=a(e),n=u.bind(null,i),s=function(){o(i)};return n(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;n(t=e)}else s()}}function h(t,e,i,n){var s=i?"":n.css;if(t.styleSheet)t.styleSheet.cssText=w(e,s);else{var r=document.createTextNode(s),o=t.childNodes;o[e]&&t.removeChild(o[e]),o.length?t.insertBefore(r,o[e]):t.appendChild(r)}}function u(t,e){var i=e.css,n=e.media,s=e.sourceMap;if(n&&t.setAttribute("media",n),s&&(i+="\n/*# sourceURL="+s.sources[0]+" */",i+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(s))))+" */"),t.styleSheet)t.styleSheet.cssText=i;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(i))}}var d={},c=function(t){var e;return function(){return"undefined"==typeof e&&(e=t.apply(this,arguments)),e}},p=c(function(){return/msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase())}),f=c(function(){return document.head||document.getElementsByTagName("head")[0]}),g=null,v=0,m=[];t.exports=function(t,e){e=e||{},"undefined"==typeof e.singleton&&(e.singleton=p()),"undefined"==typeof e.insertAt&&(e.insertAt="bottom");var i=s(t);return n(i,e),function(t){for(var r=[],o=0;o-1}},mousewheelControl:{type:Boolean,"default":!0},performanceMode:{type:Boolean,"default":!1},paginationVisible:{type:Boolean,"default":!1},paginationClickable:{type:Boolean,"default":!1},loop:{type:Boolean,"default":!1},speed:{type:Number,"default":500}},data:function(){return{currentPage:1,lastPage:1,translateX:0,translateY:0,startTranslate:0,delta:0,dragging:!1,startPos:null,transitioning:!1,slideEls:[],translateOffset:0,transitionDuration:0}},ready:function(){this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this.slideEls=[].map.call(this.$els.swiperWrap.children,function(t){return t}),this.loop?this.$nextTick(function(){this._createLoop(),this.setPage(this.currentPage,!0)}):this.setPage(this.currentPage)},methods:{next:function(){var t=this.currentPage;t1||this.loop?this.setPage(t-1):this._revert()},setPage:function(t,e){var i=this;if(this.lastPage=this.currentPage,0===t?this.currentPage=this.slideEls.length:t===this.slideEls.length+1?this.currentPage=1:this.currentPage=t,this.loop)0===this.delta&&this._setTranslate(i._getTranslateOfPage(this.lastPage)),setTimeout(function(){i._setTranslate(i._getTranslateOfPage(t)),e||i._onTransitionStart()},0);else{if(this._setTranslate(this._getTranslateOfPage(t)),e)return;this._onTransitionStart()}},isHorizontal:function(){return this.direction===n},isVertical:function(){return this.direction===i},_onTouchStart:function(t){this.startPos=this._getTouchPos(t),this.delta=0,this.startTranslate=this._getTranslateOfPage(this.currentPage),this.startTime=(new Date).getTime(),this.dragging=!0,this.transitionDuration=0,document.addEventListener("touchmove",this._onTouchMove,!1),document.addEventListener("touchend",this._onTouchEnd,!1),document.addEventListener("mousemove",this._onTouchMove,!1),document.addEventListener("mouseup",this._onTouchEnd,!1)},_onTouchMove:function(t){this.delta=this._getTouchPos(t)-this.startPos,this.performanceMode||(this._setTranslate(this.startTranslate+this.delta),this.$emit("slider-move",this._getTranslate())),(this.isVertical()||this.isHorizontal()&&Math.abs(this.delta)>0)&&t.preventDefault()},_onTouchEnd:function(t){this.dragging=!1,this.transitionDuration=this.speed;var e=(new Date).getTime()-this.startTime<1e3;this.delta<-100||e&&this.delta<-15?this.next():this.delta>100||e&&this.delta>15?this.prev():this._revert(),document.removeEventListener("touchmove",this._onTouchMove),document.removeEventListener("touchend",this._onTouchEnd),document.removeEventListener("mousemove",this._onTouchMove),document.removeEventListener("mouseup",this._onTouchEnd)},_onWheel:function(t){this.mousewheelControl&&(this.transitioning||(t.deltaY>0?this.next():this.prev()),this._isPageChanged()&&t.preventDefault())},_revert:function(){this.setPage(this.currentPage)},_getTouchPos:function(t){var e=this.isHorizontal()?"pageX":"pageY";return t.changedTouches?t.changedTouches[0][e]:t[e]},_onTransitionStart:function(){this.transitioning=!0,this.transitionDuration=this.speed,this._isPageChanged()?this.$emit("slide-change-start",this.currentPage):this.$emit("slide-revert-start",this.currentPage)},_onTransitionEnd:function(){this.transitioning=!1,this.transitionDuration=0,this.delta=0,this._isPageChanged()?this.$emit("slide-change-end",this.currentPage):this.$emit("slide-revert-end",this.currentPage)},_isPageChanged:function(){return this.lastPage!==this.currentPage},_setTranslate:function(t){var e=this.isHorizontal()?"translateX":"translateY";this[e]=t},_getTranslate:function(){var t=this.isHorizontal()?"translateX":"translateY";return this[t]},_getTranslateOfPage:function(t){if(0===t)return 0;var e=this.isHorizontal()?"clientWidth":"clientHeight";return-[].reduce.call(this.slideEls,function(i,n,s){return s>t-2?i:i+n[e]},0)+this.translateOffset},_createLoop:function(){var t=this.isHorizontal()?"clientWidth":"clientHeight",e=this.$els.swiperWrap,i=e.firstElementChild.cloneNode(!0),n=e.lastElementChild.cloneNode(!0);e.insertBefore(n,e.firstElementChild),e.appendChild(i),this.translateOffset=-n[t]}}}},function(t,e){t.exports=""}])});
--------------------------------------------------------------------------------
/src/vue-swiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
257 |
--------------------------------------------------------------------------------