123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- import { createNamespace, addUnit } from '../utils';
- import { deepClone } from '../utils/deep-clone';
- import { preventDefault } from '../utils/dom/event';
- import { range, addNumber } from '../utils/format/number';
- import { TouchMixin } from '../mixins/touch';
- import { FieldMixin } from '../mixins/field';
- var _createNamespace = createNamespace('slider'),
- createComponent = _createNamespace[0],
- bem = _createNamespace[1];
- var isSameValue = function isSameValue(newValue, oldValue) {
- return JSON.stringify(newValue) === JSON.stringify(oldValue);
- };
- export default createComponent({
- mixins: [TouchMixin, FieldMixin],
- props: {
- disabled: Boolean,
- vertical: Boolean,
- range: Boolean,
- barHeight: [Number, String],
- buttonSize: [Number, String],
- activeColor: String,
- inactiveColor: String,
- min: {
- type: [Number, String],
- default: 0
- },
- max: {
- type: [Number, String],
- default: 100
- },
- step: {
- type: [Number, String],
- default: 1
- },
- value: {
- type: [Number, Array],
- default: 0
- }
- },
- data: function data() {
- return {
- dragStatus: ''
- };
- },
- computed: {
- scope: function scope() {
- return this.max - this.min;
- },
- buttonStyle: function buttonStyle() {
- if (this.buttonSize) {
- var size = addUnit(this.buttonSize);
- return {
- width: size,
- height: size
- };
- }
- }
- },
- created: function created() {
- // format initial value
- this.updateValue(this.value);
- },
- mounted: function mounted() {
- if (this.range) {
- this.bindTouchEvent(this.$refs.wrapper0);
- this.bindTouchEvent(this.$refs.wrapper1);
- } else {
- this.bindTouchEvent(this.$refs.wrapper);
- }
- },
- methods: {
- onTouchStart: function onTouchStart(event) {
- if (this.disabled) {
- return;
- }
- this.touchStart(event);
- this.currentValue = this.value;
- if (this.range) {
- this.startValue = this.value.map(this.format);
- } else {
- this.startValue = this.format(this.value);
- }
- this.dragStatus = 'start';
- },
- onTouchMove: function onTouchMove(event) {
- if (this.disabled) {
- return;
- }
- if (this.dragStatus === 'start') {
- this.$emit('drag-start');
- }
- preventDefault(event, true);
- this.touchMove(event);
- this.dragStatus = 'draging';
- var rect = this.$el.getBoundingClientRect();
- var delta = this.vertical ? this.deltaY : this.deltaX;
- var total = this.vertical ? rect.height : rect.width;
- var diff = delta / total * this.scope;
- if (this.range) {
- this.currentValue[this.index] = this.startValue[this.index] + diff;
- } else {
- this.currentValue = this.startValue + diff;
- }
- this.updateValue(this.currentValue);
- },
- onTouchEnd: function onTouchEnd() {
- if (this.disabled) {
- return;
- }
- if (this.dragStatus === 'draging') {
- this.updateValue(this.currentValue, true);
- this.$emit('drag-end');
- }
- this.dragStatus = '';
- },
- onClick: function onClick(event) {
- event.stopPropagation();
- if (this.disabled) return;
- var rect = this.$el.getBoundingClientRect();
- var delta = this.vertical ? event.clientY - rect.top : event.clientX - rect.left;
- var total = this.vertical ? rect.height : rect.width;
- var value = +this.min + delta / total * this.scope;
- if (this.range) {
- var _this$value = this.value,
- left = _this$value[0],
- right = _this$value[1];
- var middle = (left + right) / 2;
- if (value <= middle) {
- left = value;
- } else {
- right = value;
- }
- value = [left, right];
- }
- this.startValue = this.value;
- this.updateValue(value, true);
- },
- // 处理两个滑块重叠之后的情况
- handleOverlap: function handleOverlap(value) {
- if (value[0] > value[1]) {
- value = deepClone(value);
- return value.reverse();
- }
- return value;
- },
- updateValue: function updateValue(value, end) {
- if (this.range) {
- value = this.handleOverlap(value).map(this.format);
- } else {
- value = this.format(value);
- }
- if (!isSameValue(value, this.value)) {
- this.$emit('input', value);
- }
- if (end && !isSameValue(value, this.startValue)) {
- this.$emit('change', value);
- }
- },
- format: function format(value) {
- var min = +this.min;
- var max = +this.max;
- var step = +this.step;
- value = range(value, min, max);
- var diff = Math.round((value - min) / step) * step;
- return addNumber(min, diff);
- }
- },
- render: function render() {
- var _wrapperStyle,
- _this = this,
- _barStyle;
- var h = arguments[0];
- var vertical = this.vertical;
- var mainAxis = vertical ? 'height' : 'width';
- var crossAxis = vertical ? 'width' : 'height';
- var wrapperStyle = (_wrapperStyle = {
- background: this.inactiveColor
- }, _wrapperStyle[crossAxis] = addUnit(this.barHeight), _wrapperStyle); // 计算选中条的长度百分比
- var calcMainAxis = function calcMainAxis() {
- var value = _this.value,
- min = _this.min,
- range = _this.range,
- scope = _this.scope;
- if (range) {
- return (value[1] - value[0]) * 100 / scope + "%";
- }
- return (value - min) * 100 / scope + "%";
- }; // 计算选中条的开始位置的偏移量
- var calcOffset = function calcOffset() {
- var value = _this.value,
- min = _this.min,
- range = _this.range,
- scope = _this.scope;
- if (range) {
- return (value[0] - min) * 100 / scope + "%";
- }
- return null;
- };
- var barStyle = (_barStyle = {}, _barStyle[mainAxis] = calcMainAxis(), _barStyle.left = this.vertical ? null : calcOffset(), _barStyle.top = this.vertical ? calcOffset() : null, _barStyle.background = this.activeColor, _barStyle);
- if (this.dragStatus) {
- barStyle.transition = 'none';
- }
- var renderButton = function renderButton(i) {
- var map = ['left', 'right'];
- var isNumber = typeof i === 'number';
- var current = isNumber ? _this.value[i] : _this.value;
- var getClassName = function getClassName() {
- if (isNumber) {
- return "button-wrapper-" + map[i];
- }
- return "button-wrapper";
- };
- var getRefName = function getRefName() {
- if (isNumber) {
- return "wrapper" + i;
- }
- return "wrapper";
- };
- var renderButtonContent = function renderButtonContent() {
- if (isNumber) {
- var slot = _this.slots(i === 0 ? 'left-button' : 'right-button', {
- value: current
- });
- if (slot) {
- return slot;
- }
- }
- if (_this.slots('button')) {
- return _this.slots('button');
- }
- return h("div", {
- "class": bem('button'),
- "style": _this.buttonStyle
- });
- };
- return h("div", {
- "ref": getRefName(),
- "attrs": {
- "role": "slider",
- "tabindex": _this.disabled ? -1 : 0,
- "aria-valuemin": _this.min,
- "aria-valuenow": _this.value,
- "aria-valuemax": _this.max,
- "aria-orientation": _this.vertical ? 'vertical' : 'horizontal'
- },
- "class": bem(getClassName()),
- "on": {
- "touchstart": function touchstart() {
- if (isNumber) {
- // 保存当前按钮的索引
- _this.index = i;
- }
- },
- "click": function click(e) {
- return e.stopPropagation();
- }
- }
- }, [renderButtonContent()]);
- };
- return h("div", {
- "style": wrapperStyle,
- "class": bem({
- disabled: this.disabled,
- vertical: vertical
- }),
- "on": {
- "click": this.onClick
- }
- }, [h("div", {
- "class": bem('bar'),
- "style": barStyle
- }, [this.range ? [renderButton(0), renderButton(1)] : renderButton()])]);
- }
- });
|