309 lines
8.8 KiB
Java
309 lines
8.8 KiB
Java
/**
|
||
* @fileOverview The class of slider
|
||
* @author sima.zhang
|
||
*/
|
||
var Util = require('../util');
|
||
|
||
var DomUtil = Util.DomUtil;
|
||
var Group = Util.Group;
|
||
|
||
var Slider = function Slider(cfg) {
|
||
Slider.superclass.constructor.call(this, cfg);
|
||
};
|
||
|
||
Util.extend(Slider, Group);
|
||
Util.augment(Slider, {
|
||
getDefaultCfg: function getDefaultCfg() {
|
||
return {
|
||
/**
|
||
* 范围
|
||
* @type {Array}
|
||
*/
|
||
range: null,
|
||
|
||
/**
|
||
* 中滑块属性
|
||
* 透明的,用于用户交互
|
||
* @type {ATTRS}
|
||
*/
|
||
middleAttr: {
|
||
fill: '#fff',
|
||
fillOpacity: 0
|
||
},
|
||
|
||
/**
|
||
* 背景
|
||
* @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
|
||
};
|
||
},
|
||
// arrange the zindex and cursors of each element
|
||
_beforeRenderUI: function _beforeRenderUI() {
|
||
var layout = this.get('layout');
|
||
var backgroundElement = this.get('backgroundElement');
|
||
var minHandleElement = this.get('minHandleElement');
|
||
var maxHandleElement = this.get('maxHandleElement');
|
||
var middleHandleElement = this.addShape('rect', {
|
||
attrs: this.get('middleAttr')
|
||
});
|
||
var trigerCursor = layout === 'vertical' ? 'ns-resize' : 'ew-resize';
|
||
this.add([backgroundElement, minHandleElement, maxHandleElement]);
|
||
this.set('middleHandleElement', middleHandleElement);
|
||
backgroundElement.set('zIndex', 0);
|
||
middleHandleElement.set('zIndex', 1);
|
||
minHandleElement.set('zIndex', 2);
|
||
maxHandleElement.set('zIndex', 2);
|
||
middleHandleElement.attr('cursor', 'move');
|
||
minHandleElement.attr('cursor', trigerCursor);
|
||
maxHandleElement.attr('cursor', trigerCursor);
|
||
this.sort();
|
||
},
|
||
// rendering
|
||
_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');
|
||
minHandleElement.resetMatrix();
|
||
maxHandleElement.resetMatrix();
|
||
|
||
if (layout === 'horizontal') {
|
||
middleHandleElement.attr({
|
||
x: width * minRatio,
|
||
y: 0,
|
||
width: (maxRatio - minRatio) * width,
|
||
height: height
|
||
});
|
||
minHandleElement.translate(minRatio * width, height);
|
||
maxHandleElement.translate(maxRatio * width, height);
|
||
} else {
|
||
middleHandleElement.attr({
|
||
x: 0,
|
||
y: height * (1 - maxRatio),
|
||
width: width,
|
||
height: (maxRatio - minRatio) * height
|
||
});
|
||
minHandleElement.translate(1, (1 - minRatio) * height);
|
||
maxHandleElement.translate(1, (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'));
|
||
},
|
||
// if the target matches name
|
||
_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;
|
||
},
|
||
// get the result range after adding diff to range
|
||
// insure that the result out of the interval [0, 100]
|
||
_getRange: function _getRange(diff, range) {
|
||
var rst = diff + range;
|
||
rst = rst > 100 ? 100 : rst;
|
||
rst = rst < 0 ? 0 : rst;
|
||
return rst;
|
||
},
|
||
_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]; // the distance of the mouse dragging
|
||
|
||
var diffPage = currentPage - page;
|
||
var diffRange = diffPage / totalLength * 100 * sign;
|
||
var diffStashRange; // the min and max trigger overlap, range[0] and range[1] change together
|
||
|
||
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 {
|
||
// user drags the min trigger
|
||
if (this._isElement(currentTarget, 'minHandleElement')) {
|
||
range[0] = this._getRange(diffRange, range[0]);
|
||
} // user drags the max trigger
|
||
|
||
|
||
if (this._isElement(currentTarget, 'maxHandleElement')) {
|
||
range[1] = this._getRange(diffRange, range[1]);
|
||
}
|
||
} // the user drags the middle bar
|
||
|
||
|
||
if (this._isElement(currentTarget, 'middleHandleElement')) {
|
||
// the diffrence between min and max trigger while mouse down
|
||
diffStashRange = rangeStash[1] - rangeStash[0];
|
||
range[0] = this._getRange(diffRange, range[0]); // keep the diffStashRange
|
||
|
||
range[1] = range[0] + diffStashRange;
|
||
|
||
if (range[1] > 100) {
|
||
range[1] = 100;
|
||
range[0] = range[1] - diffStashRange;
|
||
}
|
||
}
|
||
|
||
this.emit('sliderchange', {
|
||
range: range
|
||
});
|
||
this.set('page' + dim, currentPage);
|
||
|
||
this._renderUI();
|
||
|
||
this.get('canvas').draw(); // need delete
|
||
|
||
return;
|
||
},
|
||
// the listener of mouse down
|
||
_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); // stash the range
|
||
|
||
this.set('rangeStash', [range[0], range[1]]);
|
||
|
||
this._bindCanvasEvents();
|
||
},
|
||
_bindCanvasEvents: function _bindCanvasEvents() {
|
||
var containerDOM = this.get('canvas').get('containerDOM'); // this.on('mousemove', Util.wrapBehavior(this, '_onCanvasMouseMove'));
|
||
|
||
this.onMouseMoveListener = DomUtil.addEventListener(containerDOM, 'mousemove', Util.wrapBehavior(this, '_onCanvasMouseMove'));
|
||
this.onMouseUpListener = DomUtil.addEventListener(containerDOM, 'mouseup', Util.wrapBehavior(this, '_onCanvasMouseUp'));
|
||
this.onMouseLeaveListener = DomUtil.addEventListener(containerDOM, 'mouseleave', Util.wrapBehavior(this, '_onCanvasMouseUp'));
|
||
},
|
||
// listener of mouse click and move = drag
|
||
_onCanvasMouseMove: function _onCanvasMouseMove(ev) {
|
||
if (!this._mouseOutArea(ev)) {
|
||
var layout = this.get('layout');
|
||
|
||
if (layout === 'horizontal') {
|
||
this._updateStatus('x', ev);
|
||
} else {
|
||
this._updateStatus('y', ev);
|
||
}
|
||
}
|
||
},
|
||
// listener of mouse up
|
||
_onCanvasMouseUp: function _onCanvasMouseUp() {
|
||
this._removeDocumentEvents();
|
||
},
|
||
// remove listeners
|
||
_removeDocumentEvents: function _removeDocumentEvents() {
|
||
this.onMouseMoveListener.remove();
|
||
this.onMouseUpListener.remove();
|
||
},
|
||
// if the mouse is out of the area
|
||
_mouseOutArea: function _mouseOutArea(ev) {
|
||
var el = this.get('canvas').get('el');
|
||
var el_bbox = el.getBoundingClientRect();
|
||
var parent = this.get('parent');
|
||
var bbox = parent.getBBox();
|
||
var left = parent.attr('matrix')[6];
|
||
var top = parent.attr('matrix')[7];
|
||
var right = left + bbox.width;
|
||
var bottom = top + bbox.height;
|
||
var mouseX = ev.clientX - el_bbox.x;
|
||
var mouseY = ev.clientY - el_bbox.y;
|
||
|
||
if (mouseX < left || mouseX > right || mouseY < top || mouseY > bottom) {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
});
|
||
module.exports = Slider; |