var Util = require('../../util'); var G = require('../../renderer'); var Group = G.Group; var DomUtil = Util.DomUtil; var OFFSET = 5; var Range = function Range(cfg) { Range.superclass.constructor.call(this, cfg); }; Util.extend(Range, Group); Util.augment(Range, { getDefaultCfg: function getDefaultCfg() { return { /** * 范围 * @type {Array} */ range: null, /** * 中滑块属性 * @type {ATTRS} */ middleAttr: null, /** * 背景 * @type {G-Element} */ backgroundElement: null, /** * 下滑块 * @type {G-Element} */ minHandleElement: null, /** * 上滑块 * @type {G-Element} */ maxHandleElement: null, /** * 中块 * @type {G-Element} */ middleHandleElement: null, /** * 当前的激活的元素 * @type {G-Element} */ currentTarget: null, /** * 布局方式: horizontal,vertical * @type {String} */ layout: 'vertical', /** * 宽 * @type {Number} */ width: null, /** * 高 * @type {Number} */ height: null, /** * 当前的PageX * @type {Number} */ pageX: null, /** * 当前的PageY * @type {Number} */ pageY: null }; }, _initHandle: function _initHandle(type) { var self = this; var handle = self.addGroup(); var layout = self.get('layout'); var handleStyle = self.get('handleStyle'); var img = handleStyle.img; var iconWidth = handleStyle.width; var iconHeight = handleStyle.height; var text; var handleIcon; var triggerCursor; if (layout === 'horizontal') { var _iconWidth = handleStyle.width; triggerCursor = 'ew-resize'; handleIcon = handle.addShape('Image', { attrs: { x: -_iconWidth / 2, y: 0, width: _iconWidth, height: iconHeight, img: img, cursor: triggerCursor } }); text = handle.addShape('Text', { attrs: Util.mix({ x: type === 'min' ? -(_iconWidth / 2 + OFFSET) : _iconWidth / 2 + OFFSET, y: iconHeight / 2, textAlign: type === 'min' ? 'end' : 'start', textBaseline: 'middle', text: type === 'min' ? this.get('minText') : this.get('maxText'), cursor: triggerCursor }, this.get('textStyle')) }); } else { triggerCursor = 'ns-resize'; handleIcon = handle.addShape('Image', { attrs: { x: 0, y: -iconHeight / 2, width: iconWidth, height: iconHeight, img: img, cursor: triggerCursor } }); text = handle.addShape('Text', { attrs: Util.mix({ x: iconWidth / 2, y: type === 'min' ? iconHeight / 2 + OFFSET : -(iconHeight / 2 + OFFSET), textAlign: 'center', textBaseline: 'middle', text: type === 'min' ? this.get('minText') : this.get('maxText'), cursor: triggerCursor }, this.get('textStyle')) }); } this.set(type + 'TextElement', text); this.set(type + 'IconElement', handleIcon); return handle; }, _initSliderBackground: function _initSliderBackground() { var backgroundElement = this.addGroup(); backgroundElement.initTransform(); backgroundElement.translate(0, 0); backgroundElement.addShape('Rect', { attrs: Util.mix({ x: 0, y: 0, width: this.get('width'), height: this.get('height') }, this.get('backgroundStyle')) }); return backgroundElement; }, _beforeRenderUI: function _beforeRenderUI() { var backgroundElement = this._initSliderBackground(); var minHandleElement = this._initHandle('min'); var maxHandleElement = this._initHandle('max'); var middleHandleElement = this.addShape('rect', { attrs: this.get('middleAttr') }); this.set('middleHandleElement', middleHandleElement); this.set('minHandleElement', minHandleElement); this.set('maxHandleElement', maxHandleElement); this.set('backgroundElement', backgroundElement); backgroundElement.set('zIndex', 0); middleHandleElement.set('zIndex', 1); minHandleElement.set('zIndex', 2); maxHandleElement.set('zIndex', 2); middleHandleElement.attr('cursor', 'move'); this.sort(); }, _renderUI: function _renderUI() { if (this.get('layout') === 'horizontal') { this._renderHorizontal(); } else { this._renderVertical(); } }, _transform: function _transform(layout) { var range = this.get('range'); var minRatio = range[0] / 100; var maxRatio = range[1] / 100; var width = this.get('width'); var height = this.get('height'); var minHandleElement = this.get('minHandleElement'); var maxHandleElement = this.get('maxHandleElement'); var middleHandleElement = this.get('middleHandleElement'); if (minHandleElement.resetMatrix) { minHandleElement.resetMatrix(); maxHandleElement.resetMatrix(); } else { minHandleElement.initTransform(); maxHandleElement.initTransform(); } if (layout === 'horizontal') { middleHandleElement.attr({ x: width * minRatio, y: 0, width: (maxRatio - minRatio) * width, height: height }); minHandleElement.translate(minRatio * width, 0); maxHandleElement.translate(maxRatio * width, 0); } else { middleHandleElement.attr({ x: 0, y: height * (1 - maxRatio), width: width, height: (maxRatio - minRatio) * height }); minHandleElement.translate(0, (1 - minRatio) * height); maxHandleElement.translate(0, (1 - maxRatio) * height); } }, _renderHorizontal: function _renderHorizontal() { this._transform('horizontal'); }, _renderVertical: function _renderVertical() { this._transform('vertical'); }, _bindUI: function _bindUI() { this.on('mousedown', Util.wrapBehavior(this, '_onMouseDown')); }, _isElement: function _isElement(target, name) { // 判断是否是该元素 var element = this.get(name); if (target === element) { return true; } if (element.isGroup) { var elementChildren = element.get('children'); return elementChildren.indexOf(target) > -1; } return false; }, _getRange: function _getRange(diff, range) { var rst = diff + range; rst = rst > 100 ? 100 : rst; rst = rst < 0 ? 0 : rst; return rst; }, _limitRange: function _limitRange(diff, limit, range) { range[0] = this._getRange(diff, range[0]); range[1] = range[0] + limit; if (range[1] > 100) { range[1] = 100; range[0] = range[1] - limit; } }, _updateStatus: function _updateStatus(dim, ev) { var totalLength = dim === 'x' ? this.get('width') : this.get('height'); dim = Util.upperFirst(dim); var range = this.get('range'); var page = this.get('page' + dim); var currentTarget = this.get('currentTarget'); var rangeStash = this.get('rangeStash'); var layout = this.get('layout'); var sign = layout === 'vertical' ? -1 : 1; var currentPage = ev['page' + dim]; var diffPage = currentPage - page; var diffRange = diffPage / totalLength * 100 * sign; var diffStashRange; var minRange = this.get('minRange'); var maxRange = this.get('maxRange'); if (range[1] <= range[0]) { if (this._isElement(currentTarget, 'minHandleElement') || this._isElement(currentTarget, 'maxHandleElement')) { range[0] = this._getRange(diffRange, range[0]); range[1] = this._getRange(diffRange, range[0]); } } else { if (this._isElement(currentTarget, 'minHandleElement')) { range[0] = this._getRange(diffRange, range[0]); if (minRange) { // 设置了最小范围 if (range[1] - range[0] <= minRange) { this._limitRange(diffRange, minRange, range); } } if (maxRange) { // 设置了最大范围 if (range[1] - range[0] >= maxRange) { this._limitRange(diffRange, maxRange, range); } } } if (this._isElement(currentTarget, 'maxHandleElement')) { range[1] = this._getRange(diffRange, range[1]); if (minRange) { // 设置了最小范围 if (range[1] - range[0] <= minRange) { this._limitRange(diffRange, minRange, range); } } if (maxRange) { // 设置了最大范围 if (range[1] - range[0] >= maxRange) { this._limitRange(diffRange, maxRange, range); } } } } if (this._isElement(currentTarget, 'middleHandleElement')) { diffStashRange = rangeStash[1] - rangeStash[0]; this._limitRange(diffRange, diffStashRange, range); } this.emit('sliderchange', { range: range }); this.set('page' + dim, currentPage); this._renderUI(); this.get('canvas').draw(); // need delete return; }, _onMouseDown: function _onMouseDown(ev) { var currentTarget = ev.currentTarget; var originEvent = ev.event; var range = this.get('range'); originEvent.stopPropagation(); originEvent.preventDefault(); this.set('pageX', originEvent.pageX); this.set('pageY', originEvent.pageY); this.set('currentTarget', currentTarget); this.set('rangeStash', [range[0], range[1]]); this._bindCanvasEvents(); }, _bindCanvasEvents: function _bindCanvasEvents() { var containerDOM = this.get('canvas').get('containerDOM'); this.onMouseMoveListener = DomUtil.addEventListener(containerDOM, 'mousemove', Util.wrapBehavior(this, '_onCanvasMouseMove')); this.onMouseUpListener = DomUtil.addEventListener(containerDOM, 'mouseup', Util.wrapBehavior(this, '_onCanvasMouseUp')); // @2018-06-06 by blue.lb 添加mouseleave事件监听,让用户在操作出滑块区域后有一个“正常”的效果,可以正常重新触发滑块的操作流程 this.onMouseLeaveListener = DomUtil.addEventListener(containerDOM, 'mouseleave', Util.wrapBehavior(this, '_onCanvasMouseUp')); }, _onCanvasMouseMove: function _onCanvasMouseMove(ev) { var layout = this.get('layout'); if (layout === 'horizontal') { this._updateStatus('x', ev); } else { this._updateStatus('y', ev); } }, _onCanvasMouseUp: function _onCanvasMouseUp() { this._removeDocumentEvents(); }, _removeDocumentEvents: function _removeDocumentEvents() { this.onMouseMoveListener.remove(); this.onMouseUpListener.remove(); this.onMouseLeaveListener.remove(); } }); module.exports = Range;