/** * echarts组件:数据区域缩放 * * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 * @author Kener (@Kener-林峰, linzhifeng@baidu.com) * */ define(function (require) { var Base = require('./base'); // 图形依赖 var RectangleShape = require('zrender/shape/Rectangle'); var PolygonShape = require('zrender/shape/Polygon'); var IconShape = require('../util/shape/Icon'); var ecConfig = require('../config'); var ecDate = require('../util/date'); var zrUtil = require('zrender/tool/util'); /** * 构造函数 * @param {Object} messageCenter echart消息中心 * @param {ZRender} zr zrender实例 * @param {Object} option 图表参数 * @param {Object} component 组件 */ function DataZoom(ecTheme, messageCenter, zr, option, myChart) { Base.call(this, ecTheme, messageCenter, zr, option, myChart); var self = this; self._ondrift = function (dx, dy) { return self.__ondrift(this, dx, dy); }; self._ondragend = function () { return self.__ondragend(); }; this._fillerSize = 28; // 控件大小,水平布局为高,纵向布局为宽 this._handleSize = 8; // 手柄大小 // this._fillerShae; // 填充 // this._startShape; // 起始手柄 // this._endShape; // 结束手柄 // this._startFrameShape; // 起始特效边框 // this._endFrameShape; // 结束特效边框 // this._syncTicket; this._isSilence = false; this._zoom = {}; // this._originalData; this.option.dataZoom = this.reformOption(this.option.dataZoom); this.zoomOption = this.option.dataZoom; if (!this.myChart.canvasSupported) { // 不支持Canvas的强制关闭实时动画 this.zoomOption.realtime = false; } // 位置参数,通过计算所得x, y, width, height this._location = this._getLocation(); // 缩放参数 this._zoom = this._getZoom(); this._backupData(); if (this.option.dataZoom.show) { this._buildShape(); } this._syncData(); } DataZoom.prototype = { type : ecConfig.COMPONENT_TYPE_DATAZOOM, _buildShape : function () { this._buildBackground(); this._buildFiller(); this._buildHandle(); this._buildFrame(); for (var i = 0, l = this.shapeList.length; i < l; i++) { this.zr.addShape(this.shapeList[i]); } this._syncFrameShape(); }, /** * 根据选项计算实体的位置坐标 */ _getLocation : function () { var x; var y; var width; var height; var grid = this.component.grid; // 不指定则根据grid适配 if (this.zoomOption.orient == 'horizontal') { // 水平布局 width = this.zoomOption.width || grid.getWidth(); height = this.zoomOption.height || this._fillerSize; x = this.zoomOption.x != null ? this.zoomOption.x : grid.getX(); y = this.zoomOption.y != null ? this.zoomOption.y : (this.zr.getHeight() - height - 2); } else { // 垂直布局 width = this.zoomOption.width || this._fillerSize; height = this.zoomOption.height || grid.getHeight(); x = this.zoomOption.x != null ? this.zoomOption.x : 2; y = this.zoomOption.y != null ? this.zoomOption.y : grid.getY(); } return { x : x, y : y, width : width, height : height }; }, /** * 计算缩放参数 * 修正单坐标轴只传对象为数组。 */ _getZoom : function () { var series = this.option.series; var xAxis = this.option.xAxis; if (xAxis && !(xAxis instanceof Array)) { xAxis = [xAxis]; this.option.xAxis = xAxis; } var yAxis = this.option.yAxis; if (yAxis && !(yAxis instanceof Array)) { yAxis = [yAxis]; this.option.yAxis = yAxis; } var zoomSeriesIndex = []; var xAxisIndex; var yAxisIndex; var zOptIdx = this.zoomOption.xAxisIndex; if (xAxis && zOptIdx == null) { xAxisIndex = []; for (var i = 0, l = xAxis.length; i < l; i++) { // 横纵默认为类目轴 if (xAxis[i].type == 'category' || xAxis[i].type == null) { xAxisIndex.push(i); } } } else { if (zOptIdx instanceof Array) { xAxisIndex = zOptIdx; } else if (zOptIdx != null) { xAxisIndex = [zOptIdx]; } else { xAxisIndex = []; } } zOptIdx = this.zoomOption.yAxisIndex; if (yAxis && zOptIdx == null) { yAxisIndex = []; for (var i = 0, l = yAxis.length; i < l; i++) { if (yAxis[i].type == 'category') { yAxisIndex.push(i); } } } else { if (zOptIdx instanceof Array) { yAxisIndex = zOptIdx; } else if (zOptIdx != null) { yAxisIndex = [zOptIdx]; } else { yAxisIndex = []; } } // 找到缩放控制的所有series var serie; for (var i = 0, l = series.length; i < l; i++) { serie = series[i]; if (serie.type != ecConfig.CHART_TYPE_LINE && serie.type != ecConfig.CHART_TYPE_BAR && serie.type != ecConfig.CHART_TYPE_SCATTER && serie.type != ecConfig.CHART_TYPE_K ) { continue; } for (var j = 0, k = xAxisIndex.length; j < k; j++) { if (xAxisIndex[j] == (serie.xAxisIndex || 0)) { zoomSeriesIndex.push(i); break; } } for (var j = 0, k = yAxisIndex.length; j < k; j++) { if (yAxisIndex[j] == (serie.yAxisIndex || 0)) { zoomSeriesIndex.push(i); break; } } // 不指定接管坐标轴,则散点图、双数值轴折线图柱形图都被纳入接管范围 if (this.zoomOption.xAxisIndex == null && this.zoomOption.yAxisIndex == null && serie.data && serie.data[0] && serie.data[0] instanceof Array && (serie.type == ecConfig.CHART_TYPE_SCATTER || serie.type == ecConfig.CHART_TYPE_LINE || serie.type == ecConfig.CHART_TYPE_BAR) ) { zoomSeriesIndex.push(i); } } var start = this._zoom.start != null ? this._zoom.start : (this.zoomOption.start != null ? this.zoomOption.start : 0); var end = this._zoom.end != null ? this._zoom.end : (this.zoomOption.end != null ? this.zoomOption.end : 100); if (start > end) { // 大小颠倒自动翻转 start = start + end; end = start - end; start = start - end; } var size = Math.round( (end - start) / 100 * ( this.zoomOption.orient == 'horizontal' ? this._location.width : this._location.height ) ); return { start : start, end : end, start2 : 0, end2 : 100, size : size, xAxisIndex : xAxisIndex, yAxisIndex : yAxisIndex, seriesIndex : zoomSeriesIndex, scatterMap : this._zoom.scatterMap || {} }; }, _backupData : function () { this._originalData = { xAxis : {}, yAxis : {}, series : {} }; var xAxis = this.option.xAxis; var xAxisIndex = this._zoom.xAxisIndex; for (var i = 0, l = xAxisIndex.length; i < l; i++) { this._originalData.xAxis[xAxisIndex[i]] = xAxis[xAxisIndex[i]].data; } var yAxis = this.option.yAxis; var yAxisIndex = this._zoom.yAxisIndex; for (var i = 0, l = yAxisIndex.length; i < l; i++) { this._originalData.yAxis[yAxisIndex[i]] = yAxis[yAxisIndex[i]].data; } var series = this.option.series; var seriesIndex = this._zoom.seriesIndex; var serie; for (var i = 0, l = seriesIndex.length; i < l; i++) { serie = series[seriesIndex[i]]; this._originalData.series[seriesIndex[i]] = serie.data; if (serie.data && serie.data[0] && serie.data[0] instanceof Array && (serie.type == ecConfig.CHART_TYPE_SCATTER || serie.type == ecConfig.CHART_TYPE_LINE || serie.type == ecConfig.CHART_TYPE_BAR) ) { this._backupScale(); this._calculScatterMap(seriesIndex[i]); } } }, _calculScatterMap : function (seriesIndex) { this._zoom.scatterMap = this._zoom.scatterMap || {}; this._zoom.scatterMap[seriesIndex] = this._zoom.scatterMap[seriesIndex] || {}; var componentLibrary = require('../component'); // x轴极值 var Axis = componentLibrary.get('axis'); var axisOption = zrUtil.clone(this.option.xAxis); if (axisOption[0].type == 'category') { axisOption[0].type = 'value'; } // axisOption[0].scale = true; // axisOption[0].boundary = [0, 0]; if (axisOption[1] && axisOption[1].type == 'category') { axisOption[1].type = 'value'; } var vAxis = new Axis( this.ecTheme, null, // messageCenter false, // this.zr { xAxis: axisOption, series : this.option.series }, this, 'xAxis' ); var axisIndex = this.option.series[seriesIndex].xAxisIndex || 0; this._zoom.scatterMap[seriesIndex].x = vAxis.getAxis(axisIndex).getExtremum(); vAxis.dispose(); // y轴极值 axisOption = zrUtil.clone(this.option.yAxis); if (axisOption[0].type == 'category') { axisOption[0].type = 'value'; } // axisOption[0].scale = true; // axisOption[1].boundary = [0, 0]; if (axisOption[1] && axisOption[1].type == 'category') { axisOption[1].type = 'value'; } vAxis = new Axis( this.ecTheme, null, // messageCenter false, // this.zr { yAxis: axisOption, series : this.option.series }, this, 'yAxis' ); axisIndex = this.option.series[seriesIndex].yAxisIndex || 0; this._zoom.scatterMap[seriesIndex].y = vAxis.getAxis(axisIndex).getExtremum(); vAxis.dispose(); // console.log(this._zoom.scatterMap); }, _buildBackground : function () { var width = this._location.width; var height = this._location.height; // 背景 this.shapeList.push(new RectangleShape({ zlevel : this._zlevelBase, hoverable :false, style : { x : this._location.x, y : this._location.y, width : width, height : height, color : this.zoomOption.backgroundColor } })); // 数据阴影 var maxLength = 0; var xAxis = this._originalData.xAxis; var xAxisIndex = this._zoom.xAxisIndex; for (var i = 0, l = xAxisIndex.length; i < l; i++) { maxLength = Math.max( maxLength, xAxis[xAxisIndex[i]].length ); } var yAxis = this._originalData.yAxis; var yAxisIndex = this._zoom.yAxisIndex; for (var i = 0, l = yAxisIndex.length; i < l; i++) { maxLength = Math.max( maxLength, yAxis[yAxisIndex[i]].length ); } var seriesIndex = this._zoom.seriesIndex[0]; var data = this._originalData.series[seriesIndex]; var maxValue = Number.MIN_VALUE; var minValue = Number.MAX_VALUE; var value; for (var i = 0, l = data.length; i < l; i++) { value = data[i] != null ? (data[i].value != null ? data[i].value : data[i]) : 0; if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) { value = value[1]; // 收盘价 } if (isNaN(value)) { value = 0; } maxValue = Math.max(maxValue, value); minValue = Math.min(minValue, value); } var valueRange = maxValue - minValue; var pointList = []; var x = width / (maxLength - (maxLength > 1 ? 1 : 0)); var y = height / (maxLength - (maxLength > 1 ? 1 : 0)); var step = 1; if (this.zoomOption.orient == 'horizontal' && x < 1) { step = Math.floor(maxLength * 3 / width); } else if (this.zoomOption.orient == 'vertical' && y < 1){ step = Math.floor(maxLength * 3 / height); } for (var i = 0, l = maxLength; i < l; i += step) { value = data[i] != null ? (data[i].value != null ? data[i].value : data[i]) : 0; if (this.option.series[seriesIndex].type == ecConfig.CHART_TYPE_K) { value = value[1]; // 收盘价 } if (isNaN(value)) { value = 0; } if (this.zoomOption.orient == 'horizontal') { pointList.push([ this._location.x + x * i, this._location.y + height - 1 - Math.round( (value - minValue) / valueRange * (height - 10) ) ]); } else { pointList.push([ this._location.x + 1 + Math.round( (value - minValue) / valueRange * (width - 10) ), this._location.y + y * i ]); } } if (this.zoomOption.orient == 'horizontal') { pointList.push([ this._location.x + width, this._location.y + height ]); pointList.push([ this._location.x, this._location.y + height ]); } else { pointList.push([ this._location.x, this._location.y + height ]); pointList.push([ this._location.x, this._location.y ]); } this.shapeList.push(new PolygonShape({ zlevel : this._zlevelBase, style : { pointList : pointList, color : this.zoomOption.dataBackgroundColor }, hoverable : false })); }, /** * 构建填充物 */ _buildFiller : function () { this._fillerShae = { zlevel : this._zlevelBase, draggable : true, ondrift : this._ondrift, ondragend : this._ondragend, _type : 'filler' }; if (this.zoomOption.orient == 'horizontal') { // 横向 this._fillerShae.style = { x : this._location.x + Math.round(this._zoom.start / 100 * this._location.width) + this._handleSize, y : this._location.y, width : this._zoom.size - this._handleSize * 2, height : this._location.height, color : this.zoomOption.fillerColor, // strokeColor : '#fff', // this.zoomOption.handleColor, // lineWidth: 2, text : ':::', textPosition : 'inside' }; } else { // 纵向 this._fillerShae.style ={ x : this._location.x, y : this._location.y + Math.round(this._zoom.start / 100 * this._location.height) + this._handleSize, width : this._location.width, height : this._zoom.size - this._handleSize * 2, color : this.zoomOption.fillerColor, // strokeColor : '#fff', // this.zoomOption.handleColor, // lineWidth: 2, text : '::', textPosition : 'inside' }; } this._fillerShae.highlightStyle = { brushType: 'fill', color : 'rgba(0,0,0,0)' /* color : require('zrender/tool/color').alpha( this._fillerShae.style.color, 0 ) */ }; this._fillerShae = new RectangleShape(this._fillerShae); this.shapeList.push(this._fillerShae); }, /** * 构建拖拽手柄 */ _buildHandle : function () { this._startShape = { zlevel : this._zlevelBase, draggable : true, style : { iconType: 'rectangle', x: this._location.x, y: this._location.y, width: this._handleSize, height: this._handleSize, color: this.zoomOption.handleColor, text: '=', textPosition: 'inside' }, highlightStyle: { text: '', brushType: 'fill', textPosition: 'left' }, ondrift: this._ondrift, ondragend: this._ondragend }; if (this.zoomOption.orient == 'horizontal') { this._startShape.style.height = this._location.height; this._endShape = zrUtil.clone(this._startShape); this._startShape.style.x = this._fillerShae.style.x - this._handleSize, this._endShape.style.x = this._fillerShae.style.x + this._fillerShae.style.width; this._endShape.highlightStyle.textPosition = 'right'; } else { this._startShape.style.width = this._location.width; this._endShape = zrUtil.clone(this._startShape); this._startShape.style.y = this._fillerShae.style.y - this._handleSize; this._startShape.highlightStyle.textPosition = 'top'; this._endShape.style.y = this._fillerShae.style.y + this._fillerShae.style.height; this._endShape.highlightStyle.textPosition = 'bottom'; } this._startShape = new IconShape(this._startShape); this._endShape = new IconShape(this._endShape); this.shapeList.push(this._startShape); this.shapeList.push(this._endShape); }, /** * 构建特效边框 */ _buildFrame : function () { // 特效框线,亚像素优化 var x = this.subPixelOptimize(this._location.x, 1); var y = this.subPixelOptimize(this._location.y, 1); this._startFrameShape = { zlevel : this._zlevelBase, hoverable :false, style : { x : x, y : y, width : this._location.width - (x > this._location.x ? 1 : 0), height : this._location.height - (y > this._location.y ? 1 : 0), lineWidth: 1, brushType: 'stroke', strokeColor : this.zoomOption.handleColor } }; this._endFrameShape = zrUtil.clone(this._startFrameShape); this._startFrameShape = new RectangleShape(this._startFrameShape); this._endFrameShape = new RectangleShape(this._endFrameShape); this.shapeList.push(this._startFrameShape); this.shapeList.push(this._endFrameShape); return; }, _syncHandleShape : function () { if (this.zoomOption.orient == 'horizontal') { this._startShape.style.x = this._fillerShae.style.x - this._handleSize; this._endShape.style.x = this._fillerShae.style.x + this._fillerShae.style.width; this._zoom.start = Math.floor( (this._startShape.style.x - this._location.x) / this._location.width * 100 ); this._zoom.end = Math.ceil( (this._endShape.style.x + this._handleSize - this._location.x) / this._location.width * 100 ); } else { this._startShape.style.y = this._fillerShae.style.y - this._handleSize; this._endShape.style.y = this._fillerShae.style.y + this._fillerShae.style.height; this._zoom.start = Math.floor( (this._startShape.style.y - this._location.y) / this._location.height * 100 ); this._zoom.end = Math.ceil( (this._endShape.style.y + this._handleSize - this._location.y) / this._location.height * 100 ); } this.zr.modShape(this._startShape.id); this.zr.modShape(this._endShape.id); // 同步边框 this._syncFrameShape(); this.zr.refresh(); }, _syncFillerShape : function () { var a; var b; if (this.zoomOption.orient == 'horizontal') { a = this._startShape.style.x; b = this._endShape.style.x; this._fillerShae.style.x = Math.min(a, b) + this._handleSize; this._fillerShae.style.width = Math.abs(a - b) - this._handleSize; this._zoom.start = Math.floor( (Math.min(a, b) - this._location.x) / this._location.width * 100 ); this._zoom.end = Math.ceil( (Math.max(a, b) + this._handleSize - this._location.x) / this._location.width * 100 ); } else { a = this._startShape.style.y; b = this._endShape.style.y; this._fillerShae.style.y = Math.min(a, b) + this._handleSize; this._fillerShae.style.height = Math.abs(a - b) - this._handleSize; this._zoom.start = Math.floor( (Math.min(a, b) - this._location.y) / this._location.height * 100 ); this._zoom.end = Math.ceil( (Math.max(a, b) + this._handleSize - this._location.y) / this._location.height * 100 ); } this.zr.modShape(this._fillerShae.id); // 同步边框 this._syncFrameShape(); this.zr.refresh(); }, _syncFrameShape : function () { if (this.zoomOption.orient == 'horizontal') { this._startFrameShape.style.width = this._fillerShae.style.x - this._location.x; this._endFrameShape.style.x = this._fillerShae.style.x + this._fillerShae.style.width; this._endFrameShape.style.width = this._location.x + this._location.width - this._endFrameShape.style.x; } else { this._startFrameShape.style.height = this._fillerShae.style.y - this._location.y; this._endFrameShape.style.y = this._fillerShae.style.y + this._fillerShae.style.height; this._endFrameShape.style.height = this._location.y + this._location.height - this._endFrameShape.style.y; } this.zr.modShape(this._startFrameShape.id); this.zr.modShape(this._endFrameShape.id); }, _syncShape : function () { if (!this.zoomOption.show) { // 没有伸缩控件 return; } if (this.zoomOption.orient == 'horizontal') { this._startShape.style.x = this._location.x + this._zoom.start / 100 * this._location.width; this._endShape.style.x = this._location.x + this._zoom.end / 100 * this._location.width - this._handleSize; this._fillerShae.style.x = this._startShape.style.x + this._handleSize; this._fillerShae.style.width = this._endShape.style.x - this._startShape.style.x - this._handleSize; } else { this._startShape.style.y = this._location.y + this._zoom.start / 100 * this._location.height; this._endShape.style.y = this._location.y + this._zoom.end / 100 * this._location.height - this._handleSize; this._fillerShae.style.y = this._startShape.style.y + this._handleSize; this._fillerShae.style.height = this._endShape.style.y - this._startShape.style.y - this._handleSize; } this.zr.modShape(this._startShape.id); this.zr.modShape(this._endShape.id); this.zr.modShape(this._fillerShae.id); // 同步边框 this._syncFrameShape(); this.zr.refresh(); }, _syncData : function (dispatchNow) { var target; var start; var end; var length; var data; for (var key in this._originalData) { target = this._originalData[key]; for (var idx in target) { data = target[idx]; if (data == null) { continue; } length = data.length; start = Math.floor(this._zoom.start / 100 * length); end = Math.ceil(this._zoom.end / 100 * length); if (!(this.option[key][idx].data[0] instanceof Array) || this.option[key][idx].type == ecConfig.CHART_TYPE_K ) { this.option[key][idx].data = data.slice(start, end); } else { // 散点图,双数值轴折线图柱形图特殊处理 this._setScale(); this.option[key][idx].data = this._synScatterData(idx, data); } } } if (!this._isSilence && (this.zoomOption.realtime || dispatchNow)) { this.messageCenter.dispatch( ecConfig.EVENT.DATA_ZOOM, null, {zoom: this._zoom}, this.myChart ); } //this.zoomOption.start = this._zoom.start; //this.zoomOption.end = this._zoom.end; }, _synScatterData : function (seriesIndex, data) { if (this._zoom.start === 0 && this._zoom.end == 100 && this._zoom.start2 === 0 && this._zoom.end2 == 100 ) { return data; } var newData = []; var scale = this._zoom.scatterMap[seriesIndex]; var total; var xStart; var xEnd; var yStart; var yEnd; if (this.zoomOption.orient == 'horizontal') { total = scale.x.max - scale.x.min; xStart = this._zoom.start / 100 * total + scale.x.min; xEnd = this._zoom.end / 100 * total + scale.x.min; total = scale.y.max - scale.y.min; yStart = this._zoom.start2 / 100 * total + scale.y.min; yEnd = this._zoom.end2 / 100 * total + scale.y.min; } else { total = scale.x.max - scale.x.min; xStart = this._zoom.start2 / 100 * total + scale.x.min; xEnd = this._zoom.end2 / 100 * total + scale.x.min; total = scale.y.max - scale.y.min; yStart = this._zoom.start / 100 * total + scale.y.min; yEnd = this._zoom.end / 100 * total + scale.y.min; } // console.log(xStart,xEnd,yStart,yEnd); var value; for (var i = 0, l = data.length; i < l; i++) { value = data[i].value || data[i]; if (value[0] >= xStart && value[0] <= xEnd && value[1] >= yStart && value[1] <= yEnd ) { newData.push(data[i]); } } return newData; }, /** * 发生缩放后修改axis的scale */ _setScale: function() { var needScale = this._zoom.start !== 0 || this._zoom.end !== 100 || this._zoom.start2 !== 0 || this._zoom.end2 !== 100; var axis = { xAxis : this.option.xAxis, yAxis : this.option.yAxis }; for (var key in axis) { for (var i = 0, l = axis[key].length; i < l; i++) { axis[key][i].scale = needScale || axis[key][i]._scale; } } }, /** * 备份可能存在的scale设置 */ _backupScale: function() { var axis = { xAxis : this.option.xAxis, yAxis : this.option.yAxis }; for (var key in axis) { for (var i = 0, l = axis[key].length; i < l; i++) { axis[key][i]._scale = axis[key][i].scale; } } }, /** * 获取当前定位 */ _getDetail : function () { var key = this.zoomOption.orient == 'horizontal' ? 'xAxis' : 'yAxis'; var target = this._originalData[key]; for (var idx in target) { var data = target[idx]; if (data == null) { continue; } var length = data.length; var start = Math.floor(this._zoom.start / 100 * length); var end = Math.ceil(this._zoom.end / 100 * length); end -= end >= length ? 1 : 0; return { start : data[start].value != null ? data[start].value : data[start], end : data[end].value != null ? data[end].value : data[end], }; } var seriesIndex = this._zoom.seriesIndex[0]; var axisIndex = this.option.series[seriesIndex][key + 'Index'] || 0; var axisType = this.option[key][axisIndex].type; var min = this._zoom.scatterMap[seriesIndex][key.charAt(0)].min; var max = this._zoom.scatterMap[seriesIndex][key.charAt(0)].max; var gap = max - min; if (axisType == 'value') { return { start : min + gap * this._zoom.start / 100, end : min + gap * this._zoom.end / 100 }; } else if (axisType == 'time') { // 最优解 max = min + gap * this._zoom.end / 100; min = min + gap * this._zoom.start / 100; var formatter = ecDate.getAutoFormatter(min, max).formatter; return { start : ecDate.format(formatter, min), end : ecDate.format(formatter, max) }; } return { start : '', end : '' }; }, /** * 拖拽范围控制 */ __ondrift : function (shape, dx, dy) { if (this.zoomOption.zoomLock) { // zoomLock时把handle转成filler的拖拽 shape = this._fillerShae; } var detailSize = shape._type == 'filler' ? this._handleSize : 0; if (this.zoomOption.orient == 'horizontal') { if (shape.style.x + dx - detailSize <= this._location.x) { shape.style.x = this._location.x + detailSize; } else if (shape.style.x + dx + shape.style.width + detailSize >= this._location.x + this._location.width ) { shape.style.x = this._location.x + this._location.width - shape.style.width - detailSize; } else { shape.style.x += dx; } } else { if (shape.style.y + dy - detailSize <= this._location.y) { shape.style.y = this._location.y + detailSize; } else if (shape.style.y + dy + shape.style.height + detailSize >= this._location.y + this._location.height ) { shape.style.y = this._location.y + this._location.height - shape.style.height - detailSize; } else { shape.style.y += dy; } } if (shape._type == 'filler') { this._syncHandleShape(); } else { this._syncFillerShape(); } if (this.zoomOption.realtime) { this._syncData(); } if (this.zoomOption.showDetail) { var deltail = this._getDetail(); this._startShape.style.text = this._startShape.highlightStyle.text = deltail.start; this._endShape.style.text = this._endShape.highlightStyle.text = deltail.end; this._startShape.style.textPosition = this._startShape.highlightStyle.textPosition; this._endShape.style.textPosition = this._endShape.highlightStyle.textPosition; } return true; }, __ondragend : function () { if (this.zoomOption.showDetail) { this._startShape.style.text = this._endShape.style.text = '='; this._startShape.style.textPosition = this._endShape.style.textPosition = 'inside'; this.zr.modShape(this._startShape.id); this.zr.modShape(this._endShape.id); this.zr.refreshNextFrame(); } this.isDragend = true; }, /** * 数据项被拖拽出去 */ ondragend : function (param, status) { if (!this.isDragend || !param.target) { // 没有在当前实例上发生拖拽行为则直接返回 return; } !this.zoomOption.realtime && this._syncData(); // 别status = {}赋值啊!! status.dragOut = true; status.dragIn = true; if (!this._isSilence && !this.zoomOption.realtime) { this.messageCenter.dispatch( ecConfig.EVENT.DATA_ZOOM, null, {zoom: this._zoom}, this.myChart ); } status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍 // 处理完拖拽事件后复位 this.isDragend = false; return; }, ondataZoom : function (param, status) { status.needRefresh = true; return; }, absoluteZoom : function (param) { this._zoom.start = param.start; this._zoom.end = param.end; this._zoom.start2 = param.start2; this._zoom.end2 = param.end2; this._syncShape(); this._syncData(true); return; }, rectZoom : function (param) { if (!param) { // 重置拖拽 //this.zoomOption.start = //this.zoomOption.start2 = this._zoom.start = this._zoom.start2 = 0; //this.zoomOption.end = //this.zoomOption.end2 = this._zoom.end = this._zoom.end2 = 100; this._syncShape(); this._syncData(true); return this._zoom; } var gridArea = this.component.grid.getArea(); var rect = { x : param.x, y : param.y, width : param.width, height : param.height }; // 修正方向框选 if (rect.width < 0) { rect.x += rect.width; rect.width = -rect.width; } if (rect.height < 0) { rect.y += rect.height; rect.height = -rect.height; } // console.log(rect,this._zoom); // 剔除无效缩放 if (rect.x > gridArea.x + gridArea.width || rect.y > gridArea.y + gridArea.height) { return false; // 无效缩放 } // 修正框选超出 if (rect.x < gridArea.x) { rect.x = gridArea.x; } if (rect.x + rect.width > gridArea.x + gridArea.width) { rect.width = gridArea.x + gridArea.width - rect.x; } if (rect.y + rect.height > gridArea.y + gridArea.height) { rect.height = gridArea.y + gridArea.height - rect.y; } var total; var sdx = (rect.x - gridArea.x) / gridArea.width; var edx = 1 - (rect.x + rect.width - gridArea.x) / gridArea.width; var sdy = 1 - (rect.y + rect.height - gridArea.y) / gridArea.height; var edy = (rect.y - gridArea.y) / gridArea.height; // console.log('this',sdy,edy,this._zoom.start,this._zoom.end) if (this.zoomOption.orient == 'horizontal') { total = this._zoom.end - this._zoom.start; this._zoom.start += total * sdx; this._zoom.end -= total * edx; total = this._zoom.end2 - this._zoom.start2; this._zoom.start2 += total * sdy; this._zoom.end2 -= total * edy; } else { total = this._zoom.end - this._zoom.start; this._zoom.start += total * sdy; this._zoom.end -= total * edy; total = this._zoom.end2 - this._zoom.start2; this._zoom.start2 += total * sdx; this._zoom.end2 -= total * edx; } //console.log(this._zoom.start,this._zoom.end,this._zoom.start2,this._zoom.end2) //this.zoomOption.start = this._zoom.start; //this.zoomOption.end = this._zoom.end; //this.zoomOption.start2 = this._zoom.start2; //this.zoomOption.end2 = this._zoom.end2; //console.log(rect,gridArea,this._zoom,total) this._syncShape(); this._syncData(true); return this._zoom; }, syncBackupData : function (curOption) { var start; var target = this._originalData['series']; var curSeries = curOption.series; var curData; for (var i = 0, l = curSeries.length; i < l; i++) { curData = curSeries[i].data || curSeries[i].eventList; if (target[i]) { // dataZoom接管的 start = Math.floor(this._zoom.start / 100 * target[i].length); } else { // 非dataZoom接管 start = 0; } for (var j = 0, k = curData.length; j < k; j++) { //optionBackup.series[i].data[j + start] = curData[j]; if (target[i]) { // 同步内部备份 target[i][j + start] = curData[j]; } } } }, syncOption : function(magicOption) { this.silence(true); this.option = magicOption; this.option.dataZoom = this.reformOption(this.option.dataZoom); this.zoomOption = this.option.dataZoom; if (!this.myChart.canvasSupported) { // 不支持Canvas的强制关闭实时动画 this.zoomOption.realtime = false; } this.clear(); // 位置参数,通过计算所得x, y, width, height this._location = this._getLocation(); // 缩放参数 this._zoom = this._getZoom(); this._backupData(); if (this.option.dataZoom && this.option.dataZoom.show) { this._buildShape(); } this._syncData(); this.silence(false); }, silence : function (s) { this._isSilence = s; }, getRealDataIndex : function (sIdx, dIdx) { if (!this._originalData || (this._zoom.start === 0 && this._zoom.end == 100)) { return dIdx; } var sreies = this._originalData.series; if (sreies[sIdx]) { return Math.floor(this._zoom.start / 100 * sreies[sIdx].length) + dIdx; } return -1; }, /** * 避免dataZoom带来两次refresh,不设refresh接口,resize重复一下buildshape逻辑 */ resize : function () { this.clear(); // 位置参数,通过计算所得x, y, width, height this._location = this._getLocation(); // 缩放参数 this._zoom = this._getZoom(); if (this.option.dataZoom.show) { this._buildShape(); } } }; zrUtil.inherits(DataZoom, Base); require('../component').define('dataZoom', DataZoom); return DataZoom; });