|   | 
| /* | 
| * 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. | 
| */ | 
|   | 
|   | 
| /** | 
|  * AUTO-GENERATED FILE. DO NOT MODIFY. | 
|  */ | 
|   | 
| /* | 
| * 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 { __extends } from "tslib"; | 
| import { bind, each, isFunction, isString, indexOf } from 'zrender/lib/core/util.js'; | 
| import * as eventTool from 'zrender/lib/core/event.js'; | 
| import * as graphic from '../../util/graphic.js'; | 
| import * as throttle from '../../util/throttle.js'; | 
| import DataZoomView from './DataZoomView.js'; | 
| import { linearMap, asc, parsePercent } from '../../util/number.js'; | 
| import * as layout from '../../util/layout.js'; | 
| import sliderMove from '../helper/sliderMove.js'; | 
| import { getAxisMainType, collectReferCoordSysModelInfo } from './helper.js'; | 
| import { enableHoverEmphasis } from '../../util/states.js'; | 
| import { createSymbol, symbolBuildProxies } from '../../util/symbol.js'; | 
| import { deprecateLog } from '../../util/log.js'; | 
| import { createTextStyle } from '../../label/labelStyle.js'; | 
| var Rect = graphic.Rect; | 
| // Constants | 
| var DEFAULT_LOCATION_EDGE_GAP = 7; | 
| var DEFAULT_FRAME_BORDER_WIDTH = 1; | 
| var DEFAULT_FILLER_SIZE = 30; | 
| var DEFAULT_MOVE_HANDLE_SIZE = 7; | 
| var HORIZONTAL = 'horizontal'; | 
| var VERTICAL = 'vertical'; | 
| var LABEL_GAP = 5; | 
| var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; | 
| var REALTIME_ANIMATION_CONFIG = { | 
|   easing: 'cubicOut', | 
|   duration: 100, | 
|   delay: 0 | 
| }; | 
| var SliderZoomView = /** @class */function (_super) { | 
|   __extends(SliderZoomView, _super); | 
|   function SliderZoomView() { | 
|     var _this = _super !== null && _super.apply(this, arguments) || this; | 
|     _this.type = SliderZoomView.type; | 
|     _this._displayables = {}; | 
|     return _this; | 
|   } | 
|   SliderZoomView.prototype.init = function (ecModel, api) { | 
|     this.api = api; | 
|     // A unique handler for each dataZoom component | 
|     this._onBrush = bind(this._onBrush, this); | 
|     this._onBrushEnd = bind(this._onBrushEnd, this); | 
|   }; | 
|   SliderZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) { | 
|     _super.prototype.render.apply(this, arguments); | 
|     throttle.createOrUpdate(this, '_dispatchZoomAction', dataZoomModel.get('throttle'), 'fixRate'); | 
|     this._orient = dataZoomModel.getOrient(); | 
|     if (dataZoomModel.get('show') === false) { | 
|       this.group.removeAll(); | 
|       return; | 
|     } | 
|     if (dataZoomModel.noTarget()) { | 
|       this._clear(); | 
|       this.group.removeAll(); | 
|       return; | 
|     } | 
|     // Notice: this._resetInterval() should not be executed when payload.type | 
|     // is 'dataZoom', origin this._range should be maintained, otherwise 'pan' | 
|     // or 'zoom' info will be missed because of 'throttle' of this.dispatchAction, | 
|     if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) { | 
|       this._buildView(); | 
|     } | 
|     this._updateView(); | 
|   }; | 
|   SliderZoomView.prototype.dispose = function () { | 
|     this._clear(); | 
|     _super.prototype.dispose.apply(this, arguments); | 
|   }; | 
|   SliderZoomView.prototype._clear = function () { | 
|     throttle.clear(this, '_dispatchZoomAction'); | 
|     var zr = this.api.getZr(); | 
|     zr.off('mousemove', this._onBrush); | 
|     zr.off('mouseup', this._onBrushEnd); | 
|   }; | 
|   SliderZoomView.prototype._buildView = function () { | 
|     var thisGroup = this.group; | 
|     thisGroup.removeAll(); | 
|     this._brushing = false; | 
|     this._displayables.brushRect = null; | 
|     this._resetLocation(); | 
|     this._resetInterval(); | 
|     var barGroup = this._displayables.sliderGroup = new graphic.Group(); | 
|     this._renderBackground(); | 
|     this._renderHandle(); | 
|     this._renderDataShadow(); | 
|     thisGroup.add(barGroup); | 
|     this._positionGroup(); | 
|   }; | 
|   SliderZoomView.prototype._resetLocation = function () { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var api = this.api; | 
|     var showMoveHandle = dataZoomModel.get('brushSelect'); | 
|     var moveHandleSize = showMoveHandle ? DEFAULT_MOVE_HANDLE_SIZE : 0; | 
|     // If some of x/y/width/height are not specified, | 
|     // auto-adapt according to target grid. | 
|     var coordRect = this._findCoordRect(); | 
|     var ecSize = { | 
|       width: api.getWidth(), | 
|       height: api.getHeight() | 
|     }; | 
|     // Default align by coordinate system rect. | 
|     var positionInfo = this._orient === HORIZONTAL ? { | 
|       // Why using 'right', because right should be used in vertical, | 
|       // and it is better to be consistent for dealing with position param merge. | 
|       right: ecSize.width - coordRect.x - coordRect.width, | 
|       top: ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP - moveHandleSize, | 
|       width: coordRect.width, | 
|       height: DEFAULT_FILLER_SIZE | 
|     } : { | 
|       right: DEFAULT_LOCATION_EDGE_GAP, | 
|       top: coordRect.y, | 
|       width: DEFAULT_FILLER_SIZE, | 
|       height: coordRect.height | 
|     }; | 
|     // Do not write back to option and replace value 'ph', because | 
|     // the 'ph' value should be recalculated when resize. | 
|     var layoutParams = layout.getLayoutParams(dataZoomModel.option); | 
|     // Replace the placeholder value. | 
|     each(['right', 'top', 'width', 'height'], function (name) { | 
|       if (layoutParams[name] === 'ph') { | 
|         layoutParams[name] = positionInfo[name]; | 
|       } | 
|     }); | 
|     var layoutRect = layout.getLayoutRect(layoutParams, ecSize); | 
|     this._location = { | 
|       x: layoutRect.x, | 
|       y: layoutRect.y | 
|     }; | 
|     this._size = [layoutRect.width, layoutRect.height]; | 
|     this._orient === VERTICAL && this._size.reverse(); | 
|   }; | 
|   SliderZoomView.prototype._positionGroup = function () { | 
|     var thisGroup = this.group; | 
|     var location = this._location; | 
|     var orient = this._orient; | 
|     // Just use the first axis to determine mapping. | 
|     var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel(); | 
|     var inverse = targetAxisModel && targetAxisModel.get('inverse'); | 
|     var sliderGroup = this._displayables.sliderGroup; | 
|     var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse; | 
|     // Transform barGroup. | 
|     sliderGroup.attr(orient === HORIZONTAL && !inverse ? { | 
|       scaleY: otherAxisInverse ? 1 : -1, | 
|       scaleX: 1 | 
|     } : orient === HORIZONTAL && inverse ? { | 
|       scaleY: otherAxisInverse ? 1 : -1, | 
|       scaleX: -1 | 
|     } : orient === VERTICAL && !inverse ? { | 
|       scaleY: otherAxisInverse ? -1 : 1, | 
|       scaleX: 1, | 
|       rotation: Math.PI / 2 | 
|     } | 
|     // Don't use Math.PI, considering shadow direction. | 
|     : { | 
|       scaleY: otherAxisInverse ? -1 : 1, | 
|       scaleX: -1, | 
|       rotation: Math.PI / 2 | 
|     }); | 
|     // Position barGroup | 
|     var rect = thisGroup.getBoundingRect([sliderGroup]); | 
|     thisGroup.x = location.x - rect.x; | 
|     thisGroup.y = location.y - rect.y; | 
|     thisGroup.markRedraw(); | 
|   }; | 
|   SliderZoomView.prototype._getViewExtent = function () { | 
|     return [0, this._size[0]]; | 
|   }; | 
|   SliderZoomView.prototype._renderBackground = function () { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var size = this._size; | 
|     var barGroup = this._displayables.sliderGroup; | 
|     var brushSelect = dataZoomModel.get('brushSelect'); | 
|     barGroup.add(new Rect({ | 
|       silent: true, | 
|       shape: { | 
|         x: 0, | 
|         y: 0, | 
|         width: size[0], | 
|         height: size[1] | 
|       }, | 
|       style: { | 
|         fill: dataZoomModel.get('backgroundColor') | 
|       }, | 
|       z2: -40 | 
|     })); | 
|     // Click panel, over shadow, below handles. | 
|     var clickPanel = new Rect({ | 
|       shape: { | 
|         x: 0, | 
|         y: 0, | 
|         width: size[0], | 
|         height: size[1] | 
|       }, | 
|       style: { | 
|         fill: 'transparent' | 
|       }, | 
|       z2: 0, | 
|       onclick: bind(this._onClickPanel, this) | 
|     }); | 
|     var zr = this.api.getZr(); | 
|     if (brushSelect) { | 
|       clickPanel.on('mousedown', this._onBrushStart, this); | 
|       clickPanel.cursor = 'crosshair'; | 
|       zr.on('mousemove', this._onBrush); | 
|       zr.on('mouseup', this._onBrushEnd); | 
|     } else { | 
|       zr.off('mousemove', this._onBrush); | 
|       zr.off('mouseup', this._onBrushEnd); | 
|     } | 
|     barGroup.add(clickPanel); | 
|   }; | 
|   SliderZoomView.prototype._renderDataShadow = function () { | 
|     var info = this._dataShadowInfo = this._prepareDataShadowInfo(); | 
|     this._displayables.dataShadowSegs = []; | 
|     if (!info) { | 
|       return; | 
|     } | 
|     var size = this._size; | 
|     var oldSize = this._shadowSize || []; | 
|     var seriesModel = info.series; | 
|     var data = seriesModel.getRawData(); | 
|     var candlestickDim = seriesModel.getShadowDim && seriesModel.getShadowDim(); | 
|     var otherDim = candlestickDim && data.getDimensionInfo(candlestickDim) ? seriesModel.getShadowDim() // @see candlestick | 
|     : info.otherDim; | 
|     if (otherDim == null) { | 
|       return; | 
|     } | 
|     var polygonPts = this._shadowPolygonPts; | 
|     var polylinePts = this._shadowPolylinePts; | 
|     // Not re-render if data doesn't change. | 
|     if (data !== this._shadowData || otherDim !== this._shadowDim || size[0] !== oldSize[0] || size[1] !== oldSize[1]) { | 
|       var otherDataExtent_1 = data.getDataExtent(otherDim); | 
|       // Nice extent. | 
|       var otherOffset = (otherDataExtent_1[1] - otherDataExtent_1[0]) * 0.3; | 
|       otherDataExtent_1 = [otherDataExtent_1[0] - otherOffset, otherDataExtent_1[1] + otherOffset]; | 
|       var otherShadowExtent_1 = [0, size[1]]; | 
|       var thisShadowExtent = [0, size[0]]; | 
|       var areaPoints_1 = [[size[0], 0], [0, 0]]; | 
|       var linePoints_1 = []; | 
|       var step_1 = thisShadowExtent[1] / (data.count() - 1); | 
|       var thisCoord_1 = 0; | 
|       // Optimize for large data shadow | 
|       var stride_1 = Math.round(data.count() / size[0]); | 
|       var lastIsEmpty_1; | 
|       data.each([otherDim], function (value, index) { | 
|         if (stride_1 > 0 && index % stride_1) { | 
|           thisCoord_1 += step_1; | 
|           return; | 
|         } | 
|         // FIXME | 
|         // Should consider axis.min/axis.max when drawing dataShadow. | 
|         // FIXME | 
|         // 应该使用统一的空判断?还是在list里进行空判断? | 
|         var isEmpty = value == null || isNaN(value) || value === ''; | 
|         // See #4235. | 
|         var otherCoord = isEmpty ? 0 : linearMap(value, otherDataExtent_1, otherShadowExtent_1, true); | 
|         // Attempt to draw data shadow precisely when there are empty value. | 
|         if (isEmpty && !lastIsEmpty_1 && index) { | 
|           areaPoints_1.push([areaPoints_1[areaPoints_1.length - 1][0], 0]); | 
|           linePoints_1.push([linePoints_1[linePoints_1.length - 1][0], 0]); | 
|         } else if (!isEmpty && lastIsEmpty_1) { | 
|           areaPoints_1.push([thisCoord_1, 0]); | 
|           linePoints_1.push([thisCoord_1, 0]); | 
|         } | 
|         areaPoints_1.push([thisCoord_1, otherCoord]); | 
|         linePoints_1.push([thisCoord_1, otherCoord]); | 
|         thisCoord_1 += step_1; | 
|         lastIsEmpty_1 = isEmpty; | 
|       }); | 
|       polygonPts = this._shadowPolygonPts = areaPoints_1; | 
|       polylinePts = this._shadowPolylinePts = linePoints_1; | 
|     } | 
|     this._shadowData = data; | 
|     this._shadowDim = otherDim; | 
|     this._shadowSize = [size[0], size[1]]; | 
|     var dataZoomModel = this.dataZoomModel; | 
|     function createDataShadowGroup(isSelectedArea) { | 
|       var model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground'); | 
|       var group = new graphic.Group(); | 
|       var polygon = new graphic.Polygon({ | 
|         shape: { | 
|           points: polygonPts | 
|         }, | 
|         segmentIgnoreThreshold: 1, | 
|         style: model.getModel('areaStyle').getAreaStyle(), | 
|         silent: true, | 
|         z2: -20 | 
|       }); | 
|       var polyline = new graphic.Polyline({ | 
|         shape: { | 
|           points: polylinePts | 
|         }, | 
|         segmentIgnoreThreshold: 1, | 
|         style: model.getModel('lineStyle').getLineStyle(), | 
|         silent: true, | 
|         z2: -19 | 
|       }); | 
|       group.add(polygon); | 
|       group.add(polyline); | 
|       return group; | 
|     } | 
|     // let dataBackgroundModel = dataZoomModel.getModel('dataBackground'); | 
|     for (var i = 0; i < 3; i++) { | 
|       var group = createDataShadowGroup(i === 1); | 
|       this._displayables.sliderGroup.add(group); | 
|       this._displayables.dataShadowSegs.push(group); | 
|     } | 
|   }; | 
|   SliderZoomView.prototype._prepareDataShadowInfo = function () { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var showDataShadow = dataZoomModel.get('showDataShadow'); | 
|     if (showDataShadow === false) { | 
|       return; | 
|     } | 
|     // Find a representative series. | 
|     var result; | 
|     var ecModel = this.ecModel; | 
|     dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { | 
|       var seriesModels = dataZoomModel.getAxisProxy(axisDim, axisIndex).getTargetSeriesModels(); | 
|       each(seriesModels, function (seriesModel) { | 
|         if (result) { | 
|           return; | 
|         } | 
|         if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { | 
|           return; | 
|         } | 
|         var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; | 
|         var otherDim = getOtherDim(axisDim); | 
|         var otherAxisInverse; | 
|         var coordSys = seriesModel.coordinateSystem; | 
|         if (otherDim != null && coordSys.getOtherAxis) { | 
|           otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; | 
|         } | 
|         otherDim = seriesModel.getData().mapDimension(otherDim); | 
|         result = { | 
|           thisAxis: thisAxis, | 
|           series: seriesModel, | 
|           thisDim: axisDim, | 
|           otherDim: otherDim, | 
|           otherAxisInverse: otherAxisInverse | 
|         }; | 
|       }, this); | 
|     }, this); | 
|     return result; | 
|   }; | 
|   SliderZoomView.prototype._renderHandle = function () { | 
|     var thisGroup = this.group; | 
|     var displayables = this._displayables; | 
|     var handles = displayables.handles = [null, null]; | 
|     var handleLabels = displayables.handleLabels = [null, null]; | 
|     var sliderGroup = this._displayables.sliderGroup; | 
|     var size = this._size; | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var api = this.api; | 
|     var borderRadius = dataZoomModel.get('borderRadius') || 0; | 
|     var brushSelect = dataZoomModel.get('brushSelect'); | 
|     var filler = displayables.filler = new Rect({ | 
|       silent: brushSelect, | 
|       style: { | 
|         fill: dataZoomModel.get('fillerColor') | 
|       }, | 
|       textConfig: { | 
|         position: 'inside' | 
|       } | 
|     }); | 
|     sliderGroup.add(filler); | 
|     // Frame border. | 
|     sliderGroup.add(new Rect({ | 
|       silent: true, | 
|       subPixelOptimize: true, | 
|       shape: { | 
|         x: 0, | 
|         y: 0, | 
|         width: size[0], | 
|         height: size[1], | 
|         r: borderRadius | 
|       }, | 
|       style: { | 
|         // deprecated option | 
|         stroke: dataZoomModel.get('dataBackgroundColor') || dataZoomModel.get('borderColor'), | 
|         lineWidth: DEFAULT_FRAME_BORDER_WIDTH, | 
|         fill: 'rgba(0,0,0,0)' | 
|       } | 
|     })); | 
|     // Left and right handle to resize | 
|     each([0, 1], function (handleIndex) { | 
|       var iconStr = dataZoomModel.get('handleIcon'); | 
|       if (!symbolBuildProxies[iconStr] && iconStr.indexOf('path://') < 0 && iconStr.indexOf('image://') < 0) { | 
|         // Compatitable with the old icon parsers. Which can use a path string without path:// | 
|         iconStr = 'path://' + iconStr; | 
|         if (process.env.NODE_ENV !== 'production') { | 
|           deprecateLog('handleIcon now needs \'path://\' prefix when using a path string'); | 
|         } | 
|       } | 
|       var path = createSymbol(iconStr, -1, 0, 2, 2, null, true); | 
|       path.attr({ | 
|         cursor: getCursor(this._orient), | 
|         draggable: true, | 
|         drift: bind(this._onDragMove, this, handleIndex), | 
|         ondragend: bind(this._onDragEnd, this), | 
|         onmouseover: bind(this._showDataInfo, this, true), | 
|         onmouseout: bind(this._showDataInfo, this, false), | 
|         z2: 5 | 
|       }); | 
|       var bRect = path.getBoundingRect(); | 
|       var handleSize = dataZoomModel.get('handleSize'); | 
|       this._handleHeight = parsePercent(handleSize, this._size[1]); | 
|       this._handleWidth = bRect.width / bRect.height * this._handleHeight; | 
|       path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle()); | 
|       path.style.strokeNoScale = true; | 
|       path.rectHover = true; | 
|       path.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'handleStyle']).getItemStyle(); | 
|       enableHoverEmphasis(path); | 
|       var handleColor = dataZoomModel.get('handleColor'); // deprecated option | 
|       // Compatitable with previous version | 
|       if (handleColor != null) { | 
|         path.style.fill = handleColor; | 
|       } | 
|       sliderGroup.add(handles[handleIndex] = path); | 
|       var textStyleModel = dataZoomModel.getModel('textStyle'); | 
|       var handleLabel = dataZoomModel.get('handleLabel') || {}; | 
|       var handleLabelShow = handleLabel.show || false; | 
|       thisGroup.add(handleLabels[handleIndex] = new graphic.Text({ | 
|         silent: true, | 
|         invisible: !handleLabelShow, | 
|         style: createTextStyle(textStyleModel, { | 
|           x: 0, | 
|           y: 0, | 
|           text: '', | 
|           verticalAlign: 'middle', | 
|           align: 'center', | 
|           fill: textStyleModel.getTextColor(), | 
|           font: textStyleModel.getFont() | 
|         }), | 
|         z2: 10 | 
|       })); | 
|     }, this); | 
|     // Handle to move. Only visible when brushSelect is set true. | 
|     var actualMoveZone = filler; | 
|     if (brushSelect) { | 
|       var moveHandleHeight = parsePercent(dataZoomModel.get('moveHandleSize'), size[1]); | 
|       var moveHandle_1 = displayables.moveHandle = new graphic.Rect({ | 
|         style: dataZoomModel.getModel('moveHandleStyle').getItemStyle(), | 
|         silent: true, | 
|         shape: { | 
|           r: [0, 0, 2, 2], | 
|           y: size[1] - 0.5, | 
|           height: moveHandleHeight | 
|         } | 
|       }); | 
|       var iconSize = moveHandleHeight * 0.8; | 
|       var moveHandleIcon = displayables.moveHandleIcon = createSymbol(dataZoomModel.get('moveHandleIcon'), -iconSize / 2, -iconSize / 2, iconSize, iconSize, '#fff', true); | 
|       moveHandleIcon.silent = true; | 
|       moveHandleIcon.y = size[1] + moveHandleHeight / 2 - 0.5; | 
|       moveHandle_1.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'moveHandleStyle']).getItemStyle(); | 
|       var moveZoneExpandSize = Math.min(size[1] / 2, Math.max(moveHandleHeight, 10)); | 
|       actualMoveZone = displayables.moveZone = new graphic.Rect({ | 
|         invisible: true, | 
|         shape: { | 
|           y: size[1] - moveZoneExpandSize, | 
|           height: moveHandleHeight + moveZoneExpandSize | 
|         } | 
|       }); | 
|       actualMoveZone.on('mouseover', function () { | 
|         api.enterEmphasis(moveHandle_1); | 
|       }).on('mouseout', function () { | 
|         api.leaveEmphasis(moveHandle_1); | 
|       }); | 
|       sliderGroup.add(moveHandle_1); | 
|       sliderGroup.add(moveHandleIcon); | 
|       sliderGroup.add(actualMoveZone); | 
|     } | 
|     actualMoveZone.attr({ | 
|       draggable: true, | 
|       cursor: getCursor(this._orient), | 
|       drift: bind(this._onDragMove, this, 'all'), | 
|       ondragstart: bind(this._showDataInfo, this, true), | 
|       ondragend: bind(this._onDragEnd, this), | 
|       onmouseover: bind(this._showDataInfo, this, true), | 
|       onmouseout: bind(this._showDataInfo, this, false) | 
|     }); | 
|   }; | 
|   SliderZoomView.prototype._resetInterval = function () { | 
|     var range = this._range = this.dataZoomModel.getPercentRange(); | 
|     var viewExtent = this._getViewExtent(); | 
|     this._handleEnds = [linearMap(range[0], [0, 100], viewExtent, true), linearMap(range[1], [0, 100], viewExtent, true)]; | 
|   }; | 
|   SliderZoomView.prototype._updateInterval = function (handleIndex, delta) { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var handleEnds = this._handleEnds; | 
|     var viewExtend = this._getViewExtent(); | 
|     var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); | 
|     var percentExtent = [0, 100]; | 
|     sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); | 
|     var lastRange = this._range; | 
|     var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]); | 
|     return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; | 
|   }; | 
|   SliderZoomView.prototype._updateView = function (nonRealtime) { | 
|     var displaybles = this._displayables; | 
|     var handleEnds = this._handleEnds; | 
|     var handleInterval = asc(handleEnds.slice()); | 
|     var size = this._size; | 
|     each([0, 1], function (handleIndex) { | 
|       // Handles | 
|       var handle = displaybles.handles[handleIndex]; | 
|       var handleHeight = this._handleHeight; | 
|       handle.attr({ | 
|         scaleX: handleHeight / 2, | 
|         scaleY: handleHeight / 2, | 
|         // This is a trick, by adding an extra tiny offset to let the default handle's end point align to the drag window. | 
|         // NOTE: It may affect some custom shapes a bit. But we prefer to have better result by default. | 
|         x: handleEnds[handleIndex] + (handleIndex ? -1 : 1), | 
|         y: size[1] / 2 - handleHeight / 2 | 
|       }); | 
|     }, this); | 
|     // Filler | 
|     displaybles.filler.setShape({ | 
|       x: handleInterval[0], | 
|       y: 0, | 
|       width: handleInterval[1] - handleInterval[0], | 
|       height: size[1] | 
|     }); | 
|     var viewExtent = { | 
|       x: handleInterval[0], | 
|       width: handleInterval[1] - handleInterval[0] | 
|     }; | 
|     // Move handle | 
|     if (displaybles.moveHandle) { | 
|       displaybles.moveHandle.setShape(viewExtent); | 
|       displaybles.moveZone.setShape(viewExtent); | 
|       // Force update path on the invisible object | 
|       displaybles.moveZone.getBoundingRect(); | 
|       displaybles.moveHandleIcon && displaybles.moveHandleIcon.attr('x', viewExtent.x + viewExtent.width / 2); | 
|     } | 
|     // update clip path of shadow. | 
|     var dataShadowSegs = displaybles.dataShadowSegs; | 
|     var segIntervals = [0, handleInterval[0], handleInterval[1], size[0]]; | 
|     for (var i = 0; i < dataShadowSegs.length; i++) { | 
|       var segGroup = dataShadowSegs[i]; | 
|       var clipPath = segGroup.getClipPath(); | 
|       if (!clipPath) { | 
|         clipPath = new graphic.Rect(); | 
|         segGroup.setClipPath(clipPath); | 
|       } | 
|       clipPath.setShape({ | 
|         x: segIntervals[i], | 
|         y: 0, | 
|         width: segIntervals[i + 1] - segIntervals[i], | 
|         height: size[1] | 
|       }); | 
|     } | 
|     this._updateDataInfo(nonRealtime); | 
|   }; | 
|   SliderZoomView.prototype._updateDataInfo = function (nonRealtime) { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var displaybles = this._displayables; | 
|     var handleLabels = displaybles.handleLabels; | 
|     var orient = this._orient; | 
|     var labelTexts = ['', '']; | 
|     // FIXME | 
|     // date型,支持formatter,autoformatter(ec2 date.getAutoFormatter) | 
|     if (dataZoomModel.get('showDetail')) { | 
|       var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); | 
|       if (axisProxy) { | 
|         var axis = axisProxy.getAxisModel().axis; | 
|         var range = this._range; | 
|         var dataInterval = nonRealtime | 
|         // See #4434, data and axis are not processed and reset yet in non-realtime mode. | 
|         ? axisProxy.calculateDataWindow({ | 
|           start: range[0], | 
|           end: range[1] | 
|         }).valueWindow : axisProxy.getDataValueWindow(); | 
|         labelTexts = [this._formatLabel(dataInterval[0], axis), this._formatLabel(dataInterval[1], axis)]; | 
|       } | 
|     } | 
|     var orderedHandleEnds = asc(this._handleEnds.slice()); | 
|     setLabel.call(this, 0); | 
|     setLabel.call(this, 1); | 
|     function setLabel(handleIndex) { | 
|       // Label | 
|       // Text should not transform by barGroup. | 
|       // Ignore handlers transform | 
|       var barTransform = graphic.getTransform(displaybles.handles[handleIndex].parent, this.group); | 
|       var direction = graphic.transformDirection(handleIndex === 0 ? 'right' : 'left', barTransform); | 
|       var offset = this._handleWidth / 2 + LABEL_GAP; | 
|       var textPoint = graphic.applyTransform([orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), this._size[1] / 2], barTransform); | 
|       handleLabels[handleIndex].setStyle({ | 
|         x: textPoint[0], | 
|         y: textPoint[1], | 
|         verticalAlign: orient === HORIZONTAL ? 'middle' : direction, | 
|         align: orient === HORIZONTAL ? direction : 'center', | 
|         text: labelTexts[handleIndex] | 
|       }); | 
|     } | 
|   }; | 
|   SliderZoomView.prototype._formatLabel = function (value, axis) { | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var labelFormatter = dataZoomModel.get('labelFormatter'); | 
|     var labelPrecision = dataZoomModel.get('labelPrecision'); | 
|     if (labelPrecision == null || labelPrecision === 'auto') { | 
|       labelPrecision = axis.getPixelPrecision(); | 
|     } | 
|     var valueStr = value == null || isNaN(value) ? '' | 
|     // FIXME Glue code | 
|     : axis.type === 'category' || axis.type === 'time' ? axis.scale.getLabel({ | 
|       value: Math.round(value) | 
|     }) | 
|     // param of toFixed should less then 20. | 
|     : value.toFixed(Math.min(labelPrecision, 20)); | 
|     return isFunction(labelFormatter) ? labelFormatter(value, valueStr) : isString(labelFormatter) ? labelFormatter.replace('{value}', valueStr) : valueStr; | 
|   }; | 
|   /** | 
|    * @param isEmphasis true: show, false: hide | 
|    */ | 
|   SliderZoomView.prototype._showDataInfo = function (isEmphasis) { | 
|     var handleLabel = this.dataZoomModel.get('handleLabel') || {}; | 
|     var normalShow = handleLabel.show || false; | 
|     var emphasisHandleLabel = this.dataZoomModel.getModel(['emphasis', 'handleLabel']); | 
|     var emphasisShow = emphasisHandleLabel.get('show') || false; | 
|     // Dragging is considered as emphasis, unless emphasisShow is false | 
|     var toShow = isEmphasis || this._dragging ? emphasisShow : normalShow; | 
|     var displayables = this._displayables; | 
|     var handleLabels = displayables.handleLabels; | 
|     handleLabels[0].attr('invisible', !toShow); | 
|     handleLabels[1].attr('invisible', !toShow); | 
|     // Highlight move handle | 
|     displayables.moveHandle && this.api[toShow ? 'enterEmphasis' : 'leaveEmphasis'](displayables.moveHandle, 1); | 
|   }; | 
|   SliderZoomView.prototype._onDragMove = function (handleIndex, dx, dy, event) { | 
|     this._dragging = true; | 
|     // For mobile device, prevent screen slider on the button. | 
|     eventTool.stop(event.event); | 
|     // Transform dx, dy to bar coordination. | 
|     var barTransform = this._displayables.sliderGroup.getLocalTransform(); | 
|     var vertex = graphic.applyTransform([dx, dy], barTransform, true); | 
|     var changed = this._updateInterval(handleIndex, vertex[0]); | 
|     var realtime = this.dataZoomModel.get('realtime'); | 
|     this._updateView(!realtime); | 
|     // Avoid dispatch dataZoom repeatly but range not changed, | 
|     // which cause bad visual effect when progressive enabled. | 
|     changed && realtime && this._dispatchZoomAction(true); | 
|   }; | 
|   SliderZoomView.prototype._onDragEnd = function () { | 
|     this._dragging = false; | 
|     this._showDataInfo(false); | 
|     // While in realtime mode and stream mode, dispatch action when | 
|     // drag end will cause the whole view rerender, which is unnecessary. | 
|     var realtime = this.dataZoomModel.get('realtime'); | 
|     !realtime && this._dispatchZoomAction(false); | 
|   }; | 
|   SliderZoomView.prototype._onClickPanel = function (e) { | 
|     var size = this._size; | 
|     var localPoint = this._displayables.sliderGroup.transformCoordToLocal(e.offsetX, e.offsetY); | 
|     if (localPoint[0] < 0 || localPoint[0] > size[0] || localPoint[1] < 0 || localPoint[1] > size[1]) { | 
|       return; | 
|     } | 
|     var handleEnds = this._handleEnds; | 
|     var center = (handleEnds[0] + handleEnds[1]) / 2; | 
|     var changed = this._updateInterval('all', localPoint[0] - center); | 
|     this._updateView(); | 
|     changed && this._dispatchZoomAction(false); | 
|   }; | 
|   SliderZoomView.prototype._onBrushStart = function (e) { | 
|     var x = e.offsetX; | 
|     var y = e.offsetY; | 
|     this._brushStart = new graphic.Point(x, y); | 
|     this._brushing = true; | 
|     this._brushStartTime = +new Date(); | 
|     // this._updateBrushRect(x, y); | 
|   }; | 
|   SliderZoomView.prototype._onBrushEnd = function (e) { | 
|     if (!this._brushing) { | 
|       return; | 
|     } | 
|     var brushRect = this._displayables.brushRect; | 
|     this._brushing = false; | 
|     if (!brushRect) { | 
|       return; | 
|     } | 
|     brushRect.attr('ignore', true); | 
|     var brushShape = brushRect.shape; | 
|     var brushEndTime = +new Date(); | 
|     // console.log(brushEndTime - this._brushStartTime); | 
|     if (brushEndTime - this._brushStartTime < 200 && Math.abs(brushShape.width) < 5) { | 
|       // Will treat it as a click | 
|       return; | 
|     } | 
|     var viewExtend = this._getViewExtent(); | 
|     var percentExtent = [0, 100]; | 
|     this._range = asc([linearMap(brushShape.x, viewExtend, percentExtent, true), linearMap(brushShape.x + brushShape.width, viewExtend, percentExtent, true)]); | 
|     this._handleEnds = [brushShape.x, brushShape.x + brushShape.width]; | 
|     this._updateView(); | 
|     this._dispatchZoomAction(false); | 
|   }; | 
|   SliderZoomView.prototype._onBrush = function (e) { | 
|     if (this._brushing) { | 
|       // For mobile device, prevent screen slider on the button. | 
|       eventTool.stop(e.event); | 
|       this._updateBrushRect(e.offsetX, e.offsetY); | 
|     } | 
|   }; | 
|   SliderZoomView.prototype._updateBrushRect = function (mouseX, mouseY) { | 
|     var displayables = this._displayables; | 
|     var dataZoomModel = this.dataZoomModel; | 
|     var brushRect = displayables.brushRect; | 
|     if (!brushRect) { | 
|       brushRect = displayables.brushRect = new Rect({ | 
|         silent: true, | 
|         style: dataZoomModel.getModel('brushStyle').getItemStyle() | 
|       }); | 
|       displayables.sliderGroup.add(brushRect); | 
|     } | 
|     brushRect.attr('ignore', false); | 
|     var brushStart = this._brushStart; | 
|     var sliderGroup = this._displayables.sliderGroup; | 
|     var endPoint = sliderGroup.transformCoordToLocal(mouseX, mouseY); | 
|     var startPoint = sliderGroup.transformCoordToLocal(brushStart.x, brushStart.y); | 
|     var size = this._size; | 
|     endPoint[0] = Math.max(Math.min(size[0], endPoint[0]), 0); | 
|     brushRect.setShape({ | 
|       x: startPoint[0], | 
|       y: 0, | 
|       width: endPoint[0] - startPoint[0], | 
|       height: size[1] | 
|     }); | 
|   }; | 
|   /** | 
|    * This action will be throttled. | 
|    */ | 
|   SliderZoomView.prototype._dispatchZoomAction = function (realtime) { | 
|     var range = this._range; | 
|     this.api.dispatchAction({ | 
|       type: 'dataZoom', | 
|       from: this.uid, | 
|       dataZoomId: this.dataZoomModel.id, | 
|       animation: realtime ? REALTIME_ANIMATION_CONFIG : null, | 
|       start: range[0], | 
|       end: range[1] | 
|     }); | 
|   }; | 
|   SliderZoomView.prototype._findCoordRect = function () { | 
|     // Find the grid corresponding to the first axis referred by dataZoom. | 
|     var rect; | 
|     var coordSysInfoList = collectReferCoordSysModelInfo(this.dataZoomModel).infoList; | 
|     if (!rect && coordSysInfoList.length) { | 
|       var coordSys = coordSysInfoList[0].model.coordinateSystem; | 
|       rect = coordSys.getRect && coordSys.getRect(); | 
|     } | 
|     if (!rect) { | 
|       var width = this.api.getWidth(); | 
|       var height = this.api.getHeight(); | 
|       rect = { | 
|         x: width * 0.2, | 
|         y: height * 0.2, | 
|         width: width * 0.6, | 
|         height: height * 0.6 | 
|       }; | 
|     } | 
|     return rect; | 
|   }; | 
|   SliderZoomView.type = 'dataZoom.slider'; | 
|   return SliderZoomView; | 
| }(DataZoomView); | 
| function getOtherDim(thisDim) { | 
|   // FIXME | 
|   // 这个逻辑和getOtherAxis里一致,但是写在这里是否不好 | 
|   var map = { | 
|     x: 'y', | 
|     y: 'x', | 
|     radius: 'angle', | 
|     angle: 'radius' | 
|   }; | 
|   return map[thisDim]; | 
| } | 
| function getCursor(orient) { | 
|   return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; | 
| } | 
| export default SliderZoomView; |