vivo-ui
Version:
vivo ui component lib for vue
224 lines (209 loc) • 8.65 kB
JavaScript
(function () {
if (typeof document !== 'undefined') {
var head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style'),
css = " .vui-swipeout { width: 100%; overflow: hidden; position: relative; } .vui-swipeout-button-grounp { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #eee; } .vui-swipeout-button-grounp > div { display: -webkit-flex; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: flex; -webkit-align-items: stretch; -webkit-box-align: stretch; -moz-box-align: stretch; -ms-flex-align: stretch; align-items: stretch; height: 100%; } .vui-swipeout-button-left > div { -webkit-box-pack: start; -moz-box-pack: start; -ms-flex-pack: start; justify-content: flex-start; -webkit-justify-content: flex-start; } .vui-swipeout-button-right > div { -webkit-box-pack: end; -moz-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; -webkit-justify-content: flex-end; } .vui-swipeout-content { position: relative; background: #fff; } .vui-swipeout-content-animated { -webkit-transition: -webkit-transform 0.2s; transition: -webkit-transform 0.2s; -o-transition: -o-transform 0.2s; -moz-transition: transform 0.2s, -moz-transform 0.2s; transition: transform 0.2s; transition: transform 0.2s, -webkit-transform 0.2s, -moz-transform 0.2s, -o-transform 0.2s; transition: transform 0.2s, -webkit-transform 0.2s; } ";style.type = 'text/css';if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}head.appendChild(style);
}
})();
var swipeout = { render: function render() {
var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('div', { class: _vm.prefixCls, on: { "touchstart": _vm.onPanStart, "mousedown": _vm.onPanStart, "touchmove": _vm.onPanMove, "mousemove": _vm.onPanMove, "touchend": _vm.onPanEnd, "mouseup": _vm.onPanEnd, "touchcancel": _vm.onPanEnd } }, [_c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.distX >= 0, expression: "distX >= 0" }], class: [_vm.prefixCls + '-button-grounp', _vm.prefixCls + '-button-left'] }, [_vm._t("left-button")], 2), _vm._v(" "), _c('div', { directives: [{ name: "show", rawName: "v-show", value: _vm.distX <= 0, expression: "distX <= 0" }], class: [_vm.prefixCls + '-button-grounp', _vm.prefixCls + '-button-right'] }, [_vm._t("right-button")], 2), _vm._v(" "), _c('div', { ref: "content", class: _vm.prefixCls + '-content', style: _vm.styles, on: { "mousedown": _vm.onContentClick, "touchstart": _vm.onContentClick } }, [_vm._t("default")], 2)]);
}, staticRenderFns: [],
name: 'swipeout',
props: {
disabled: Boolean,
prefixCls: {
type: String,
default: 'vui-swipeout'
},
threshold: {
type: Number,
default: 0.3
}
},
data: function data() {
return {
pageX: undefined, // 记录start开始时到x位置
pageY: undefined, // 记录start开始时到y位置
distX: 0, // 拖动到x距离
distY: 0, // 拖动到x距离
styles: {
transform: 'translate3d(0px, 0, 0)'
},
opened: false, // swipe打开状态
initDirection: '', // 初始化swipe方向
leftWidth: 0,
rightWidth: 0,
needShowLeft: false,
needShowRight: false,
isScrolling: undefined // 判断滑动的轴(x || y)
};
},
watch: {
disabled: function disabled(newVal, oldVal) {
if (newVal === true && !oldVal) {
this.close();
}
}
},
computed: {
buttonWidth: function buttonWidth() {
if (this.leftWidth <= 0 && this.rightWidth > 0) {
return this.rightWidth;
}
if (this.leftWidth > 0 && this.rightWidth <= 0) {
return this.leftWidth;
}
if (this.leftWidth > 0 && this.rightWidth > 0) {
return this.distX < 0 ? this.rightWidth : this.leftWidth;
}
}
},
mounted: function mounted() {
var _this = this;
this.$nextTick(function () {
if (_this.$slots['left-button']) {
_this.needShowLeft = true;
_this.caculateButtonWidth('left');
}
if (_this.$slots['right-button']) {
_this.needShowRight = true;
_this.caculateButtonWidth('right');
}
});
},
methods: {
// 计算两侧按钮的总宽度
caculateButtonWidth: function caculateButtonWidth(direction) {
var list = this.$slots[direction + '-button'][0].children.filter(function (node) {
return node.tag;
});
var width = 0;
list.forEach(function (node) {
return width += node.elm.clientWidth;
});
this[direction + 'Width'] = width;
},
// 点击内容区域关闭
onContentClick: function onContentClick() {
if (this.styles.transform.indexOf('(0px, 0, 0)') === -1) this.close();
},
// 点击按钮
onButtonClick: function onButtonClick() {
this.close();
},
onPanStart: function onPanStart(e) {
if (this.disabled || this.opened) {
return;
}
// 关闭已经打开的swipe
var openedSwipe = this.$parent.$children.filter(function (item) {
return item.$options._componentTag === 'swipeout' && item.$data.styles.transform.indexOf('(0px, 0, 0)') === -1;
});
if (openedSwipe.length > 0) {
openedSwipe.forEach(function (item) {
item.close();
item._setStyle(true);
});
e.preventDefault();
return;
}
var touch = e.touches ? e.touches[0] : e;
this.pageX = touch.pageX;
this.pageY = touch.pageY;
},
onPanMove: function onPanMove(e) {
if (this.disabled) {
return;
}
if (this.pageX === undefined) {
e.preventDefault();
return;
}
var touch = e.touches ? e.touches[0] : e;
this.distX = touch.pageX - this.pageX;
this.distY = touch.pageY - this.pageY;
// 如果移动的x大于y说明是横向的,否则return
if (typeof this.isScrolling === 'undefined') {
this.isScrolling = !!(this.isScrolling || Math.abs(this.distY) > Math.abs(this.distX));
}
if (this.isScrolling) {
return;
}
// 设置初始方向值
if (!this.initDirection) {
this.initDirection = this.distX > 0 ? 'toRight' : 'toLeft';
}
if (this.distX > 0 && this.needShowLeft || this.distX < 0 && this.needShowRight) {
this._setStyle();
if (Math.abs(this.distX) <= this.buttonWidth) {
this._setOffset(this.distX);
} else {
var extra = (Math.abs(this.distX) - this.buttonWidth) * 0.5;
var offset = (this.buttonWidth + extra) * (this.distX < 0 ? -1 : 1);
this._setOffset(offset);
}
}
e.preventDefault();
},
onPanEnd: function onPanEnd() {
if (this.disabled || this.isScrolling) {
return;
}
if (this.initDirection === 'toRight' && this.distX > 0) {
if (this.distX > this.threshold * this.leftWidth) {
this._setOffset(this.leftWidth);
this.$emit('on-open');
this.opened = true;
} else {
this.close();
}
} else if (this.initDirection === 'toLeft' && this.distX < 0) {
if (Math.abs(this.distX) > this.threshold * this.rightWidth) {
this._setOffset(-this.rightWidth);
this.$emit('on-open');
this.opened = true;
} else {
this.close();
}
}
this._setStyle(true);
this.pageX = this.pageY = undefined;
this.initDirection = '';
this.isScrolling = undefined;
},
open: function open(position) {
this.distX = position === 'right' ? -this.rightWidth : this.leftWidth;
this._setOffset(this.distX);
this.opened = true;
this._setStyle(true);
},
close: function close() {
var _this2 = this;
this._setOffset(0);
this.$emit('on-close');
setTimeout(function () {
_this2.opened = false;
}, 100);
this.distX = 0;
},
_setStyle: function _setStyle(animated) {
if (animated) {
this.$refs.content.classList.add('vui-swipeout-content-animated');
} else {
this.$refs.content.classList.remove('vui-swipeout-content-animated');
}
},
_setOffset: function _setOffset(x) {
// 临界以后
if (this.initDirection === 'toRight' && x < 0 || this.initDirection === 'toLeft' && x > 0) {
x = 0;
}
this.styles.transform = 'translate3d(' + x + 'px, 0, 0)';
}
}
};
export default swipeout;