天津投入产出系统后端
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.
 
 
 
 
 
 

1516 lines
60 KiB

/**
* echarts组件:值域
*
* @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
* @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
*
*/
define(function (require) {
var Base = require('./base');
// 图形依赖
var TextShape = require('zrender/shape/Text');
var RectangleShape = require('zrender/shape/Rectangle');
var HandlePolygonShape = require('../util/shape/HandlePolygon');
var ecConfig = require('../config');
// 值域
ecConfig.dataRange = {
zlevel: 0, // 一级层叠
z: 4, // 二级层叠
show: true,
orient: 'vertical', // 布局方式,默认为垂直布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'left', // 水平安放位置,默认为全图左对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'bottom', // 垂直安放位置,默认为全图底部,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#ccc', // 值域边框颜色
borderWidth: 0, // 值域边框线宽,单位px,默认为0(无边框)
padding: 5, // 值域内边距,单位px,默认各方向内边距为5,
// 接受数组分别设定上右下左边距,同css
itemGap: 10, // 各个item之间的间隔,单位px,默认为10,
// 横向布局时为水平间隔,纵向布局时为纵向间隔
itemWidth: 20, // 值域图形宽度,线性渐变水平布局宽度为该值 * 10
itemHeight: 14, // 值域图形高度,线性渐变垂直布局高度为该值 * 10
// min: null, // 最小值
// max: null, // 最大值
precision: 0, // 小数精度,默认为0,无小数点
splitNumber: 5, // 分割段数,默认为5,为0时为线性渐变
calculable: false, // 是否值域漫游,启用后无视splitNumber,线性渐变
selectedMode: true, // 选择模式,默认开启值域开关
hoverLink: true,
realtime: true,
color:['#006edd','#e0ffff'],//颜色
// formatter: null,
// text:['高','低'], // 文本,默认为数值文本
textStyle: {
color: '#333' // 值域文字颜色
}
};
var zrUtil = require('zrender/tool/util');
var zrEvent = require('zrender/tool/event');
var zrArea = require('zrender/tool/area');
var zrColor = require('zrender/tool/color');
/**
* 构造函数
* @param {Object} messageCenter echart消息中心
* @param {ZRender} zr zrender实例
* @param {Object} option 图表参数
* @param {Object=} selected 用于状态保持
*/
function DataRange(ecTheme, messageCenter, zr, option, myChart) {
if (typeof this.query(option, 'dataRange.min') == 'undefined'
|| typeof this.query(option, 'dataRange.max') == 'undefined'
) {
console.error('option.dataRange.min or option.dataRange.max has not been defined.');
return;
}
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();
};
self._dataRangeSelected = function(param) {
return self.__dataRangeSelected(param);
};
self._dispatchHoverLink = function(param) {
return self.__dispatchHoverLink(param);
};
self._onhoverlink = function(params) {
return self.__onhoverlink(params);
};
this._selectedMap = {};
this._range = {};
this.refresh(option);
messageCenter.bind(ecConfig.EVENT.HOVER, this._onhoverlink);
}
DataRange.prototype = {
type : ecConfig.COMPONENT_TYPE_DATARANGE,
_textGap : 10, // 非值文字间隔
_buildShape : function () {
// 值域元素组的位置参数,通过计算所得x, y, width, height
this._itemGroupLocation = this._getItemGroupLocation();
this._buildBackground();
if (this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable
) {
this._buildGradient();
}
else {
this._buildItem();
}
if (this.dataRangeOption.show) {
for (var i = 0, l = this.shapeList.length; i < l; i++) {
this.zr.addShape(this.shapeList[i]);
}
}
this._syncShapeFromRange();
},
/**
* 构建图例型的值域元素
*/
_buildItem : function () {
var data = this._valueTextList;
var dataLength = data.length;
var itemName;
var itemShape;
var textShape;
var font = this.getFont(this.dataRangeOption.textStyle);
var lastX = this._itemGroupLocation.x;
var lastY = this._itemGroupLocation.y;
var itemWidth = this.dataRangeOption.itemWidth;
var itemHeight = this.dataRangeOption.itemHeight;
var itemGap = this.dataRangeOption.itemGap;
var textHeight = zrArea.getTextHeight('国', font);
var color;
if (this.dataRangeOption.orient == 'vertical'
&& this.dataRangeOption.x == 'right'
) {
lastX = this._itemGroupLocation.x
+ this._itemGroupLocation.width
- itemWidth;
}
var needValueText = true;
if (this.dataRangeOption.text) {
needValueText = false;
// 第一个文字
if (this.dataRangeOption.text[0]) {
textShape = this._getTextShape(
lastX, lastY, this.dataRangeOption.text[0]
);
if (this.dataRangeOption.orient == 'horizontal') {
lastX += zrArea.getTextWidth(
this.dataRangeOption.text[0],
font
)
+ this._textGap;
}
else {
lastY += textHeight + this._textGap;
textShape.style.y += textHeight / 2 + this._textGap;
textShape.style.textBaseline = 'bottom';
}
this.shapeList.push(new TextShape(textShape));
}
}
for (var i = 0; i < dataLength; i++) {
itemName = data[i];
color = this.getColorByIndex(i);
// 图形
itemShape = this._getItemShape(
lastX, lastY,
itemWidth, itemHeight,
(this._selectedMap[i] ? color : '#ccc')
);
itemShape._idx = i;
itemShape.onmousemove = this._dispatchHoverLink;
if (this.dataRangeOption.selectedMode) {
itemShape.clickable = true;
itemShape.onclick = this._dataRangeSelected;
}
this.shapeList.push(new RectangleShape(itemShape));
if (needValueText) {
// 文字
textShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style : {
x : lastX + itemWidth + 5,
y : lastY,
color : this._selectedMap[i]
? this.dataRangeOption.textStyle.color
: '#ccc',
text: data[i],
textFont: font,
textBaseline: 'top'
},
highlightStyle:{
brushType: 'fill'
}
};
if (this.dataRangeOption.orient == 'vertical'
&& this.dataRangeOption.x == 'right'
) {
textShape.style.x -= (itemWidth + 10);
textShape.style.textAlign = 'right';
}
textShape._idx = i;
textShape.onmousemove = this._dispatchHoverLink;
if (this.dataRangeOption.selectedMode) {
textShape.clickable = true;
textShape.onclick = this._dataRangeSelected;
}
this.shapeList.push(new TextShape(textShape));
}
if (this.dataRangeOption.orient == 'horizontal') {
lastX += itemWidth
+ (needValueText ? 5 : 0)
+ (needValueText
? zrArea.getTextWidth(itemName, font)
: 0)
+ itemGap;
}
else {
lastY += itemHeight + itemGap;
}
}
if (!needValueText && this.dataRangeOption.text[1]) {
if (this.dataRangeOption.orient == 'horizontal') {
lastX = lastX - itemGap + this._textGap;
}
else {
lastY = lastY - itemGap + this._textGap;
}
// 最后一个文字
textShape = this._getTextShape(
lastX, lastY, this.dataRangeOption.text[1]
);
if (this.dataRangeOption.orient != 'horizontal') {
textShape.style.y -= 5;
textShape.style.textBaseline = 'top';
}
this.shapeList.push(new TextShape(textShape));
}
},
/**
* 构建渐变型的值域元素
*/
_buildGradient : function () {
var itemShape;
var textShape;
var font = this.getFont(this.dataRangeOption.textStyle);
var lastX = this._itemGroupLocation.x;
var lastY = this._itemGroupLocation.y;
var itemWidth = this.dataRangeOption.itemWidth;
var itemHeight = this.dataRangeOption.itemHeight;
var textHeight = zrArea.getTextHeight('国', font);
var mSize = 10;
var needValueText = true;
if (this.dataRangeOption.text) {
needValueText = false;
// 第一个文字
if (this.dataRangeOption.text[0]) {
textShape = this._getTextShape(
lastX, lastY, this.dataRangeOption.text[0]
);
if (this.dataRangeOption.orient == 'horizontal') {
lastX += zrArea.getTextWidth(
this.dataRangeOption.text[0],
font
)
+ this._textGap;
}
else {
lastY += textHeight + this._textGap;
textShape.style.y += textHeight / 2 + this._textGap;
textShape.style.textBaseline = 'bottom';
}
this.shapeList.push(new TextShape(textShape));
}
}
var zrColor = require('zrender/tool/color');
var per = 1 / (this.dataRangeOption.color.length - 1);
var colorList = [];
for (var i = 0, l = this.dataRangeOption.color.length; i < l; i++) {
colorList.push([i * per, this.dataRangeOption.color[i]]);
}
if (this.dataRangeOption.orient == 'horizontal') {
itemShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style : {
x : lastX,
y : lastY,
width : itemWidth * mSize,
height : itemHeight,
color : zrColor.getLinearGradient(
lastX, lastY, lastX + itemWidth * mSize, lastY,
colorList
)
},
hoverable : false
};
lastX += itemWidth * mSize + this._textGap;
}
else {
itemShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style : {
x : lastX,
y : lastY,
width : itemWidth,
height : itemHeight * mSize,
color : zrColor.getLinearGradient(
lastX, lastY, lastX, lastY + itemHeight * mSize,
colorList
)
},
hoverable : false
};
lastY += itemHeight * mSize + this._textGap;
}
this.shapeList.push(new RectangleShape(itemShape));
// 可计算元素的位置缓存
this._calculableLocation = itemShape.style;
if (this.dataRangeOption.calculable) {
this._buildFiller();
this._bulidMask();
this._bulidHandle();
}
this._buildIndicator();
if (!needValueText && this.dataRangeOption.text[1]) {
// 最后一个文字
textShape = this._getTextShape(
lastX, lastY, this.dataRangeOption.text[1]
);
this.shapeList.push(new TextShape(textShape));
}
},
/**
* 构建指示器
*/
_buildIndicator : function() {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
var size = 5;
var pointList;
var textPosition;
if (this.dataRangeOption.orient == 'horizontal') {
// 水平
if (this.dataRangeOption.y != 'bottom') {
// 手柄统统在下方
pointList = [
[x, y + height],
[x - size, y + height + size],
[x + size, y + height + size]
];
textPosition = 'bottom';
}
else {
// 手柄在上方
pointList = [
[x, y],
[x - size, y - size],
[x + size, y - size]
];
textPosition = 'top';
}
}
else {
// 垂直
if (this.dataRangeOption.x != 'right') {
// 手柄统统在右侧
pointList = [
[x + width, y],
[x + width + size, y - size],
[x + width + size, y + size]
];
textPosition = 'right';
}
else {
// 手柄在左侧
pointList = [
[x, y],
[x - size, y - size],
[x - size, y + size]
];
textPosition = 'left';
}
}
this._indicatorShape = {
style : {
pointList : pointList,
color : '#fff',
__rect : {
x : Math.min(pointList[0][0], pointList[1][0]),
y : Math.min(pointList[0][1], pointList[1][1]),
width : size * (this.dataRangeOption.orient == 'horizontal' ? 2 : 1),
height : size * (this.dataRangeOption.orient == 'horizontal' ? 1 : 2)
}
},
highlightStyle : {
brushType : 'fill',
textPosition : textPosition,
textColor : this.dataRangeOption.textStyle.color
},
hoverable: false
};
this._indicatorShape = new HandlePolygonShape(this._indicatorShape);
},
/**
* 构建填充物
*/
_buildFiller : function () {
this._fillerShape = {
zlevel: this.getZlevelBase(),
z: this.getZBase() + 1,
style : {
x : this._calculableLocation.x,
y : this._calculableLocation.y,
width : this._calculableLocation.width,
height : this._calculableLocation.height,
color : 'rgba(255,255,255,0)'
},
highlightStyle : {
strokeColor : 'rgba(255,255,255,0.5)',
lineWidth : 1
},
draggable : true,
ondrift : this._ondrift,
ondragend : this._ondragend,
onmousemove : this._dispatchHoverLink,
_type : 'filler'
};
this._fillerShape = new RectangleShape(this._fillerShape);
this.shapeList.push(this._fillerShape);
},
/**
* 构建拖拽手柄
*/
_bulidHandle : function () {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
var font = this.getFont(this.dataRangeOption.textStyle);
var textHeight = zrArea.getTextHeight('国', font);
var textWidth = Math.max(
zrArea.getTextWidth(this._textFormat(this.dataRangeOption.max), font),
zrArea.getTextWidth(this._textFormat(this.dataRangeOption.min), font)
) + 2;
var pointListStart;
var textXStart;
var textYStart;
var coverRectStart;
var pointListEnd;
var textXEnd;
var textYEnd;
var coverRectEnd;
if (this.dataRangeOption.orient == 'horizontal') {
// 水平
if (this.dataRangeOption.y != 'bottom') {
// 手柄统统在下方
pointListStart = [
[x, y],
[x, y + height + textHeight],
[x - textHeight, y + height + textHeight],
[x - 1, y + height],
[x - 1, y]
];
textXStart = x - textWidth / 2 - textHeight;
textYStart = y + height + textHeight / 2 + 2;
coverRectStart = {
x : x - textWidth - textHeight,
y : y + height,
width : textWidth + textHeight,
height : textHeight
};
pointListEnd = [
[x + width, y],
[x + width, y + height + textHeight],
[x + width + textHeight, y + height + textHeight],
[x + width + 1, y + height],
[x + width + 1, y]
];
textXEnd = x + width + textWidth / 2 + textHeight;
textYEnd = textYStart;
coverRectEnd = {
x : x + width,
y : y + height,
width : textWidth + textHeight,
height : textHeight
};
}
else {
// 手柄在上方
pointListStart = [
[x, y + height],
[x, y - textHeight],
[x - textHeight, y - textHeight],
[x - 1, y],
[x - 1, y + height]
];
textXStart = x - textWidth / 2 - textHeight;
textYStart = y - textHeight / 2 - 2;
coverRectStart = {
x : x - textWidth - textHeight,
y : y - textHeight,
width : textWidth + textHeight,
height : textHeight
};
pointListEnd = [
[x + width, y + height],
[x + width, y - textHeight],
[x + width + textHeight, y - textHeight],
[x + width + 1, y],
[x + width + 1, y + height]
];
textXEnd = x + width + textWidth / 2 + textHeight;
textYEnd = textYStart;
coverRectEnd = {
x : x + width,
y : y - textHeight,
width : textWidth + textHeight,
height : textHeight
};
}
}
else {
textWidth += textHeight;
// 垂直
if (this.dataRangeOption.x != 'right') {
// 手柄统统在右侧
pointListStart = [
[x, y],
[x + width + textHeight, y],
[x + width + textHeight, y - textHeight],
[x + width, y - 1],
[x, y - 1]
];
textXStart = x + width + textWidth / 2 + textHeight / 2;
textYStart = y - textHeight / 2;
coverRectStart = {
x : x + width,
y : y - textHeight,
width : textWidth + textHeight,
height : textHeight
};
pointListEnd = [
[x, y + height],
[x + width + textHeight, y + height],
[x + width + textHeight, y + textHeight + height],
[x + width, y + 1 + height],
[x, y + height + 1]
];
textXEnd = textXStart;
textYEnd = y + height + textHeight / 2;
coverRectEnd = {
x : x + width,
y : y + height,
width : textWidth + textHeight,
height : textHeight
};
}
else {
// 手柄在左侧
pointListStart = [
[x + width, y],
[x - textHeight, y],
[x - textHeight, y - textHeight],
[x, y - 1],
[x + width, y - 1]
];
textXStart = x - textWidth / 2 - textHeight / 2;
textYStart = y - textHeight / 2;
coverRectStart = {
x : x - textWidth - textHeight,
y : y - textHeight,
width : textWidth + textHeight,
height : textHeight
};
pointListEnd = [
[x + width, y + height],
[x - textHeight, y + height],
[x - textHeight, y + textHeight + height],
[x, y + 1 + height],
[x + width, y + height + 1]
];
textXEnd = textXStart;
textYEnd = y + height + textHeight / 2;
coverRectEnd = {
x : x - textWidth - textHeight,
y : y + height,
width : textWidth + textHeight,
height : textHeight
};
}
}
this._startShape = {
style : {
pointList : pointListStart,
text : this._textFormat(this.dataRangeOption.max),
textX : textXStart,
textY : textYStart,
textFont: font,
color : this.getColor(this.dataRangeOption.max),
rect : coverRectStart,
x : pointListStart[0][0],
y : pointListStart[0][1],
_x : pointListStart[0][0], // 拖拽区域控制缓存
_y : pointListStart[0][1]
}
};
this._startShape.highlightStyle = {
strokeColor : this._startShape.style.color,
lineWidth : 1
};
this._endShape = {
style : {
pointList : pointListEnd,
text : this._textFormat(this.dataRangeOption.min),
textX : textXEnd,
textY : textYEnd,
textFont: font,
color : this.getColor(this.dataRangeOption.min),
rect : coverRectEnd,
x : pointListEnd[0][0],
y : pointListEnd[0][1],
_x : pointListEnd[0][0], // 拖拽区域控制缓存
_y : pointListEnd[0][1]
}
};
this._endShape.highlightStyle = {
strokeColor : this._endShape.style.color,
lineWidth : 1
};
// 统一参数
this._startShape.zlevel = this._endShape.zlevel = this.getZlevelBase();
this._startShape.z = this._endShape.z = this.getZBase() + 1;
this._startShape.draggable = this._endShape.draggable = true;
this._startShape.ondrift = this._endShape.ondrift = this._ondrift;
this._startShape.ondragend = this._endShape.ondragend = this._ondragend;
this._startShape.style.textColor = this._endShape.style.textColor
= this.dataRangeOption.textStyle.color;
this._startShape.style.textAlign = this._endShape.style.textAlign = 'center';
this._startShape.style.textPosition = this._endShape.style.textPosition = 'specific';
this._startShape.style.textBaseline = this._endShape.style.textBaseline = 'middle';
// for ondrif计算统一
this._startShape.style.width = this._endShape.style.width = 0;
this._startShape.style.height = this._endShape.style.height = 0;
this._startShape.style.textPosition = this._endShape.style.textPosition = 'specific';
this._startShape = new HandlePolygonShape(this._startShape);
this._endShape = new HandlePolygonShape(this._endShape);
this.shapeList.push(this._startShape);
this.shapeList.push(this._endShape);
},
_bulidMask : function () {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
this._startMask = {
zlevel: this.getZlevelBase(),
z: this.getZBase() + 1,
style : {
x : x,
y : y,
width : this.dataRangeOption.orient == 'horizontal'
? 0 : width,
height : this.dataRangeOption.orient == 'horizontal'
? height : 0,
color : '#ccc'
},
hoverable:false
};
this._endMask = {
zlevel: this.getZlevelBase(),
z: this.getZBase() + 1,
style : {
x : this.dataRangeOption.orient == 'horizontal'
? x + width : x,
y : this.dataRangeOption.orient == 'horizontal'
? y : y + height,
width : this.dataRangeOption.orient == 'horizontal'
? 0 : width,
height : this.dataRangeOption.orient == 'horizontal'
? height : 0,
color : '#ccc'
},
hoverable:false
};
this._startMask = new RectangleShape(this._startMask);
this._endMask = new RectangleShape(this._endMask);
this.shapeList.push(this._startMask);
this.shapeList.push(this._endMask);
},
_buildBackground : function () {
var padding = this.reformCssArray(this.dataRangeOption.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 : this.dataRangeOption.borderWidth === 0
? 'fill' : 'both',
color : this.dataRangeOption.backgroundColor,
strokeColor : this.dataRangeOption.borderColor,
lineWidth : this.dataRangeOption.borderWidth
}
}));
},
/**
* 根据选项计算值域实体的位置坐标
*/
_getItemGroupLocation : function () {
var data = this._valueTextList;
var dataLength = data.length;
var itemGap = this.dataRangeOption.itemGap;
var itemWidth = this.dataRangeOption.itemWidth;
var itemHeight = this.dataRangeOption.itemHeight;
var totalWidth = 0;
var totalHeight = 0;
var font = this.getFont(this.dataRangeOption.textStyle);
var textHeight = zrArea.getTextHeight('国', font);
var mSize = 10;
if (this.dataRangeOption.orient == 'horizontal') {
// 水平布局,计算总宽度
if (this.dataRangeOption.text
|| this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable
) {
// 指定文字或线性渐变
totalWidth =
((this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable)
? (itemWidth * mSize + itemGap)
: dataLength * (itemWidth + itemGap))
+ (this.dataRangeOption.text
&& typeof this.dataRangeOption.text[0] != 'undefined'
? (zrArea.getTextWidth(
this.dataRangeOption.text[0],
font
) + this._textGap)
: 0)
+ (this.dataRangeOption.text
&& typeof this.dataRangeOption.text[1] != 'undefined'
? (zrArea.getTextWidth(
this.dataRangeOption.text[1],
font
) + this._textGap)
: 0);
}
else {
// 值标签
itemWidth += 5;
for (var i = 0; i < dataLength; i++) {
totalWidth += itemWidth
+ zrArea.getTextWidth(
data[i],
font
)
+ itemGap;
}
}
totalWidth -= itemGap; // 减去最后一个的itemGap
totalHeight = Math.max(textHeight, itemHeight);
}
else {
// 垂直布局,计算总高度
var maxWidth;
if (this.dataRangeOption.text
|| this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable
) {
// 指定文字或线性渐变
totalHeight =
((this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable)
? (itemHeight * mSize + itemGap)
: dataLength * (itemHeight + itemGap))
+ (this.dataRangeOption.text
&& typeof this.dataRangeOption.text[0] != 'undefined'
? (this._textGap + textHeight)
: 0)
+ (this.dataRangeOption.text
&& typeof this.dataRangeOption.text[1] != 'undefined'
? (this._textGap + textHeight)
: 0);
maxWidth = Math.max(
zrArea.getTextWidth(
(this.dataRangeOption.text && this.dataRangeOption.text[0])
|| '',
font
),
zrArea.getTextWidth(
(this.dataRangeOption.text && this.dataRangeOption.text[1])
|| '',
font
)
);
totalWidth = Math.max(itemWidth, maxWidth);
}
else {
totalHeight = (itemHeight + itemGap) * dataLength;
// 值标签
itemWidth += 5;
maxWidth = 0;
for (var i = 0; i < dataLength; i++) {
maxWidth = Math.max(
maxWidth,
zrArea.getTextWidth(
data[i],
font
)
);
}
totalWidth = itemWidth + maxWidth;
}
totalHeight -= itemGap; // 减去最后一个的itemGap;
}
var padding = this.reformCssArray(this.dataRangeOption.padding);
var x;
var zrWidth = this.zr.getWidth();
switch (this.dataRangeOption.x) {
case 'center' :
x = Math.floor((zrWidth - totalWidth) / 2);
break;
case 'left' :
x = padding[3] + this.dataRangeOption.borderWidth;
break;
case 'right' :
x = zrWidth
- totalWidth
- padding[1]
- this.dataRangeOption.borderWidth;
break;
default :
x = this.parsePercent(this.dataRangeOption.x, zrWidth);
x = isNaN(x) ? 0 : x;
break;
}
var y;
var zrHeight = this.zr.getHeight();
switch (this.dataRangeOption.y) {
case 'top' :
y = padding[0] + this.dataRangeOption.borderWidth;
break;
case 'bottom' :
y = zrHeight
- totalHeight
- padding[2]
- this.dataRangeOption.borderWidth;
break;
case 'center' :
y = Math.floor((zrHeight - totalHeight) / 2);
break;
default :
y = this.parsePercent(this.dataRangeOption.y, zrHeight);
y = isNaN(y) ? 0 : y;
break;
}
if (this.dataRangeOption.calculable) {
// 留出手柄控件
var handlerWidth = Math.max(
zrArea.getTextWidth(this.dataRangeOption.max, font),
zrArea.getTextWidth(this.dataRangeOption.min, font)
) + textHeight;
if (this.dataRangeOption.orient == 'horizontal') {
if (x < handlerWidth) {
x = handlerWidth;
}
if (x + totalWidth + handlerWidth > zrWidth) {
x -= handlerWidth;
}
}
else {
if (y < textHeight) {
y = textHeight;
}
if (y + totalHeight + textHeight > zrHeight) {
y -= textHeight;
}
}
}
return {
x : x,
y : y,
width : totalWidth,
height : totalHeight
};
},
// 指定文本
_getTextShape : function (x, y, text) {
return {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style : {
x : (this.dataRangeOption.orient == 'horizontal'
? x
: this._itemGroupLocation.x
+ this._itemGroupLocation.width / 2
),
y : (this.dataRangeOption.orient == 'horizontal'
? this._itemGroupLocation.y
+ this._itemGroupLocation.height / 2
: y
),
color : this.dataRangeOption.textStyle.color,
text: text,
textFont: this.getFont(this.dataRangeOption.textStyle),
textBaseline: (this.dataRangeOption.orient == 'horizontal'
? 'middle' : 'top'),
textAlign: (this.dataRangeOption.orient == 'horizontal'
? 'left' : 'center')
},
hoverable : false
};
},
// 色尺legend item shape
_getItemShape : function (x, y, width, height, color) {
return {
zlevel: this.getZlevelBase(),
z: this.getZBase(),
style : {
x : x,
y : y + 1,
width : width,
height : height - 2,
color : color
},
highlightStyle: {
strokeColor: color,
lineWidth : 1
}
};
},
/**
* 拖拽范围控制
*/
__ondrift : function (shape, dx, dy) {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
if (this.dataRangeOption.orient == 'horizontal') {
if (shape.style.x + dx <= x) {
shape.style.x = x;
}
else if (shape.style.x + dx + shape.style.width >= x + width) {
shape.style.x = x + width - shape.style.width;
}
else {
shape.style.x += dx;
}
}
else {
if (shape.style.y + dy <= y) {
shape.style.y = y;
}
else if (shape.style.y + dy + shape.style.height >= y + height) {
shape.style.y = y + height - shape.style.height;
}
else {
shape.style.y += dy;
}
}
if (shape._type == 'filler') {
this._syncHandleShape();
}
else {
this._syncFillerShape(shape);
}
if (this.dataRangeOption.realtime) {
this._dispatchDataRange();
}
return true;
},
__ondragend : function () {
this.isDragend = true;
},
/**
* 数据项被拖拽出去
*/
ondragend : function (param, status) {
if (!this.isDragend || !param.target) {
// 没有在当前实例上发生拖拽行为则直接返回
return;
}
// 别status = {}赋值啊!!
status.dragOut = true;
status.dragIn = true;
if (!this.dataRangeOption.realtime) {
this._dispatchDataRange();
}
status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍
// 处理完拖拽事件后复位
this.isDragend = false;
return;
},
// 外部传入range
_syncShapeFromRange : function () {
var range = this.dataRangeOption.range || {};
// 做一个反转
this._range.end = typeof this._range.end != 'undefined'
? this._range.end
: (typeof range.start != 'undefined' ? range.start : 0);
this._range.start = typeof this._range.start != 'undefined'
? this._range.start
: (typeof range.end != 'undefined' ? range.end : 100);
if (this._range.start != 100 || this._range.end !== 0) {
// 非默认满值同步一下图形
if (this.dataRangeOption.orient == 'horizontal') {
// 横向
var width = this._fillerShape.style.width;
this._fillerShape.style.x +=
width * (100 - this._range.start) / 100;
this._fillerShape.style.width =
width * (this._range.start - this._range.end) / 100;
}
else {
// 纵向
var height = this._fillerShape.style.height;
this._fillerShape.style.y +=
height * (100 - this._range.start) / 100;
this._fillerShape.style.height =
height * (this._range.start - this._range.end) / 100;
}
this.zr.modShape(this._fillerShape.id);
this._syncHandleShape();
}
},
_syncHandleShape : function () {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
if (this.dataRangeOption.orient == 'horizontal') {
this._startShape.style.x = this._fillerShape.style.x;
this._startMask.style.width = this._startShape.style.x - x;
this._endShape.style.x = this._fillerShape.style.x
+ this._fillerShape.style.width;
this._endMask.style.x = this._endShape.style.x;
this._endMask.style.width = x + width - this._endShape.style.x;
this._range.start = Math.ceil(
100 - (this._startShape.style.x - x) / width * 100
);
this._range.end = Math.floor(
100 - (this._endShape.style.x - x) / width * 100
);
}
else {
this._startShape.style.y = this._fillerShape.style.y;
this._startMask.style.height = this._startShape.style.y - y;
this._endShape.style.y = this._fillerShape.style.y
+ this._fillerShape.style.height;
this._endMask.style.y = this._endShape.style.y;
this._endMask.style.height = y + height - this._endShape.style.y;
this._range.start = Math.ceil(
100 - (this._startShape.style.y - y) / height * 100
);
this._range.end = Math.floor(
100 - (this._endShape.style.y - y) / height * 100
);
}
this._syncShape();
},
_syncFillerShape : function (e) {
var x = this._calculableLocation.x;
var y = this._calculableLocation.y;
var width = this._calculableLocation.width;
var height = this._calculableLocation.height;
var a;
var b;
if (this.dataRangeOption.orient == 'horizontal') {
a = this._startShape.style.x;
b = this._endShape.style.x;
if (e.id == this._startShape.id && a >= b) {
// _startShape触发
b = a;
this._endShape.style.x = a;
}
else if (e.id == this._endShape.id && a >= b) {
// _endShape触发
a = b;
this._startShape.style.x = a;
}
this._fillerShape.style.x = a;
this._fillerShape.style.width = b - a;
this._startMask.style.width = a - x;
this._endMask.style.x = b;
this._endMask.style.width = x + width - b;
this._range.start = Math.ceil(100 - (a - x) / width * 100);
this._range.end = Math.floor(100 - (b - x) / width * 100);
}
else {
a = this._startShape.style.y;
b = this._endShape.style.y;
if (e.id == this._startShape.id && a >= b) {
// _startShape触发
b = a;
this._endShape.style.y = a;
}
else if (e.id == this._endShape.id && a >= b) {
// _endShape触发
a = b;
this._startShape.style.y = a;
}
this._fillerShape.style.y = a;
this._fillerShape.style.height = b - a;
this._startMask.style.height = a - y;
this._endMask.style.y = b;
this._endMask.style.height = y + height - b;
this._range.start = Math.ceil(100 - (a - y) / height * 100);
this._range.end = Math.floor(100 - (b - y) / height * 100);
}
this._syncShape();
},
_syncShape : function () {
this._startShape.position = [
this._startShape.style.x - this._startShape.style._x,
this._startShape.style.y - this._startShape.style._y
];
this._startShape.style.text = this._textFormat(
this._gap * this._range.start + this.dataRangeOption.min
);
this._startShape.style.color
= this._startShape.highlightStyle.strokeColor
= this.getColor(
this._gap * this._range.start + this.dataRangeOption.min
);
this._endShape.position = [
this._endShape.style.x - this._endShape.style._x,
this._endShape.style.y - this._endShape.style._y
];
this._endShape.style.text = this._textFormat(
this._gap * this._range.end + this.dataRangeOption.min
);
this._endShape.style.color
= this._endShape.highlightStyle.strokeColor
= this.getColor(
this._gap * this._range.end + this.dataRangeOption.min
);
this.zr.modShape(this._startShape.id);
this.zr.modShape(this._endShape.id);
this.zr.modShape(this._startMask.id);
this.zr.modShape(this._endMask.id);
this.zr.modShape(this._fillerShape.id);
this.zr.refreshNextFrame();
},
_dispatchDataRange : function () {
this.messageCenter.dispatch(
ecConfig.EVENT.DATA_RANGE,
null,
{
range : {
start : this._range.end,
end : this._range.start
}
},
this.myChart
);
},
__dataRangeSelected : function (param) {
if (this.dataRangeOption.selectedMode === 'single') {
for (var k in this._selectedMap) {
this._selectedMap[k] = false;
}
}
var idx = param.target._idx;
this._selectedMap[idx] = !this._selectedMap[idx];
var valueMax = (this._colorList.length - idx) * this._gap + this.dataRangeOption.min;
this.messageCenter.dispatch(
ecConfig.EVENT.DATA_RANGE_SELECTED,
param.event,
{
selected: this._selectedMap,
target: idx,
valueMax: valueMax,
valueMin: valueMax - this._gap
},
this.myChart
);
this.messageCenter.dispatch(ecConfig.EVENT.REFRESH, null, null, this.myChart);
},
/**
* 产生hover link事件
*/
__dispatchHoverLink : function(param) {
var valueMin;
var valueMax;
if (this.dataRangeOption.calculable) {
var totalValue = this.dataRangeOption.max - this.dataRangeOption.min;
var curValue;
if (this.dataRangeOption.orient == 'horizontal') {
curValue = (1 - (zrEvent.getX(param.event) - this._calculableLocation.x)
/ this._calculableLocation.width)
* totalValue;
}
else {
curValue = (1 - (zrEvent.getY(param.event) - this._calculableLocation.y)
/ this._calculableLocation.height)
* totalValue;
}
valueMin = curValue - totalValue * 0.05;
valueMax = curValue + totalValue * 0.05;
}
else {
var idx = param.target._idx;
valueMax = (this._colorList.length - idx) * this._gap + this.dataRangeOption.min;
valueMin = valueMax - this._gap;
}
this.messageCenter.dispatch(
ecConfig.EVENT.DATA_RANGE_HOVERLINK,
param.event,
{
valueMin : valueMin,
valueMax : valueMax
},
this.myChart
);
// console.log(param,curValue);
return;
},
__onhoverlink: function(param) {
if (this.dataRangeOption.show
&& this.dataRangeOption.hoverLink
&& this._indicatorShape
&& param
&& param.seriesIndex != null && param.dataIndex != null
) {
var curValue = param.value;
if (curValue === '' || isNaN(curValue)) {
return;
}
if (curValue < this.dataRangeOption.min) {
curValue = this.dataRangeOption.min;
}
else if (curValue > this.dataRangeOption.max) {
curValue = this.dataRangeOption.max;
}
if (this.dataRangeOption.orient == 'horizontal') {
this._indicatorShape.position = [
(this.dataRangeOption.max - curValue)
/ (this.dataRangeOption.max - this.dataRangeOption.min)
* this._calculableLocation.width,
0
];
}
else {
this._indicatorShape.position = [
0,
(this.dataRangeOption.max - curValue)
/ (this.dataRangeOption.max - this.dataRangeOption.min)
* this._calculableLocation.height
];
}
this._indicatorShape.style.text = this._textFormat(param.value);
this._indicatorShape.style.color = this.getColor(curValue);
this.zr.addHoverShape(this._indicatorShape);
}
},
_textFormat : function(valueStart, valueEnd) {
valueStart = (+valueStart).toFixed(this.dataRangeOption.precision);
valueEnd = valueEnd != null ? (+valueEnd).toFixed(this.dataRangeOption.precision) : '';
if (this.dataRangeOption.formatter) {
if (typeof this.dataRangeOption.formatter == 'string') {
return this.dataRangeOption.formatter.replace('{value}', valueStart)
.replace('{value2}', valueEnd);
}
else if (typeof this.dataRangeOption.formatter == 'function') {
return this.dataRangeOption.formatter.call(
this.myChart, valueStart, valueEnd
);
}
}
if (valueEnd !== '') {
return valueStart + ' - ' + valueEnd;
}
return valueStart;
},
/**
* 刷新
*/
refresh : function (newOption) {
if (newOption) {
this.option = newOption;
this.option.dataRange = this.reformOption(this.option.dataRange);
this.dataRangeOption = this.option.dataRange;
if (!this.myChart.canvasSupported) {
// 不支持Canvas的强制关闭实时动画
this.dataRangeOption.realtime = false;
}
var splitNumber = this.dataRangeOption.splitNumber <= 0
|| this.dataRangeOption.calculable
? 100
: this.dataRangeOption.splitNumber;
this._colorList = zrColor.getGradientColors(
this.dataRangeOption.color,
Math.max(
(splitNumber - this.dataRangeOption.color.length)
/ (this.dataRangeOption.color.length - 1),
0
) + 1
);
if (this._colorList.length > splitNumber) {
var len = this._colorList.length;
var newColorList = [this._colorList[0]];
var step = len / (splitNumber - 1);
for (var i = 1; i < splitNumber - 1; i++) {
newColorList.push(this._colorList[Math.floor(i * step)]);
}
newColorList.push(this._colorList[len - 1]);
this._colorList = newColorList;
}
// console.log(this._colorList.length)
var precision = this.dataRangeOption.precision;
this._gap = (this.dataRangeOption.max - this.dataRangeOption.min) / splitNumber;
while (this._gap.toFixed(precision) - 0 != this._gap && precision < 5) {
// 精度自适应
precision++;
}
this.dataRangeOption.precision = precision;
this._gap = (
(this.dataRangeOption.max - this.dataRangeOption.min) / splitNumber
).toFixed(precision) - 0;
this._valueTextList = [];
for (var i = 0; i < splitNumber; i++) {
this._selectedMap[i] = true;
this._valueTextList.unshift(
this._textFormat(
i * this._gap + this.dataRangeOption.min,
(i + 1) * this._gap + this.dataRangeOption.min
)
);
}
}
this.clear();
this._buildShape();
},
getColor : function (value) {
if (isNaN(value)) {
return null;
}
if (this.dataRangeOption.min == this.dataRangeOption.max) {
return this._colorList[0];
}
if (value < this.dataRangeOption.min) {
value = this.dataRangeOption.min;
}
else if (value > this.dataRangeOption.max) {
value = this.dataRangeOption.max;
}
if (this.dataRangeOption.calculable) {
if (value - (this._gap * this._range.start + this.dataRangeOption.min) > 0.00005
|| value - (this._gap * this._range.end + this.dataRangeOption.min) < -0.00005) {
return null;
}
}
var idx = this._colorList.length - Math.ceil(
(value - this.dataRangeOption.min)
/ (this.dataRangeOption.max - this.dataRangeOption.min)
* this._colorList.length
);
if (idx == this._colorList.length) {
idx--;
}
//console.log(value, idx,this._colorList[idx])
if (this._selectedMap[idx]) {
return this._colorList[idx];
}
else {
return null;
}
},
getColorByIndex : function (idx) {
if (idx >= this._colorList.length) {
idx = this._colorList.length - 1;
}
else if (idx < 0) {
idx = 0;
}
return this._colorList[idx];
},
/**
* 释放后实例不可用
*/
onbeforDispose : function () {
this.messageCenter.unbind(ecConfig.EVENT.HOVER, this._onhoverlink);
}
};
zrUtil.inherits(DataRange, Base);
require('../component').define('dataRange', DataRange);
return DataRange;
});