| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| import * as zrUtil from 'zrender/src/core/util'; |
| import LinearGradient from 'zrender/src/graphic/LinearGradient'; |
| import * as eventTool from 'zrender/src/core/event'; |
| import VisualMapView from './VisualMapView'; |
| import * as graphic from '../../util/graphic'; |
| import * as numberUtil from '../../util/number'; |
| import sliderMove from '../helper/sliderMove'; |
| import * as helper from './helper'; |
| import * as modelUtil from '../../util/model'; |
| var linearMap = numberUtil.linearMap; |
| var each = zrUtil.each; |
| var mathMin = Math.min; |
| var mathMax = Math.max; // Arbitrary value |
| |
| var HOVER_LINK_SIZE = 12; |
| var HOVER_LINK_OUT = 6; // Notice: |
| // Any "interval" should be by the order of [low, high]. |
| // "handle0" (handleIndex === 0) maps to |
| // low data value: this._dataInterval[0] and has low coord. |
| // "handle1" (handleIndex === 1) maps to |
| // high data value: this._dataInterval[1] and has high coord. |
| // The logic of transform is implemented in this._createBarGroup. |
| |
| var ContinuousView = VisualMapView.extend({ |
| type: 'visualMap.continuous', |
| |
| /** |
| * @override |
| */ |
| init: function () { |
| ContinuousView.superApply(this, 'init', arguments); |
| /** |
| * @private |
| */ |
| |
| this._shapes = {}; |
| /** |
| * @private |
| */ |
| |
| this._dataInterval = []; |
| /** |
| * @private |
| */ |
| |
| this._handleEnds = []; |
| /** |
| * @private |
| */ |
| |
| this._orient; |
| /** |
| * @private |
| */ |
| |
| this._useHandle; |
| /** |
| * @private |
| */ |
| |
| this._hoverLinkDataIndices = []; |
| /** |
| * @private |
| */ |
| |
| this._dragging; |
| /** |
| * @private |
| */ |
| |
| this._hovering; |
| }, |
| |
| /** |
| * @protected |
| * @override |
| */ |
| doRender: function (visualMapModel, ecModel, api, payload) { |
| if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) { |
| this._buildView(); |
| } |
| }, |
| |
| /** |
| * @private |
| */ |
| _buildView: function () { |
| this.group.removeAll(); |
| var visualMapModel = this.visualMapModel; |
| var thisGroup = this.group; |
| this._orient = visualMapModel.get('orient'); |
| this._useHandle = visualMapModel.get('calculable'); |
| |
| this._resetInterval(); |
| |
| this._renderBar(thisGroup); |
| |
| var dataRangeText = visualMapModel.get('text'); |
| |
| this._renderEndsText(thisGroup, dataRangeText, 0); |
| |
| this._renderEndsText(thisGroup, dataRangeText, 1); // Do this for background size calculation. |
| |
| |
| this._updateView(true); // After updating view, inner shapes is built completely, |
| // and then background can be rendered. |
| |
| |
| this.renderBackground(thisGroup); // Real update view |
| |
| this._updateView(); |
| |
| this._enableHoverLinkToSeries(); |
| |
| this._enableHoverLinkFromSeries(); |
| |
| this.positionGroup(thisGroup); |
| }, |
| |
| /** |
| * @private |
| */ |
| _renderEndsText: function (group, dataRangeText, endsIndex) { |
| if (!dataRangeText) { |
| return; |
| } // Compatible with ec2, text[0] map to high value, text[1] map low value. |
| |
| |
| var text = dataRangeText[1 - endsIndex]; |
| text = text != null ? text + '' : ''; |
| var visualMapModel = this.visualMapModel; |
| var textGap = visualMapModel.get('textGap'); |
| var itemSize = visualMapModel.itemSize; |
| var barGroup = this._shapes.barGroup; |
| |
| var position = this._applyTransform([itemSize[0] / 2, endsIndex === 0 ? -textGap : itemSize[1] + textGap], barGroup); |
| |
| var align = this._applyTransform(endsIndex === 0 ? 'bottom' : 'top', barGroup); |
| |
| var orient = this._orient; |
| var textStyleModel = this.visualMapModel.textStyleModel; |
| this.group.add(new graphic.Text({ |
| style: { |
| x: position[0], |
| y: position[1], |
| textVerticalAlign: orient === 'horizontal' ? 'middle' : align, |
| textAlign: orient === 'horizontal' ? align : 'center', |
| text: text, |
| textFont: textStyleModel.getFont(), |
| textFill: textStyleModel.getTextColor() |
| } |
| })); |
| }, |
| |
| /** |
| * @private |
| */ |
| _renderBar: function (targetGroup) { |
| var visualMapModel = this.visualMapModel; |
| var shapes = this._shapes; |
| var itemSize = visualMapModel.itemSize; |
| var orient = this._orient; |
| var useHandle = this._useHandle; |
| var itemAlign = helper.getItemAlign(visualMapModel, this.api, itemSize); |
| |
| var barGroup = shapes.barGroup = this._createBarGroup(itemAlign); // Bar |
| |
| |
| barGroup.add(shapes.outOfRange = createPolygon()); |
| barGroup.add(shapes.inRange = createPolygon(null, useHandle ? getCursor(this._orient) : null, zrUtil.bind(this._dragHandle, this, 'all', false), zrUtil.bind(this._dragHandle, this, 'all', true))); |
| var textRect = visualMapModel.textStyleModel.getTextRect('国'); |
| var textSize = mathMax(textRect.width, textRect.height); // Handle |
| |
| if (useHandle) { |
| shapes.handleThumbs = []; |
| shapes.handleLabels = []; |
| shapes.handleLabelPoints = []; |
| |
| this._createHandle(barGroup, 0, itemSize, textSize, orient, itemAlign); |
| |
| this._createHandle(barGroup, 1, itemSize, textSize, orient, itemAlign); |
| } |
| |
| this._createIndicator(barGroup, itemSize, textSize, orient); |
| |
| targetGroup.add(barGroup); |
| }, |
| |
| /** |
| * @private |
| */ |
| _createHandle: function (barGroup, handleIndex, itemSize, textSize, orient) { |
| var onDrift = zrUtil.bind(this._dragHandle, this, handleIndex, false); |
| var onDragEnd = zrUtil.bind(this._dragHandle, this, handleIndex, true); |
| var handleThumb = createPolygon(createHandlePoints(handleIndex, textSize), getCursor(this._orient), onDrift, onDragEnd); |
| handleThumb.position[0] = itemSize[0]; |
| barGroup.add(handleThumb); // Text is always horizontal layout but should not be effected by |
| // transform (orient/inverse). So label is built separately but not |
| // use zrender/graphic/helper/RectText, and is located based on view |
| // group (according to handleLabelPoint) but not barGroup. |
| |
| var textStyleModel = this.visualMapModel.textStyleModel; |
| var handleLabel = new graphic.Text({ |
| draggable: true, |
| drift: onDrift, |
| onmousemove: function (e) { |
| // Fot mobile devicem, prevent screen slider on the button. |
| eventTool.stop(e.event); |
| }, |
| ondragend: onDragEnd, |
| style: { |
| x: 0, |
| y: 0, |
| text: '', |
| textFont: textStyleModel.getFont(), |
| textFill: textStyleModel.getTextColor() |
| } |
| }); |
| this.group.add(handleLabel); |
| var handleLabelPoint = [orient === 'horizontal' ? textSize / 2 : textSize * 1.5, orient === 'horizontal' ? handleIndex === 0 ? -(textSize * 1.5) : textSize * 1.5 : handleIndex === 0 ? -textSize / 2 : textSize / 2]; |
| var shapes = this._shapes; |
| shapes.handleThumbs[handleIndex] = handleThumb; |
| shapes.handleLabelPoints[handleIndex] = handleLabelPoint; |
| shapes.handleLabels[handleIndex] = handleLabel; |
| }, |
| |
| /** |
| * @private |
| */ |
| _createIndicator: function (barGroup, itemSize, textSize, orient) { |
| var indicator = createPolygon([[0, 0]], 'move'); |
| indicator.position[0] = itemSize[0]; |
| indicator.attr({ |
| invisible: true, |
| silent: true |
| }); |
| barGroup.add(indicator); |
| var textStyleModel = this.visualMapModel.textStyleModel; |
| var indicatorLabel = new graphic.Text({ |
| silent: true, |
| invisible: true, |
| style: { |
| x: 0, |
| y: 0, |
| text: '', |
| textFont: textStyleModel.getFont(), |
| textFill: textStyleModel.getTextColor() |
| } |
| }); |
| this.group.add(indicatorLabel); |
| var indicatorLabelPoint = [orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT + 3, 0]; |
| var shapes = this._shapes; |
| shapes.indicator = indicator; |
| shapes.indicatorLabel = indicatorLabel; |
| shapes.indicatorLabelPoint = indicatorLabelPoint; |
| }, |
| |
| /** |
| * @private |
| */ |
| _dragHandle: function (handleIndex, isEnd, dx, dy) { |
| if (!this._useHandle) { |
| return; |
| } |
| |
| this._dragging = !isEnd; |
| |
| if (!isEnd) { |
| // Transform dx, dy to bar coordination. |
| var vertex = this._applyTransform([dx, dy], this._shapes.barGroup, true); |
| |
| this._updateInterval(handleIndex, vertex[1]); // Considering realtime, update view should be executed |
| // before dispatch action. |
| |
| |
| this._updateView(); |
| } // dragEnd do not dispatch action when realtime. |
| |
| |
| if (isEnd === !this.visualMapModel.get('realtime')) { |
| // jshint ignore:line |
| this.api.dispatchAction({ |
| type: 'selectDataRange', |
| from: this.uid, |
| visualMapId: this.visualMapModel.id, |
| selected: this._dataInterval.slice() |
| }); |
| } |
| |
| if (isEnd) { |
| !this._hovering && this._clearHoverLinkToSeries(); |
| } else if (useHoverLinkOnHandle(this.visualMapModel)) { |
| this._doHoverLinkToSeries(this._handleEnds[handleIndex], false); |
| } |
| }, |
| |
| /** |
| * @private |
| */ |
| _resetInterval: function () { |
| var visualMapModel = this.visualMapModel; |
| var dataInterval = this._dataInterval = visualMapModel.getSelected(); |
| var dataExtent = visualMapModel.getExtent(); |
| var sizeExtent = [0, visualMapModel.itemSize[1]]; |
| this._handleEnds = [linearMap(dataInterval[0], dataExtent, sizeExtent, true), linearMap(dataInterval[1], dataExtent, sizeExtent, true)]; |
| }, |
| |
| /** |
| * @private |
| * @param {(number|string)} handleIndex 0 or 1 or 'all' |
| * @param {number} dx |
| * @param {number} dy |
| */ |
| _updateInterval: function (handleIndex, delta) { |
| delta = delta || 0; |
| var visualMapModel = this.visualMapModel; |
| var handleEnds = this._handleEnds; |
| var sizeExtent = [0, visualMapModel.itemSize[1]]; |
| sliderMove(delta, handleEnds, sizeExtent, handleIndex, // cross is forbiden |
| 0); |
| var dataExtent = visualMapModel.getExtent(); // Update data interval. |
| |
| this._dataInterval = [linearMap(handleEnds[0], sizeExtent, dataExtent, true), linearMap(handleEnds[1], sizeExtent, dataExtent, true)]; |
| }, |
| |
| /** |
| * @private |
| */ |
| _updateView: function (forSketch) { |
| var visualMapModel = this.visualMapModel; |
| var dataExtent = visualMapModel.getExtent(); |
| var shapes = this._shapes; |
| var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]]; |
| var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds; |
| |
| var visualInRange = this._createBarVisual(this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'); |
| |
| var visualOutOfRange = this._createBarVisual(dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'); |
| |
| shapes.inRange.setStyle({ |
| fill: visualInRange.barColor, |
| opacity: visualInRange.opacity |
| }).setShape('points', visualInRange.barPoints); |
| shapes.outOfRange.setStyle({ |
| fill: visualOutOfRange.barColor, |
| opacity: visualOutOfRange.opacity |
| }).setShape('points', visualOutOfRange.barPoints); |
| |
| this._updateHandle(inRangeHandleEnds, visualInRange); |
| }, |
| |
| /** |
| * @private |
| */ |
| _createBarVisual: function (dataInterval, dataExtent, handleEnds, forceState) { |
| var opts = { |
| forceState: forceState, |
| convertOpacityToAlpha: true |
| }; |
| |
| var colorStops = this._makeColorGradient(dataInterval, opts); |
| |
| var symbolSizes = [this.getControllerVisual(dataInterval[0], 'symbolSize', opts), this.getControllerVisual(dataInterval[1], 'symbolSize', opts)]; |
| |
| var barPoints = this._createBarPoints(handleEnds, symbolSizes); |
| |
| return { |
| barColor: new LinearGradient(0, 0, 0, 1, colorStops), |
| barPoints: barPoints, |
| handlesColor: [colorStops[0].color, colorStops[colorStops.length - 1].color] |
| }; |
| }, |
| |
| /** |
| * @private |
| */ |
| _makeColorGradient: function (dataInterval, opts) { |
| // Considering colorHue, which is not linear, so we have to sample |
| // to calculate gradient color stops, but not only caculate head |
| // and tail. |
| var sampleNumber = 100; // Arbitrary value. |
| |
| var colorStops = []; |
| var step = (dataInterval[1] - dataInterval[0]) / sampleNumber; |
| colorStops.push({ |
| color: this.getControllerVisual(dataInterval[0], 'color', opts), |
| offset: 0 |
| }); |
| |
| for (var i = 1; i < sampleNumber; i++) { |
| var currValue = dataInterval[0] + step * i; |
| |
| if (currValue > dataInterval[1]) { |
| break; |
| } |
| |
| colorStops.push({ |
| color: this.getControllerVisual(currValue, 'color', opts), |
| offset: i / sampleNumber |
| }); |
| } |
| |
| colorStops.push({ |
| color: this.getControllerVisual(dataInterval[1], 'color', opts), |
| offset: 1 |
| }); |
| return colorStops; |
| }, |
| |
| /** |
| * @private |
| */ |
| _createBarPoints: function (handleEnds, symbolSizes) { |
| var itemSize = this.visualMapModel.itemSize; |
| return [[itemSize[0] - symbolSizes[0], handleEnds[0]], [itemSize[0], handleEnds[0]], [itemSize[0], handleEnds[1]], [itemSize[0] - symbolSizes[1], handleEnds[1]]]; |
| }, |
| |
| /** |
| * @private |
| */ |
| _createBarGroup: function (itemAlign) { |
| var orient = this._orient; |
| var inverse = this.visualMapModel.get('inverse'); |
| return new graphic.Group(orient === 'horizontal' && !inverse ? { |
| scale: itemAlign === 'bottom' ? [1, 1] : [-1, 1], |
| rotation: Math.PI / 2 |
| } : orient === 'horizontal' && inverse ? { |
| scale: itemAlign === 'bottom' ? [-1, 1] : [1, 1], |
| rotation: -Math.PI / 2 |
| } : orient === 'vertical' && !inverse ? { |
| scale: itemAlign === 'left' ? [1, -1] : [-1, -1] |
| } : { |
| scale: itemAlign === 'left' ? [1, 1] : [-1, 1] |
| }); |
| }, |
| |
| /** |
| * @private |
| */ |
| _updateHandle: function (handleEnds, visualInRange) { |
| if (!this._useHandle) { |
| return; |
| } |
| |
| var shapes = this._shapes; |
| var visualMapModel = this.visualMapModel; |
| var handleThumbs = shapes.handleThumbs; |
| var handleLabels = shapes.handleLabels; |
| each([0, 1], function (handleIndex) { |
| var handleThumb = handleThumbs[handleIndex]; |
| handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]); |
| handleThumb.position[1] = handleEnds[handleIndex]; // Update handle label position. |
| |
| var textPoint = graphic.applyTransform(shapes.handleLabelPoints[handleIndex], graphic.getTransform(handleThumb, this.group)); |
| handleLabels[handleIndex].setStyle({ |
| x: textPoint[0], |
| y: textPoint[1], |
| text: visualMapModel.formatValueText(this._dataInterval[handleIndex]), |
| textVerticalAlign: 'middle', |
| textAlign: this._applyTransform(this._orient === 'horizontal' ? handleIndex === 0 ? 'bottom' : 'top' : 'left', shapes.barGroup) |
| }); |
| }, this); |
| }, |
| |
| /** |
| * @private |
| * @param {number} cursorValue |
| * @param {number} textValue |
| * @param {string} [rangeSymbol] |
| * @param {number} [halfHoverLinkSize] |
| */ |
| _showIndicator: function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) { |
| var visualMapModel = this.visualMapModel; |
| var dataExtent = visualMapModel.getExtent(); |
| var itemSize = visualMapModel.itemSize; |
| var sizeExtent = [0, itemSize[1]]; |
| var pos = linearMap(cursorValue, dataExtent, sizeExtent, true); |
| var shapes = this._shapes; |
| var indicator = shapes.indicator; |
| |
| if (!indicator) { |
| return; |
| } |
| |
| indicator.position[1] = pos; |
| indicator.attr('invisible', false); |
| indicator.setShape('points', createIndicatorPoints(!!rangeSymbol, halfHoverLinkSize, pos, itemSize[1])); |
| var opts = { |
| convertOpacityToAlpha: true |
| }; |
| var color = this.getControllerVisual(cursorValue, 'color', opts); |
| indicator.setStyle('fill', color); // Update handle label position. |
| |
| var textPoint = graphic.applyTransform(shapes.indicatorLabelPoint, graphic.getTransform(indicator, this.group)); |
| var indicatorLabel = shapes.indicatorLabel; |
| indicatorLabel.attr('invisible', false); |
| |
| var align = this._applyTransform('left', shapes.barGroup); |
| |
| var orient = this._orient; |
| indicatorLabel.setStyle({ |
| text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue), |
| textVerticalAlign: orient === 'horizontal' ? align : 'middle', |
| textAlign: orient === 'horizontal' ? 'center' : align, |
| x: textPoint[0], |
| y: textPoint[1] |
| }); |
| }, |
| |
| /** |
| * @private |
| */ |
| _enableHoverLinkToSeries: function () { |
| var self = this; |
| |
| this._shapes.barGroup.on('mousemove', function (e) { |
| self._hovering = true; |
| |
| if (!self._dragging) { |
| var itemSize = self.visualMapModel.itemSize; |
| |
| var pos = self._applyTransform([e.offsetX, e.offsetY], self._shapes.barGroup, true, true); // For hover link show when hover handle, which might be |
| // below or upper than sizeExtent. |
| |
| |
| pos[1] = mathMin(mathMax(0, pos[1]), itemSize[1]); |
| |
| self._doHoverLinkToSeries(pos[1], 0 <= pos[0] && pos[0] <= itemSize[0]); |
| } |
| }).on('mouseout', function () { |
| // When mouse is out of handle, hoverLink still need |
| // to be displayed when realtime is set as false. |
| self._hovering = false; |
| !self._dragging && self._clearHoverLinkToSeries(); |
| }); |
| }, |
| |
| /** |
| * @private |
| */ |
| _enableHoverLinkFromSeries: function () { |
| var zr = this.api.getZr(); |
| |
| if (this.visualMapModel.option.hoverLink) { |
| zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this); |
| zr.on('mouseout', this._hideIndicator, this); |
| } else { |
| this._clearHoverLinkFromSeries(); |
| } |
| }, |
| |
| /** |
| * @private |
| */ |
| _doHoverLinkToSeries: function (cursorPos, hoverOnBar) { |
| var visualMapModel = this.visualMapModel; |
| var itemSize = visualMapModel.itemSize; |
| |
| if (!visualMapModel.option.hoverLink) { |
| return; |
| } |
| |
| var sizeExtent = [0, itemSize[1]]; |
| var dataExtent = visualMapModel.getExtent(); // For hover link show when hover handle, which might be below or upper than sizeExtent. |
| |
| cursorPos = mathMin(mathMax(sizeExtent[0], cursorPos), sizeExtent[1]); |
| var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent); |
| var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize]; |
| var cursorValue = linearMap(cursorPos, sizeExtent, dataExtent, true); |
| var valueRange = [linearMap(hoverRange[0], sizeExtent, dataExtent, true), linearMap(hoverRange[1], sizeExtent, dataExtent, true)]; // Consider data range is out of visualMap range, see test/visualMap-continuous.html, |
| // where china and india has very large population. |
| |
| hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity); |
| hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); // Do not show indicator when mouse is over handle, |
| // otherwise labels overlap, especially when dragging. |
| |
| if (hoverOnBar) { |
| if (valueRange[0] === -Infinity) { |
| this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize); |
| } else if (valueRange[1] === Infinity) { |
| this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize); |
| } else { |
| this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize); |
| } |
| } // When realtime is set as false, handles, which are in barGroup, |
| // also trigger hoverLink, which help user to realize where they |
| // focus on when dragging. (see test/heatmap-large.html) |
| // When realtime is set as true, highlight will not show when hover |
| // handle, because the label on handle, which displays a exact value |
| // but not range, might mislead users. |
| |
| |
| var oldBatch = this._hoverLinkDataIndices; |
| var newBatch = []; |
| |
| if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) { |
| newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange); |
| } |
| |
| var resultBatches = modelUtil.compressBatches(oldBatch, newBatch); |
| |
| this._dispatchHighDown('downplay', helper.makeHighDownBatch(resultBatches[0], visualMapModel)); |
| |
| this._dispatchHighDown('highlight', helper.makeHighDownBatch(resultBatches[1], visualMapModel)); |
| }, |
| |
| /** |
| * @private |
| */ |
| _hoverLinkFromSeriesMouseOver: function (e) { |
| var el = e.target; |
| var visualMapModel = this.visualMapModel; |
| |
| if (!el || el.dataIndex == null) { |
| return; |
| } |
| |
| var dataModel = this.ecModel.getSeriesByIndex(el.seriesIndex); |
| |
| if (!visualMapModel.isTargetSeries(dataModel)) { |
| return; |
| } |
| |
| var data = dataModel.getData(el.dataType); |
| var value = data.get(visualMapModel.getDataDimension(data), el.dataIndex, true); |
| |
| if (!isNaN(value)) { |
| this._showIndicator(value, value); |
| } |
| }, |
| |
| /** |
| * @private |
| */ |
| _hideIndicator: function () { |
| var shapes = this._shapes; |
| shapes.indicator && shapes.indicator.attr('invisible', true); |
| shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true); |
| }, |
| |
| /** |
| * @private |
| */ |
| _clearHoverLinkToSeries: function () { |
| this._hideIndicator(); |
| |
| var indices = this._hoverLinkDataIndices; |
| |
| this._dispatchHighDown('downplay', helper.makeHighDownBatch(indices, this.visualMapModel)); |
| |
| indices.length = 0; |
| }, |
| |
| /** |
| * @private |
| */ |
| _clearHoverLinkFromSeries: function () { |
| this._hideIndicator(); |
| |
| var zr = this.api.getZr(); |
| zr.off('mouseover', this._hoverLinkFromSeriesMouseOver); |
| zr.off('mouseout', this._hideIndicator); |
| }, |
| |
| /** |
| * @private |
| */ |
| _applyTransform: function (vertex, element, inverse, global) { |
| var transform = graphic.getTransform(element, global ? null : this.group); |
| return graphic[zrUtil.isArray(vertex) ? 'applyTransform' : 'transformDirection'](vertex, transform, inverse); |
| }, |
| |
| /** |
| * @private |
| */ |
| _dispatchHighDown: function (type, batch) { |
| batch && batch.length && this.api.dispatchAction({ |
| type: type, |
| batch: batch |
| }); |
| }, |
| |
| /** |
| * @override |
| */ |
| dispose: function () { |
| this._clearHoverLinkFromSeries(); |
| |
| this._clearHoverLinkToSeries(); |
| }, |
| |
| /** |
| * @override |
| */ |
| remove: function () { |
| this._clearHoverLinkFromSeries(); |
| |
| this._clearHoverLinkToSeries(); |
| } |
| }); |
| |
| function createPolygon(points, cursor, onDrift, onDragEnd) { |
| return new graphic.Polygon({ |
| shape: { |
| points: points |
| }, |
| draggable: !!onDrift, |
| cursor: cursor, |
| drift: onDrift, |
| onmousemove: function (e) { |
| // Fot mobile devicem, prevent screen slider on the button. |
| eventTool.stop(e.event); |
| }, |
| ondragend: onDragEnd |
| }); |
| } |
| |
| function createHandlePoints(handleIndex, textSize) { |
| return handleIndex === 0 ? [[0, 0], [textSize, 0], [textSize, -textSize]] : [[0, 0], [textSize, 0], [textSize, textSize]]; |
| } |
| |
| function createIndicatorPoints(isRange, halfHoverLinkSize, pos, extentMax) { |
| return isRange ? [// indicate range |
| [0, -mathMin(halfHoverLinkSize, mathMax(pos, 0))], [HOVER_LINK_OUT, 0], [0, mathMin(halfHoverLinkSize, mathMax(extentMax - pos, 0))]] : [// indicate single value |
| [0, 0], [5, -5], [5, 5]]; |
| } |
| |
| function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) { |
| var halfHoverLinkSize = HOVER_LINK_SIZE / 2; |
| var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize'); |
| |
| if (hoverLinkDataSize) { |
| halfHoverLinkSize = linearMap(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2; |
| } |
| |
| return halfHoverLinkSize; |
| } |
| |
| function useHoverLinkOnHandle(visualMapModel) { |
| var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle'); |
| return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle); |
| } |
| |
| function getCursor(orient) { |
| return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; |
| } |
| |
| export default ContinuousView; |