123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- import {
- getStyleStr
- } from '../../../utils/style.js';
- // #ifdef APP-NVUE
- const animation = uni.requireNativePlugin('animation')
- // #endif
- export default {
- data() {
- return {
- timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
- isAnimated: false,
- isScrolling: false,
- customDuration: 0,
- left: 0,
- mCurrent: this.current
- };
- },
- created() {},
- mounted() {
- // #ifdef MP
- this.swiperViews = this.$children
- // #endif
- // #ifdef APP-PLUS || H5
- this.swiperViews = this.$slots.default.map(it => it.child)
- // #endif
- this._setLeft();
- this.mCurrent = this.current
- this._notifyCurrentForItems(this.current, this.position)
- },
- watch: {
- mCurrent() {
- let current = this.mCurrent
- if (this.circular) {
- if (this.position == 1) {
- current = this.actualSize - (this.plus - 1)
- // console.log('最前了', current)
- } else if (this.position == this._size - 2) {
- current = this.plus - 2;
- // console.log('最后了', current)
- }
- if (current < 0) {
- current = this.position + 1
- }
- current %= this.actualSize
- }
- // console.log('position', this.position, current)
- this.$emit('update:current', current)
- this.$emit('change', current)
- this._notifyCurrentForItems(current, this.position)
- }
- },
- computed: {
- is3D() {
- return this.mode == '3d'
- },
- position() {
- return this.circular ? (this.mCurrent + this.plus) : this.mCurrent
- },
- manualDuration() {
- if (this.customDuration > 0)
- return this.customDuration
- return this.isAnimated ? this.duration : 0
- },
- boxStyle() {
- return getStyleStr({
- width: this.width + 'rpx',
- height: this.height + 'rpx'
- });
- },
- containerStyle() {
- const style = {
- height: this.height + 'rpx'
- };
- // #ifdef APP-NVUE
- // FIXME: 理论isAnimated=false应该不设置transform,但是ios有个奇怪的问题,top不为0导致布局错位
- const isIOS = uni.getSystemInfoSync().platform == 'ios'
- if (isIOS) {
- style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
- } else {
- if (this.isAnimated == false) {
- style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
- }
- }
- // #endif
- // #ifndef APP-NVUE
- style.left = this.left + 'rpx'
- style.transition = 'left ' + this.manualDuration + 'ms ' + this.timingFunction
- // #endif
- return getStyleStr(style);
- },
- _size() {
- return (this.$slots && this.$slots.default && this.$slots.default.length) || this.size;
- },
- // plus * 2
- plusSize() {
- return this.circular ? this.plus * 2 : 0;
- },
- // 真实长度
- actualSize() {
- return this._size - this.plusSize;
- }
- },
- methods: {
- prev() {
- if (this.isAnimated) return;
- if (this.isScrolling) return;
- if (this.mCurrent == 0 && this.circular == false) return
- this.mCurrent--;
- this._run()
- },
- next() {
- if (this.isAnimated) return;
- if (this.isScrolling) return;
- if (this.circular == true) {
- this.mCurrent++;
- if (this.mCurrent == this._size) {
- this.mCurrent = 0;
- }
- } else {
- if (this.mCurrent == this._size - 1) return
- this.mCurrent++;
- }
- this._run()
- },
- moveTo(e) {
- if (this.isAnimated) return
- const {
- deltaX,
- left
- } = e
- this.isScrolling = true
- if (!this.circular) {
- if (
- // 第一项,不能向右滑(上一项)
- (deltaX > 0 && this.mCurrent == 0) ||
- // 最后一项,不能向左滑(下一项)
- (deltaX < 0 && this.mCurrent == this._size - 1)
- ) {
- if (!this.bounce) return
- // 添加阻尼滑动
- const _left = this._left || this.wxsData.left
- this.left = _left + (deltaX * (1 - Math.abs(deltaX) * 3 / (this.width * 5)))
- this._set3DScale(deltaX)
- return
- }
- }
- this.left = left
- this._set3DScale(deltaX)
- },
- moveEnd(e) {
- const {
- velocity,
- deltaX,
- deltaY
- } = e
- this.isScrolling = false
- if (!this.circular) {
- // 第一项,不能向右滑(上一项)
- if (deltaX > 0 && this.mCurrent == 0) {
- this._restoreStartTouch()
- return
- }
- // 最后一项,不能向左滑(下一项)
- if (deltaX < 0 && this.mCurrent == this._size - 1) {
- this._restoreStartTouch()
- return
- }
- }
- const isTurnPage = Math.abs(deltaX) > this.itemWidth / 2
- if (isTurnPage || velocity > 0.2) {
- if (deltaX < 0) {
- this.customDuration = 350
- this.next()
- } else if (deltaX > 0) {
- this.customDuration = 350
- this.prev()
- }
- } else {
- this._restoreStartTouch()
- }
- },
- _set3DScale(deltaX) {
- if (this.is3D) {
- const min = Math.min
- const maxScale = Math.abs(this.scale - 1)
- const mScale = deltaX * maxScale / this.width
- const mRealScale = min(this.scale, this.scale - Math.abs(mScale))
- this.swiperViews[this.position].mScale = mRealScale < 1 ? 1 : mRealScale
- if (this.position - 1 > -1) {
- this.swiperViews[this.position - 1].mScale = mScale > 0 ? min(this.scale, 1 + mScale) : min(1, 1 + mScale)
- }
- if (this.position + 1 < this._size) {
- this.swiperViews[this.position + 1].mScale = mScale > 0 ? min(1, 1 - mScale) : min(this.scale, 1 - mScale)
- }
- }
- },
- _restoreStartTouch() {
- const self = this
- this.customDuration = 300
- // #ifdef APP-VUE || MP-WEIXIN || H5
- this.left = this.wxsData.left
- // #endif
- // #ifndef APP-PLUS || MP-WEIXIN || H5
- this.left = this._left
- // #endif
- this._run(false)
- if (this.is3D) {
- this.swiperViews[this.position].restoreScale(this.manualDuration)
- if (this.position - 1 > -1) {
- this.swiperViews[this.position - 1].restoreScale(this.manualDuration)
- }
- if (this.position + 1 < this._size) {
- this.swiperViews[this.position + 1].restoreScale(this.manualDuration)
- }
- }
- },
- _notifyCurrentForItems(current, position) {
- this.swiperViews && this.swiperViews.forEach(it => {
- it.current = current
- it.position = position
- })
- },
- _run(isSet = true) {
- this.isAnimated = true;
- if (isSet)
- this._setLeft();
- const self = this;
- if (this.is3D) {
- this.swiperViews[this.position].restoreToScale(this.scale, this.manualDuration)
- if (this.position - 1 > -1) {
- this.swiperViews[this.position - 1].restoreToScale(1, this.manualDuration)
- }
- if (this.position + 1 < this._size) {
- this.swiperViews[this.position + 1].restoreToScale(1, this.manualDuration)
- }
- }
- // #ifdef APP-NVUE
- animation.transition(this.$refs.container, {
- styles: {
- transform: 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)',
- },
- duration: this.manualDuration, //ms
- timingFunction: this.timingFunction,
- needLayout: false,
- delay: 0 //ms
- }, function() {
- self._reset();
- })
- // #endif
- // #ifndef APP-NVUE
- setTimeout(() => {
- this._reset();
- }, this.manualDuration);
- // #endif
- },
- _setLeft() {
- if (this.circular == true) {
- const s1 = (this.width - this.itemWidth - this.space * 2) / 2;
- let left = (this.plus + this.mCurrent) * (this.space + this.itemWidth) - s1;
- this.left = -left;
- } else {
- this.left = -(this.itemWidth + this.space) * this.mCurrent
- }
- // #ifdef APP-VUE || MP-WEIXIN || H5
- this.wxsData = {
- left: this.left,
- bounce: this.bounce
- }
- // #endif
- },
- _reset() {
- this.isScrolling = false
- this.isAnimated = false
- this.customDuration = 0
- if (this.circular == true) {
- if (this.position == 1) {
- this.mCurrent = this.actualSize - (this.plus - 1);
- this._setLeft();
- this._restoreScale()
- }
- // -2:原数组索引-1 + plus数组索引-1
- if (this.position == this._size - 2) {
- this.mCurrent = this.plus - 2;
- this._setLeft();
- this._restoreScale()
- }
- }
- },
- _restoreScale() {
- if (this.is3D) {
- this.swiperViews[this.position].restoreToScale(this.scale, 0)
- if (this.position - 1 > -1) {
- this.swiperViews[this.position - 1].restoreToScale(1, 0)
- }
- if (this.position + 1 < this._size) {
- this.swiperViews[this.position + 1].restoreToScale(1, 0)
- }
- }
- }
- }
- }
|