You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1244 lines
48 KiB
1244 lines
48 KiB
/**
|
|
* echarts组件:工具箱
|
|
*
|
|
* @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
|
|
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
|
|
*
|
|
*/
|
|
define(function (require) {
|
|
var Base = require('./base');
|
|
|
|
// 图形依赖
|
|
var LineShape = require('zrender/shape/Line');
|
|
var ImageShape = require('zrender/shape/Image');
|
|
var RectangleShape = require('zrender/shape/Rectangle');
|
|
var IconShape = require('../util/shape/Icon');
|
|
|
|
var ecConfig = require('../config');
|
|
ecConfig.toolbox = {
|
|
zlevel: 0, // 一级层叠
|
|
z: 6, // 二级层叠
|
|
show: false,
|
|
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
|
|
// 'horizontal' ¦ 'vertical'
|
|
x: 'right', // 水平安放位置,默认为全图右对齐,可选为:
|
|
// 'center' ¦ 'left' ¦ 'right'
|
|
// ¦ {number}(x坐标,单位px)
|
|
y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
|
|
// 'top' ¦ 'bottom' ¦ 'center'
|
|
// ¦ {number}(y坐标,单位px)
|
|
color: ['#1e90ff','#22bb22','#4b0082','#d2691e'],
|
|
disableColor: '#ddd',
|
|
effectiveColor: 'red',
|
|
backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色
|
|
borderColor: '#ccc', // 工具箱边框颜色
|
|
borderWidth: 0, // 工具箱边框线宽,单位px,默认为0(无边框)
|
|
padding: 5, // 工具箱内边距,单位px,默认各方向内边距为5,
|
|
// 接受数组分别设定上右下左边距,同css
|
|
itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
|
|
// 横向布局时为水平间隔,纵向布局时为纵向间隔
|
|
itemSize: 16, // 工具箱图形宽度
|
|
showTitle: true,
|
|
// textStyle: {},
|
|
feature: {
|
|
mark: {
|
|
show: false,
|
|
title: {
|
|
mark: '辅助线开关',
|
|
markUndo: '删除辅助线',
|
|
markClear: '清空辅助线'
|
|
},
|
|
lineStyle: {
|
|
width: 1,
|
|
color: '#1e90ff',
|
|
type: 'dashed'
|
|
}
|
|
},
|
|
dataZoom: {
|
|
show: false,
|
|
title: {
|
|
dataZoom: '区域缩放',
|
|
dataZoomReset: '区域缩放后退'
|
|
}
|
|
},
|
|
dataView: {
|
|
show: false,
|
|
title: '数据视图',
|
|
readOnly: false,
|
|
lang: ['数据视图', '关闭', '刷新']
|
|
},
|
|
magicType: {
|
|
show: false,
|
|
title: {
|
|
line: '折线图切换',
|
|
bar: '柱形图切换',
|
|
stack: '堆积',
|
|
tiled: '平铺',
|
|
force: '力导向布局图切换',
|
|
chord: '和弦图切换',
|
|
pie: '饼图切换',
|
|
funnel: '漏斗图切换'
|
|
},
|
|
/*
|
|
option: {
|
|
line: {},
|
|
bar: {},
|
|
stack: {},
|
|
tiled: {},
|
|
force: {},
|
|
chord: {},
|
|
pie: {},
|
|
funnel: {}
|
|
},
|
|
*/
|
|
type: [] // 'line', 'bar', 'stack', 'tiled', 'force', 'chord', 'pie', 'funnel'
|
|
},
|
|
restore: {
|
|
show: false,
|
|
title: '还原'
|
|
},
|
|
saveAsImage: {
|
|
show: false,
|
|
title: '保存为图片',
|
|
type: 'png',
|
|
lang: ['点击保存']
|
|
}
|
|
}
|
|
};
|
|
|
|
var zrUtil = require('zrender/tool/util');
|
|
var zrConfig = require('zrender/config');
|
|
var zrEvent = require('zrender/tool/event');
|
|
|
|
var _MAGICTYPE_STACK = 'stack';
|
|
var _MAGICTYPE_TILED = 'tiled';
|
|
|
|
/**
|
|
* 构造函数
|
|
* @param {Object} messageCenter echart消息中心
|
|
* @param {ZRender} zr zrender实例
|
|
* @param {HtmlElement} dom 目标对象
|
|
* @param {ECharts} myChart 当前图表实例
|
|
*/
|
|
function Toolbox(ecTheme, messageCenter, zr, option, myChart) {
|
|
Base.call(this, ecTheme, messageCenter, zr, option, myChart);
|
|
|
|
this.dom = myChart.dom;
|
|
|
|
this._magicType = {};
|
|
this._magicMap = {};
|
|
this._isSilence = false;
|
|
|
|
this._iconList;
|
|
this._iconShapeMap = {};
|
|
//this._itemGroupLocation;
|
|
this._featureTitle = {}; // 文字
|
|
this._featureIcon = {}; // 图标
|
|
this._featureColor = {}; // 颜色
|
|
this._featureOption = {};
|
|
this._enableColor = 'red';
|
|
this._disableColor = '#ccc';
|
|
// this._markStart;
|
|
// this._marking;
|
|
// this._markShape;
|
|
// this._zoomStart;
|
|
// this._zooming;
|
|
// this._zoomShape;
|
|
// this._zoomQueue;
|
|
// this._dataView;
|
|
this._markShapeList = [];
|
|
var self = this;
|
|
self._onMark = function (param) {
|
|
self.__onMark(param);
|
|
};
|
|
self._onMarkUndo = function (param) {
|
|
self.__onMarkUndo(param);
|
|
};
|
|
self._onMarkClear = function (param) {
|
|
self.__onMarkClear(param);
|
|
};
|
|
self._onDataZoom = function (param) {
|
|
self.__onDataZoom(param);
|
|
};
|
|
self._onDataZoomReset = function (param) {
|
|
self.__onDataZoomReset(param);
|
|
};
|
|
self._onDataView = function (param) {
|
|
self.__onDataView(param);
|
|
};
|
|
self._onRestore = function (param) {
|
|
self.__onRestore(param);
|
|
};
|
|
self._onSaveAsImage = function (param) {
|
|
self.__onSaveAsImage(param);
|
|
};
|
|
self._onMagicType = function (param) {
|
|
self.__onMagicType(param);
|
|
};
|
|
self._onCustomHandler = function (param) {
|
|
self.__onCustomHandler(param);
|
|
};
|
|
self._onmousemove = function (param) {
|
|
return self.__onmousemove(param);
|
|
};
|
|
|
|
self._onmousedown = function (param) {
|
|
return self.__onmousedown(param);
|
|
};
|
|
|
|
self._onmouseup = function (param) {
|
|
return self.__onmouseup(param);
|
|
};
|
|
|
|
self._onclick = function (param) {
|
|
return self.__onclick(param);
|
|
};
|
|
}
|
|
|
|
Toolbox.prototype = {
|
|
type: ecConfig.COMPONENT_TYPE_TOOLBOX,
|
|
_buildShape: function () {
|
|
this._iconList = [];
|
|
var toolboxOption = this.option.toolbox;
|
|
this._enableColor = toolboxOption.effectiveColor;
|
|
this._disableColor = toolboxOption.disableColor;
|
|
var feature = toolboxOption.feature;
|
|
var iconName = [];
|
|
for (var key in feature){
|
|
if (feature[key].show) {
|
|
switch (key) {
|
|
case 'mark' :
|
|
iconName.push({ key: key, name: 'mark' });
|
|
iconName.push({ key: key, name: 'markUndo' });
|
|
iconName.push({ key: key, name: 'markClear' });
|
|
break;
|
|
case 'magicType' :
|
|
for (var i = 0, l = feature[key].type.length; i < l; i++) {
|
|
feature[key].title[feature[key].type[i] + 'Chart']
|
|
= feature[key].title[feature[key].type[i]];
|
|
if (feature[key].option) {
|
|
feature[key].option[feature[key].type[i] + 'Chart']
|
|
= feature[key].option[feature[key].type[i]];
|
|
}
|
|
iconName.push({ key: key, name: feature[key].type[i] + 'Chart' });
|
|
}
|
|
break;
|
|
case 'dataZoom' :
|
|
iconName.push({ key: key, name: 'dataZoom' });
|
|
iconName.push({ key: key, name: 'dataZoomReset' });
|
|
break;
|
|
case 'saveAsImage' :
|
|
if (this.canvasSupported) {
|
|
iconName.push({ key: key, name: 'saveAsImage' });
|
|
}
|
|
break;
|
|
default :
|
|
iconName.push({ key: key, name: key });
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (iconName.length > 0) {
|
|
var name;
|
|
var key;
|
|
for (var i = 0, l = iconName.length; i < l; i++) {
|
|
name = iconName[i].name;
|
|
key = iconName[i].key;
|
|
this._iconList.push(name);
|
|
this._featureTitle[name] = feature[key].title[name] || feature[key].title;
|
|
if (feature[key].icon) {
|
|
this._featureIcon[name] = feature[key].icon[name] || feature[key].icon;
|
|
}
|
|
if (feature[key].color) {
|
|
this._featureColor[name] = feature[key].color[name] || feature[key].color;
|
|
}
|
|
if (feature[key].option) {
|
|
this._featureOption[name] = feature[key].option[name]
|
|
|| feature[key].option;
|
|
}
|
|
}
|
|
this._itemGroupLocation = this._getItemGroupLocation();
|
|
|
|
this._buildBackground();
|
|
this._buildItem();
|
|
|
|
for (var i = 0, l = this.shapeList.length; i < l; i++) {
|
|
this.zr.addShape(this.shapeList[i]);
|
|
}
|
|
if (this._iconShapeMap['mark']) {
|
|
this._iconDisable(this._iconShapeMap['markUndo']);
|
|
this._iconDisable(this._iconShapeMap['markClear']);
|
|
}
|
|
if (this._iconShapeMap['dataZoomReset'] && this._zoomQueue.length === 0) {
|
|
this._iconDisable(this._iconShapeMap['dataZoomReset']);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 构建所有图例元素
|
|
*/
|
|
_buildItem: function () {
|
|
var toolboxOption = this.option.toolbox;
|
|
var iconLength = this._iconList.length;
|
|
var lastX = this._itemGroupLocation.x;
|
|
var lastY = this._itemGroupLocation.y;
|
|
var itemSize = toolboxOption.itemSize;
|
|
var itemGap = toolboxOption.itemGap;
|
|
var itemShape;
|
|
|
|
var color = toolboxOption.color instanceof Array
|
|
? toolboxOption.color : [toolboxOption.color];
|
|
|
|
var textFont = this.getFont(toolboxOption.textStyle);
|
|
var textPosition;
|
|
var textAlign;
|
|
var textBaseline;
|
|
if (toolboxOption.orient === 'horizontal') {
|
|
textPosition = this._itemGroupLocation.y / this.zr.getHeight() < 0.5
|
|
? 'bottom' : 'top';
|
|
textAlign = this._itemGroupLocation.x / this.zr.getWidth() < 0.5
|
|
? 'left' : 'right';
|
|
textBaseline = this._itemGroupLocation.y / this.zr.getHeight() < 0.5
|
|
? 'top' : 'bottom';
|
|
}
|
|
else {
|
|
textPosition = this._itemGroupLocation.x / this.zr.getWidth() < 0.5
|
|
? 'right' : 'left';
|
|
}
|
|
|
|
this._iconShapeMap = {};
|
|
var self = this;
|
|
|
|
for (var i = 0; i < iconLength; i++) {
|
|
// 图形
|
|
itemShape = {
|
|
type: 'icon',
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
style: {
|
|
x: lastX,
|
|
y: lastY,
|
|
width: itemSize,
|
|
height: itemSize,
|
|
iconType: this._iconList[i],
|
|
lineWidth: 1,
|
|
strokeColor: this._featureColor[this._iconList[i]]
|
|
|| color[i % color.length],
|
|
brushType: 'stroke'
|
|
},
|
|
highlightStyle: {
|
|
lineWidth: 1,
|
|
text: toolboxOption.showTitle
|
|
? this._featureTitle[this._iconList[i]]
|
|
: undefined,
|
|
textFont: textFont,
|
|
textPosition: textPosition,
|
|
strokeColor: this._featureColor[this._iconList[i]]
|
|
|| color[i % color.length]
|
|
},
|
|
hoverable: true,
|
|
clickable: true
|
|
};
|
|
|
|
if (this._featureIcon[this._iconList[i]]) {
|
|
itemShape.style.image = this._featureIcon[this._iconList[i]].replace(
|
|
new RegExp('^image:\\/\\/'), ''
|
|
);
|
|
itemShape.style.opacity = 0.8;
|
|
itemShape.highlightStyle.opacity = 1;
|
|
itemShape.type = 'image';
|
|
}
|
|
|
|
if (toolboxOption.orient === 'horizontal') {
|
|
// 修正左对齐第一个或右对齐最后一个
|
|
if (i === 0 && textAlign === 'left') {
|
|
itemShape.highlightStyle.textPosition = 'specific';
|
|
itemShape.highlightStyle.textAlign = textAlign;
|
|
itemShape.highlightStyle.textBaseline = textBaseline;
|
|
itemShape.highlightStyle.textX = lastX;
|
|
itemShape.highlightStyle.textY = textBaseline === 'top'
|
|
? lastY + itemSize + 10
|
|
: lastY - 10;
|
|
}
|
|
if (i === iconLength - 1 && textAlign === 'right') {
|
|
itemShape.highlightStyle.textPosition = 'specific';
|
|
itemShape.highlightStyle.textAlign = textAlign;
|
|
itemShape.highlightStyle.textBaseline = textBaseline;
|
|
itemShape.highlightStyle.textX = lastX + itemSize;
|
|
itemShape.highlightStyle.textY = textBaseline === 'top'
|
|
? lastY + itemSize + 10
|
|
: lastY - 10;
|
|
}
|
|
}
|
|
|
|
switch(this._iconList[i]) {
|
|
case 'mark':
|
|
itemShape.onclick = self._onMark;
|
|
break;
|
|
case 'markUndo':
|
|
itemShape.onclick = self._onMarkUndo;
|
|
break;
|
|
case 'markClear':
|
|
itemShape.onclick = self._onMarkClear;
|
|
break;
|
|
case 'dataZoom':
|
|
itemShape.onclick = self._onDataZoom;
|
|
break;
|
|
case 'dataZoomReset':
|
|
itemShape.onclick = self._onDataZoomReset;
|
|
break;
|
|
case 'dataView' :
|
|
if (!this._dataView) {
|
|
var DataView = require('./dataView');
|
|
this._dataView = new DataView(
|
|
this.ecTheme, this.messageCenter, this.zr, this.option, this.myChart
|
|
);
|
|
}
|
|
itemShape.onclick = self._onDataView;
|
|
break;
|
|
case 'restore':
|
|
itemShape.onclick = self._onRestore;
|
|
break;
|
|
case 'saveAsImage':
|
|
itemShape.onclick = self._onSaveAsImage;
|
|
break;
|
|
default:
|
|
if (this._iconList[i].match('Chart')) {
|
|
itemShape._name = this._iconList[i].replace('Chart', '');
|
|
itemShape.onclick = self._onMagicType;
|
|
}
|
|
else {
|
|
itemShape.onclick = self._onCustomHandler;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (itemShape.type === 'icon') {
|
|
itemShape = new IconShape(itemShape);
|
|
}
|
|
else if (itemShape.type === 'image') {
|
|
itemShape = new ImageShape(itemShape);
|
|
}
|
|
this.shapeList.push(itemShape);
|
|
this._iconShapeMap[this._iconList[i]] = itemShape;
|
|
|
|
if (toolboxOption.orient === 'horizontal') {
|
|
lastX += itemSize + itemGap;
|
|
}
|
|
else {
|
|
lastY += itemSize + itemGap;
|
|
}
|
|
}
|
|
},
|
|
|
|
_buildBackground: function () {
|
|
var toolboxOption = this.option.toolbox;
|
|
var padding = this.reformCssArray(this.option.toolbox.padding);
|
|
|
|
this.shapeList.push(new RectangleShape({
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
hoverable :false,
|
|
style: {
|
|
x: this._itemGroupLocation.x - padding[3],
|
|
y: this._itemGroupLocation.y - padding[0],
|
|
width: this._itemGroupLocation.width + padding[3] + padding[1],
|
|
height: this._itemGroupLocation.height + padding[0] + padding[2],
|
|
brushType: toolboxOption.borderWidth === 0 ? 'fill' : 'both',
|
|
color: toolboxOption.backgroundColor,
|
|
strokeColor: toolboxOption.borderColor,
|
|
lineWidth: toolboxOption.borderWidth
|
|
}
|
|
}));
|
|
},
|
|
|
|
/**
|
|
* 根据选项计算图例实体的位置坐标
|
|
*/
|
|
_getItemGroupLocation: function () {
|
|
var toolboxOption = this.option.toolbox;
|
|
var padding = this.reformCssArray(this.option.toolbox.padding);
|
|
var iconLength = this._iconList.length;
|
|
var itemGap = toolboxOption.itemGap;
|
|
var itemSize = toolboxOption.itemSize;
|
|
var totalWidth = 0;
|
|
var totalHeight = 0;
|
|
|
|
if (toolboxOption.orient === 'horizontal') {
|
|
// 水平布局,计算总宽度,别忘减去最后一个的itemGap
|
|
totalWidth = (itemSize + itemGap) * iconLength - itemGap;
|
|
totalHeight = itemSize;
|
|
}
|
|
else {
|
|
// 垂直布局,计算总高度
|
|
totalHeight = (itemSize + itemGap) * iconLength - itemGap;
|
|
totalWidth = itemSize;
|
|
}
|
|
|
|
var x;
|
|
var zrWidth = this.zr.getWidth();
|
|
switch (toolboxOption.x) {
|
|
case 'center' :
|
|
x = Math.floor((zrWidth - totalWidth) / 2);
|
|
break;
|
|
case 'left' :
|
|
x = padding[3] + toolboxOption.borderWidth;
|
|
break;
|
|
case 'right' :
|
|
x = zrWidth
|
|
- totalWidth
|
|
- padding[1]
|
|
- toolboxOption.borderWidth;
|
|
break;
|
|
default :
|
|
x = toolboxOption.x - 0;
|
|
x = isNaN(x) ? 0 : x;
|
|
break;
|
|
}
|
|
|
|
var y;
|
|
var zrHeight = this.zr.getHeight();
|
|
switch (toolboxOption.y) {
|
|
case 'top' :
|
|
y = padding[0] + toolboxOption.borderWidth;
|
|
break;
|
|
case 'bottom' :
|
|
y = zrHeight
|
|
- totalHeight
|
|
- padding[2]
|
|
- toolboxOption.borderWidth;
|
|
break;
|
|
case 'center' :
|
|
y = Math.floor((zrHeight - totalHeight) / 2);
|
|
break;
|
|
default :
|
|
y = toolboxOption.y - 0;
|
|
y = isNaN(y) ? 0 : y;
|
|
break;
|
|
}
|
|
|
|
return {
|
|
x: x,
|
|
y: y,
|
|
width: totalWidth,
|
|
height: totalHeight
|
|
};
|
|
},
|
|
|
|
__onmousemove: function (param) {
|
|
if (this._marking) {
|
|
this._markShape.style.xEnd = zrEvent.getX(param.event);
|
|
this._markShape.style.yEnd = zrEvent.getY(param.event);
|
|
this.zr.addHoverShape(this._markShape);
|
|
}
|
|
if (this._zooming) {
|
|
this._zoomShape.style.width =
|
|
zrEvent.getX(param.event) - this._zoomShape.style.x;
|
|
this._zoomShape.style.height =
|
|
zrEvent.getY(param.event) - this._zoomShape.style.y;
|
|
this.zr.addHoverShape(this._zoomShape);
|
|
this.dom.style.cursor = 'crosshair';
|
|
zrEvent.stop(param.event);
|
|
}
|
|
if (this._zoomStart
|
|
&& (this.dom.style.cursor != 'pointer' && this.dom.style.cursor != 'move')
|
|
) {
|
|
this.dom.style.cursor = 'crosshair';
|
|
}
|
|
},
|
|
|
|
__onmousedown: function (param) {
|
|
if (param.target) {
|
|
return;
|
|
}
|
|
this._zooming = true;
|
|
var x = zrEvent.getX(param.event);
|
|
var y = zrEvent.getY(param.event);
|
|
var zoomOption = this.option.dataZoom || {};
|
|
this._zoomShape = new RectangleShape({
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
style: {
|
|
x: x,
|
|
y: y,
|
|
width: 1,
|
|
height: 1,
|
|
brushType: 'both'
|
|
},
|
|
highlightStyle: {
|
|
lineWidth: 2,
|
|
color: zoomOption.fillerColor
|
|
|| ecConfig.dataZoom.fillerColor,
|
|
strokeColor: zoomOption.handleColor
|
|
|| ecConfig.dataZoom.handleColor,
|
|
brushType: 'both'
|
|
}
|
|
});
|
|
this.zr.addHoverShape(this._zoomShape);
|
|
return true; // 阻塞全局事件
|
|
},
|
|
|
|
__onmouseup: function (/*param*/) {
|
|
if (!this._zoomShape
|
|
|| Math.abs(this._zoomShape.style.width) < 10
|
|
|| Math.abs(this._zoomShape.style.height) < 10
|
|
) {
|
|
this._zooming = false;
|
|
return true;
|
|
}
|
|
if (this._zooming && this.component.dataZoom) {
|
|
this._zooming = false;
|
|
|
|
var zoom = this.component.dataZoom.rectZoom(this._zoomShape.style);
|
|
if (zoom) {
|
|
this._zoomQueue.push({
|
|
start: zoom.start,
|
|
end: zoom.end,
|
|
start2: zoom.start2,
|
|
end2: zoom.end2
|
|
});
|
|
this._iconEnable(this._iconShapeMap['dataZoomReset']);
|
|
this.zr.refreshNextFrame();
|
|
}
|
|
}
|
|
return true; // 阻塞全局事件
|
|
},
|
|
|
|
__onclick: function (param) {
|
|
if (param.target) {
|
|
return;
|
|
}
|
|
if (this._marking) {
|
|
this._marking = false;
|
|
this._markShapeList.push(this._markShape);
|
|
this._iconEnable(this._iconShapeMap['markUndo']);
|
|
this._iconEnable(this._iconShapeMap['markClear']);
|
|
this.zr.addShape(this._markShape);
|
|
this.zr.refreshNextFrame();
|
|
}
|
|
else if (this._markStart) {
|
|
this._marking = true;
|
|
var x = zrEvent.getX(param.event);
|
|
var y = zrEvent.getY(param.event);
|
|
this._markShape = new LineShape({
|
|
zlevel: this.getZlevelBase(),
|
|
z: this.getZBase(),
|
|
style: {
|
|
xStart: x,
|
|
yStart: y,
|
|
xEnd: x,
|
|
yEnd: y,
|
|
lineWidth: this.query(
|
|
this.option,
|
|
'toolbox.feature.mark.lineStyle.width'
|
|
),
|
|
strokeColor: this.query(
|
|
this.option,
|
|
'toolbox.feature.mark.lineStyle.color'
|
|
),
|
|
lineType: this.query(
|
|
this.option,
|
|
'toolbox.feature.mark.lineStyle.type'
|
|
)
|
|
}
|
|
});
|
|
this.zr.addHoverShape(this._markShape);
|
|
}
|
|
},
|
|
|
|
__onMark: function (param) {
|
|
var target = param.target;
|
|
if (this._marking || this._markStart) {
|
|
// 取消
|
|
this._resetMark();
|
|
this.zr.refreshNextFrame();
|
|
}
|
|
else {
|
|
// 启用Mark
|
|
this._resetZoom(); // mark与dataZoom互斥
|
|
|
|
this.zr.modShape(target.id, {style: {strokeColor: this._enableColor}});
|
|
this.zr.refreshNextFrame();
|
|
this._markStart = true;
|
|
var self = this;
|
|
setTimeout(function (){
|
|
self.zr
|
|
&& self.zr.on(zrConfig.EVENT.CLICK, self._onclick)
|
|
&& self.zr.on(zrConfig.EVENT.MOUSEMOVE, self._onmousemove);
|
|
}, 10);
|
|
}
|
|
return true; // 阻塞全局事件
|
|
},
|
|
|
|
__onMarkUndo: function () {
|
|
if (this._marking) {
|
|
this._marking = false;
|
|
} else {
|
|
var len = this._markShapeList.length;
|
|
if (len >= 1) {
|
|
var target = this._markShapeList[len - 1];
|
|
this.zr.delShape(target.id);
|
|
this.zr.refreshNextFrame();
|
|
this._markShapeList.pop();
|
|
if (len === 1) {
|
|
this._iconDisable(this._iconShapeMap['markUndo']);
|
|
this._iconDisable(this._iconShapeMap['markClear']);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
|
|
__onMarkClear: function () {
|
|
if (this._marking) {
|
|
this._marking = false;
|
|
}
|
|
var len = this._markShapeList.length;
|
|
if (len > 0) {
|
|
while(len--) {
|
|
this.zr.delShape(this._markShapeList.pop().id);
|
|
}
|
|
this._iconDisable(this._iconShapeMap['markUndo']);
|
|
this._iconDisable(this._iconShapeMap['markClear']);
|
|
this.zr.refreshNextFrame();
|
|
}
|
|
return true;
|
|
},
|
|
|
|
__onDataZoom: function (param) {
|
|
var target = param.target;
|
|
if (this._zooming || this._zoomStart) {
|
|
// 取消
|
|
this._resetZoom();
|
|
this.zr.refreshNextFrame();
|
|
this.dom.style.cursor = 'default';
|
|
}
|
|
else {
|
|
// 启用Zoom
|
|
this._resetMark(); // mark与dataZoom互斥
|
|
|
|
this.zr.modShape(target.id, {style: {strokeColor: this._enableColor}});
|
|
this.zr.refreshNextFrame();
|
|
this._zoomStart = true;
|
|
var self = this;
|
|
setTimeout(function (){
|
|
self.zr
|
|
&& self.zr.on(zrConfig.EVENT.MOUSEDOWN, self._onmousedown)
|
|
&& self.zr.on(zrConfig.EVENT.MOUSEUP, self._onmouseup)
|
|
&& self.zr.on(zrConfig.EVENT.MOUSEMOVE, self._onmousemove);
|
|
}, 10);
|
|
|
|
this.dom.style.cursor = 'crosshair';
|
|
}
|
|
return true; // 阻塞全局事件
|
|
},
|
|
|
|
__onDataZoomReset: function () {
|
|
if (this._zooming) {
|
|
this._zooming = false;
|
|
}
|
|
this._zoomQueue.pop();
|
|
//console.log(this._zoomQueue)
|
|
if (this._zoomQueue.length > 0) {
|
|
this.component.dataZoom.absoluteZoom(
|
|
this._zoomQueue[this._zoomQueue.length - 1]
|
|
);
|
|
}
|
|
else {
|
|
this.component.dataZoom.rectZoom();
|
|
this._iconDisable(this._iconShapeMap['dataZoomReset']);
|
|
this.zr.refreshNextFrame();
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
_resetMark: function () {
|
|
this._marking = false;
|
|
if (this._markStart) {
|
|
this._markStart = false;
|
|
if (this._iconShapeMap['mark']) {
|
|
// 还原图标为未生效状态
|
|
this.zr.modShape(
|
|
this._iconShapeMap['mark'].id,
|
|
{
|
|
style: {
|
|
strokeColor: this._iconShapeMap['mark']
|
|
.highlightStyle
|
|
.strokeColor
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
this.zr.un(zrConfig.EVENT.CLICK, this._onclick);
|
|
this.zr.un(zrConfig.EVENT.MOUSEMOVE, this._onmousemove);
|
|
}
|
|
},
|
|
|
|
_resetZoom: function () {
|
|
this._zooming = false;
|
|
if (this._zoomStart) {
|
|
this._zoomStart = false;
|
|
if (this._iconShapeMap['dataZoom']) {
|
|
// 还原图标为未生效状态
|
|
this.zr.modShape(
|
|
this._iconShapeMap['dataZoom'].id,
|
|
{
|
|
style: {
|
|
strokeColor: this._iconShapeMap['dataZoom']
|
|
.highlightStyle
|
|
.strokeColor
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
this.zr.un(zrConfig.EVENT.MOUSEDOWN, this._onmousedown);
|
|
this.zr.un(zrConfig.EVENT.MOUSEUP, this._onmouseup);
|
|
this.zr.un(zrConfig.EVENT.MOUSEMOVE, this._onmousemove);
|
|
}
|
|
},
|
|
|
|
_iconDisable: function (target) {
|
|
if (target.type != 'image') {
|
|
this.zr.modShape(target.id, {
|
|
hoverable: false,
|
|
clickable: false,
|
|
style: {
|
|
strokeColor: this._disableColor
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
this.zr.modShape(target.id, {
|
|
hoverable: false,
|
|
clickable: false,
|
|
style: {
|
|
opacity: 0.3
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
_iconEnable: function (target) {
|
|
if (target.type != 'image') {
|
|
this.zr.modShape(target.id, {
|
|
hoverable: true,
|
|
clickable: true,
|
|
style: {
|
|
strokeColor: target.highlightStyle.strokeColor
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
this.zr.modShape(target.id, {
|
|
hoverable: true,
|
|
clickable: true,
|
|
style: {
|
|
opacity: 0.8
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
__onDataView: function () {
|
|
this._dataView.show(this.option);
|
|
return true;
|
|
},
|
|
|
|
__onRestore: function (){
|
|
this._resetMark();
|
|
this._resetZoom();
|
|
this.messageCenter.dispatch(ecConfig.EVENT.RESTORE, null, null, this.myChart);
|
|
return true;
|
|
},
|
|
|
|
__onSaveAsImage: function () {
|
|
var saveOption = this.option.toolbox.feature.saveAsImage;
|
|
var imgType = saveOption.type || 'png';
|
|
if (imgType != 'png' && imgType != 'jpeg') {
|
|
imgType = 'png';
|
|
}
|
|
|
|
var image;
|
|
if (!this.myChart.isConnected()) {
|
|
image = this.zr.toDataURL(
|
|
'image/' + imgType,
|
|
this.option.backgroundColor
|
|
&& this.option.backgroundColor.replace(' ','') === 'rgba(0,0,0,0)'
|
|
? '#fff' : this.option.backgroundColor
|
|
);
|
|
}
|
|
else {
|
|
image = this.myChart.getConnectedDataURL(imgType);
|
|
}
|
|
|
|
var downloadDiv = document.createElement('div');
|
|
downloadDiv.id = '__echarts_download_wrap__';
|
|
downloadDiv.style.cssText = 'position:fixed;'
|
|
+ 'z-index:99999;'
|
|
+ 'display:block;'
|
|
+ 'top:0;left:0;'
|
|
+ 'background-color:rgba(33,33,33,0.5);'
|
|
+ 'text-align:center;'
|
|
+ 'width:100%;'
|
|
+ 'height:100%;'
|
|
+ 'line-height:'
|
|
+ document.documentElement.clientHeight + 'px;';
|
|
|
|
var downloadLink = document.createElement('a');
|
|
//downloadLink.onclick = _saveImageForIE;
|
|
downloadLink.href = image;
|
|
downloadLink.setAttribute(
|
|
'download',
|
|
(saveOption.name
|
|
? saveOption.name
|
|
: (this.option.title && (this.option.title.text || this.option.title.subtext))
|
|
? (this.option.title.text || this.option.title.subtext)
|
|
: 'ECharts')
|
|
+ '.' + imgType
|
|
);
|
|
downloadLink.innerHTML = '<img style="vertical-align:middle" src="' + image
|
|
+ '" title="'
|
|
+ ((!!window.ActiveXObject || 'ActiveXObject' in window)
|
|
? '右键->图片另存为'
|
|
: (saveOption.lang ? saveOption.lang[0] : '点击保存'))
|
|
+ '"/>';
|
|
|
|
downloadDiv.appendChild(downloadLink);
|
|
document.body.appendChild(downloadDiv);
|
|
downloadLink = null;
|
|
downloadDiv = null;
|
|
|
|
setTimeout(function (){
|
|
var _d = document.getElementById('__echarts_download_wrap__');
|
|
if (_d) {
|
|
_d.onclick = function () {
|
|
var d = document.getElementById(
|
|
'__echarts_download_wrap__'
|
|
);
|
|
d.onclick = null;
|
|
d.innerHTML = '';
|
|
document.body.removeChild(d);
|
|
d = null;
|
|
};
|
|
_d = null;
|
|
}
|
|
}, 500);
|
|
|
|
/*
|
|
function _saveImageForIE() {
|
|
window.win = window.open(image);
|
|
win.document.execCommand("SaveAs");
|
|
win.close()
|
|
}
|
|
*/
|
|
return;
|
|
},
|
|
|
|
__onMagicType: function (param) {
|
|
this._resetMark();
|
|
var itemName = param.target._name;
|
|
if (!this._magicType[itemName]) {
|
|
// 启用
|
|
this._magicType[itemName] = true;
|
|
// 折柱互斥
|
|
if (itemName === ecConfig.CHART_TYPE_LINE) {
|
|
this._magicType[ecConfig.CHART_TYPE_BAR] = false;
|
|
}
|
|
else if (itemName === ecConfig.CHART_TYPE_BAR) {
|
|
this._magicType[ecConfig.CHART_TYPE_LINE] = false;
|
|
}
|
|
// 饼图漏斗互斥
|
|
if (itemName === ecConfig.CHART_TYPE_PIE) {
|
|
this._magicType[ecConfig.CHART_TYPE_FUNNEL] = false;
|
|
}
|
|
else if (itemName === ecConfig.CHART_TYPE_FUNNEL) {
|
|
this._magicType[ecConfig.CHART_TYPE_PIE] = false;
|
|
}
|
|
// 力导和弦互斥
|
|
if (itemName === ecConfig.CHART_TYPE_FORCE) {
|
|
this._magicType[ecConfig.CHART_TYPE_CHORD] = false;
|
|
}
|
|
else if (itemName === ecConfig.CHART_TYPE_CHORD) {
|
|
this._magicType[ecConfig.CHART_TYPE_FORCE] = false;
|
|
}
|
|
// 堆积平铺互斥
|
|
if (itemName === _MAGICTYPE_STACK) {
|
|
this._magicType[_MAGICTYPE_TILED] = false;
|
|
}
|
|
else if (itemName === _MAGICTYPE_TILED) {
|
|
this._magicType[_MAGICTYPE_STACK] = false;
|
|
}
|
|
this.messageCenter.dispatch(
|
|
ecConfig.EVENT.MAGIC_TYPE_CHANGED,
|
|
param.event,
|
|
{ magicType: this._magicType },
|
|
this.myChart
|
|
);
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
setMagicType: function (magicType) {
|
|
this._resetMark();
|
|
this._magicType = magicType;
|
|
|
|
!this._isSilence && this.messageCenter.dispatch(
|
|
ecConfig.EVENT.MAGIC_TYPE_CHANGED,
|
|
null,
|
|
{ magicType: this._magicType },
|
|
this.myChart
|
|
);
|
|
},
|
|
|
|
// 用户自定义扩展toolbox方法
|
|
__onCustomHandler: function (param) {
|
|
var target = param.target.style.iconType;
|
|
var featureHandler = this.option.toolbox.feature[target].onclick;
|
|
if (typeof featureHandler === 'function') {
|
|
featureHandler.call(this, this.option);
|
|
}
|
|
},
|
|
|
|
// 重置备份还原状态等
|
|
reset: function (newOption, isRestore) {
|
|
isRestore && this.clear();
|
|
|
|
if (this.query(newOption, 'toolbox.show')
|
|
&& this.query(newOption, 'toolbox.feature.magicType.show')
|
|
) {
|
|
var magicType = newOption.toolbox.feature.magicType.type;
|
|
var len = magicType.length;
|
|
this._magicMap = {}; // 标识可控类型
|
|
while (len--) {
|
|
this._magicMap[magicType[len]] = true;
|
|
}
|
|
|
|
len = newOption.series.length;
|
|
var oriType; // 备份还原可控类型
|
|
var axis;
|
|
while (len--) {
|
|
oriType = newOption.series[len].type;
|
|
if (this._magicMap[oriType]) {
|
|
axis = newOption.xAxis instanceof Array
|
|
? newOption.xAxis[newOption.series[len].xAxisIndex || 0]
|
|
: newOption.xAxis;
|
|
if (axis && (axis.type || 'category') === 'category') {
|
|
axis.__boundaryGap = axis.boundaryGap != null
|
|
? axis.boundaryGap : true;
|
|
}
|
|
axis = newOption.yAxis instanceof Array
|
|
? newOption.yAxis[newOption.series[len].yAxisIndex || 0]
|
|
: newOption.yAxis;
|
|
if (axis && axis.type === 'category') {
|
|
axis.__boundaryGap = axis.boundaryGap != null
|
|
? axis.boundaryGap : true;
|
|
}
|
|
newOption.series[len].__type = oriType;
|
|
// 避免不同类型图表类型的样式污染
|
|
newOption.series[len].__itemStyle = zrUtil.clone(
|
|
newOption.series[len].itemStyle || {}
|
|
);
|
|
}
|
|
|
|
if (this._magicMap[_MAGICTYPE_STACK] || this._magicMap[_MAGICTYPE_TILED]) {
|
|
newOption.series[len].__stack = newOption.series[len].stack;
|
|
}
|
|
}
|
|
}
|
|
|
|
this._magicType = isRestore ? {} : (this._magicType || {});
|
|
for (var itemName in this._magicType) {
|
|
if (this._magicType[itemName]) {
|
|
this.option = newOption;
|
|
this.getMagicOption();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 框选缩放
|
|
var zoomOption = newOption.dataZoom;
|
|
if (zoomOption && zoomOption.show) {
|
|
var start = zoomOption.start != null
|
|
&& zoomOption.start >= 0
|
|
&& zoomOption.start <= 100
|
|
? zoomOption.start : 0;
|
|
var end = zoomOption.end != null
|
|
&& zoomOption.end >= 0
|
|
&& zoomOption.end <= 100
|
|
? zoomOption.end : 100;
|
|
if (start > end) {
|
|
// 大小颠倒自动翻转
|
|
start = start + end;
|
|
end = start - end;
|
|
start = start - end;
|
|
}
|
|
this._zoomQueue = [{
|
|
start: start,
|
|
end: end,
|
|
start2: 0,
|
|
end2: 100
|
|
}];
|
|
}
|
|
else {
|
|
this._zoomQueue = [];
|
|
}
|
|
},
|
|
|
|
getMagicOption: function (){
|
|
var axis;
|
|
var chartType;
|
|
if (this._magicType[ecConfig.CHART_TYPE_LINE]
|
|
|| this._magicType[ecConfig.CHART_TYPE_BAR]
|
|
) {
|
|
// 图表类型有折柱切换
|
|
var boundaryGap = this._magicType[ecConfig.CHART_TYPE_LINE] ? false : true;
|
|
for (var i = 0, l = this.option.series.length; i < l; i++) {
|
|
chartType = this.option.series[i].type;
|
|
if (chartType == ecConfig.CHART_TYPE_LINE
|
|
|| chartType == ecConfig.CHART_TYPE_BAR
|
|
) {
|
|
axis = this.option.xAxis instanceof Array
|
|
? this.option.xAxis[this.option.series[i].xAxisIndex || 0]
|
|
: this.option.xAxis;
|
|
if (axis && (axis.type || 'category') === 'category') {
|
|
axis.boundaryGap = boundaryGap ? true : axis.__boundaryGap;
|
|
}
|
|
axis = this.option.yAxis instanceof Array
|
|
? this.option.yAxis[this.option.series[i].yAxisIndex || 0]
|
|
: this.option.yAxis;
|
|
if (axis && axis.type === 'category') {
|
|
axis.boundaryGap = boundaryGap ? true : axis.__boundaryGap;
|
|
}
|
|
}
|
|
}
|
|
|
|
this._defaultMagic(ecConfig.CHART_TYPE_LINE, ecConfig.CHART_TYPE_BAR);
|
|
}
|
|
this._defaultMagic(ecConfig.CHART_TYPE_CHORD, ecConfig.CHART_TYPE_FORCE);
|
|
this._defaultMagic(ecConfig.CHART_TYPE_PIE, ecConfig.CHART_TYPE_FUNNEL);
|
|
|
|
if (this._magicType[_MAGICTYPE_STACK] || this._magicType[_MAGICTYPE_TILED]) {
|
|
// 有堆积平铺切换
|
|
for (var i = 0, l = this.option.series.length; i < l; i++) {
|
|
if (this._magicType[_MAGICTYPE_STACK]) {
|
|
// 启用堆积
|
|
this.option.series[i].stack = '_ECHARTS_STACK_KENER_2014_';
|
|
chartType = _MAGICTYPE_STACK;
|
|
}
|
|
else if (this._magicType[_MAGICTYPE_TILED]) {
|
|
// 启用平铺
|
|
this.option.series[i].stack = null;
|
|
chartType = _MAGICTYPE_TILED;
|
|
}
|
|
if (this._featureOption[chartType + 'Chart']) {
|
|
zrUtil.merge(
|
|
this.option.series[i],
|
|
this._featureOption[chartType + 'Chart'] || {},
|
|
true
|
|
);
|
|
}
|
|
}
|
|
}
|
|
return this.option;
|
|
},
|
|
|
|
_defaultMagic : function(cType1, cType2) {
|
|
if (this._magicType[cType1] || this._magicType[cType2]) {
|
|
for (var i = 0, l = this.option.series.length; i < l; i++) {
|
|
var chartType = this.option.series[i].type;
|
|
if (chartType == cType1 || chartType == cType2) {
|
|
this.option.series[i].type = this._magicType[cType1] ? cType1 : cType2;
|
|
// 避免不同类型图表类型的样式污染
|
|
this.option.series[i].itemStyle = zrUtil.clone(
|
|
this.option.series[i].__itemStyle
|
|
);
|
|
chartType = this.option.series[i].type;
|
|
if (this._featureOption[chartType + 'Chart']) {
|
|
zrUtil.merge(
|
|
this.option.series[i],
|
|
this._featureOption[chartType + 'Chart'] || {},
|
|
true
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
silence: function (s) {
|
|
this._isSilence = s;
|
|
},
|
|
|
|
resize: function () {
|
|
this._resetMark();
|
|
this.clear();
|
|
if (this.option && this.option.toolbox && this.option.toolbox.show) {
|
|
this._buildShape();
|
|
}
|
|
if (this._dataView) {
|
|
this._dataView.resize();
|
|
}
|
|
},
|
|
|
|
hideDataView: function () {
|
|
if (this._dataView) {
|
|
this._dataView.hide();
|
|
}
|
|
},
|
|
|
|
clear: function(notMark) {
|
|
if (this.zr) {
|
|
this.zr.delShape(this.shapeList);
|
|
this.shapeList = [];
|
|
|
|
if (!notMark) {
|
|
this.zr.delShape(this._markShapeList);
|
|
this._markShapeList = [];
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 释放后实例不可用
|
|
*/
|
|
onbeforDispose: function () {
|
|
if (this._dataView) {
|
|
this._dataView.dispose();
|
|
this._dataView = null;
|
|
}
|
|
this._markShapeList = null;
|
|
},
|
|
|
|
/**
|
|
* 刷新
|
|
*/
|
|
refresh: function (newOption) {
|
|
if (newOption) {
|
|
this._resetMark();
|
|
this._resetZoom();
|
|
|
|
newOption.toolbox = this.reformOption(newOption.toolbox);
|
|
this.option = newOption;
|
|
|
|
this.clear(true);
|
|
|
|
if (newOption.toolbox.show) {
|
|
this._buildShape();
|
|
}
|
|
|
|
this.hideDataView();
|
|
}
|
|
}
|
|
};
|
|
|
|
zrUtil.inherits(Toolbox, Base);
|
|
|
|
require('../component').define('toolbox', Toolbox);
|
|
|
|
return Toolbox;
|
|
});
|
|
|