UNPKG

vivo-ui

Version:

vivo ui component lib for vue

268 lines (250 loc) 8.82 kB
import _defineProperty from 'babel-runtime/helpers/defineProperty'; import Tween from '../../tools/tween/index'; import { raf, caf } from '../../tools/prefix/index'; (function () { if (typeof document !== 'undefined') { var head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'), css = " .src-components-swiper-index--swiper--27769 { overflow: hidden; } .src-components-swiper-index--swiper--27769 > ul { list-style-type: none; margin: 0; padding: 0; } .src-components-swiper-index--horizontal--3oOKy > ul { white-space: nowrap; } .src-components-swiper-index--horizontal--3oOKy > ul > li { display: inline-block; vertical-align: top; width: 100%; white-space: normal; } ";style.type = 'text/css';if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); }head.appendChild(style); } })(); var index = { render: function render() { var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('div', { class: [_vm.$style.swiper, _defineProperty({}, _vm.$style.horizontal, !_vm.vertical)], on: { "touchmove": _vm.touchmove, "touchend": _vm.touchend } }, [_c('ul', { ref: "list", style: _vm.style }, [_vm._t("default")], 2)]); }, staticRenderFns: [], cssModules: { "swiper": "src-components-swiper-index--swiper--27769", "horizontal": "src-components-swiper-index--horizontal--3oOKy" }, name: 'swiper', inheritAttrs: false, props: { value: { type: Number, default: 0 }, direction: { type: String, default: 'left', validator: function validator(value) { return ['up', 'down', 'left', 'right'].indexOf(value) !== -1; } }, loop: { // 是否循环 type: Boolean, default: true }, interval: { // 轮播间隔时间 type: Number, default: 3000 }, duration: { // 动画时间,表示多少帧 type: Number, default: 30 }, swipe: { // 是否可以手指滑动 type: Boolean, default: true }, threshold: { // 超过了多少百分比才切换 type: Number, default: 0.2 } }, data: function data() { return { index: this.value, pos: this.value + this.loop, height: undefined }; }, computed: { $style: function $style() { return this.$options.cssModules; }, style: function style() { return { height: this.height + 'px', transform: 'translate' + (this.vertical ? 'Y' : 'X') + '(' + -this.pos * 100 + '%)' }; }, vertical: function vertical() { return ['up', 'down'].indexOf(this.direction) !== -1; } }, watch: { value: function value(_value) { this.index = _value; }, index: function index(value) { this.preventUpdate(); this.clear(); this.$emit('input', value); value + this.loop - this.pos && this.buffer(this.pos, value + this.loop - this.pos, Math.round(Math.min(Math.abs(value + this.loop - this.pos), 1) * this.duration) || 1); }, direction: 'preventUpdate', interval: 'preventUpdate', duration: 'preventUpdate', swipe: 'preventUpdate', threshold: 'preventUpdate', pos: 'preventUpdate', height: 'preventUpdate' }, methods: { preventUpdate: function preventUpdate() { // 组件属性变化时阻止触发updated钩子,确保只有slot内容变化才触发 this.prevent = true; }, update: function update() { var _this = this; // 内容有变化 var first = void 0, last = void 0, max = void 0; // 获取子项最高的高度 this.$children.forEach(function (child, index) { !index && (first = child.$el); index === _this.$children.length - 1 && (last = child.$el);(!index || child.$el.offsetHeight > max) && (max = child.$el.offsetHeight); }); // 给每个子项设置成最高高度 this.$children.forEach(function (child) { child.$el.style.height = max + 'px'; }); // 将第一项复制到最后,将最后一项复制到最前 if (this.first) { this.first.parentElement.removeChild(this.first); this.first = undefined; } if (this.last) { this.last.parentElement.removeChild(this.last); this.last = undefined; } if (this.loop) { this.first = first.cloneNode(true); this.last = last.cloneNode(true); this.$refs.list.insertBefore(this.last, first); this.$refs.list.appendChild(this.first); } // 这里必须要用max记录最大值后赋值,因为只要this.height中途变化了,即使最后的结果没变,也会调用render函数,触发updated钩子。但只要最后的结果没变,watch钩子是不会执行的 this.height = max; this.check(true); }, check: function check(slotChange) { if (slotChange) { // slot内容变化 this.clear(); this.pos = Math.round(this.pos); } // 处理边界情况,slot内容更改后有可能大于 if (this.loop) { if (this.pos >= this.$children.length + 1) { this.pos = 1; } else if (this.pos <= 0) { this.pos = this.$children.length; } } else { if (this.pos >= this.$children.length) { this.pos = this.$children.length - 1; } else if (this.pos < 0) { this.pos = 0; } } // 同步index this.index = this.pos - this.loop; this.$nextTick(function () { // 触发位置变化事件 this.$emit('change', this.index); this.next(); }); }, next: function next() { var _this2 = this; // 下一步 this.interval && (this.intervalId = setTimeout(function () { if (['up', 'left'].indexOf(_this2.direction) !== -1) { _this2.index = _this2.loop ? _this2.index + 1 : (_this2.index + 1) % _this2.$children.length; } else { _this2.index = _this2.loop ? _this2.index - 1 : (_this2.index - 1 + _this2.$children.length) % _this2.$children.length; } }, this.interval)); }, buffer: function buffer(b, c, d) { var _this3 = this; // 缓冲 var t = 0; var fn = function fn() { t++; _this3.pos = Tween.Cubic.easeOut(t, b, c, d); t === d && (_this3.pos = Math.round(_this3.pos)); t < d ? _this3.rafId = raf(fn) : _this3.check(); }; this.rafId = raf(fn); }, clear: function clear() { caf(this.rafId); clearInterval(this.intervalId); }, touchmove: function touchmove(event) { var _this4 = this; if (!this.swipe) { return; } if (this.touchId === undefined) { this.clear(); this.touchId = event.changedTouches[0].identifier; this.prev = this.vertical ? event.changedTouches[0].clientY : event.changedTouches[0].clientX; this.offset = 0; } else { var touch = [].slice.call(event.changedTouches).filter(function (touch) { return touch.identifier === _this4.touchId; })[0]; if (touch) { // 同一个触点移动 var current = this.vertical ? touch.clientY : touch.clientX; this.offset = (this.prev - current) / this.$refs.list[this.vertical ? 'offsetHeight' : 'offsetWidth']; this.pos += this.offset; this.prev = current; } } }, touchend: function touchend(event) { var _this5 = this; if (!this.swipe) { return; } if ([].slice.call(event.changedTouches).some(function (touch) { return touch.identifier === _this5.touchId; })) { // 同一个触点移除了 var offset = this.pos - parseInt(this.pos); var pos = void 0; // 判断是否超过阈值 if (this.offset > 0 && offset >= this.threshold || this.offset <= 0 && offset > 1 - this.threshold) { pos = Math.ceil(this.pos); } else { pos = Math.floor(this.pos); } this.touchId = undefined; pos < 0 && (pos = 0); pos === this.$children.length + (this.loop ? 2 : 0) && pos--; this.buffer(this.pos, pos - this.pos, Math.round(Math.abs(pos - this.pos) * this.duration) || 1); } } }, mounted: function mounted() { this.$nextTick(this.update); }, updated: function updated() { this.$nextTick(function () { if (!this.prevent) { // slot内容更新 this.update(); } else { this.prevent = false; } }); }, beforeDestroy: function beforeDestroy() { this.clear(); } }; export default index;