mirror of
https://gitlab.com/JKANetwork/CheckServer.git
synced 2026-03-24 11:22:02 +01:00
Start again
This commit is contained in:
45
vendors/echarts/src/CoordinateSystem.js
vendored
Normal file
45
vendors/echarts/src/CoordinateSystem.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// var zrUtil = require('zrender/core/util');
|
||||
var coordinateSystemCreators = {};
|
||||
|
||||
function CoordinateSystemManager() {
|
||||
|
||||
this._coordinateSystems = [];
|
||||
}
|
||||
|
||||
CoordinateSystemManager.prototype = {
|
||||
|
||||
constructor: CoordinateSystemManager,
|
||||
|
||||
create: function (ecModel, api) {
|
||||
var coordinateSystems = [];
|
||||
for (var type in coordinateSystemCreators) {
|
||||
var list = coordinateSystemCreators[type].create(ecModel, api);
|
||||
list && (coordinateSystems = coordinateSystems.concat(list));
|
||||
}
|
||||
|
||||
this._coordinateSystems = coordinateSystems;
|
||||
},
|
||||
|
||||
update: function (ecModel, api) {
|
||||
var coordinateSystems = this._coordinateSystems;
|
||||
for (var i = 0; i < coordinateSystems.length; i++) {
|
||||
// FIXME MUST have
|
||||
coordinateSystems[i].update && coordinateSystems[i].update(ecModel, api);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CoordinateSystemManager.register = function (type, coordinateSystemCreator) {
|
||||
coordinateSystemCreators[type] = coordinateSystemCreator;
|
||||
};
|
||||
|
||||
CoordinateSystemManager.get = function (type) {
|
||||
return coordinateSystemCreators[type];
|
||||
};
|
||||
|
||||
return CoordinateSystemManager;
|
||||
});
|
||||
19
vendors/echarts/src/ExtensionAPI.js
vendored
Normal file
19
vendors/echarts/src/ExtensionAPI.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var echartsAPIList = [
|
||||
'getDom', 'getZr', 'getWidth', 'getHeight', 'dispatchAction',
|
||||
'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getModel', 'getOption'
|
||||
];
|
||||
|
||||
function ExtensionAPI(chartInstance) {
|
||||
zrUtil.each(echartsAPIList, function (name) {
|
||||
this[name] = zrUtil.bind(chartInstance[name], chartInstance);
|
||||
}, this);
|
||||
}
|
||||
|
||||
return ExtensionAPI;
|
||||
});
|
||||
35
vendors/echarts/src/action/createDataSelectAction.js
vendored
Normal file
35
vendors/echarts/src/action/createDataSelectAction.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
define(function (require) {
|
||||
var echarts = require('../echarts');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
return function (seriesType, actionInfos) {
|
||||
zrUtil.each(actionInfos, function (actionInfo) {
|
||||
actionInfo.update = 'updateView';
|
||||
/**
|
||||
* @payload
|
||||
* @property {string} seriesName
|
||||
* @property {string} name
|
||||
*/
|
||||
echarts.registerAction(actionInfo, function (payload, ecModel) {
|
||||
var selected = {};
|
||||
ecModel.eachComponent(
|
||||
{mainType: 'series', subType: seriesType, query: payload},
|
||||
function (seriesModel) {
|
||||
if (seriesModel[actionInfo.method]) {
|
||||
seriesModel[actionInfo.method](payload.name);
|
||||
}
|
||||
var data = seriesModel.getData();
|
||||
// Create selected map
|
||||
data.each(function (idx) {
|
||||
var name = data.getName(idx);
|
||||
selected[name] = seriesModel.isSelected(name) || false;
|
||||
});
|
||||
}
|
||||
);
|
||||
return {
|
||||
name: payload.name,
|
||||
selected: selected
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
53
vendors/echarts/src/action/geoRoam.js
vendored
Normal file
53
vendors/echarts/src/action/geoRoam.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var roamHelper = require('./roamHelper');
|
||||
|
||||
var echarts = require('../echarts');
|
||||
|
||||
/**
|
||||
* @payload
|
||||
* @property {string} [componentType=series]
|
||||
* @property {number} [dx]
|
||||
* @property {number} [dy]
|
||||
* @property {number} [zoom]
|
||||
* @property {number} [originX]
|
||||
* @property {number} [originY]
|
||||
*/
|
||||
echarts.registerAction({
|
||||
type: 'geoRoam',
|
||||
event: 'geoRoam',
|
||||
update: 'updateLayout'
|
||||
}, function (payload, ecModel) {
|
||||
var componentType = payload.componentType || 'series';
|
||||
|
||||
ecModel.eachComponent(
|
||||
{ mainType: componentType, query: payload },
|
||||
function (componentModel) {
|
||||
var geo = componentModel.coordinateSystem;
|
||||
if (geo.type !== 'geo') {
|
||||
return;
|
||||
}
|
||||
|
||||
var res = roamHelper.updateCenterAndZoom(
|
||||
geo, payload, componentModel.get('scaleLimit')
|
||||
);
|
||||
|
||||
componentModel.setCenter
|
||||
&& componentModel.setCenter(res.center);
|
||||
|
||||
componentModel.setZoom
|
||||
&& componentModel.setZoom(res.zoom);
|
||||
|
||||
// All map series with same `map` use the same geo coordinate system
|
||||
// So the center and zoom must be in sync. Include the series not selected by legend
|
||||
if (componentType === 'series') {
|
||||
zrUtil.each(componentModel.seriesGroup, function (seriesModel) {
|
||||
seriesModel.setCenter(res.center);
|
||||
seriesModel.setZoom(res.zoom);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
60
vendors/echarts/src/action/roamHelper.js
vendored
Normal file
60
vendors/echarts/src/action/roamHelper.js
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
define(function (require) {
|
||||
|
||||
var roamHelper = {};
|
||||
|
||||
/**
|
||||
* @param {module:echarts/coord/View} view
|
||||
* @param {Object} payload
|
||||
* @param {Object} [zoomLimit]
|
||||
*/
|
||||
roamHelper.updateCenterAndZoom = function (
|
||||
view, payload, zoomLimit
|
||||
) {
|
||||
var previousZoom = view.getZoom();
|
||||
var center = view.getCenter();
|
||||
var zoom = payload.zoom;
|
||||
|
||||
var point = view.dataToPoint(center);
|
||||
|
||||
if (payload.dx != null && payload.dy != null) {
|
||||
point[0] -= payload.dx;
|
||||
point[1] -= payload.dy;
|
||||
|
||||
var center = view.pointToData(point);
|
||||
view.setCenter(center);
|
||||
}
|
||||
if (zoom != null) {
|
||||
if (zoomLimit) {
|
||||
var zoomMin = zoomLimit.min || 0;
|
||||
var zoomMax = zoomLimit.max || Infinity;
|
||||
zoom = Math.max(
|
||||
Math.min(previousZoom * zoom, zoomMax),
|
||||
zoomMin
|
||||
) / previousZoom;
|
||||
}
|
||||
|
||||
// Zoom on given point(originX, originY)
|
||||
view.scale[0] *= zoom;
|
||||
view.scale[1] *= zoom;
|
||||
var position = view.position;
|
||||
var fixX = (payload.originX - position[0]) * (zoom - 1);
|
||||
var fixY = (payload.originY - position[1]) * (zoom - 1);
|
||||
|
||||
position[0] -= fixX;
|
||||
position[1] -= fixY;
|
||||
|
||||
view.updateTransform();
|
||||
// Get the new center
|
||||
var center = view.pointToData(point);
|
||||
view.setCenter(center);
|
||||
view.setZoom(zoom * previousZoom);
|
||||
}
|
||||
|
||||
return {
|
||||
center: view.getCenter(),
|
||||
zoom: view.getZoom()
|
||||
};
|
||||
};
|
||||
|
||||
return roamHelper;
|
||||
});
|
||||
24
vendors/echarts/src/chart/bar.js
vendored
Normal file
24
vendors/echarts/src/chart/bar.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
require('../coord/cartesian/Grid');
|
||||
|
||||
require('./bar/BarSeries');
|
||||
require('./bar/BarView');
|
||||
|
||||
var barLayoutGrid = require('../layout/barGrid');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
echarts.registerLayout(zrUtil.curry(barLayoutGrid, 'bar'));
|
||||
// Visual coding for legend
|
||||
echarts.registerVisualCoding('chart', function (ecModel) {
|
||||
ecModel.eachSeriesByType('bar', function (seriesModel) {
|
||||
var data = seriesModel.getData();
|
||||
data.setVisual('legendSymbol', 'roundRect');
|
||||
});
|
||||
});
|
||||
|
||||
// In case developer forget to include grid component
|
||||
require('../component/grid');
|
||||
});
|
||||
76
vendors/echarts/src/chart/bar/BarSeries.js
vendored
Normal file
76
vendors/echarts/src/chart/bar/BarSeries.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var createListFromArray = require('../helper/createListFromArray');
|
||||
|
||||
return SeriesModel.extend({
|
||||
|
||||
type: 'series.bar',
|
||||
|
||||
dependencies: ['grid', 'polar'],
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
return createListFromArray(option.data, this, ecModel);
|
||||
},
|
||||
|
||||
getMarkerPosition: function (value) {
|
||||
var coordSys = this.coordinateSystem;
|
||||
if (coordSys) {
|
||||
var pt = coordSys.dataToPoint(value);
|
||||
var data = this.getData();
|
||||
var offset = data.getLayout('offset');
|
||||
var size = data.getLayout('size');
|
||||
var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1;
|
||||
pt[offsetIndex] += offset + size / 2;
|
||||
return pt;
|
||||
}
|
||||
return [NaN, NaN];
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
coordinateSystem: 'cartesian2d',
|
||||
legendHoverLink: true,
|
||||
// stack: null
|
||||
|
||||
// Cartesian coordinate system
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
// 最小高度改为0
|
||||
barMinHeight: 0,
|
||||
|
||||
// barMaxWidth: null,
|
||||
// 默认自适应
|
||||
// barWidth: null,
|
||||
// 柱间距离,默认为柱形宽度的30%,可设固定值
|
||||
// barGap: '30%',
|
||||
// 类目间柱形距离,默认为类目间距的20%,可设固定值
|
||||
// barCategoryGap: '20%',
|
||||
// label: {
|
||||
// normal: {
|
||||
// show: false
|
||||
// }
|
||||
// },
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// color: '各异',
|
||||
// 柱条边线
|
||||
barBorderColor: '#fff',
|
||||
// 柱条边线线宽,单位px,默认为1
|
||||
barBorderWidth: 0
|
||||
},
|
||||
emphasis: {
|
||||
// color: '各异',
|
||||
// 柱条边线
|
||||
barBorderColor: '#fff',
|
||||
// 柱条边线线宽,单位px,默认为1
|
||||
barBorderWidth: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
215
vendors/echarts/src/chart/bar/BarView.js
vendored
Normal file
215
vendors/echarts/src/chart/bar/BarView.js
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
define(function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var graphic = require('../../util/graphic');
|
||||
|
||||
zrUtil.extend(require('../../model/Model').prototype, require('./barItemStyle'));
|
||||
|
||||
function fixLayoutWithLineWidth(layout, lineWidth) {
|
||||
var signX = layout.width > 0 ? 1 : -1;
|
||||
var signY = layout.height > 0 ? 1 : -1;
|
||||
// In case width or height are too small.
|
||||
lineWidth = Math.min(lineWidth, Math.abs(layout.width), Math.abs(layout.height));
|
||||
layout.x += signX * lineWidth / 2;
|
||||
layout.y += signY * lineWidth / 2;
|
||||
layout.width -= signX * lineWidth;
|
||||
layout.height -= signY * lineWidth;
|
||||
}
|
||||
|
||||
return require('../../echarts').extendChartView({
|
||||
|
||||
type: 'bar',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var coordinateSystemType = seriesModel.get('coordinateSystem');
|
||||
|
||||
if (coordinateSystemType === 'cartesian2d') {
|
||||
this._renderOnCartesian(seriesModel, ecModel, api);
|
||||
}
|
||||
|
||||
return this.group;
|
||||
},
|
||||
|
||||
_renderOnCartesian: function (seriesModel, ecModel, api) {
|
||||
var group = this.group;
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
|
||||
var cartesian = seriesModel.coordinateSystem;
|
||||
var baseAxis = cartesian.getBaseAxis();
|
||||
var isHorizontal = baseAxis.isHorizontal();
|
||||
|
||||
var enableAnimation = seriesModel.get('animation');
|
||||
|
||||
var barBorderWidthQuery = ['itemStyle', 'normal', 'barBorderWidth'];
|
||||
|
||||
function createRect(dataIndex, isUpdate) {
|
||||
var layout = data.getItemLayout(dataIndex);
|
||||
var lineWidth = data.getItemModel(dataIndex).get(barBorderWidthQuery) || 0;
|
||||
fixLayoutWithLineWidth(layout, lineWidth);
|
||||
|
||||
var rect = new graphic.Rect({
|
||||
shape: zrUtil.extend({}, layout)
|
||||
});
|
||||
// Animation
|
||||
if (enableAnimation) {
|
||||
var rectShape = rect.shape;
|
||||
var animateProperty = isHorizontal ? 'height' : 'width';
|
||||
var animateTarget = {};
|
||||
rectShape[animateProperty] = 0;
|
||||
animateTarget[animateProperty] = layout[animateProperty];
|
||||
graphic[isUpdate? 'updateProps' : 'initProps'](rect, {
|
||||
shape: animateTarget
|
||||
}, seriesModel, dataIndex);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
data.diff(oldData)
|
||||
.add(function (dataIndex) {
|
||||
// 空数据
|
||||
if (!data.hasValue(dataIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = createRect(dataIndex);
|
||||
|
||||
data.setItemGraphicEl(dataIndex, rect);
|
||||
|
||||
group.add(rect);
|
||||
|
||||
})
|
||||
.update(function (newIndex, oldIndex) {
|
||||
var rect = oldData.getItemGraphicEl(oldIndex);
|
||||
// 空数据
|
||||
if (!data.hasValue(newIndex)) {
|
||||
group.remove(rect);
|
||||
return;
|
||||
}
|
||||
if (!rect) {
|
||||
rect = createRect(newIndex, true);
|
||||
}
|
||||
|
||||
var layout = data.getItemLayout(newIndex);
|
||||
var lineWidth = data.getItemModel(newIndex).get(barBorderWidthQuery) || 0;
|
||||
fixLayoutWithLineWidth(layout, lineWidth);
|
||||
|
||||
graphic.updateProps(rect, {
|
||||
shape: layout
|
||||
}, seriesModel, newIndex);
|
||||
|
||||
data.setItemGraphicEl(newIndex, rect);
|
||||
|
||||
// Add back
|
||||
group.add(rect);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
var rect = oldData.getItemGraphicEl(idx);
|
||||
if (rect) {
|
||||
// Not show text when animating
|
||||
rect.style.text = '';
|
||||
graphic.updateProps(rect, {
|
||||
shape: {
|
||||
width: 0
|
||||
}
|
||||
}, seriesModel, idx, function () {
|
||||
group.remove(rect);
|
||||
});
|
||||
}
|
||||
})
|
||||
.execute();
|
||||
|
||||
this._updateStyle(seriesModel, data, isHorizontal);
|
||||
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
_updateStyle: function (seriesModel, data, isHorizontal) {
|
||||
function setLabel(style, model, color, labelText, labelPositionOutside) {
|
||||
graphic.setText(style, model, color);
|
||||
style.text = labelText;
|
||||
if (style.textPosition === 'outside') {
|
||||
style.textPosition = labelPositionOutside;
|
||||
}
|
||||
}
|
||||
|
||||
data.eachItemGraphicEl(function (rect, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
var opacity = data.getItemVisual(idx, 'opacity');
|
||||
var layout = data.getItemLayout(idx);
|
||||
var itemStyleModel = itemModel.getModel('itemStyle.normal');
|
||||
|
||||
var hoverStyle = itemModel.getModel('itemStyle.emphasis').getBarItemStyle();
|
||||
|
||||
rect.setShape('r', itemStyleModel.get('barBorderRadius') || 0);
|
||||
|
||||
rect.useStyle(zrUtil.defaults(
|
||||
{
|
||||
fill: color,
|
||||
opacity: opacity
|
||||
},
|
||||
itemStyleModel.getBarItemStyle()
|
||||
));
|
||||
|
||||
var labelPositionOutside = isHorizontal
|
||||
? (layout.height > 0 ? 'bottom' : 'top')
|
||||
: (layout.width > 0 ? 'left' : 'right');
|
||||
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var hoverLabelModel = itemModel.getModel('label.emphasis');
|
||||
var rectStyle = rect.style;
|
||||
if (labelModel.get('show')) {
|
||||
setLabel(
|
||||
rectStyle, labelModel, color,
|
||||
zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'normal'),
|
||||
seriesModel.getRawValue(idx)
|
||||
),
|
||||
labelPositionOutside
|
||||
);
|
||||
}
|
||||
else {
|
||||
rectStyle.text = '';
|
||||
}
|
||||
if (hoverLabelModel.get('show')) {
|
||||
setLabel(
|
||||
hoverStyle, hoverLabelModel, color,
|
||||
zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'emphasis'),
|
||||
seriesModel.getRawValue(idx)
|
||||
),
|
||||
labelPositionOutside
|
||||
);
|
||||
}
|
||||
else {
|
||||
hoverStyle.text = '';
|
||||
}
|
||||
graphic.setHoverStyle(rect, hoverStyle);
|
||||
});
|
||||
},
|
||||
|
||||
remove: function (ecModel, api) {
|
||||
var group = this.group;
|
||||
if (ecModel.get('animation')) {
|
||||
if (this._data) {
|
||||
this._data.eachItemGraphicEl(function (el) {
|
||||
// Not show text when animating
|
||||
el.style.text = '';
|
||||
graphic.updateProps(el, {
|
||||
shape: {
|
||||
width: 0
|
||||
}
|
||||
}, ecModel, el.dataIndex, function () {
|
||||
group.remove(el);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
group.removeAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
19
vendors/echarts/src/chart/bar/barItemStyle.js
vendored
Normal file
19
vendors/echarts/src/chart/bar/barItemStyle.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
define(function (require) {
|
||||
return {
|
||||
getBarItemStyle: require('../../model/mixin/makeStyleMapper')(
|
||||
[
|
||||
['fill', 'color'],
|
||||
['stroke', 'borderColor'],
|
||||
['lineWidth', 'borderWidth'],
|
||||
// Compatitable with 2
|
||||
['stroke', 'barBorderColor'],
|
||||
['lineWidth', 'barBorderWidth'],
|
||||
['opacity'],
|
||||
['shadowBlur'],
|
||||
['shadowOffsetX'],
|
||||
['shadowOffsetY'],
|
||||
['shadowColor']
|
||||
]
|
||||
)
|
||||
};
|
||||
});
|
||||
11
vendors/echarts/src/chart/boxplot.js
vendored
Normal file
11
vendors/echarts/src/chart/boxplot.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./boxplot/BoxplotSeries');
|
||||
require('./boxplot/BoxplotView');
|
||||
|
||||
echarts.registerVisualCoding('chart', require('./boxplot/boxplotVisual'));
|
||||
echarts.registerLayout(require('./boxplot/boxplotLayout'));
|
||||
|
||||
});
|
||||
72
vendors/echarts/src/chart/boxplot/BoxplotSeries.js
vendored
Normal file
72
vendors/echarts/src/chart/boxplot/BoxplotSeries.js
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var whiskerBoxCommon = require('../helper/whiskerBoxCommon');
|
||||
|
||||
var BoxplotSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.boxplot',
|
||||
|
||||
dependencies: ['xAxis', 'yAxis', 'grid'],
|
||||
|
||||
// TODO
|
||||
// box width represents group size, so dimension should have 'size'.
|
||||
|
||||
/**
|
||||
* @see <https://en.wikipedia.org/wiki/Box_plot>
|
||||
* The meanings of 'min' and 'max' depend on user,
|
||||
* and echarts do not need to know it.
|
||||
* @readOnly
|
||||
*/
|
||||
valueDimensions: ['min', 'Q1', 'median', 'Q3', 'max'],
|
||||
|
||||
/**
|
||||
* @type {Array.<string>}
|
||||
* @readOnly
|
||||
*/
|
||||
dimensions: null,
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
coordinateSystem: 'cartesian2d',
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
layout: null, // 'horizontal' or 'vertical'
|
||||
boxWidth: [7, 50], // [min, max] can be percent of band width.
|
||||
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#fff',
|
||||
borderWidth: 1
|
||||
},
|
||||
emphasis: {
|
||||
borderWidth: 2,
|
||||
shadowBlur: 5,
|
||||
shadowOffsetX: 2,
|
||||
shadowOffsetY: 2,
|
||||
shadowColor: 'rgba(0,0,0,0.4)'
|
||||
}
|
||||
},
|
||||
|
||||
animationEasing: 'elasticOut',
|
||||
animationDuration: 800
|
||||
}
|
||||
});
|
||||
|
||||
zrUtil.mixin(BoxplotSeries, whiskerBoxCommon.seriesModelMixin, true);
|
||||
|
||||
return BoxplotSeries;
|
||||
|
||||
});
|
||||
49
vendors/echarts/src/chart/boxplot/BoxplotView.js
vendored
Normal file
49
vendors/echarts/src/chart/boxplot/BoxplotView.js
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var ChartView = require('../../view/Chart');
|
||||
var graphic = require('../../util/graphic');
|
||||
var whiskerBoxCommon = require('../helper/whiskerBoxCommon');
|
||||
|
||||
var BoxplotView = ChartView.extend({
|
||||
|
||||
type: 'boxplot',
|
||||
|
||||
getStyleUpdater: function () {
|
||||
return updateStyle;
|
||||
}
|
||||
});
|
||||
|
||||
zrUtil.mixin(BoxplotView, whiskerBoxCommon.viewMixin, true);
|
||||
|
||||
// Update common properties
|
||||
var normalStyleAccessPath = ['itemStyle', 'normal'];
|
||||
var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
|
||||
|
||||
function updateStyle(itemGroup, data, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
|
||||
var borderColor = data.getItemVisual(idx, 'color');
|
||||
|
||||
// Exclude borderColor.
|
||||
var itemStyle = normalItemStyleModel.getItemStyle(['borderColor']);
|
||||
|
||||
var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex);
|
||||
whiskerEl.style.set(itemStyle);
|
||||
whiskerEl.style.stroke = borderColor;
|
||||
whiskerEl.dirty();
|
||||
|
||||
var bodyEl = itemGroup.childAt(itemGroup.bodyIndex);
|
||||
bodyEl.style.set(itemStyle);
|
||||
bodyEl.style.stroke = borderColor;
|
||||
bodyEl.dirty();
|
||||
|
||||
var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
|
||||
graphic.setHoverStyle(itemGroup, hoverStyle);
|
||||
}
|
||||
|
||||
return BoxplotView;
|
||||
|
||||
});
|
||||
181
vendors/echarts/src/chart/boxplot/boxplotLayout.js
vendored
Normal file
181
vendors/echarts/src/chart/boxplot/boxplotLayout.js
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var numberUtil = require('../../util/number');
|
||||
var parsePercent = numberUtil.parsePercent;
|
||||
var each = zrUtil.each;
|
||||
|
||||
return function (ecModel, api) {
|
||||
|
||||
var groupResult = groupSeriesByAxis(ecModel);
|
||||
|
||||
each(groupResult, function (groupItem) {
|
||||
var seriesModels = groupItem.seriesModels;
|
||||
|
||||
if (!seriesModels.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
calculateBase(groupItem);
|
||||
|
||||
each(seriesModels, function (seriesModel, idx) {
|
||||
layoutSingleSeries(
|
||||
seriesModel,
|
||||
groupItem.boxOffsetList[idx],
|
||||
groupItem.boxWidthList[idx]
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Group series by axis.
|
||||
*/
|
||||
function groupSeriesByAxis(ecModel) {
|
||||
var result = [];
|
||||
var axisList = [];
|
||||
|
||||
ecModel.eachSeriesByType('boxplot', function (seriesModel) {
|
||||
var baseAxis = seriesModel.getBaseAxis();
|
||||
var idx = zrUtil.indexOf(axisList, baseAxis);
|
||||
|
||||
if (idx < 0) {
|
||||
idx = axisList.length;
|
||||
axisList[idx] = baseAxis;
|
||||
result[idx] = {axis: baseAxis, seriesModels: []};
|
||||
}
|
||||
|
||||
result[idx].seriesModels.push(seriesModel);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate offset and box width for each series.
|
||||
*/
|
||||
function calculateBase(groupItem) {
|
||||
var extent;
|
||||
var baseAxis = groupItem.axis;
|
||||
var seriesModels = groupItem.seriesModels;
|
||||
var seriesCount = seriesModels.length;
|
||||
|
||||
var boxWidthList = groupItem.boxWidthList = [];
|
||||
var boxOffsetList = groupItem.boxOffsetList = [];
|
||||
var boundList = [];
|
||||
|
||||
var bandWidth;
|
||||
if (baseAxis.type === 'category') {
|
||||
bandWidth = baseAxis.getBandWidth();
|
||||
}
|
||||
else {
|
||||
var maxDataCount = 0;
|
||||
each(seriesModels, function (seriesModel) {
|
||||
maxDataCount = Math.max(maxDataCount, seriesModel.getData().count());
|
||||
});
|
||||
extent = baseAxis.getExtent(),
|
||||
Math.abs(extent[1] - extent[0]) / maxDataCount;
|
||||
}
|
||||
|
||||
each(seriesModels, function (seriesModel) {
|
||||
var boxWidthBound = seriesModel.get('boxWidth');
|
||||
if (!zrUtil.isArray(boxWidthBound)) {
|
||||
boxWidthBound = [boxWidthBound, boxWidthBound];
|
||||
}
|
||||
boundList.push([
|
||||
parsePercent(boxWidthBound[0], bandWidth) || 0,
|
||||
parsePercent(boxWidthBound[1], bandWidth) || 0
|
||||
]);
|
||||
});
|
||||
|
||||
var availableWidth = bandWidth * 0.8 - 2;
|
||||
var boxGap = availableWidth / seriesCount * 0.3;
|
||||
var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount;
|
||||
var base = boxWidth / 2 - availableWidth / 2;
|
||||
|
||||
each(seriesModels, function (seriesModel, idx) {
|
||||
boxOffsetList.push(base);
|
||||
base += boxGap + boxWidth;
|
||||
|
||||
boxWidthList.push(
|
||||
Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate points location for each series.
|
||||
*/
|
||||
function layoutSingleSeries(seriesModel, offset, boxWidth) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var data = seriesModel.getData();
|
||||
var dimensions = seriesModel.dimensions;
|
||||
var chartLayout = seriesModel.get('layout');
|
||||
var halfWidth = boxWidth / 2;
|
||||
|
||||
data.each(dimensions, function () {
|
||||
var args = arguments;
|
||||
var dimLen = dimensions.length;
|
||||
var axisDimVal = args[0];
|
||||
var idx = args[dimLen];
|
||||
var variableDim = chartLayout === 'horizontal' ? 0 : 1;
|
||||
var constDim = 1 - variableDim;
|
||||
|
||||
var median = getPoint(args[3]);
|
||||
var end1 = getPoint(args[1]);
|
||||
var end5 = getPoint(args[5]);
|
||||
var whiskerEnds = [
|
||||
[end1, getPoint(args[2])],
|
||||
[end5, getPoint(args[4])]
|
||||
];
|
||||
layEndLine(end1);
|
||||
layEndLine(end5);
|
||||
layEndLine(median);
|
||||
|
||||
var bodyEnds = [];
|
||||
addBodyEnd(whiskerEnds[0][1], 0);
|
||||
addBodyEnd(whiskerEnds[1][1], 1);
|
||||
|
||||
data.setItemLayout(idx, {
|
||||
chartLayout: chartLayout,
|
||||
initBaseline: median[constDim],
|
||||
median: median,
|
||||
bodyEnds: bodyEnds,
|
||||
whiskerEnds: whiskerEnds
|
||||
});
|
||||
|
||||
function getPoint(val) {
|
||||
var p = [];
|
||||
p[variableDim] = axisDimVal;
|
||||
p[constDim] = val;
|
||||
var point;
|
||||
if (isNaN(axisDimVal) || isNaN(val)) {
|
||||
point = [NaN, NaN];
|
||||
}
|
||||
else {
|
||||
point = coordSys.dataToPoint(p);
|
||||
point[variableDim] += offset;
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
function addBodyEnd(point, start) {
|
||||
var point1 = point.slice();
|
||||
var point2 = point.slice();
|
||||
point1[variableDim] += halfWidth;
|
||||
point2[variableDim] -= halfWidth;
|
||||
start
|
||||
? bodyEnds.push(point1, point2)
|
||||
: bodyEnds.push(point2, point1);
|
||||
}
|
||||
|
||||
function layEndLine(endCenter) {
|
||||
var line = [endCenter.slice(), endCenter.slice()];
|
||||
line[0][variableDim] -= halfWidth;
|
||||
line[1][variableDim] += halfWidth;
|
||||
whiskerEnds.push(line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
34
vendors/echarts/src/chart/boxplot/boxplotVisual.js
vendored
Normal file
34
vendors/echarts/src/chart/boxplot/boxplotVisual.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
define(function (require) {
|
||||
|
||||
var borderColorQuery = ['itemStyle', 'normal', 'borderColor'];
|
||||
|
||||
return function (ecModel, api) {
|
||||
|
||||
var globalColors = ecModel.get('color');
|
||||
|
||||
ecModel.eachRawSeriesByType('boxplot', function (seriesModel) {
|
||||
|
||||
var defaulColor = globalColors[seriesModel.seriesIndex % globalColors.length];
|
||||
var data = seriesModel.getData();
|
||||
|
||||
data.setVisual({
|
||||
legendSymbol: 'roundRect',
|
||||
// Use name 'color' but not 'borderColor' for legend usage and
|
||||
// visual coding from other component like dataRange.
|
||||
color: seriesModel.get(borderColorQuery) || defaulColor
|
||||
});
|
||||
|
||||
// Only visible series has each data be visual encoded
|
||||
if (!ecModel.isSeriesFiltered(seriesModel)) {
|
||||
data.each(function (idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
data.setItemVisual(
|
||||
idx,
|
||||
{color: itemModel.get(borderColorQuery, true)}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
15
vendors/echarts/src/chart/candlestick.js
vendored
Normal file
15
vendors/echarts/src/chart/candlestick.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./candlestick/CandlestickSeries');
|
||||
require('./candlestick/CandlestickView');
|
||||
|
||||
echarts.registerPreprocessor(
|
||||
require('./candlestick/preprocessor')
|
||||
);
|
||||
|
||||
echarts.registerVisualCoding('chart', require('./candlestick/candlestickVisual'));
|
||||
echarts.registerLayout(require('./candlestick/candlestickLayout'));
|
||||
|
||||
});
|
||||
92
vendors/echarts/src/chart/candlestick/CandlestickSeries.js
vendored
Normal file
92
vendors/echarts/src/chart/candlestick/CandlestickSeries.js
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var whiskerBoxCommon = require('../helper/whiskerBoxCommon');
|
||||
var formatUtil = require('../../util/format');
|
||||
var encodeHTML = formatUtil.encodeHTML;
|
||||
var addCommas = formatUtil.addCommas;
|
||||
|
||||
var CandlestickSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.candlestick',
|
||||
|
||||
dependencies: ['xAxis', 'yAxis', 'grid'],
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
*/
|
||||
valueDimensions: ['open', 'close', 'lowest', 'highest'],
|
||||
|
||||
/**
|
||||
* @type {Array.<string>}
|
||||
* @readOnly
|
||||
*/
|
||||
dimensions: null,
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
coordinateSystem: 'cartesian2d',
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
layout: null, // 'horizontal' or 'vertical'
|
||||
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#c23531', // 阳线 positive
|
||||
color0: '#314656', // 阴线 negative '#c23531', '#314656'
|
||||
borderWidth: 1,
|
||||
// FIXME
|
||||
// ec2中使用的是lineStyle.color 和 lineStyle.color0
|
||||
borderColor: '#c23531',
|
||||
borderColor0: '#314656'
|
||||
},
|
||||
emphasis: {
|
||||
borderWidth: 2
|
||||
}
|
||||
},
|
||||
|
||||
animationUpdate: false,
|
||||
animationEasing: 'linear',
|
||||
animationDuration: 300
|
||||
},
|
||||
|
||||
/**
|
||||
* Get dimension for shadow in dataZoom
|
||||
* @return {string} dimension name
|
||||
*/
|
||||
getShadowDim: function () {
|
||||
return 'open';
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
formatTooltip: function (dataIndex, mutipleSeries) {
|
||||
// It rearly use mutiple candlestick series in one cartesian,
|
||||
// so only consider one series in this default tooltip.
|
||||
var valueHTMLArr = zrUtil.map(this.valueDimensions, function (dim) {
|
||||
return dim + ': ' + addCommas(this._data.get(dim, dataIndex));
|
||||
}, this);
|
||||
|
||||
return encodeHTML(this.name) + '<br />' + valueHTMLArr.join('<br />');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
zrUtil.mixin(CandlestickSeries, whiskerBoxCommon.seriesModelMixin, true);
|
||||
|
||||
return CandlestickSeries;
|
||||
|
||||
});
|
||||
54
vendors/echarts/src/chart/candlestick/CandlestickView.js
vendored
Normal file
54
vendors/echarts/src/chart/candlestick/CandlestickView.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var ChartView = require('../../view/Chart');
|
||||
var graphic = require('../../util/graphic');
|
||||
var whiskerBoxCommon = require('../helper/whiskerBoxCommon');
|
||||
|
||||
var CandlestickView = ChartView.extend({
|
||||
|
||||
type: 'candlestick',
|
||||
|
||||
getStyleUpdater: function () {
|
||||
return updateStyle;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
zrUtil.mixin(CandlestickView, whiskerBoxCommon.viewMixin, true);
|
||||
|
||||
// Update common properties
|
||||
var normalStyleAccessPath = ['itemStyle', 'normal'];
|
||||
var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
|
||||
|
||||
function updateStyle(itemGroup, data, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
var borderColor = data.getItemVisual(idx, 'borderColor');
|
||||
|
||||
// Color must be excluded.
|
||||
// Because symbol provide setColor individually to set fill and stroke
|
||||
var itemStyle = normalItemStyleModel.getItemStyle(
|
||||
['color', 'color0', 'borderColor', 'borderColor0']
|
||||
);
|
||||
|
||||
var whiskerEl = itemGroup.childAt(itemGroup.whiskerIndex);
|
||||
whiskerEl.useStyle(itemStyle);
|
||||
whiskerEl.style.stroke = borderColor;
|
||||
|
||||
var bodyEl = itemGroup.childAt(itemGroup.bodyIndex);
|
||||
bodyEl.useStyle(itemStyle);
|
||||
bodyEl.style.fill = color;
|
||||
bodyEl.style.stroke = borderColor;
|
||||
|
||||
var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
|
||||
graphic.setHoverStyle(itemGroup, hoverStyle);
|
||||
}
|
||||
|
||||
|
||||
return CandlestickView;
|
||||
|
||||
});
|
||||
103
vendors/echarts/src/chart/candlestick/candlestickLayout.js
vendored
Normal file
103
vendors/echarts/src/chart/candlestick/candlestickLayout.js
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
define(function (require) {
|
||||
|
||||
var CANDLE_MIN_WIDTH = 2;
|
||||
var CANDLE_MIN_NICE_WIDTH = 5;
|
||||
var GPA_MIN = 4;
|
||||
|
||||
return function (ecModel, api) {
|
||||
|
||||
ecModel.eachSeriesByType('candlestick', function (seriesModel) {
|
||||
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var data = seriesModel.getData();
|
||||
var dimensions = seriesModel.dimensions;
|
||||
var chartLayout = seriesModel.get('layout');
|
||||
|
||||
var candleWidth = calculateCandleWidth(seriesModel, data);
|
||||
|
||||
data.each(dimensions, function () {
|
||||
var args = arguments;
|
||||
var dimLen = dimensions.length;
|
||||
var axisDimVal = args[0];
|
||||
var idx = args[dimLen];
|
||||
var variableDim = chartLayout === 'horizontal' ? 0 : 1;
|
||||
var constDim = 1 - variableDim;
|
||||
|
||||
var openVal = args[1];
|
||||
var closeVal = args[2];
|
||||
var lowestVal = args[3];
|
||||
var highestVal = args[4];
|
||||
|
||||
var ocLow = Math.min(openVal, closeVal);
|
||||
var ocHigh = Math.max(openVal, closeVal);
|
||||
|
||||
var ocLowPoint = getPoint(ocLow);
|
||||
var ocHighPoint = getPoint(ocHigh);
|
||||
var lowestPoint = getPoint(lowestVal);
|
||||
var highestPoint = getPoint(highestVal);
|
||||
|
||||
var whiskerEnds = [
|
||||
[highestPoint, ocHighPoint],
|
||||
[lowestPoint, ocLowPoint]
|
||||
];
|
||||
|
||||
var bodyEnds = [];
|
||||
addBodyEnd(ocHighPoint, 0);
|
||||
addBodyEnd(ocLowPoint, 1);
|
||||
|
||||
data.setItemLayout(idx, {
|
||||
chartLayout: chartLayout,
|
||||
sign: openVal > closeVal ? -1 : openVal < closeVal ? 1 : 0,
|
||||
initBaseline: openVal > closeVal
|
||||
? ocHighPoint[constDim] : ocLowPoint[constDim], // open point.
|
||||
bodyEnds: bodyEnds,
|
||||
whiskerEnds: whiskerEnds
|
||||
});
|
||||
|
||||
function getPoint(val) {
|
||||
var p = [];
|
||||
p[variableDim] = axisDimVal;
|
||||
p[constDim] = val;
|
||||
return (isNaN(axisDimVal) || isNaN(val))
|
||||
? [NaN, NaN]
|
||||
: coordSys.dataToPoint(p);
|
||||
}
|
||||
|
||||
function addBodyEnd(point, start) {
|
||||
var point1 = point.slice();
|
||||
var point2 = point.slice();
|
||||
point1[variableDim] += candleWidth / 2;
|
||||
point2[variableDim] -= candleWidth / 2;
|
||||
start
|
||||
? bodyEnds.push(point1, point2)
|
||||
: bodyEnds.push(point2, point1);
|
||||
}
|
||||
|
||||
}, true);
|
||||
});
|
||||
};
|
||||
|
||||
function calculateCandleWidth(seriesModel, data) {
|
||||
var baseAxis = seriesModel.getBaseAxis();
|
||||
var extent;
|
||||
|
||||
var bandWidth = baseAxis.type === 'category'
|
||||
? baseAxis.getBandWidth()
|
||||
: (
|
||||
extent = baseAxis.getExtent(),
|
||||
Math.abs(extent[1] - extent[0]) / data.count()
|
||||
);
|
||||
|
||||
// Half band width is perfect when space is enouph, otherwise
|
||||
// try not to be smaller than CANDLE_MIN_NICE_WIDTH (and only
|
||||
// gap is compressed), otherwise ensure not to be smaller than
|
||||
// CANDLE_MIN_WIDTH in spite of overlap.
|
||||
|
||||
return bandWidth / 2 - 2 > CANDLE_MIN_NICE_WIDTH // "- 2" is minus border width
|
||||
? bandWidth / 2 - 2
|
||||
: bandWidth - CANDLE_MIN_NICE_WIDTH > GPA_MIN
|
||||
? CANDLE_MIN_NICE_WIDTH
|
||||
: Math.max(bandWidth - GPA_MIN, CANDLE_MIN_WIDTH);
|
||||
}
|
||||
|
||||
});
|
||||
40
vendors/echarts/src/chart/candlestick/candlestickVisual.js
vendored
Normal file
40
vendors/echarts/src/chart/candlestick/candlestickVisual.js
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
define(function (require) {
|
||||
|
||||
var positiveBorderColorQuery = ['itemStyle', 'normal', 'borderColor'];
|
||||
var negativeBorderColorQuery = ['itemStyle', 'normal', 'borderColor0'];
|
||||
var positiveColorQuery = ['itemStyle', 'normal', 'color'];
|
||||
var negativeColorQuery = ['itemStyle', 'normal', 'color0'];
|
||||
|
||||
return function (ecModel, api) {
|
||||
|
||||
ecModel.eachRawSeriesByType('candlestick', function (seriesModel) {
|
||||
|
||||
var data = seriesModel.getData();
|
||||
|
||||
data.setVisual({
|
||||
legendSymbol: 'roundRect'
|
||||
});
|
||||
|
||||
// Only visible series has each data be visual encoded
|
||||
if (!ecModel.isSeriesFiltered(seriesModel)) {
|
||||
data.each(function (idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var sign = data.getItemLayout(idx).sign;
|
||||
|
||||
data.setItemVisual(
|
||||
idx,
|
||||
{
|
||||
color: itemModel.get(
|
||||
sign > 0 ? positiveColorQuery : negativeColorQuery
|
||||
),
|
||||
borderColor: itemModel.get(
|
||||
sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery
|
||||
)
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
18
vendors/echarts/src/chart/candlestick/preprocessor.js
vendored
Normal file
18
vendors/echarts/src/chart/candlestick/preprocessor.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
return function (option) {
|
||||
if (!option || !zrUtil.isArray(option.series)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate 'k' to 'candlestick'.
|
||||
zrUtil.each(option.series, function (seriesItem) {
|
||||
if (zrUtil.isObject(seriesItem) && seriesItem.type === 'k') {
|
||||
seriesItem.type = 'candlestick';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
17
vendors/echarts/src/chart/chord.js
vendored
Normal file
17
vendors/echarts/src/chart/chord.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
define(function (require) {
|
||||
|
||||
require('./chord/ChordSeries');
|
||||
require('./chord/ChordView');
|
||||
|
||||
var echarts = require('../echarts');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
echarts.registerLayout(require('./chord/chordCircularLayout'));
|
||||
|
||||
echarts.registerVisualCoding(
|
||||
'chart', zrUtil.curry(require('../visual/dataColor'), 'chord')
|
||||
);
|
||||
|
||||
echarts.registerProcessor(
|
||||
'filter', zrUtil.curry(require('../processor/dataFilter'), 'pie')
|
||||
);
|
||||
});
|
||||
64
vendors/echarts/src/chart/chord/ChordSeries.js
vendored
Normal file
64
vendors/echarts/src/chart/chord/ChordSeries.js
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
define(function (require) {
|
||||
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var createGraphFromNodeEdge = require('../helper/createGraphFromNodeEdge');
|
||||
var createGraphFromNodeMatrix = require('../helper/createGraphFromNodeMatrix');
|
||||
|
||||
var ChordSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.chord',
|
||||
|
||||
getInitialData: function (option) {
|
||||
var edges = option.edges || option.links;
|
||||
var nodes = option.data || option.nodes;
|
||||
var matrix = option.matrix;
|
||||
if (nodes && edges) {
|
||||
var graph = createGraphFromNodeEdge(nodes, edges, this, true);
|
||||
return graph.data;
|
||||
}
|
||||
else if (nodes && matrix) {
|
||||
var graph = createGraphFromNodeMatrix(nodes, matrix, this, true);
|
||||
return graph.data;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/data/Graph}
|
||||
*/
|
||||
getGraph: function () {
|
||||
return this.getData().graph;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/data/List}
|
||||
*/
|
||||
getEdgeData: function () {
|
||||
return this.getGraph().edgeData;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
center: ['50%', '50%'],
|
||||
radius: ['65%', '75%'],
|
||||
//
|
||||
// layout: 'circular',
|
||||
|
||||
sort: 'none',
|
||||
sortSub: 'none',
|
||||
padding: 0.02,
|
||||
startAngle: 90,
|
||||
clockwise: true,
|
||||
|
||||
itemStyle: {
|
||||
normal: {},
|
||||
emphasis: {}
|
||||
},
|
||||
|
||||
chordStyle: {
|
||||
normal: {},
|
||||
emphasis: {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ChordSeries;
|
||||
});
|
||||
75
vendors/echarts/src/chart/chord/ChordView.js
vendored
Normal file
75
vendors/echarts/src/chart/chord/ChordView.js
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
define(function (require) {
|
||||
|
||||
var RibbonPath = require('./Ribbon');
|
||||
var graphic = require('../../util/graphic');
|
||||
|
||||
return require('../../echarts').extendChartView({
|
||||
|
||||
type: 'chord',
|
||||
|
||||
init: function (option) {
|
||||
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var data = seriesModel.getData();
|
||||
var graph = seriesModel.getGraph();
|
||||
var edgeData = seriesModel.getEdgeData();
|
||||
|
||||
var group = this.group;
|
||||
group.removeAll();
|
||||
|
||||
data.each(function (idx) {
|
||||
var layout = data.getItemLayout(idx);
|
||||
var sector = new graphic.Sector({
|
||||
shape: {
|
||||
cx: layout.cx,
|
||||
cy: layout.cy,
|
||||
clockwise: layout.clockwise,
|
||||
r0: layout.r0,
|
||||
r: layout.r,
|
||||
startAngle: layout.startAngle,
|
||||
endAngle: layout.endAngle
|
||||
}
|
||||
});
|
||||
|
||||
sector.setStyle({
|
||||
fill: data.getItemVisual(idx, 'color')
|
||||
});
|
||||
|
||||
data.setItemLayout(idx);
|
||||
group.add(sector);
|
||||
});
|
||||
|
||||
var edgeRendered = {};
|
||||
edgeData.each(function (idx) {
|
||||
if (edgeRendered[idx]) {
|
||||
return;
|
||||
}
|
||||
var layout = edgeData.getItemLayout(idx);
|
||||
var edge = graph.getEdgeByIndex(idx);
|
||||
var otherEdge = graph.getEdge(edge.node2, edge.node1);
|
||||
var otherEdgeLayout = otherEdge.getLayout();
|
||||
edgeRendered[idx] = edgeRendered[otherEdge.dataIndex] = true;
|
||||
var ribbon = new RibbonPath({
|
||||
shape: {
|
||||
cx: layout.cx,
|
||||
cy: layout.cy,
|
||||
r: layout.r,
|
||||
s0: layout.startAngle,
|
||||
s1: layout.endAngle,
|
||||
t0: otherEdgeLayout.startAngle,
|
||||
t1: otherEdgeLayout.endAngle,
|
||||
clockwise: layout.clockwise
|
||||
}
|
||||
});
|
||||
ribbon.setStyle({
|
||||
// Use color of source
|
||||
fill: edge.node1.getVisual('color'),
|
||||
opacity: 0.5
|
||||
});
|
||||
group.add(ribbon);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
67
vendors/echarts/src/chart/chord/Ribbon.js
vendored
Normal file
67
vendors/echarts/src/chart/chord/Ribbon.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
define(function (require) {
|
||||
|
||||
var sin = Math.sin;
|
||||
var cos = Math.cos;
|
||||
|
||||
return require('../../util/graphic').extendShape({
|
||||
|
||||
type: 'ec-ribbon',
|
||||
|
||||
shape: {
|
||||
cx: 0,
|
||||
cy: 0,
|
||||
r: 0,
|
||||
s0: 0,
|
||||
s1: 0,
|
||||
t0: 0,
|
||||
t1: 0
|
||||
},
|
||||
|
||||
style: {
|
||||
fill: '#000'
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
|
||||
var clockwise = shape.clockwise || false;
|
||||
|
||||
var cx = shape.cx;
|
||||
var cy = shape.cy;
|
||||
var r = shape.r;
|
||||
var s0 = shape.s0;
|
||||
var s1 = shape.s1;
|
||||
var t0 = shape.t0;
|
||||
var t1 = shape.t1;
|
||||
var sx0 = cx + cos(s0) * r;
|
||||
var sy0 = cy + sin(s0) * r;
|
||||
var sx1 = cx + cos(s1) * r;
|
||||
var sy1 = cy + sin(s1) * r;
|
||||
var tx0 = cx + cos(t0) * r;
|
||||
var ty0 = cy + sin(t0) * r;
|
||||
var tx1 = cx + cos(t1) * r;
|
||||
var ty1 = cy + sin(t1) * r;
|
||||
|
||||
ctx.moveTo(sx0, sy0);
|
||||
ctx.arc(cx, cy, shape.r, s0, s1, !clockwise);
|
||||
ctx.bezierCurveTo(
|
||||
(cx - sx1) * 0.70 + sx1,
|
||||
(cy - sy1) * 0.70 + sy1,
|
||||
(cx - tx0) * 0.70 + tx0,
|
||||
(cy - ty0) * 0.70 + ty0,
|
||||
tx0, ty0
|
||||
);
|
||||
// Chord to self
|
||||
if (shape.s0 === shape.t0 && shape.s1 === shape.t1) {
|
||||
return;
|
||||
}
|
||||
ctx.arc(cx, cy, shape.r, t0, t1, !clockwise);
|
||||
ctx.bezierCurveTo(
|
||||
(cx - tx1) * 0.70 + tx1,
|
||||
(cy - ty1) * 0.70 + ty1,
|
||||
(cx - sx0) * 0.70 + sx0,
|
||||
(cy - sy0) * 0.70 + sy0,
|
||||
sx0, sy0
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
123
vendors/echarts/src/chart/chord/chordCircularLayout.js
vendored
Normal file
123
vendors/echarts/src/chart/chord/chordCircularLayout.js
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Chord layout
|
||||
* @module echarts/chart/chord/chordCircularLayout
|
||||
* @author pissang(http://github.com/pissang)
|
||||
*/
|
||||
define(function (require) {
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var numberUtil = require('../../util/number');
|
||||
/**
|
||||
* @param {module:echarts/data/Graph} graph
|
||||
*/
|
||||
function layout(graphs, opts) {
|
||||
if (!zrUtil.isArray(graphs)) {
|
||||
graphs = [graphs];
|
||||
}
|
||||
|
||||
var graph0 = graphs[0];
|
||||
|
||||
var groups = [];
|
||||
|
||||
// Init groups
|
||||
graph0.eachNode(function (node) {
|
||||
var group = {
|
||||
size: 0,
|
||||
subGroups: [],
|
||||
node: node
|
||||
};
|
||||
groups.push(group);
|
||||
});
|
||||
|
||||
zrUtil.each(graphs, function (graph) {
|
||||
graph.eachEdge(function (edge) {
|
||||
var g1 = groups[edge.node1.dataIndex];
|
||||
g1.size += edge.getValue('value') || 0;
|
||||
|
||||
g1.subGroups.push({
|
||||
size: edge.getValue('value'),
|
||||
edge: edge
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var sumSize = zrUtil.reduce(groups, function (sumSize, group) {
|
||||
return sumSize + group.size;
|
||||
}, 0);
|
||||
|
||||
if (opts.sort && opts.sort != 'none') {
|
||||
groups.sort(compareGroups);
|
||||
if (opts.sort === 'descending') {
|
||||
groups.revert();
|
||||
}
|
||||
}
|
||||
|
||||
var unitAngle = (Math.PI * 2 - opts.padding * graph0.data.count()) / sumSize;
|
||||
var angle = opts.startAngle * Math.PI / 180;
|
||||
var sign = opts.clockwise ? -1 : 1;
|
||||
zrUtil.each(groups, function (group) {
|
||||
if (opts.sortSub && opts.sortSub != 'none') {
|
||||
group.subGroups.sort(compareGroups);
|
||||
if (opts.sortSub === 'descending') {
|
||||
group.subGroups.revert();
|
||||
}
|
||||
}
|
||||
|
||||
var endAngle = angle + sign * group.size * unitAngle;
|
||||
group.node.setLayout({
|
||||
startAngle: -angle,
|
||||
endAngle: -endAngle,
|
||||
cx: opts.cx,
|
||||
cy: opts.cy,
|
||||
r0: opts.r0,
|
||||
r: opts.r,
|
||||
clockwise: opts.clockwise
|
||||
});
|
||||
zrUtil.each(group.subGroups, function (subGroup) {
|
||||
var startAngle = angle;
|
||||
var endAngle = angle + sign * subGroup.size * unitAngle;
|
||||
var layout = subGroup.edge.getLayout() || {
|
||||
cx: opts.cx,
|
||||
cy: opts.cy,
|
||||
r: opts.r0,
|
||||
clockwise: opts.clockwise
|
||||
};
|
||||
layout.startAngle = -startAngle;
|
||||
layout.endAngle = -endAngle;
|
||||
subGroup.edge.setLayout(layout);
|
||||
angle = endAngle;
|
||||
});
|
||||
|
||||
angle = endAngle + sign * opts.padding;
|
||||
});
|
||||
}
|
||||
|
||||
var compareGroups = function (a, b) {
|
||||
return a.size - b.size;
|
||||
};
|
||||
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('chord', function (chordSeries) {
|
||||
var graph = chordSeries.getGraph();
|
||||
|
||||
var center = chordSeries.get('center');
|
||||
var radius = chordSeries.get('radius');
|
||||
|
||||
var parsePercent = numberUtil.parsePercent;
|
||||
var viewWidth = api.getWidth();
|
||||
var viewHeight = api.getHeight();
|
||||
var viewSize = Math.min(viewWidth, viewHeight) / 2;
|
||||
|
||||
layout(graph, {
|
||||
sort: chordSeries.get('sort'),
|
||||
sortSub: chordSeries.get('sortSub'),
|
||||
padding: chordSeries.get('padding'),
|
||||
startAngle: chordSeries.get('startAngle'),
|
||||
clockwise: chordSeries.get('clockwise'),
|
||||
cx: parsePercent(center[0], viewWidth),
|
||||
cy: parsePercent(center[1], viewHeight),
|
||||
r0: parsePercent(radius[0], viewSize),
|
||||
r: parsePercent(radius[1], viewSize)
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
15
vendors/echarts/src/chart/effectScatter.js
vendored
Normal file
15
vendors/echarts/src/chart/effectScatter.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./effectScatter/EffectScatterSeries');
|
||||
require('./effectScatter/EffectScatterView');
|
||||
|
||||
echarts.registerVisualCoding('chart', zrUtil.curry(
|
||||
require('../visual/symbol'), 'effectScatter', 'circle', null
|
||||
));
|
||||
echarts.registerLayout(zrUtil.curry(
|
||||
require('../layout/points'), 'effectScatter'
|
||||
));
|
||||
});
|
||||
64
vendors/echarts/src/chart/effectScatter/EffectScatterSeries.js
vendored
Normal file
64
vendors/echarts/src/chart/effectScatter/EffectScatterSeries.js
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
define(function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var createListFromArray = require('../helper/createListFromArray');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
|
||||
return SeriesModel.extend({
|
||||
|
||||
type: 'series.effectScatter',
|
||||
|
||||
dependencies: ['grid', 'polar'],
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var list = createListFromArray(option.data, this, ecModel);
|
||||
return list;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
coordinateSystem: 'cartesian2d',
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
legendHoverLink: true,
|
||||
|
||||
effectType: 'ripple',
|
||||
|
||||
// When to show the effect, option: 'render'|'emphasis'
|
||||
showEffectOn: 'render',
|
||||
|
||||
// Ripple effect config
|
||||
rippleEffect: {
|
||||
period: 4,
|
||||
// Scale of ripple
|
||||
scale: 2.5,
|
||||
// Brush type can be fill or stroke
|
||||
brushType: 'fill'
|
||||
},
|
||||
|
||||
// Cartesian coordinate system
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
// Polar coordinate system
|
||||
polarIndex: 0,
|
||||
|
||||
// Geo coordinate system
|
||||
geoIndex: 0,
|
||||
|
||||
// symbol: null, // 图形类型
|
||||
symbolSize: 10 // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
|
||||
// symbolRotate: null, // 图形旋转控制
|
||||
|
||||
// large: false,
|
||||
// Available when large is true
|
||||
// largeThreshold: 2000,
|
||||
|
||||
// itemStyle: {
|
||||
// normal: {
|
||||
// opacity: 1
|
||||
// }
|
||||
// }
|
||||
}
|
||||
});
|
||||
});
|
||||
29
vendors/echarts/src/chart/effectScatter/EffectScatterView.js
vendored
Normal file
29
vendors/echarts/src/chart/effectScatter/EffectScatterView.js
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
define(function (require) {
|
||||
|
||||
var SymbolDraw = require('../helper/SymbolDraw');
|
||||
var EffectSymbol = require('../helper/EffectSymbol');
|
||||
|
||||
require('../../echarts').extendChartView({
|
||||
|
||||
type: 'effectScatter',
|
||||
|
||||
init: function () {
|
||||
this._symbolDraw = new SymbolDraw(EffectSymbol);
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var data = seriesModel.getData();
|
||||
var effectSymbolDraw = this._symbolDraw;
|
||||
effectSymbolDraw.updateData(data);
|
||||
this.group.add(effectSymbolDraw.group);
|
||||
},
|
||||
|
||||
updateLayout: function () {
|
||||
this._symbolDraw.updateLayout();
|
||||
},
|
||||
|
||||
remove: function (ecModel, api) {
|
||||
this._symbolDraw && this._symbolDraw.remove(api);
|
||||
}
|
||||
});
|
||||
});
|
||||
17
vendors/echarts/src/chart/funnel.js
vendored
Normal file
17
vendors/echarts/src/chart/funnel.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./funnel/FunnelSeries');
|
||||
require('./funnel/FunnelView');
|
||||
|
||||
echarts.registerVisualCoding(
|
||||
'chart', zrUtil.curry(require('../visual/dataColor'), 'funnel')
|
||||
);
|
||||
echarts.registerLayout(require('./funnel/funnelLayout'));
|
||||
|
||||
echarts.registerProcessor(
|
||||
'filter', zrUtil.curry(require('../processor/dataFilter'), 'funnel')
|
||||
);
|
||||
});
|
||||
101
vendors/echarts/src/chart/funnel/FunnelSeries.js
vendored
Normal file
101
vendors/echarts/src/chart/funnel/FunnelSeries.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var List = require('../../data/List');
|
||||
var modelUtil = require('../../util/model');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
|
||||
var FunnelSeries = require('../../echarts').extendSeriesModel({
|
||||
|
||||
type: 'series.funnel',
|
||||
|
||||
init: function (option) {
|
||||
FunnelSeries.superApply(this, 'init', arguments);
|
||||
|
||||
// Enable legend selection for each data item
|
||||
// Use a function instead of direct access because data reference may changed
|
||||
this.legendDataProvider = function () {
|
||||
return this._dataBeforeProcessed;
|
||||
};
|
||||
// Extend labelLine emphasis
|
||||
this._defaultLabelLine(option);
|
||||
},
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var dimensions = completeDimensions(['value'], option.data);
|
||||
var list = new List(dimensions, this);
|
||||
list.initData(option.data);
|
||||
return list;
|
||||
},
|
||||
|
||||
_defaultLabelLine: function (option) {
|
||||
// Extend labelLine emphasis
|
||||
modelUtil.defaultEmphasis(option.labelLine, ['show']);
|
||||
|
||||
var labelLineNormalOpt = option.labelLine.normal;
|
||||
var labelLineEmphasisOpt = option.labelLine.emphasis;
|
||||
// Not show label line if `label.normal.show = false`
|
||||
labelLineNormalOpt.show = labelLineNormalOpt.show
|
||||
&& option.label.normal.show;
|
||||
labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
|
||||
&& option.label.emphasis.show;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
legendHoverLink: true,
|
||||
left: 80,
|
||||
top: 60,
|
||||
right: 80,
|
||||
bottom: 60,
|
||||
// width: {totalWidth} - left - right,
|
||||
// height: {totalHeight} - top - bottom,
|
||||
|
||||
// 默认取数据最小最大值
|
||||
// min: 0,
|
||||
// max: 100,
|
||||
minSize: '0%',
|
||||
maxSize: '100%',
|
||||
sort: 'descending', // 'ascending', 'descending'
|
||||
gap: 0,
|
||||
funnelAlign: 'center',
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'outer'
|
||||
// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
|
||||
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
normal: {
|
||||
show: true,
|
||||
length: 20,
|
||||
lineStyle: {
|
||||
// color: 各异,
|
||||
width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
emphasis: {}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// color: 各异,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 1
|
||||
},
|
||||
emphasis: {
|
||||
// color: 各异,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return FunnelSeries;
|
||||
});
|
||||
213
vendors/echarts/src/chart/funnel/FunnelView.js
vendored
Normal file
213
vendors/echarts/src/chart/funnel/FunnelView.js
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
/**
|
||||
* Piece of pie including Sector, Label, LabelLine
|
||||
* @constructor
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
*/
|
||||
function FunnelPiece(data, idx) {
|
||||
|
||||
graphic.Group.call(this);
|
||||
|
||||
var polygon = new graphic.Polygon();
|
||||
var labelLine = new graphic.Polyline();
|
||||
var text = new graphic.Text();
|
||||
this.add(polygon);
|
||||
this.add(labelLine);
|
||||
this.add(text);
|
||||
|
||||
this.updateData(data, idx, true);
|
||||
|
||||
// Hover to change label and labelLine
|
||||
function onEmphasis() {
|
||||
labelLine.ignore = labelLine.hoverIgnore;
|
||||
text.ignore = text.hoverIgnore;
|
||||
}
|
||||
function onNormal() {
|
||||
labelLine.ignore = labelLine.normalIgnore;
|
||||
text.ignore = text.normalIgnore;
|
||||
}
|
||||
this.on('emphasis', onEmphasis)
|
||||
.on('normal', onNormal)
|
||||
.on('mouseover', onEmphasis)
|
||||
.on('mouseout', onNormal);
|
||||
}
|
||||
|
||||
var funnelPieceProto = FunnelPiece.prototype;
|
||||
|
||||
function getLabelStyle(data, idx, state, labelModel) {
|
||||
var textStyleModel = labelModel.getModel('textStyle');
|
||||
var position = labelModel.get('position');
|
||||
var isLabelInside = position === 'inside' || position === 'inner' || position === 'center';
|
||||
return {
|
||||
fill: textStyleModel.getTextColor()
|
||||
|| (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')),
|
||||
textFont: textStyleModel.getFont(),
|
||||
text: zrUtil.retrieve(
|
||||
data.hostModel.getFormattedLabel(idx, state),
|
||||
data.getName(idx)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
var opacityAccessPath = ['itemStyle', 'normal', 'opacity'];
|
||||
funnelPieceProto.updateData = function (data, idx, firstCreate) {
|
||||
|
||||
var polygon = this.childAt(0);
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var layout = data.getItemLayout(idx);
|
||||
var opacity = data.getItemModel(idx).get(opacityAccessPath);
|
||||
opacity = opacity == null ? 1 : opacity;
|
||||
|
||||
// Reset style
|
||||
polygon.useStyle({});
|
||||
|
||||
if (firstCreate) {
|
||||
polygon.setShape({
|
||||
points: layout.points
|
||||
});
|
||||
polygon.setStyle({ opacity : 0 });
|
||||
graphic.initProps(polygon, {
|
||||
style: {
|
||||
opacity: opacity
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
}
|
||||
else {
|
||||
graphic.updateProps(polygon, {
|
||||
style: {
|
||||
opacity: opacity
|
||||
},
|
||||
shape: {
|
||||
points: layout.points
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
}
|
||||
|
||||
// Update common style
|
||||
var itemStyleModel = itemModel.getModel('itemStyle');
|
||||
var visualColor = data.getItemVisual(idx, 'color');
|
||||
|
||||
polygon.setStyle(
|
||||
zrUtil.defaults(
|
||||
{
|
||||
fill: visualColor
|
||||
},
|
||||
itemStyleModel.getModel('normal').getItemStyle(['opacity'])
|
||||
)
|
||||
);
|
||||
polygon.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle();
|
||||
|
||||
this._updateLabel(data, idx);
|
||||
|
||||
graphic.setHoverStyle(this);
|
||||
};
|
||||
|
||||
funnelPieceProto._updateLabel = function (data, idx) {
|
||||
|
||||
var labelLine = this.childAt(1);
|
||||
var labelText = this.childAt(2);
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var layout = data.getItemLayout(idx);
|
||||
var labelLayout = layout.label;
|
||||
var visualColor = data.getItemVisual(idx, 'color');
|
||||
|
||||
graphic.updateProps(labelLine, {
|
||||
shape: {
|
||||
points: labelLayout.linePoints || labelLayout.linePoints
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
|
||||
graphic.updateProps(labelText, {
|
||||
style: {
|
||||
x: labelLayout.x,
|
||||
y: labelLayout.y
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
labelText.attr({
|
||||
style: {
|
||||
textAlign: labelLayout.textAlign,
|
||||
textVerticalAlign: labelLayout.verticalAlign,
|
||||
textFont: labelLayout.font
|
||||
},
|
||||
rotation: labelLayout.rotation,
|
||||
origin: [labelLayout.x, labelLayout.y],
|
||||
z2: 10
|
||||
});
|
||||
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var labelHoverModel = itemModel.getModel('label.emphasis');
|
||||
var labelLineModel = itemModel.getModel('labelLine.normal');
|
||||
var labelLineHoverModel = itemModel.getModel('labelLine.emphasis');
|
||||
|
||||
labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel));
|
||||
|
||||
labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
|
||||
labelText.hoverIgnore = !labelHoverModel.get('show');
|
||||
|
||||
labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
|
||||
labelLine.hoverIgnore = !labelLineHoverModel.get('show');
|
||||
|
||||
// Default use item visual color
|
||||
labelLine.setStyle({
|
||||
stroke: visualColor
|
||||
});
|
||||
labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
|
||||
|
||||
labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel);
|
||||
labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
|
||||
};
|
||||
|
||||
zrUtil.inherits(FunnelPiece, graphic.Group);
|
||||
|
||||
|
||||
var Funnel = require('../../view/Chart').extend({
|
||||
|
||||
type: 'funnel',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
|
||||
var group = this.group;
|
||||
|
||||
data.diff(oldData)
|
||||
.add(function (idx) {
|
||||
var funnelPiece = new FunnelPiece(data, idx);
|
||||
|
||||
data.setItemGraphicEl(idx, funnelPiece);
|
||||
|
||||
group.add(funnelPiece);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var piePiece = oldData.getItemGraphicEl(oldIdx);
|
||||
|
||||
piePiece.updateData(data, newIdx);
|
||||
|
||||
group.add(piePiece);
|
||||
data.setItemGraphicEl(newIdx, piePiece);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
var piePiece = oldData.getItemGraphicEl(idx);
|
||||
group.remove(piePiece);
|
||||
})
|
||||
.execute();
|
||||
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this.group.removeAll();
|
||||
this._data = null;
|
||||
}
|
||||
});
|
||||
|
||||
return Funnel;
|
||||
});
|
||||
170
vendors/echarts/src/chart/funnel/funnelLayout.js
vendored
Normal file
170
vendors/echarts/src/chart/funnel/funnelLayout.js
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
define(function (require) {
|
||||
|
||||
var layout = require('../../util/layout');
|
||||
var number = require('../../util/number');
|
||||
|
||||
var parsePercent = number.parsePercent;
|
||||
|
||||
function getViewRect(seriesModel, api) {
|
||||
return layout.getLayoutRect(
|
||||
seriesModel.getBoxLayoutParams(), {
|
||||
width: api.getWidth(),
|
||||
height: api.getHeight()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getSortedIndices(data, sort) {
|
||||
var valueArr = data.mapArray('value', function (val) {
|
||||
return val;
|
||||
});
|
||||
var indices = [];
|
||||
var isAscending = sort === 'ascending';
|
||||
for (var i = 0, len = data.count(); i < len; i++) {
|
||||
indices[i] = i;
|
||||
}
|
||||
indices.sort(function (a, b) {
|
||||
return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a];
|
||||
});
|
||||
return indices;
|
||||
}
|
||||
|
||||
function labelLayout (data) {
|
||||
data.each(function (idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var labelPosition = labelModel.get('position');
|
||||
|
||||
var labelLineModel = itemModel.getModel('labelLine.normal');
|
||||
|
||||
var layout = data.getItemLayout(idx);
|
||||
var points = layout.points;
|
||||
|
||||
var isLabelInside = labelPosition === 'inner'
|
||||
|| labelPosition === 'inside' || labelPosition === 'center';
|
||||
|
||||
var textAlign;
|
||||
var textX;
|
||||
var textY;
|
||||
var linePoints;
|
||||
|
||||
if (isLabelInside) {
|
||||
textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
|
||||
textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
|
||||
textAlign = 'center';
|
||||
linePoints = [
|
||||
[textX, textY], [textX, textY]
|
||||
];
|
||||
}
|
||||
else {
|
||||
var x1;
|
||||
var y1;
|
||||
var x2;
|
||||
var labelLineLen = labelLineModel.get('length');
|
||||
if (labelPosition === 'left') {
|
||||
// Left side
|
||||
x1 = (points[3][0] + points[0][0]) / 2;
|
||||
y1 = (points[3][1] + points[0][1]) / 2;
|
||||
x2 = x1 - labelLineLen;
|
||||
textX = x2 - 5;
|
||||
textAlign = 'right';
|
||||
}
|
||||
else {
|
||||
// Right side
|
||||
x1 = (points[1][0] + points[2][0]) / 2;
|
||||
y1 = (points[1][1] + points[2][1]) / 2;
|
||||
x2 = x1 + labelLineLen;
|
||||
textX = x2 + 5;
|
||||
textAlign = 'left';
|
||||
}
|
||||
var y2 = y1;
|
||||
|
||||
linePoints = [[x1, y1], [x2, y2]];
|
||||
textY = y2;
|
||||
}
|
||||
|
||||
layout.label = {
|
||||
linePoints: linePoints,
|
||||
x: textX,
|
||||
y: textY,
|
||||
verticalAlign: 'middle',
|
||||
textAlign: textAlign,
|
||||
inside: isLabelInside
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('funnel', function (seriesModel) {
|
||||
var data = seriesModel.getData();
|
||||
var sort = seriesModel.get('sort');
|
||||
var viewRect = getViewRect(seriesModel, api);
|
||||
var indices = getSortedIndices(data, sort);
|
||||
|
||||
var sizeExtent = [
|
||||
parsePercent(seriesModel.get('minSize'), viewRect.width),
|
||||
parsePercent(seriesModel.get('maxSize'), viewRect.width)
|
||||
];
|
||||
var dataExtent = data.getDataExtent('value');
|
||||
var min = seriesModel.get('min');
|
||||
var max = seriesModel.get('max');
|
||||
if (min == null) {
|
||||
min = Math.min(dataExtent[0], 0);
|
||||
}
|
||||
if (max == null) {
|
||||
max = dataExtent[1];
|
||||
}
|
||||
|
||||
var funnelAlign = seriesModel.get('funnelAlign');
|
||||
var gap = seriesModel.get('gap');
|
||||
var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
|
||||
|
||||
var y = viewRect.y;
|
||||
|
||||
var getLinePoints = function (idx, offY) {
|
||||
// End point index is data.count() and we assign it 0
|
||||
var val = data.get('value', idx) || 0;
|
||||
var itemWidth = number.linearMap(val, [min, max], sizeExtent, true);
|
||||
var x0;
|
||||
switch (funnelAlign) {
|
||||
case 'left':
|
||||
x0 = viewRect.x;
|
||||
break;
|
||||
case 'center':
|
||||
x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
|
||||
break;
|
||||
case 'right':
|
||||
x0 = viewRect.x + viewRect.width - itemWidth;
|
||||
break;
|
||||
}
|
||||
return [
|
||||
[x0, offY],
|
||||
[x0 + itemWidth, offY]
|
||||
];
|
||||
};
|
||||
|
||||
if (sort === 'ascending') {
|
||||
// From bottom to top
|
||||
itemHeight = -itemHeight;
|
||||
gap = -gap;
|
||||
y += viewRect.height;
|
||||
indices = indices.reverse();
|
||||
}
|
||||
|
||||
for (var i = 0; i < indices.length; i++) {
|
||||
var idx = indices[i];
|
||||
var nextIdx = indices[i + 1];
|
||||
var start = getLinePoints(idx, y);
|
||||
var end = getLinePoints(nextIdx, y + itemHeight);
|
||||
|
||||
y += itemHeight + gap;
|
||||
|
||||
data.setItemLayout(idx, {
|
||||
points: start.concat(end.slice().reverse())
|
||||
});
|
||||
}
|
||||
|
||||
labelLayout(data);
|
||||
});
|
||||
};
|
||||
});
|
||||
4
vendors/echarts/src/chart/gauge.js
vendored
Normal file
4
vendors/echarts/src/chart/gauge.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
define(function (require) {
|
||||
require('./gauge/GaugeSeries');
|
||||
require('./gauge/GaugeView');
|
||||
});
|
||||
122
vendors/echarts/src/chart/gauge/GaugeSeries.js
vendored
Normal file
122
vendors/echarts/src/chart/gauge/GaugeSeries.js
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
define(function (require) {
|
||||
|
||||
var List = require('../../data/List');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var GaugeSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.gauge',
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var list = new List(['value'], this);
|
||||
var dataOpt = option.data || [];
|
||||
if (!zrUtil.isArray(dataOpt)) {
|
||||
dataOpt = [dataOpt];
|
||||
}
|
||||
// Only use the first data item
|
||||
list.initData(dataOpt);
|
||||
return list;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
// 默认全局居中
|
||||
center: ['50%', '50%'],
|
||||
legendHoverLink: true,
|
||||
radius: '75%',
|
||||
startAngle: 225,
|
||||
endAngle: -45,
|
||||
clockwise: true,
|
||||
// 最小值
|
||||
min: 0,
|
||||
// 最大值
|
||||
max: 100,
|
||||
// 分割段数,默认为10
|
||||
splitNumber: 10,
|
||||
// 坐标轴线
|
||||
axisLine: {
|
||||
// 默认显示,属性show控制显示与否
|
||||
show: true,
|
||||
lineStyle: { // 属性lineStyle控制线条样式
|
||||
color: [[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']],
|
||||
width: 30
|
||||
}
|
||||
},
|
||||
// 分隔线
|
||||
splitLine: {
|
||||
// 默认显示,属性show控制显示与否
|
||||
show: true,
|
||||
// 属性length控制线长
|
||||
length: 30,
|
||||
// 属性lineStyle(详见lineStyle)控制线条样式
|
||||
lineStyle: {
|
||||
color: '#eee',
|
||||
width: 2,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
// 坐标轴小标记
|
||||
axisTick: {
|
||||
// 属性show控制显示与否,默认不显示
|
||||
show: true,
|
||||
// 每份split细分多少段
|
||||
splitNumber: 5,
|
||||
// 属性length控制线长
|
||||
length: 8,
|
||||
// 属性lineStyle控制线条样式
|
||||
lineStyle: {
|
||||
color: '#eee',
|
||||
width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
show: true,
|
||||
// formatter: null,
|
||||
textStyle: { // 其余属性默认使用全局文本样式,详见TEXTSTYLE
|
||||
color: 'auto'
|
||||
}
|
||||
},
|
||||
pointer: {
|
||||
show: true,
|
||||
length: '80%',
|
||||
width: 8
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'auto'
|
||||
}
|
||||
},
|
||||
title: {
|
||||
show: true,
|
||||
// x, y,单位px
|
||||
offsetCenter: [0, '-40%'],
|
||||
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
|
||||
textStyle: {
|
||||
color: '#333',
|
||||
fontSize: 15
|
||||
}
|
||||
},
|
||||
detail: {
|
||||
show: true,
|
||||
backgroundColor: 'rgba(0,0,0,0)',
|
||||
borderWidth: 0,
|
||||
borderColor: '#ccc',
|
||||
width: 100,
|
||||
height: 40,
|
||||
// x, y,单位px
|
||||
offsetCenter: [0, '40%'],
|
||||
// formatter: null,
|
||||
// 其余属性默认使用全局文本样式,详见TEXTSTYLE
|
||||
textStyle: {
|
||||
color: 'auto',
|
||||
fontSize: 30
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return GaugeSeries;
|
||||
});
|
||||
410
vendors/echarts/src/chart/gauge/GaugeView.js
vendored
Normal file
410
vendors/echarts/src/chart/gauge/GaugeView.js
vendored
Normal file
@@ -0,0 +1,410 @@
|
||||
define(function (require) {
|
||||
|
||||
var PointerPath = require('./PointerPath');
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var numberUtil = require('../../util/number');
|
||||
var parsePercent = numberUtil.parsePercent;
|
||||
|
||||
function parsePosition(seriesModel, api) {
|
||||
var center = seriesModel.get('center');
|
||||
var width = api.getWidth();
|
||||
var height = api.getHeight();
|
||||
var size = Math.min(width, height);
|
||||
var cx = parsePercent(center[0], api.getWidth());
|
||||
var cy = parsePercent(center[1], api.getHeight());
|
||||
var r = parsePercent(seriesModel.get('radius'), size / 2);
|
||||
|
||||
return {
|
||||
cx: cx,
|
||||
cy: cy,
|
||||
r: r
|
||||
};
|
||||
}
|
||||
|
||||
function formatLabel(label, labelFormatter) {
|
||||
if (labelFormatter) {
|
||||
if (typeof labelFormatter === 'string') {
|
||||
label = labelFormatter.replace('{value}', label);
|
||||
}
|
||||
else if (typeof labelFormatter === 'function') {
|
||||
label = labelFormatter(label);
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
var PI2 = Math.PI * 2;
|
||||
|
||||
var GaugeView = require('../../view/Chart').extend({
|
||||
|
||||
type: 'gauge',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
|
||||
this.group.removeAll();
|
||||
|
||||
var colorList = seriesModel.get('axisLine.lineStyle.color');
|
||||
var posInfo = parsePosition(seriesModel, api);
|
||||
|
||||
this._renderMain(
|
||||
seriesModel, ecModel, api, colorList, posInfo
|
||||
);
|
||||
},
|
||||
|
||||
_renderMain: function (seriesModel, ecModel, api, colorList, posInfo) {
|
||||
var group = this.group;
|
||||
|
||||
var axisLineModel = seriesModel.getModel('axisLine');
|
||||
var lineStyleModel = axisLineModel.getModel('lineStyle');
|
||||
|
||||
var clockwise = seriesModel.get('clockwise');
|
||||
var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
|
||||
var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;
|
||||
|
||||
var angleRangeSpan = (endAngle - startAngle) % PI2;
|
||||
|
||||
var prevEndAngle = startAngle;
|
||||
var axisLineWidth = lineStyleModel.get('width');
|
||||
|
||||
for (var i = 0; i < colorList.length; i++) {
|
||||
// Clamp
|
||||
var percent = Math.min(Math.max(colorList[i][0], 0), 1);
|
||||
var endAngle = startAngle + angleRangeSpan * percent;
|
||||
var sector = new graphic.Sector({
|
||||
shape: {
|
||||
startAngle: prevEndAngle,
|
||||
endAngle: endAngle,
|
||||
cx: posInfo.cx,
|
||||
cy: posInfo.cy,
|
||||
clockwise: clockwise,
|
||||
r0: posInfo.r - axisLineWidth,
|
||||
r: posInfo.r
|
||||
},
|
||||
silent: true
|
||||
});
|
||||
|
||||
sector.setStyle({
|
||||
fill: colorList[i][1]
|
||||
});
|
||||
|
||||
sector.setStyle(lineStyleModel.getLineStyle(
|
||||
// Because we use sector to simulate arc
|
||||
// so the properties for stroking are useless
|
||||
['color', 'borderWidth', 'borderColor']
|
||||
));
|
||||
|
||||
group.add(sector);
|
||||
|
||||
prevEndAngle = endAngle;
|
||||
}
|
||||
|
||||
var getColor = function (percent) {
|
||||
// Less than 0
|
||||
if (percent <= 0) {
|
||||
return colorList[0][1];
|
||||
}
|
||||
for (var i = 0; i < colorList.length; i++) {
|
||||
if (colorList[i][0] >= percent
|
||||
&& (i === 0 ? 0 : colorList[i - 1][0]) < percent
|
||||
) {
|
||||
return colorList[i][1];
|
||||
}
|
||||
}
|
||||
// More than 1
|
||||
return colorList[i - 1][1];
|
||||
};
|
||||
|
||||
if (!clockwise) {
|
||||
var tmp = startAngle;
|
||||
startAngle = endAngle;
|
||||
endAngle = tmp;
|
||||
}
|
||||
|
||||
this._renderTicks(
|
||||
seriesModel, ecModel, api, getColor, posInfo,
|
||||
startAngle, endAngle, clockwise
|
||||
);
|
||||
|
||||
this._renderPointer(
|
||||
seriesModel, ecModel, api, getColor, posInfo,
|
||||
startAngle, endAngle, clockwise
|
||||
);
|
||||
|
||||
this._renderTitle(
|
||||
seriesModel, ecModel, api, getColor, posInfo
|
||||
);
|
||||
this._renderDetail(
|
||||
seriesModel, ecModel, api, getColor, posInfo
|
||||
);
|
||||
},
|
||||
|
||||
_renderTicks: function (
|
||||
seriesModel, ecModel, api, getColor, posInfo,
|
||||
startAngle, endAngle, clockwise
|
||||
) {
|
||||
var group = this.group;
|
||||
var cx = posInfo.cx;
|
||||
var cy = posInfo.cy;
|
||||
var r = posInfo.r;
|
||||
|
||||
var minVal = seriesModel.get('min');
|
||||
var maxVal = seriesModel.get('max');
|
||||
|
||||
var splitLineModel = seriesModel.getModel('splitLine');
|
||||
var tickModel = seriesModel.getModel('axisTick');
|
||||
var labelModel = seriesModel.getModel('axisLabel');
|
||||
|
||||
var splitNumber = seriesModel.get('splitNumber');
|
||||
var subSplitNumber = tickModel.get('splitNumber');
|
||||
|
||||
var splitLineLen = parsePercent(
|
||||
splitLineModel.get('length'), r
|
||||
);
|
||||
var tickLen = parsePercent(
|
||||
tickModel.get('length'), r
|
||||
);
|
||||
|
||||
var angle = startAngle;
|
||||
var step = (endAngle - startAngle) / splitNumber;
|
||||
var subStep = step / subSplitNumber;
|
||||
|
||||
var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
|
||||
var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();
|
||||
var textStyleModel = labelModel.getModel('textStyle');
|
||||
|
||||
for (var i = 0; i <= splitNumber; i++) {
|
||||
var unitX = Math.cos(angle);
|
||||
var unitY = Math.sin(angle);
|
||||
// Split line
|
||||
if (splitLineModel.get('show')) {
|
||||
var splitLine = new graphic.Line({
|
||||
shape: {
|
||||
x1: unitX * r + cx,
|
||||
y1: unitY * r + cy,
|
||||
x2: unitX * (r - splitLineLen) + cx,
|
||||
y2: unitY * (r - splitLineLen) + cy
|
||||
},
|
||||
style: splitLineStyle,
|
||||
silent: true
|
||||
});
|
||||
if (splitLineStyle.stroke === 'auto') {
|
||||
splitLine.setStyle({
|
||||
stroke: getColor(i / splitNumber)
|
||||
});
|
||||
}
|
||||
|
||||
group.add(splitLine);
|
||||
}
|
||||
|
||||
// Label
|
||||
if (labelModel.get('show')) {
|
||||
var label = formatLabel(
|
||||
numberUtil.round(i / splitNumber * (maxVal - minVal) + minVal),
|
||||
labelModel.get('formatter')
|
||||
);
|
||||
|
||||
var text = new graphic.Text({
|
||||
style: {
|
||||
text: label,
|
||||
x: unitX * (r - splitLineLen - 5) + cx,
|
||||
y: unitY * (r - splitLineLen - 5) + cy,
|
||||
fill: textStyleModel.getTextColor(),
|
||||
textFont: textStyleModel.getFont(),
|
||||
textVerticalAlign: unitY < -0.4 ? 'top' : (unitY > 0.4 ? 'bottom' : 'middle'),
|
||||
textAlign: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center')
|
||||
},
|
||||
silent: true
|
||||
});
|
||||
if (text.style.fill === 'auto') {
|
||||
text.setStyle({
|
||||
fill: getColor(i / splitNumber)
|
||||
});
|
||||
}
|
||||
|
||||
group.add(text);
|
||||
}
|
||||
|
||||
// Axis tick
|
||||
if (tickModel.get('show') && i !== splitNumber) {
|
||||
for (var j = 0; j <= subSplitNumber; j++) {
|
||||
var unitX = Math.cos(angle);
|
||||
var unitY = Math.sin(angle);
|
||||
var tickLine = new graphic.Line({
|
||||
shape: {
|
||||
x1: unitX * r + cx,
|
||||
y1: unitY * r + cy,
|
||||
x2: unitX * (r - tickLen) + cx,
|
||||
y2: unitY * (r - tickLen) + cy
|
||||
},
|
||||
silent: true,
|
||||
style: tickLineStyle
|
||||
});
|
||||
|
||||
if (tickLineStyle.stroke === 'auto') {
|
||||
tickLine.setStyle({
|
||||
stroke: getColor((i + j / subSplitNumber) / splitNumber)
|
||||
});
|
||||
}
|
||||
|
||||
group.add(tickLine);
|
||||
angle += subStep;
|
||||
}
|
||||
angle -= subStep;
|
||||
}
|
||||
else {
|
||||
angle += step;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_renderPointer: function (
|
||||
seriesModel, ecModel, api, getColor, posInfo,
|
||||
startAngle, endAngle, clockwise
|
||||
) {
|
||||
var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')];
|
||||
var angleExtent = [startAngle, endAngle];
|
||||
|
||||
if (!clockwise) {
|
||||
angleExtent = angleExtent.reverse();
|
||||
}
|
||||
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
|
||||
var group = this.group;
|
||||
|
||||
data.diff(oldData)
|
||||
.add(function (idx) {
|
||||
var pointer = new PointerPath({
|
||||
shape: {
|
||||
angle: startAngle
|
||||
}
|
||||
});
|
||||
|
||||
graphic.updateProps(pointer, {
|
||||
shape: {
|
||||
angle: numberUtil.linearMap(data.get('value', idx), valueExtent, angleExtent, true)
|
||||
}
|
||||
}, seriesModel);
|
||||
|
||||
group.add(pointer);
|
||||
data.setItemGraphicEl(idx, pointer);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var pointer = oldData.getItemGraphicEl(oldIdx);
|
||||
|
||||
graphic.updateProps(pointer, {
|
||||
shape: {
|
||||
angle: numberUtil.linearMap(data.get('value', newIdx), valueExtent, angleExtent, true)
|
||||
}
|
||||
}, seriesModel);
|
||||
|
||||
group.add(pointer);
|
||||
data.setItemGraphicEl(newIdx, pointer);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
var pointer = oldData.getItemGraphicEl(idx);
|
||||
group.remove(pointer);
|
||||
})
|
||||
.execute();
|
||||
|
||||
data.eachItemGraphicEl(function (pointer, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var pointerModel = itemModel.getModel('pointer');
|
||||
|
||||
pointer.setShape({
|
||||
x: posInfo.cx,
|
||||
y: posInfo.cy,
|
||||
width: parsePercent(
|
||||
pointerModel.get('width'), posInfo.r
|
||||
),
|
||||
r: parsePercent(pointerModel.get('length'), posInfo.r)
|
||||
});
|
||||
|
||||
pointer.useStyle(itemModel.getModel('itemStyle.normal').getItemStyle());
|
||||
|
||||
if (pointer.style.fill === 'auto') {
|
||||
pointer.setStyle('fill', getColor(
|
||||
(data.get('value', idx) - valueExtent[0]) / (valueExtent[1] - valueExtent[0])
|
||||
));
|
||||
}
|
||||
|
||||
graphic.setHoverStyle(
|
||||
pointer, itemModel.getModel('itemStyle.emphasis').getItemStyle()
|
||||
);
|
||||
});
|
||||
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
_renderTitle: function (
|
||||
seriesModel, ecModel, api, getColor, posInfo
|
||||
) {
|
||||
var titleModel = seriesModel.getModel('title');
|
||||
if (titleModel.get('show')) {
|
||||
var textStyleModel = titleModel.getModel('textStyle');
|
||||
var offsetCenter = titleModel.get('offsetCenter');
|
||||
var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
|
||||
var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
|
||||
var text = new graphic.Text({
|
||||
style: {
|
||||
x: x,
|
||||
y: y,
|
||||
// FIXME First data name ?
|
||||
text: seriesModel.getData().getName(0),
|
||||
fill: textStyleModel.getTextColor(),
|
||||
textFont: textStyleModel.getFont(),
|
||||
textAlign: 'center',
|
||||
textVerticalAlign: 'middle'
|
||||
}
|
||||
});
|
||||
this.group.add(text);
|
||||
}
|
||||
},
|
||||
|
||||
_renderDetail: function (
|
||||
seriesModel, ecModel, api, getColor, posInfo
|
||||
) {
|
||||
var detailModel = seriesModel.getModel('detail');
|
||||
var minVal = seriesModel.get('min');
|
||||
var maxVal = seriesModel.get('max');
|
||||
if (detailModel.get('show')) {
|
||||
var textStyleModel = detailModel.getModel('textStyle');
|
||||
var offsetCenter = detailModel.get('offsetCenter');
|
||||
var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
|
||||
var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
|
||||
var width = parsePercent(detailModel.get('width'), posInfo.r);
|
||||
var height = parsePercent(detailModel.get('height'), posInfo.r);
|
||||
var value = seriesModel.getData().get('value', 0);
|
||||
var rect = new graphic.Rect({
|
||||
shape: {
|
||||
x: x - width / 2,
|
||||
y: y - height / 2,
|
||||
width: width,
|
||||
height: height
|
||||
},
|
||||
style: {
|
||||
text: formatLabel(
|
||||
// FIXME First data name ?
|
||||
value, detailModel.get('formatter')
|
||||
),
|
||||
fill: detailModel.get('backgroundColor'),
|
||||
textFill: textStyleModel.getTextColor(),
|
||||
textFont: textStyleModel.getFont()
|
||||
}
|
||||
});
|
||||
if (rect.style.textFill === 'auto') {
|
||||
rect.setStyle('textFill', getColor(
|
||||
numberUtil.linearMap(value, [minVal, maxVal], [0, 1], true)
|
||||
));
|
||||
}
|
||||
rect.setStyle(detailModel.getItemStyle(['color']));
|
||||
this.group.add(rect);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return GaugeView;
|
||||
});
|
||||
47
vendors/echarts/src/chart/gauge/PointerPath.js
vendored
Normal file
47
vendors/echarts/src/chart/gauge/PointerPath.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
define(function (require) {
|
||||
|
||||
return require('zrender/graphic/Path').extend({
|
||||
|
||||
type: 'echartsGaugePointer',
|
||||
|
||||
shape: {
|
||||
angle: 0,
|
||||
|
||||
width: 10,
|
||||
|
||||
r: 10,
|
||||
|
||||
x: 0,
|
||||
|
||||
y: 0
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
var mathCos = Math.cos;
|
||||
var mathSin = Math.sin;
|
||||
|
||||
var r = shape.r;
|
||||
var width = shape.width;
|
||||
var angle = shape.angle;
|
||||
var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2);
|
||||
var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2);
|
||||
|
||||
angle = shape.angle - Math.PI / 2;
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(
|
||||
shape.x + mathCos(angle) * width,
|
||||
shape.y + mathSin(angle) * width
|
||||
);
|
||||
ctx.lineTo(
|
||||
shape.x + mathCos(shape.angle) * r,
|
||||
shape.y + mathSin(shape.angle) * r
|
||||
);
|
||||
ctx.lineTo(
|
||||
shape.x - mathCos(angle) * width,
|
||||
shape.y - mathSin(angle) * width
|
||||
);
|
||||
ctx.lineTo(x, y);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
27
vendors/echarts/src/chart/graph.js
vendored
Normal file
27
vendors/echarts/src/chart/graph.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../echarts');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
require('./graph/GraphSeries');
|
||||
require('./graph/GraphView');
|
||||
|
||||
require('./graph/roamAction');
|
||||
|
||||
echarts.registerProcessor('filter', require('./graph/categoryFilter'));
|
||||
|
||||
echarts.registerVisualCoding('chart', zrUtil.curry(
|
||||
require('../visual/symbol'), 'graph', 'circle', null
|
||||
));
|
||||
echarts.registerVisualCoding('chart', require('./graph/categoryVisual'));
|
||||
echarts.registerVisualCoding('chart', require('./graph/edgeVisual'));
|
||||
|
||||
echarts.registerLayout(require('./graph/simpleLayout'));
|
||||
echarts.registerLayout(require('./graph/circularLayout'));
|
||||
echarts.registerLayout(require('./graph/forceLayout'));
|
||||
|
||||
// Graph view coordinate system
|
||||
echarts.registerCoordinateSystem('graphView', {
|
||||
create: require('./graph/createView')
|
||||
});
|
||||
});
|
||||
249
vendors/echarts/src/chart/graph/GraphSeries.js
vendored
Normal file
249
vendors/echarts/src/chart/graph/GraphSeries.js
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
define(function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var List = require('../../data/List');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var modelUtil = require('../../util/model');
|
||||
var Model = require('../../model/Model');
|
||||
|
||||
var createGraphFromNodeEdge = require('../helper/createGraphFromNodeEdge');
|
||||
|
||||
var GraphSeries = require('../../echarts').extendSeriesModel({
|
||||
|
||||
type: 'series.graph',
|
||||
|
||||
init: function (option) {
|
||||
GraphSeries.superApply(this, 'init', arguments);
|
||||
|
||||
// Provide data for legend select
|
||||
this.legendDataProvider = function () {
|
||||
return this._categoriesData;
|
||||
};
|
||||
|
||||
this.fillDataTextStyle(option.edges || option.links);
|
||||
|
||||
this._updateCategoriesData();
|
||||
},
|
||||
|
||||
mergeOption: function (option) {
|
||||
GraphSeries.superApply(this, 'mergeOption', arguments);
|
||||
|
||||
this.fillDataTextStyle(option.edges || option.links);
|
||||
|
||||
this._updateCategoriesData();
|
||||
},
|
||||
|
||||
mergeDefaultAndTheme: function (option) {
|
||||
GraphSeries.superApply(this, 'mergeDefaultAndTheme', arguments);
|
||||
modelUtil.defaultEmphasis(option.edgeLabel, modelUtil.LABEL_OPTIONS);
|
||||
},
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var edges = option.edges || option.links || [];
|
||||
var nodes = option.data || option.nodes || [];
|
||||
var self = this;
|
||||
|
||||
if (nodes && edges) {
|
||||
return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data;
|
||||
}
|
||||
|
||||
function beforeLink(nodeData, edgeData) {
|
||||
// Overwrite nodeData.getItemModel to
|
||||
nodeData.wrapMethod('getItemModel', function (model) {
|
||||
var categoriesModels = self._categoriesModels;
|
||||
var categoryIdx = model.getShallow('category');
|
||||
var categoryModel = categoriesModels[categoryIdx];
|
||||
if (categoryModel) {
|
||||
categoryModel.parentModel = model.parentModel;
|
||||
model.parentModel = categoryModel;
|
||||
}
|
||||
return model;
|
||||
});
|
||||
|
||||
var edgeLabelModel = self.getModel('edgeLabel');
|
||||
var wrappedGetEdgeModel = function (path, parentModel) {
|
||||
var pathArr = (path || '').split('.');
|
||||
if (pathArr[0] === 'label') {
|
||||
parentModel = parentModel
|
||||
|| edgeLabelModel.getModel(pathArr.slice(1));
|
||||
}
|
||||
var model = Model.prototype.getModel.call(this, pathArr, parentModel);
|
||||
model.getModel = wrappedGetEdgeModel;
|
||||
return model;
|
||||
};
|
||||
edgeData.wrapMethod('getItemModel', function (model) {
|
||||
// FIXME Wrap get method ?
|
||||
model.getModel = wrappedGetEdgeModel;
|
||||
return model;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/data/Graph}
|
||||
*/
|
||||
getGraph: function () {
|
||||
return this.getData().graph;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/data/List}
|
||||
*/
|
||||
getEdgeData: function () {
|
||||
return this.getGraph().edgeData;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/data/List}
|
||||
*/
|
||||
getCategoriesData: function () {
|
||||
return this._categoriesData;
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
formatTooltip: function (dataIndex, multipleSeries, dataType) {
|
||||
if (dataType === 'edge') {
|
||||
var nodeData = this.getData();
|
||||
var params = this.getDataParams(dataIndex, dataType);
|
||||
var edge = nodeData.graph.getEdgeByIndex(dataIndex);
|
||||
var sourceName = nodeData.getName(edge.node1.dataIndex);
|
||||
var targetName = nodeData.getName(edge.node2.dataIndex);
|
||||
var html = sourceName + ' > ' + targetName;
|
||||
if (params.value) {
|
||||
html += ' : ' + params.value;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
else { // dataType === 'node' or empty
|
||||
return GraphSeries.superApply(this, 'formatTooltip', arguments);
|
||||
}
|
||||
},
|
||||
|
||||
_updateCategoriesData: function () {
|
||||
var categories = zrUtil.map(this.option.categories || [], function (category) {
|
||||
// Data must has value
|
||||
return category.value != null ? category : zrUtil.extend({
|
||||
value: 0
|
||||
}, category);
|
||||
});
|
||||
var categoriesData = new List(['value'], this);
|
||||
categoriesData.initData(categories);
|
||||
|
||||
this._categoriesData = categoriesData;
|
||||
|
||||
this._categoriesModels = categoriesData.mapArray(function (idx) {
|
||||
return categoriesData.getItemModel(idx, true);
|
||||
});
|
||||
},
|
||||
|
||||
setZoom: function (zoom) {
|
||||
this.option.zoom = zoom;
|
||||
},
|
||||
|
||||
setCenter: function (center) {
|
||||
this.option.center = center;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
|
||||
color: ['#61a0a8', '#d14a61', '#fd9c35', '#675bba', '#fec42c',
|
||||
'#dd4444', '#fd9c35', '#cd4870'],
|
||||
|
||||
coordinateSystem: 'view',
|
||||
|
||||
// Default option for all coordinate systems
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
polarIndex: 0,
|
||||
geoIndex: 0,
|
||||
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
|
||||
layout: null,
|
||||
|
||||
// Configuration of force
|
||||
force: {
|
||||
initLayout: null,
|
||||
repulsion: 50,
|
||||
gravity: 0.1,
|
||||
edgeLength: 30,
|
||||
|
||||
layoutAnimation: true
|
||||
},
|
||||
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
// right: null,
|
||||
// bottom: null,
|
||||
// width: '80%',
|
||||
// height: '80%',
|
||||
|
||||
symbol: 'circle',
|
||||
symbolSize: 10,
|
||||
|
||||
edgeSymbol: ['none', 'none'],
|
||||
edgeSymbolSize: 10,
|
||||
edgeLabel: {
|
||||
normal: {
|
||||
position: 'middle'
|
||||
},
|
||||
emphasis: {}
|
||||
},
|
||||
|
||||
draggable: false,
|
||||
|
||||
roam: false,
|
||||
|
||||
// Default on center of graph
|
||||
center: null,
|
||||
|
||||
zoom: 1,
|
||||
// Symbol size scale ratio in roam
|
||||
nodeScaleRatio: 0.6,
|
||||
|
||||
// categories: [],
|
||||
|
||||
// data: []
|
||||
// Or
|
||||
// nodes: []
|
||||
//
|
||||
// links: []
|
||||
// Or
|
||||
// edges: []
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
show: false,
|
||||
formatter: '{b}'
|
||||
},
|
||||
emphasis: {
|
||||
show: true
|
||||
}
|
||||
},
|
||||
|
||||
itemStyle: {
|
||||
normal: {},
|
||||
emphasis: {}
|
||||
},
|
||||
|
||||
lineStyle: {
|
||||
normal: {
|
||||
color: '#aaa',
|
||||
width: 1,
|
||||
curveness: 0,
|
||||
opacity: 0.5
|
||||
},
|
||||
emphasis: {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return GraphSeries;
|
||||
});
|
||||
204
vendors/echarts/src/chart/graph/GraphView.js
vendored
Normal file
204
vendors/echarts/src/chart/graph/GraphView.js
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
define(function (require) {
|
||||
|
||||
var SymbolDraw = require('../helper/SymbolDraw');
|
||||
var LineDraw = require('../helper/LineDraw');
|
||||
var RoamController = require('../../component/helper/RoamController');
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var adjustEdge = require('./adjustEdge');
|
||||
|
||||
require('../../echarts').extendChartView({
|
||||
|
||||
type: 'graph',
|
||||
|
||||
init: function (ecModel, api) {
|
||||
var symbolDraw = new SymbolDraw();
|
||||
var lineDraw = new LineDraw();
|
||||
var group = this.group;
|
||||
|
||||
var controller = new RoamController(api.getZr(), group);
|
||||
|
||||
group.add(symbolDraw.group);
|
||||
group.add(lineDraw.group);
|
||||
|
||||
this._symbolDraw = symbolDraw;
|
||||
this._lineDraw = lineDraw;
|
||||
this._controller = controller;
|
||||
|
||||
this._firstRender = true;
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
// Only support view and geo coordinate system
|
||||
// if (coordSys.type !== 'geo' && coordSys.type !== 'view') {
|
||||
// return;
|
||||
// }
|
||||
|
||||
this._model = seriesModel;
|
||||
this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');
|
||||
|
||||
var symbolDraw = this._symbolDraw;
|
||||
var lineDraw = this._lineDraw;
|
||||
|
||||
var group = this.group;
|
||||
|
||||
if (coordSys.type === 'view') {
|
||||
var groupNewProp = {
|
||||
position: coordSys.position,
|
||||
scale: coordSys.scale
|
||||
};
|
||||
if (this._firstRender) {
|
||||
group.attr(groupNewProp);
|
||||
}
|
||||
else {
|
||||
graphic.updateProps(group, groupNewProp, seriesModel);
|
||||
}
|
||||
}
|
||||
// Fix edge contact point with node
|
||||
adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
|
||||
|
||||
|
||||
var data = seriesModel.getData();
|
||||
symbolDraw.updateData(data);
|
||||
|
||||
var edgeData = seriesModel.getEdgeData();
|
||||
lineDraw.updateData(edgeData);
|
||||
|
||||
this._updateNodeAndLinkScale();
|
||||
|
||||
this._updateController(seriesModel, api);
|
||||
|
||||
clearTimeout(this._layoutTimeout);
|
||||
var forceLayout = seriesModel.forceLayout;
|
||||
var layoutAnimation = seriesModel.get('force.layoutAnimation');
|
||||
if (forceLayout) {
|
||||
this._startForceLayoutIteration(forceLayout, layoutAnimation);
|
||||
}
|
||||
// Update draggable
|
||||
data.eachItemGraphicEl(function (el, idx) {
|
||||
var draggable = data.getItemModel(idx).get('draggable');
|
||||
if (draggable) {
|
||||
el.on('drag', function () {
|
||||
if (forceLayout) {
|
||||
forceLayout.warmUp();
|
||||
!this._layouting
|
||||
&& this._startForceLayoutIteration(forceLayout, layoutAnimation);
|
||||
forceLayout.setFixed(idx);
|
||||
// Write position back to layout
|
||||
data.setItemLayout(idx, el.position);
|
||||
}
|
||||
}, this).on('dragend', function () {
|
||||
if (forceLayout) {
|
||||
forceLayout.setUnfixed(idx);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
else {
|
||||
el.off('drag');
|
||||
}
|
||||
el.setDraggable(draggable && forceLayout);
|
||||
}, this);
|
||||
|
||||
this._firstRender = false;
|
||||
},
|
||||
|
||||
_startForceLayoutIteration: function (forceLayout, layoutAnimation) {
|
||||
var self = this;
|
||||
(function step() {
|
||||
forceLayout.step(function (stopped) {
|
||||
self.updateLayout(self._model);
|
||||
(self._layouting = !stopped) && (
|
||||
layoutAnimation
|
||||
? (self._layoutTimeout = setTimeout(step, 16))
|
||||
: step()
|
||||
);
|
||||
});
|
||||
})();
|
||||
},
|
||||
|
||||
_updateController: function (seriesModel, api) {
|
||||
var controller = this._controller;
|
||||
var group = this.group;
|
||||
controller.rectProvider = function () {
|
||||
var rect = group.getBoundingRect();
|
||||
rect.applyTransform(group.transform);
|
||||
return rect;
|
||||
};
|
||||
if (seriesModel.coordinateSystem.type !== 'view') {
|
||||
controller.disable();
|
||||
return;
|
||||
}
|
||||
controller.enable(seriesModel.get('roam'));
|
||||
controller.zoomLimit = seriesModel.get('scaleLimit');
|
||||
// Update zoom from model
|
||||
controller.zoom = seriesModel.coordinateSystem.getZoom();
|
||||
|
||||
controller
|
||||
.off('pan')
|
||||
.off('zoom')
|
||||
.on('pan', function (dx, dy) {
|
||||
api.dispatchAction({
|
||||
seriesId: seriesModel.id,
|
||||
type: 'graphRoam',
|
||||
dx: dx,
|
||||
dy: dy
|
||||
});
|
||||
})
|
||||
.on('zoom', function (zoom, mouseX, mouseY) {
|
||||
api.dispatchAction({
|
||||
seriesId: seriesModel.id,
|
||||
type: 'graphRoam',
|
||||
zoom: zoom,
|
||||
originX: mouseX,
|
||||
originY: mouseY
|
||||
});
|
||||
this._updateNodeAndLinkScale();
|
||||
adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
|
||||
this._lineDraw.updateLayout();
|
||||
}, this);
|
||||
},
|
||||
|
||||
_updateNodeAndLinkScale: function () {
|
||||
var seriesModel = this._model;
|
||||
var data = seriesModel.getData();
|
||||
|
||||
var nodeScale = this._getNodeGlobalScale(seriesModel);
|
||||
var invScale = [nodeScale, nodeScale];
|
||||
|
||||
data.eachItemGraphicEl(function (el, idx) {
|
||||
el.attr('scale', invScale);
|
||||
});
|
||||
},
|
||||
|
||||
_getNodeGlobalScale: function (seriesModel) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (coordSys.type !== 'view') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
var nodeScaleRatio = this._nodeScaleRatio;
|
||||
|
||||
var groupScale = this.group.scale;
|
||||
var groupZoom = (groupScale && groupScale[0]) || 1;
|
||||
// Scale node when zoom changes
|
||||
var roamZoom = coordSys.getZoom();
|
||||
var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
|
||||
|
||||
return nodeScale / groupZoom;
|
||||
},
|
||||
|
||||
updateLayout: function (seriesModel) {
|
||||
this._symbolDraw.updateLayout();
|
||||
this._lineDraw.updateLayout();
|
||||
|
||||
adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
|
||||
},
|
||||
|
||||
remove: function (ecModel, api) {
|
||||
this._symbolDraw && this._symbolDraw.remove();
|
||||
this._lineDraw && this._lineDraw.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
145
vendors/echarts/src/chart/graph/adjustEdge.js
vendored
Normal file
145
vendors/echarts/src/chart/graph/adjustEdge.js
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
define(function (require) {
|
||||
|
||||
var curveTool = require('zrender/core/curve');
|
||||
var vec2 = require('zrender/core/vector');
|
||||
|
||||
var v1 = [];
|
||||
var v2 = [];
|
||||
var v3 = [];
|
||||
var quadraticAt = curveTool.quadraticAt;
|
||||
var v2DistSquare = vec2.distSquare;
|
||||
var mathAbs = Math.abs;
|
||||
function intersectCurveCircle(curvePoints, center, radius) {
|
||||
var p0 = curvePoints[0];
|
||||
var p1 = curvePoints[1];
|
||||
var p2 = curvePoints[2];
|
||||
|
||||
var d = Infinity;
|
||||
var t;
|
||||
var radiusSquare = radius * radius;
|
||||
var interval = 0.1;
|
||||
|
||||
for (var _t = 0.1; _t <= 0.9; _t += 0.1) {
|
||||
v1[0] = quadraticAt(p0[0], p1[0], p2[0], _t);
|
||||
v1[1] = quadraticAt(p0[1], p1[1], p2[1], _t);
|
||||
var diff = mathAbs(v2DistSquare(v1, center) - radiusSquare);
|
||||
if (diff < d) {
|
||||
d = diff;
|
||||
t = _t;
|
||||
}
|
||||
}
|
||||
|
||||
// Assume the segment is monotone,Find root through Bisection method
|
||||
// At most 32 iteration
|
||||
for (var i = 0; i < 32; i++) {
|
||||
// var prev = t - interval;
|
||||
var next = t + interval;
|
||||
// v1[0] = quadraticAt(p0[0], p1[0], p2[0], prev);
|
||||
// v1[1] = quadraticAt(p0[1], p1[1], p2[1], prev);
|
||||
v2[0] = quadraticAt(p0[0], p1[0], p2[0], t);
|
||||
v2[1] = quadraticAt(p0[1], p1[1], p2[1], t);
|
||||
v3[0] = quadraticAt(p0[0], p1[0], p2[0], next);
|
||||
v3[1] = quadraticAt(p0[1], p1[1], p2[1], next);
|
||||
|
||||
var diff = v2DistSquare(v2, center) - radiusSquare;
|
||||
if (mathAbs(diff) < 1e-2) {
|
||||
break;
|
||||
}
|
||||
|
||||
// var prevDiff = v2DistSquare(v1, center) - radiusSquare;
|
||||
var nextDiff = v2DistSquare(v3, center) - radiusSquare;
|
||||
|
||||
interval /= 2;
|
||||
if (diff < 0) {
|
||||
if (nextDiff >= 0) {
|
||||
t = t + interval;
|
||||
}
|
||||
else {
|
||||
t = t - interval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nextDiff >= 0) {
|
||||
t = t - interval;
|
||||
}
|
||||
else {
|
||||
t = t + interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
// Adjust edge to avoid
|
||||
return function (graph, scale) {
|
||||
var tmp0 = [];
|
||||
var quadraticSubdivide = curveTool.quadraticSubdivide;
|
||||
var pts = [[], [], []];
|
||||
var pts2 = [[], []];
|
||||
var v = [];
|
||||
scale /= 2;
|
||||
|
||||
graph.eachEdge(function (edge) {
|
||||
var linePoints = edge.getLayout();
|
||||
var fromSymbol = edge.getVisual('fromSymbol');
|
||||
var toSymbol = edge.getVisual('toSymbol');
|
||||
|
||||
if (!linePoints.__original) {
|
||||
linePoints.__original = [
|
||||
vec2.clone(linePoints[0]),
|
||||
vec2.clone(linePoints[1])
|
||||
];
|
||||
if (linePoints[2]) {
|
||||
linePoints.__original.push(vec2.clone(linePoints[2]));
|
||||
}
|
||||
}
|
||||
var originalPoints = linePoints.__original;
|
||||
// Quadratic curve
|
||||
if (linePoints[2] != null) {
|
||||
vec2.copy(pts[0], originalPoints[0]);
|
||||
vec2.copy(pts[1], originalPoints[2]);
|
||||
vec2.copy(pts[2], originalPoints[1]);
|
||||
if (fromSymbol && fromSymbol != 'none') {
|
||||
var t = intersectCurveCircle(pts, originalPoints[0], edge.node1.getVisual('symbolSize') * scale);
|
||||
// Subdivide and get the second
|
||||
quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
|
||||
pts[0][0] = tmp0[3];
|
||||
pts[1][0] = tmp0[4];
|
||||
quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
|
||||
pts[0][1] = tmp0[3];
|
||||
pts[1][1] = tmp0[4];
|
||||
}
|
||||
if (toSymbol && toSymbol != 'none') {
|
||||
var t = intersectCurveCircle(pts, originalPoints[1], edge.node2.getVisual('symbolSize') * scale);
|
||||
// Subdivide and get the first
|
||||
quadraticSubdivide(pts[0][0], pts[1][0], pts[2][0], t, tmp0);
|
||||
pts[1][0] = tmp0[1];
|
||||
pts[2][0] = tmp0[2];
|
||||
quadraticSubdivide(pts[0][1], pts[1][1], pts[2][1], t, tmp0);
|
||||
pts[1][1] = tmp0[1];
|
||||
pts[2][1] = tmp0[2];
|
||||
}
|
||||
// Copy back to layout
|
||||
vec2.copy(linePoints[0], pts[0]);
|
||||
vec2.copy(linePoints[1], pts[2]);
|
||||
vec2.copy(linePoints[2], pts[1]);
|
||||
}
|
||||
// Line
|
||||
else {
|
||||
vec2.copy(pts2[0], originalPoints[0]);
|
||||
vec2.copy(pts2[1], originalPoints[1]);
|
||||
|
||||
vec2.sub(v, pts2[1], pts2[0]);
|
||||
vec2.normalize(v, v);
|
||||
if (fromSymbol && fromSymbol != 'none') {
|
||||
vec2.scaleAndAdd(pts2[0], pts2[0], v, edge.node1.getVisual('symbolSize') * scale);
|
||||
}
|
||||
if (toSymbol && toSymbol != 'none') {
|
||||
vec2.scaleAndAdd(pts2[1], pts2[1], v, -edge.node2.getVisual('symbolSize') * scale);
|
||||
}
|
||||
vec2.copy(linePoints[0], pts2[0]);
|
||||
vec2.copy(linePoints[1], pts2[1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
3
vendors/echarts/src/chart/graph/backwardCompat.js
vendored
Normal file
3
vendors/echarts/src/chart/graph/backwardCompat.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
define(function (require) {
|
||||
|
||||
});
|
||||
35
vendors/echarts/src/chart/graph/categoryFilter.js
vendored
Normal file
35
vendors/echarts/src/chart/graph/categoryFilter.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
define(function (require) {
|
||||
|
||||
return function (ecModel) {
|
||||
var legendModels = ecModel.findComponents({
|
||||
mainType: 'legend'
|
||||
});
|
||||
if (!legendModels || !legendModels.length) {
|
||||
return;
|
||||
}
|
||||
ecModel.eachSeriesByType('graph', function (graphSeries) {
|
||||
var categoriesData = graphSeries.getCategoriesData();
|
||||
var graph = graphSeries.getGraph();
|
||||
var data = graph.data;
|
||||
|
||||
var categoryNames = categoriesData.mapArray(categoriesData.getName);
|
||||
|
||||
data.filterSelf(function (idx) {
|
||||
var model = data.getItemModel(idx);
|
||||
var category = model.getShallow('category');
|
||||
if (category != null) {
|
||||
if (typeof category === 'number') {
|
||||
category = categoryNames[category];
|
||||
}
|
||||
// If in any legend component the status is not selected.
|
||||
for (var i = 0; i < legendModels.length; i++) {
|
||||
if (!legendModels[i].isSelected(category)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, this);
|
||||
};
|
||||
});
|
||||
41
vendors/echarts/src/chart/graph/categoryVisual.js
vendored
Normal file
41
vendors/echarts/src/chart/graph/categoryVisual.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
define(function (require) {
|
||||
|
||||
return function (ecModel) {
|
||||
ecModel.eachSeriesByType('graph', function (seriesModel) {
|
||||
var colorList = seriesModel.get('color');
|
||||
var categoriesData = seriesModel.getCategoriesData();
|
||||
var data = seriesModel.getData();
|
||||
|
||||
var categoryNameIdxMap = {};
|
||||
|
||||
categoriesData.each(function (idx) {
|
||||
categoryNameIdxMap[categoriesData.getName(idx)] = idx;
|
||||
|
||||
var itemModel = categoriesData.getItemModel(idx);
|
||||
var rawIdx = categoriesData.getRawIndex(idx);
|
||||
var color = itemModel.get('itemStyle.normal.color')
|
||||
|| colorList[rawIdx % colorList.length];
|
||||
categoriesData.setItemVisual(idx, 'color', color);
|
||||
});
|
||||
|
||||
// Assign category color to visual
|
||||
if (categoriesData.count()) {
|
||||
data.each(function (idx) {
|
||||
var model = data.getItemModel(idx);
|
||||
var category = model.getShallow('category');
|
||||
if (category != null) {
|
||||
if (typeof category === 'string') {
|
||||
category = categoryNameIdxMap[category];
|
||||
}
|
||||
if (!data.getItemVisual(idx, 'color', true)) {
|
||||
data.setItemVisual(
|
||||
idx, 'color',
|
||||
categoriesData.getItemVisual(category, 'color')
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
10
vendors/echarts/src/chart/graph/circularLayout.js
vendored
Normal file
10
vendors/echarts/src/chart/graph/circularLayout.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
define(function (require) {
|
||||
var circularLayoutHelper = require('./circularLayoutHelper');
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('graph', function (seriesModel) {
|
||||
if (seriesModel.get('layout') === 'circular') {
|
||||
circularLayoutHelper(seriesModel);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
53
vendors/echarts/src/chart/graph/circularLayoutHelper.js
vendored
Normal file
53
vendors/echarts/src/chart/graph/circularLayoutHelper.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
define(function (require) {
|
||||
var vec2 = require('zrender/core/vector');
|
||||
return function (seriesModel) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (coordSys && coordSys.type !== 'view') {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = coordSys.getBoundingRect();
|
||||
|
||||
var nodeData = seriesModel.getData();
|
||||
var graph = nodeData.graph;
|
||||
|
||||
var angle = 0;
|
||||
var sum = nodeData.getSum('value');
|
||||
var unitAngle = Math.PI * 2 / (sum || nodeData.count());
|
||||
|
||||
var cx = rect.width / 2 + rect.x;
|
||||
var cy = rect.height / 2 + rect.y;
|
||||
|
||||
var r = Math.min(rect.width, rect.height) / 2;
|
||||
|
||||
graph.eachNode(function (node) {
|
||||
var value = node.getValue('value');
|
||||
|
||||
angle += unitAngle * (sum ? value : 2) / 2;
|
||||
|
||||
node.setLayout([
|
||||
r * Math.cos(angle) + cx,
|
||||
r * Math.sin(angle) + cy
|
||||
]);
|
||||
|
||||
angle += unitAngle * (sum ? value : 2) / 2;
|
||||
});
|
||||
|
||||
graph.eachEdge(function (edge) {
|
||||
var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0;
|
||||
var p1 = vec2.clone(edge.node1.getLayout());
|
||||
var p2 = vec2.clone(edge.node2.getLayout());
|
||||
var cp1;
|
||||
var x12 = (p1[0] + p2[0]) / 2;
|
||||
var y12 = (p1[1] + p2[1]) / 2;
|
||||
if (curveness > 0) {
|
||||
curveness *= 3;
|
||||
cp1 = [
|
||||
cx * curveness + x12 * (1 - curveness),
|
||||
cy * curveness + y12 * (1 - curveness)
|
||||
];
|
||||
}
|
||||
edge.setLayout([p1, p2, cp1]);
|
||||
});
|
||||
};
|
||||
});
|
||||
76
vendors/echarts/src/chart/graph/createView.js
vendored
Normal file
76
vendors/echarts/src/chart/graph/createView.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
define(function (require) {
|
||||
// FIXME Where to create the simple view coordinate system
|
||||
var View = require('../../coord/View');
|
||||
var layout = require('../../util/layout');
|
||||
var bbox = require('zrender/core/bbox');
|
||||
|
||||
function getViewRect(seriesModel, api, aspect) {
|
||||
var option = seriesModel.getBoxLayoutParams();
|
||||
option.aspect = aspect;
|
||||
return layout.getLayoutRect(option, {
|
||||
width: api.getWidth(),
|
||||
height: api.getHeight()
|
||||
});
|
||||
}
|
||||
|
||||
return function (ecModel, api) {
|
||||
var viewList = [];
|
||||
ecModel.eachSeriesByType('graph', function (seriesModel) {
|
||||
var coordSysType = seriesModel.get('coordinateSystem');
|
||||
if (!coordSysType || coordSysType === 'view') {
|
||||
var viewCoordSys = new View();
|
||||
viewList.push(viewCoordSys);
|
||||
|
||||
var data = seriesModel.getData();
|
||||
var positions = data.mapArray(function (idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
return [+itemModel.get('x'), +itemModel.get('y')];
|
||||
});
|
||||
|
||||
var min = [];
|
||||
var max = [];
|
||||
|
||||
bbox.fromPoints(positions, min, max);
|
||||
|
||||
// If width or height is 0
|
||||
if (max[0] - min[0] === 0) {
|
||||
max[0] += 1;
|
||||
min[0] -= 1;
|
||||
}
|
||||
if (max[1] - min[1] === 0) {
|
||||
max[1] += 1;
|
||||
min[1] -= 1;
|
||||
}
|
||||
var aspect = (max[0] - min[0]) / (max[1] - min[1]);
|
||||
// FIXME If get view rect after data processed?
|
||||
var viewRect = getViewRect(seriesModel, api, aspect);
|
||||
// Position may be NaN, use view rect instead
|
||||
if (isNaN(aspect)) {
|
||||
min = [viewRect.x, viewRect.y];
|
||||
max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height];
|
||||
}
|
||||
|
||||
var bbWidth = max[0] - min[0];
|
||||
var bbHeight = max[1] - min[1];
|
||||
|
||||
var viewWidth = viewRect.width;
|
||||
var viewHeight = viewRect.height;
|
||||
|
||||
viewCoordSys = seriesModel.coordinateSystem = new View();
|
||||
viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
|
||||
|
||||
viewCoordSys.setBoundingRect(
|
||||
min[0], min[1], bbWidth, bbHeight
|
||||
);
|
||||
viewCoordSys.setViewRect(
|
||||
viewRect.x, viewRect.y, viewWidth, viewHeight
|
||||
);
|
||||
|
||||
// Update roam info
|
||||
viewCoordSys.setCenter(seriesModel.get('center'));
|
||||
viewCoordSys.setZoom(seriesModel.get('zoom'));
|
||||
}
|
||||
});
|
||||
return viewList;
|
||||
};
|
||||
});
|
||||
33
vendors/echarts/src/chart/graph/edgeVisual.js
vendored
Normal file
33
vendors/echarts/src/chart/graph/edgeVisual.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
define(function (require) {
|
||||
|
||||
function normalize(a) {
|
||||
if (!(a instanceof Array)) {
|
||||
a = [a, a];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return function (ecModel) {
|
||||
ecModel.eachSeriesByType('graph', function (seriesModel) {
|
||||
var edgeData = seriesModel.getEdgeData();
|
||||
var symbolType = normalize(seriesModel.get('edgeSymbol'));
|
||||
var symbolSize = normalize(seriesModel.get('edgeSymbolSize'));
|
||||
|
||||
edgeData.setVisual('fromSymbol', symbolType && symbolType[0]);
|
||||
edgeData.setVisual('toSymbol', symbolType && symbolType[1]);
|
||||
edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]);
|
||||
edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
|
||||
edgeData.setVisual('color', seriesModel.get('lineStyle.normal.color'));
|
||||
|
||||
edgeData.each(function (idx) {
|
||||
var itemModel = edgeData.getItemModel(idx);
|
||||
var symbolType = normalize(itemModel.getShallow('symbol', true));
|
||||
var symbolSize = normalize(itemModel.getShallow('symbolSize', true));
|
||||
|
||||
symbolType[0] && edgeData.setItemVisual(idx, 'fromSymbol', symbolType[0]);
|
||||
symbolType[1] && edgeData.setItemVisual(idx, 'toSymbol', symbolType[1]);
|
||||
symbolSize[0] && edgeData.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]);
|
||||
symbolSize[1] && edgeData.setItemVisual(idx, 'toSymbolSize', symbolSize[1]);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
137
vendors/echarts/src/chart/graph/forceHelper.js
vendored
Normal file
137
vendors/echarts/src/chart/graph/forceHelper.js
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
define(function (require) {
|
||||
|
||||
var vec2 = require('zrender/core/vector');
|
||||
var scaleAndAdd = vec2.scaleAndAdd;
|
||||
|
||||
// function adjacentNode(n, e) {
|
||||
// return e.n1 === n ? e.n2 : e.n1;
|
||||
// }
|
||||
|
||||
return function (nodes, edges, opts) {
|
||||
var rect = opts.rect;
|
||||
var width = rect.width;
|
||||
var height = rect.height;
|
||||
var center = [rect.x + width / 2, rect.y + height / 2];
|
||||
// var scale = opts.scale || 1;
|
||||
var gravity = opts.gravity == null ? 0.1 : opts.gravity;
|
||||
|
||||
// for (var i = 0; i < edges.length; i++) {
|
||||
// var e = edges[i];
|
||||
// var n1 = e.n1;
|
||||
// var n2 = e.n2;
|
||||
// n1.edges = n1.edges || [];
|
||||
// n2.edges = n2.edges || [];
|
||||
// n1.edges.push(e);
|
||||
// n2.edges.push(e);
|
||||
// }
|
||||
// Init position
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var n = nodes[i];
|
||||
if (!n.p) {
|
||||
// Use the position from first adjecent node with defined position
|
||||
// Or use a random position
|
||||
// From d3
|
||||
// if (n.edges) {
|
||||
// var j = -1;
|
||||
// while (++j < n.edges.length) {
|
||||
// var e = n.edges[j];
|
||||
// var other = adjacentNode(n, e);
|
||||
// if (other.p) {
|
||||
// n.p = vec2.clone(other.p);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!n.p) {
|
||||
n.p = vec2.create(
|
||||
width * (Math.random() - 0.5) + center[0],
|
||||
height * (Math.random() - 0.5) + center[1]
|
||||
);
|
||||
// }
|
||||
}
|
||||
n.pp = vec2.clone(n.p);
|
||||
n.edges = null;
|
||||
}
|
||||
|
||||
// Formula in 'Graph Drawing by Force-directed Placement'
|
||||
// var k = scale * Math.sqrt(width * height / nodes.length);
|
||||
// var k2 = k * k;
|
||||
|
||||
var friction = 0.6;
|
||||
|
||||
return {
|
||||
warmUp: function () {
|
||||
friction = 0.5;
|
||||
},
|
||||
|
||||
setFixed: function (idx) {
|
||||
nodes[idx].fixed = true;
|
||||
},
|
||||
|
||||
setUnfixed: function (idx) {
|
||||
nodes[idx].fixed = false;
|
||||
},
|
||||
|
||||
step: function (cb) {
|
||||
var v12 = [];
|
||||
var nLen = nodes.length;
|
||||
for (var i = 0; i < edges.length; i++) {
|
||||
var e = edges[i];
|
||||
var n1 = e.n1;
|
||||
var n2 = e.n2;
|
||||
|
||||
vec2.sub(v12, n2.p, n1.p);
|
||||
var d = vec2.len(v12) - e.d;
|
||||
var w = n2.w / (n1.w + n2.w);
|
||||
vec2.normalize(v12, v12);
|
||||
|
||||
!n1.fixed && scaleAndAdd(n1.p, n1.p, v12, w * d * friction);
|
||||
!n2.fixed && scaleAndAdd(n2.p, n2.p, v12, -(1 - w) * d * friction);
|
||||
}
|
||||
// Gravity
|
||||
for (var i = 0; i < nLen; i++) {
|
||||
var n = nodes[i];
|
||||
if (!n.fixed) {
|
||||
vec2.sub(v12, center, n.p);
|
||||
// var d = vec2.len(v12);
|
||||
// vec2.scale(v12, v12, 1 / d);
|
||||
// var gravityFactor = gravity;
|
||||
vec2.scaleAndAdd(n.p, n.p, v12, gravity * friction);
|
||||
}
|
||||
}
|
||||
|
||||
// Repulsive
|
||||
// PENDING
|
||||
for (var i = 0; i < nLen; i++) {
|
||||
var n1 = nodes[i];
|
||||
for (var j = i + 1; j < nLen; j++) {
|
||||
var n2 = nodes[j];
|
||||
vec2.sub(v12, n2.p, n1.p);
|
||||
var d = vec2.len(v12);
|
||||
if (d === 0) {
|
||||
// Random repulse
|
||||
vec2.set(v12, Math.random() - 0.5, Math.random() - 0.5);
|
||||
d = 1;
|
||||
}
|
||||
var repFact = (n1.rep + n2.rep) / d / d;
|
||||
!n1.fixed && scaleAndAdd(n1.pp, n1.pp, v12, repFact);
|
||||
!n2.fixed && scaleAndAdd(n2.pp, n2.pp, v12, -repFact);
|
||||
}
|
||||
}
|
||||
var v = [];
|
||||
for (var i = 0; i < nLen; i++) {
|
||||
var n = nodes[i];
|
||||
if (!n.fixed) {
|
||||
vec2.sub(v, n.p, n.pp);
|
||||
vec2.scaleAndAdd(n.p, n.p, v, friction);
|
||||
vec2.copy(n.pp, n.p);
|
||||
}
|
||||
}
|
||||
|
||||
friction = friction * 0.992;
|
||||
|
||||
cb && cb(nodes, edges, friction < 0.01);
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
||||
111
vendors/echarts/src/chart/graph/forceLayout.js
vendored
Normal file
111
vendors/echarts/src/chart/graph/forceLayout.js
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
define(function (require) {
|
||||
|
||||
var forceHelper = require('./forceHelper');
|
||||
var numberUtil = require('../../util/number');
|
||||
var simpleLayoutHelper = require('./simpleLayoutHelper');
|
||||
var circularLayoutHelper = require('./circularLayoutHelper');
|
||||
var vec2 = require('zrender/core/vector');
|
||||
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('graph', function (graphSeries) {
|
||||
var coordSys = graphSeries.coordinateSystem;
|
||||
if (coordSys && coordSys.type !== 'view') {
|
||||
return;
|
||||
}
|
||||
if (graphSeries.get('layout') === 'force') {
|
||||
var preservedPoints = graphSeries.preservedPoints || {};
|
||||
var graph = graphSeries.getGraph();
|
||||
var nodeData = graph.data;
|
||||
var edgeData = graph.edgeData;
|
||||
var forceModel = graphSeries.getModel('force');
|
||||
var initLayout = forceModel.get('initLayout');
|
||||
if (graphSeries.preservedPoints) {
|
||||
nodeData.each(function (idx) {
|
||||
var id = nodeData.getId(idx);
|
||||
nodeData.setItemLayout(idx, preservedPoints[id] || [NaN, NaN]);
|
||||
});
|
||||
}
|
||||
else if (!initLayout || initLayout === 'none') {
|
||||
simpleLayoutHelper(graphSeries);
|
||||
}
|
||||
else if (initLayout === 'circular') {
|
||||
circularLayoutHelper(graphSeries);
|
||||
}
|
||||
|
||||
var nodeDataExtent = nodeData.getDataExtent('value');
|
||||
// var edgeDataExtent = edgeData.getDataExtent('value');
|
||||
var repulsion = forceModel.get('repulsion');
|
||||
var edgeLength = forceModel.get('edgeLength');
|
||||
var nodes = nodeData.mapArray('value', function (value, idx) {
|
||||
var point = nodeData.getItemLayout(idx);
|
||||
// var w = numberUtil.linearMap(value, nodeDataExtent, [0, 50]);
|
||||
var rep = numberUtil.linearMap(value, nodeDataExtent, [0, repulsion]) || (repulsion / 2);
|
||||
return {
|
||||
w: rep,
|
||||
rep: rep,
|
||||
p: (!point || isNaN(point[0]) || isNaN(point[1])) ? null : point
|
||||
};
|
||||
});
|
||||
var edges = edgeData.mapArray('value', function (value, idx) {
|
||||
var edge = graph.getEdgeByIndex(idx);
|
||||
// var w = numberUtil.linearMap(value, edgeDataExtent, [0, 100]);
|
||||
return {
|
||||
n1: nodes[edge.node1.dataIndex],
|
||||
n2: nodes[edge.node2.dataIndex],
|
||||
d: edgeLength,
|
||||
curveness: edge.getModel().get('lineStyle.normal.curveness') || 0
|
||||
};
|
||||
});
|
||||
|
||||
var coordSys = graphSeries.coordinateSystem;
|
||||
var rect = coordSys.getBoundingRect();
|
||||
var forceInstance = forceHelper(nodes, edges, {
|
||||
rect: rect,
|
||||
gravity: forceModel.get('gravity')
|
||||
});
|
||||
var oldStep = forceInstance.step;
|
||||
forceInstance.step = function (cb) {
|
||||
for (var i = 0, l = nodes.length; i < l; i++) {
|
||||
if (nodes[i].fixed) {
|
||||
// Write back to layout instance
|
||||
vec2.copy(nodes[i].p, graph.getNodeByIndex(i).getLayout());
|
||||
}
|
||||
}
|
||||
oldStep(function (nodes, edges, stopped) {
|
||||
for (var i = 0, l = nodes.length; i < l; i++) {
|
||||
if (!nodes[i].fixed) {
|
||||
graph.getNodeByIndex(i).setLayout(nodes[i].p);
|
||||
}
|
||||
preservedPoints[nodeData.getId(i)] = nodes[i].p;
|
||||
}
|
||||
for (var i = 0, l = edges.length; i < l; i++) {
|
||||
var e = edges[i];
|
||||
var p1 = e.n1.p;
|
||||
var p2 = e.n2.p;
|
||||
var points = [p1, p2];
|
||||
if (e.curveness > 0) {
|
||||
points.push([
|
||||
(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness,
|
||||
(p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness
|
||||
]);
|
||||
}
|
||||
graph.getEdgeByIndex(i).setLayout(points);
|
||||
}
|
||||
// Update layout
|
||||
|
||||
cb && cb(stopped);
|
||||
});
|
||||
};
|
||||
graphSeries.forceLayout = forceInstance;
|
||||
graphSeries.preservedPoints = preservedPoints;
|
||||
|
||||
// Step to get the layout
|
||||
forceInstance.step();
|
||||
}
|
||||
else {
|
||||
// Remove prev injected forceLayout instance
|
||||
graphSeries.forceLayout = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
35
vendors/echarts/src/chart/graph/roamAction.js
vendored
Normal file
35
vendors/echarts/src/chart/graph/roamAction.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../../echarts');
|
||||
var roamHelper = require('../../action/roamHelper');
|
||||
|
||||
var actionInfo = {
|
||||
type: 'graphRoam',
|
||||
event: 'graphRoam',
|
||||
update: 'none'
|
||||
};
|
||||
|
||||
/**
|
||||
* @payload
|
||||
* @property {string} name Series name
|
||||
* @property {number} [dx]
|
||||
* @property {number} [dy]
|
||||
* @property {number} [zoom]
|
||||
* @property {number} [originX]
|
||||
* @property {number} [originY]
|
||||
*/
|
||||
|
||||
echarts.registerAction(actionInfo, function (payload, ecModel) {
|
||||
ecModel.eachComponent({mainType: 'series', query: payload}, function (seriesModel) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
|
||||
var res = roamHelper.updateCenterAndZoom(coordSys, payload);
|
||||
|
||||
seriesModel.setCenter
|
||||
&& seriesModel.setCenter(res.center);
|
||||
|
||||
seriesModel.setZoom
|
||||
&& seriesModel.setZoom(res.zoom);
|
||||
});
|
||||
});
|
||||
});
|
||||
28
vendors/echarts/src/chart/graph/simpleLayout.js
vendored
Normal file
28
vendors/echarts/src/chart/graph/simpleLayout.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
define(function (require) {
|
||||
|
||||
var simpleLayoutHelper = require('./simpleLayoutHelper');
|
||||
var simpleLayoutEdge = require('./simpleLayoutEdge');
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('graph', function (seriesModel) {
|
||||
var layout = seriesModel.get('layout');
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (coordSys && coordSys.type !== 'view') {
|
||||
var data = seriesModel.getData();
|
||||
data.each(coordSys.dimensions, function (x, y, idx) {
|
||||
if (!isNaN(x) && !isNaN(y)) {
|
||||
data.setItemLayout(idx, coordSys.dataToPoint([x, y]));
|
||||
}
|
||||
else {
|
||||
// Also {Array.<number>}, not undefined to avoid if...else... statement
|
||||
data.setItemLayout(idx, [NaN, NaN]);
|
||||
}
|
||||
});
|
||||
|
||||
simpleLayoutEdge(data.graph);
|
||||
}
|
||||
else if (!layout || layout === 'none') {
|
||||
simpleLayoutHelper(seriesModel);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
18
vendors/echarts/src/chart/graph/simpleLayoutEdge.js
vendored
Normal file
18
vendors/echarts/src/chart/graph/simpleLayoutEdge.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
define(function (require) {
|
||||
var vec2 = require('zrender/core/vector');
|
||||
return function (graph) {
|
||||
graph.eachEdge(function (edge) {
|
||||
var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0;
|
||||
var p1 = vec2.clone(edge.node1.getLayout());
|
||||
var p2 = vec2.clone(edge.node2.getLayout());
|
||||
var points = [p1, p2];
|
||||
if (curveness > 0) {
|
||||
points.push([
|
||||
(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness,
|
||||
(p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness
|
||||
]);
|
||||
}
|
||||
edge.setLayout(points);
|
||||
});
|
||||
};
|
||||
});
|
||||
19
vendors/echarts/src/chart/graph/simpleLayoutHelper.js
vendored
Normal file
19
vendors/echarts/src/chart/graph/simpleLayoutHelper.js
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
define(function (require) {
|
||||
|
||||
var simpleLayoutEdge = require('./simpleLayoutEdge');
|
||||
|
||||
return function (seriesModel) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (coordSys && coordSys.type !== 'view') {
|
||||
return;
|
||||
}
|
||||
var graph = seriesModel.getGraph();
|
||||
|
||||
graph.eachNode(function (node) {
|
||||
var model = node.getModel();
|
||||
node.setLayout([+model.get('x'), +model.get('y')]);
|
||||
});
|
||||
|
||||
simpleLayoutEdge(graph);
|
||||
};
|
||||
});
|
||||
5
vendors/echarts/src/chart/heatmap.js
vendored
Normal file
5
vendors/echarts/src/chart/heatmap.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
define(function (require) {
|
||||
|
||||
require('./heatmap/HeatmapSeries');
|
||||
require('./heatmap/HeatmapView');
|
||||
});
|
||||
148
vendors/echarts/src/chart/heatmap/HeatmapLayer.js
vendored
Normal file
148
vendors/echarts/src/chart/heatmap/HeatmapLayer.js
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* @file defines echarts Heatmap Chart
|
||||
* @author Ovilia (me@zhangwenli.com)
|
||||
* Inspired by https://github.com/mourner/simpleheat
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var GRADIENT_LEVELS = 256;
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
/**
|
||||
* Heatmap Chart
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
function Heatmap() {
|
||||
var canvas = zrUtil.createCanvas();
|
||||
this.canvas = canvas;
|
||||
|
||||
this.blurSize = 30;
|
||||
this.pointSize = 20;
|
||||
|
||||
this.maxOpacity = 1;
|
||||
this.minOpacity = 0;
|
||||
|
||||
this._gradientPixels = {};
|
||||
}
|
||||
|
||||
Heatmap.prototype = {
|
||||
/**
|
||||
* Renders Heatmap and returns the rendered canvas
|
||||
* @param {Array} data array of data, each has x, y, value
|
||||
* @param {number} width canvas width
|
||||
* @param {number} height canvas height
|
||||
*/
|
||||
update: function(data, width, height, normalize, colorFunc, isInRange) {
|
||||
var brush = this._getBrush();
|
||||
var gradientInRange = this._getGradient(data, colorFunc, 'inRange');
|
||||
var gradientOutOfRange = this._getGradient(data, colorFunc, 'outOfRange');
|
||||
var r = this.pointSize + this.blurSize;
|
||||
|
||||
var canvas = this.canvas;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var len = data.length;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
var p = data[i];
|
||||
var x = p[0];
|
||||
var y = p[1];
|
||||
var value = p[2];
|
||||
|
||||
// calculate alpha using value
|
||||
var alpha = normalize(value);
|
||||
|
||||
// draw with the circle brush with alpha
|
||||
ctx.globalAlpha = alpha;
|
||||
ctx.drawImage(brush, x - r, y - r);
|
||||
}
|
||||
|
||||
// colorize the canvas using alpha value and set with gradient
|
||||
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
var pixels = imageData.data;
|
||||
var offset = 0;
|
||||
var pixelLen = pixels.length;
|
||||
var minOpacity = this.minOpacity;
|
||||
var maxOpacity = this.maxOpacity;
|
||||
var diffOpacity = maxOpacity - minOpacity;
|
||||
|
||||
while(offset < pixelLen) {
|
||||
var alpha = pixels[offset + 3] / 256;
|
||||
var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4;
|
||||
// Simple optimize to ignore the empty data
|
||||
if (alpha > 0) {
|
||||
var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange;
|
||||
// Any alpha > 0 will be mapped to [minOpacity, maxOpacity]
|
||||
alpha > 0 && (alpha = alpha * diffOpacity + minOpacity);
|
||||
pixels[offset++] = gradient[gradientOffset];
|
||||
pixels[offset++] = gradient[gradientOffset + 1];
|
||||
pixels[offset++] = gradient[gradientOffset + 2];
|
||||
pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256;
|
||||
}
|
||||
else {
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
return canvas;
|
||||
},
|
||||
|
||||
/**
|
||||
* get canvas of a black circle brush used for canvas to draw later
|
||||
* @private
|
||||
* @returns {Object} circle brush canvas
|
||||
*/
|
||||
_getBrush: function() {
|
||||
var brushCanvas = this._brushCanvas || (this._brushCanvas = zrUtil.createCanvas());
|
||||
// set brush size
|
||||
var r = this.pointSize + this.blurSize;
|
||||
var d = r * 2;
|
||||
brushCanvas.width = d;
|
||||
brushCanvas.height = d;
|
||||
|
||||
var ctx = brushCanvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, d, d);
|
||||
|
||||
// in order to render shadow without the distinct circle,
|
||||
// draw the distinct circle in an invisible place,
|
||||
// and use shadowOffset to draw shadow in the center of the canvas
|
||||
ctx.shadowOffsetX = d;
|
||||
ctx.shadowBlur = this.blurSize;
|
||||
// draw the shadow in black, and use alpha and shadow blur to generate
|
||||
// color in color map
|
||||
ctx.shadowColor = '#000';
|
||||
|
||||
// draw circle in the left to the canvas
|
||||
ctx.beginPath();
|
||||
ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
return brushCanvas;
|
||||
},
|
||||
|
||||
/**
|
||||
* get gradient color map
|
||||
* @private
|
||||
*/
|
||||
_getGradient: function (data, colorFunc, state) {
|
||||
var gradientPixels = this._gradientPixels;
|
||||
var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4));
|
||||
var color = [];
|
||||
var off = 0;
|
||||
for (var i = 0; i < 256; i++) {
|
||||
colorFunc[state](i / 255, true, color);
|
||||
pixelsSingleState[off++] = color[0];
|
||||
pixelsSingleState[off++] = color[1];
|
||||
pixelsSingleState[off++] = color[2];
|
||||
pixelsSingleState[off++] = color[3];
|
||||
}
|
||||
return pixelsSingleState;
|
||||
}
|
||||
};
|
||||
|
||||
return Heatmap;
|
||||
});
|
||||
38
vendors/echarts/src/chart/heatmap/HeatmapSeries.js
vendored
Normal file
38
vendors/echarts/src/chart/heatmap/HeatmapSeries.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
define(function (require) {
|
||||
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var createListFromArray = require('../helper/createListFromArray');
|
||||
|
||||
return SeriesModel.extend({
|
||||
type: 'series.heatmap',
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
return createListFromArray(option.data, this, ecModel);
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
|
||||
// Cartesian2D or geo
|
||||
coordinateSystem: 'cartesian2d',
|
||||
|
||||
zlevel: 0,
|
||||
|
||||
z: 2,
|
||||
|
||||
// Cartesian coordinate system
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
// Geo coordinate system
|
||||
geoIndex: 0,
|
||||
|
||||
blurSize: 30,
|
||||
|
||||
pointSize: 20,
|
||||
|
||||
maxOpacity: 1,
|
||||
|
||||
minOpacity: 0
|
||||
}
|
||||
});
|
||||
});
|
||||
213
vendors/echarts/src/chart/heatmap/HeatmapView.js
vendored
Normal file
213
vendors/echarts/src/chart/heatmap/HeatmapView.js
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var HeatmapLayer = require('./HeatmapLayer');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
function getIsInPiecewiseRange(dataExtent, pieceList, selected) {
|
||||
var dataSpan = dataExtent[1] - dataExtent[0];
|
||||
pieceList = zrUtil.map(pieceList, function (piece) {
|
||||
return {
|
||||
interval: [
|
||||
(piece.interval[0] - dataExtent[0]) / dataSpan,
|
||||
(piece.interval[1] - dataExtent[0]) / dataSpan
|
||||
]
|
||||
};
|
||||
});
|
||||
var len = pieceList.length;
|
||||
var lastIndex = 0;
|
||||
return function (val) {
|
||||
// Try to find in the location of the last found
|
||||
for (var i = lastIndex; i < len; i++) {
|
||||
var interval = pieceList[i].interval;
|
||||
if (interval[0] <= val && val <= interval[1]) {
|
||||
lastIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i === len) { // Not found, back interation
|
||||
for (var i = lastIndex - 1; i >= 0; i--) {
|
||||
var interval = pieceList[i].interval;
|
||||
if (interval[0] <= val && val <= interval[1]) {
|
||||
lastIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return i >= 0 && i < len && selected[i];
|
||||
};
|
||||
}
|
||||
|
||||
function getIsInContinuousRange(dataExtent, range) {
|
||||
var dataSpan = dataExtent[1] - dataExtent[0];
|
||||
range = [
|
||||
(range[0] - dataExtent[0]) / dataSpan,
|
||||
(range[1] - dataExtent[0]) / dataSpan
|
||||
];
|
||||
return function (val) {
|
||||
return val >= range[0] && val <= range[1];
|
||||
};
|
||||
}
|
||||
|
||||
function isGeoCoordSys(coordSys) {
|
||||
var dimensions = coordSys.dimensions;
|
||||
// Not use coorSys.type === 'geo' because coordSys maybe extended
|
||||
return dimensions[0] === 'lng' && dimensions[1] === 'lat';
|
||||
}
|
||||
|
||||
return require('../../echarts').extendChartView({
|
||||
|
||||
type: 'heatmap',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var visualMapOfThisSeries;
|
||||
ecModel.eachComponent('visualMap', function (visualMap) {
|
||||
visualMap.eachTargetSeries(function (targetSeries) {
|
||||
if (targetSeries === seriesModel) {
|
||||
visualMapOfThisSeries = visualMap;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!visualMapOfThisSeries) {
|
||||
throw new Error('Heatmap must use with visualMap');
|
||||
}
|
||||
|
||||
this.group.removeAll();
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (coordSys.type === 'cartesian2d') {
|
||||
this._renderOnCartesian(coordSys, seriesModel, api);
|
||||
}
|
||||
else if (isGeoCoordSys(coordSys)) {
|
||||
this._renderOnGeo(
|
||||
coordSys, seriesModel, visualMapOfThisSeries, api
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_renderOnCartesian: function (cartesian, seriesModel, api) {
|
||||
var xAxis = cartesian.getAxis('x');
|
||||
var yAxis = cartesian.getAxis('y');
|
||||
var group = this.group;
|
||||
|
||||
if (!(xAxis.type === 'category' && yAxis.type === 'category')) {
|
||||
throw new Error('Heatmap on cartesian must have two category axes');
|
||||
}
|
||||
if (!(xAxis.onBand && yAxis.onBand)) {
|
||||
throw new Error('Heatmap on cartesian must have two axes with boundaryGap true');
|
||||
}
|
||||
var width = xAxis.getBandWidth();
|
||||
var height = yAxis.getBandWidth();
|
||||
|
||||
var data = seriesModel.getData();
|
||||
data.each(['x', 'y', 'z'], function (x, y, z, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var point = cartesian.dataToPoint([x, y]);
|
||||
// Ignore empty data
|
||||
if (isNaN(z)) {
|
||||
return;
|
||||
}
|
||||
var rect = new graphic.Rect({
|
||||
shape: {
|
||||
x: point[0] - width / 2,
|
||||
y: point[1] - height / 2,
|
||||
width: width,
|
||||
height: height
|
||||
},
|
||||
style: {
|
||||
fill: data.getItemVisual(idx, 'color'),
|
||||
opacity: data.getItemVisual(idx, 'opacity')
|
||||
}
|
||||
});
|
||||
var style = itemModel.getModel('itemStyle.normal').getItemStyle(['color']);
|
||||
var hoverStl = itemModel.getModel('itemStyle.emphasis').getItemStyle();
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var hoverLabelModel = itemModel.getModel('label.emphasis');
|
||||
|
||||
var rawValue = seriesModel.getRawValue(idx);
|
||||
var defaultText = '-';
|
||||
if (rawValue && rawValue[2] != null) {
|
||||
defaultText = rawValue[2];
|
||||
}
|
||||
if (labelModel.get('show')) {
|
||||
graphic.setText(style, labelModel);
|
||||
style.text = seriesModel.getFormattedLabel(idx, 'normal') || defaultText;
|
||||
}
|
||||
if (hoverLabelModel.get('show')) {
|
||||
graphic.setText(hoverStl, hoverLabelModel);
|
||||
hoverStl.text = seriesModel.getFormattedLabel(idx, 'emphasis') || defaultText;
|
||||
}
|
||||
|
||||
rect.setStyle(style);
|
||||
|
||||
graphic.setHoverStyle(rect, hoverStl);
|
||||
|
||||
group.add(rect);
|
||||
data.setItemGraphicEl(idx, rect);
|
||||
});
|
||||
},
|
||||
|
||||
_renderOnGeo: function (geo, seriesModel, visualMapModel, api) {
|
||||
var inRangeVisuals = visualMapModel.targetVisuals.inRange;
|
||||
var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange;
|
||||
// if (!visualMapping) {
|
||||
// throw new Error('Data range must have color visuals');
|
||||
// }
|
||||
|
||||
var data = seriesModel.getData();
|
||||
var hmLayer = this._hmLayer || (this._hmLayer || new HeatmapLayer());
|
||||
hmLayer.blurSize = seriesModel.get('blurSize');
|
||||
hmLayer.pointSize = seriesModel.get('pointSize');
|
||||
hmLayer.minOpacity = seriesModel.get('minOpacity');
|
||||
hmLayer.maxOpacity = seriesModel.get('maxOpacity');
|
||||
|
||||
var rect = geo.getViewRect().clone();
|
||||
var roamTransform = geo.getRoamTransform().transform;
|
||||
rect.applyTransform(roamTransform);
|
||||
|
||||
// Clamp on viewport
|
||||
var x = Math.max(rect.x, 0);
|
||||
var y = Math.max(rect.y, 0);
|
||||
var x2 = Math.min(rect.width + rect.x, api.getWidth());
|
||||
var y2 = Math.min(rect.height + rect.y, api.getHeight());
|
||||
var width = x2 - x;
|
||||
var height = y2 - y;
|
||||
|
||||
var points = data.mapArray(['lng', 'lat', 'value'], function (lng, lat, value) {
|
||||
var pt = geo.dataToPoint([lng, lat]);
|
||||
pt[0] -= x;
|
||||
pt[1] -= y;
|
||||
pt.push(value);
|
||||
return pt;
|
||||
});
|
||||
|
||||
var dataExtent = visualMapModel.getExtent();
|
||||
var isInRange = visualMapModel.type === 'visualMap.continuous'
|
||||
? getIsInContinuousRange(dataExtent, visualMapModel.option.range)
|
||||
: getIsInPiecewiseRange(
|
||||
dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected
|
||||
);
|
||||
|
||||
hmLayer.update(
|
||||
points, width, height,
|
||||
inRangeVisuals.color.getNormalizer(),
|
||||
{
|
||||
inRange: inRangeVisuals.color.getColorMapper(),
|
||||
outOfRange: outOfRangeVisuals.color.getColorMapper()
|
||||
},
|
||||
isInRange
|
||||
);
|
||||
var img = new graphic.Image({
|
||||
style: {
|
||||
width: width,
|
||||
height: height,
|
||||
x: x,
|
||||
y: y,
|
||||
image: hmLayer.canvas
|
||||
},
|
||||
silent: true
|
||||
});
|
||||
this.group.add(img);
|
||||
}
|
||||
});
|
||||
});
|
||||
116
vendors/echarts/src/chart/helper/EffectLine.js
vendored
Normal file
116
vendors/echarts/src/chart/helper/EffectLine.js
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/EffectLine
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var Line = require('./Line');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
|
||||
var curveUtil = require('zrender/core/curve');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
* @alias {module:echarts/chart/helper/Line}
|
||||
*/
|
||||
function EffectLine(lineData, idx) {
|
||||
graphic.Group.call(this);
|
||||
|
||||
var line = new Line(lineData, idx);
|
||||
this.add(line);
|
||||
|
||||
this._updateEffectSymbol(lineData, idx);
|
||||
}
|
||||
|
||||
var effectLineProto = EffectLine.prototype;
|
||||
|
||||
function setAnimationPoints(symbol, points) {
|
||||
symbol.__p1 = points[0];
|
||||
symbol.__p2 = points[1];
|
||||
symbol.__cp1 = points[2] || [
|
||||
(points[0][0] + points[1][0]) / 2,
|
||||
(points[0][1] + points[1][1]) / 2
|
||||
];
|
||||
}
|
||||
|
||||
function updateSymbolPosition() {
|
||||
var p1 = this.__p1;
|
||||
var p2 = this.__p2;
|
||||
var cp1 = this.__cp1;
|
||||
var t = this.__t;
|
||||
var pos = this.position;
|
||||
var quadraticAt = curveUtil.quadraticAt;
|
||||
var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt;
|
||||
pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t);
|
||||
pos[1] = quadraticAt(p1[1], cp1[1], p2[1], t);
|
||||
|
||||
// Tangent
|
||||
var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t);
|
||||
var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t);
|
||||
|
||||
this.rotation = -Math.atan2(ty, tx) - Math.PI / 2;
|
||||
|
||||
this.ignore = false;
|
||||
}
|
||||
|
||||
effectLineProto._updateEffectSymbol = function (lineData, idx) {
|
||||
var itemModel = lineData.getItemModel(idx);
|
||||
var effectModel = itemModel.getModel('effect');
|
||||
var size = effectModel.get('symbolSize');
|
||||
var symbolType = effectModel.get('symbol');
|
||||
if (!zrUtil.isArray(size)) {
|
||||
size = [size, size];
|
||||
}
|
||||
var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color');
|
||||
var symbol = this.childAt(1);
|
||||
var period = effectModel.get('period') * 1000;
|
||||
if (this._symbolType !== symbolType || period !== this._period) {
|
||||
symbol = symbolUtil.createSymbol(
|
||||
symbolType, -0.5, -0.5, 1, 1, color
|
||||
);
|
||||
symbol.ignore = true;
|
||||
symbol.z2 = 100;
|
||||
this._symbolType = symbolType;
|
||||
this._period = period;
|
||||
|
||||
this.add(symbol);
|
||||
|
||||
symbol.__t = 0;
|
||||
symbol.animate('', true)
|
||||
.when(period, {
|
||||
__t: 1
|
||||
})
|
||||
.delay(idx / lineData.count() * period / 2)
|
||||
.during(zrUtil.bind(updateSymbolPosition, symbol))
|
||||
.start();
|
||||
}
|
||||
// Shadow color is same with color in default
|
||||
symbol.setStyle('shadowColor', color);
|
||||
symbol.setStyle(effectModel.getItemStyle(['color']));
|
||||
|
||||
symbol.attr('scale', size);
|
||||
var points = lineData.getItemLayout(idx);
|
||||
setAnimationPoints(symbol, points);
|
||||
|
||||
symbol.setColor(color);
|
||||
symbol.attr('scale', size);
|
||||
};
|
||||
|
||||
effectLineProto.updateData = function (lineData, idx) {
|
||||
this.childAt(0).updateData(lineData, idx);
|
||||
this._updateEffectSymbol(lineData, idx);
|
||||
};
|
||||
|
||||
effectLineProto.updateLayout = function (lineData, idx) {
|
||||
this.childAt(0).updateLayout(lineData, idx);
|
||||
var symbol = this.childAt(1);
|
||||
var points = lineData.getItemLayout(idx);
|
||||
setAnimationPoints(symbol, points);
|
||||
};
|
||||
|
||||
zrUtil.inherits(EffectLine, graphic.Group);
|
||||
|
||||
return EffectLine;
|
||||
});
|
||||
184
vendors/echarts/src/chart/helper/EffectSymbol.js
vendored
Normal file
184
vendors/echarts/src/chart/helper/EffectSymbol.js
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Symbol with ripple effect
|
||||
* @module echarts/chart/helper/EffectSymbol
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
var graphic = require('../../util/graphic');
|
||||
var numberUtil = require('../../util/number');
|
||||
var Symbol = require('./Symbol');
|
||||
var Group = graphic.Group;
|
||||
|
||||
var EFFECT_RIPPLE_NUMBER = 3;
|
||||
|
||||
function normalizeSymbolSize(symbolSize) {
|
||||
if (!zrUtil.isArray(symbolSize)) {
|
||||
symbolSize = [+symbolSize, +symbolSize];
|
||||
}
|
||||
return symbolSize;
|
||||
}
|
||||
/**
|
||||
* @constructor
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
*/
|
||||
function EffectSymbol(data, idx) {
|
||||
Group.call(this);
|
||||
|
||||
var symbol = new Symbol(data, idx);
|
||||
var rippleGroup = new Group();
|
||||
this.add(symbol);
|
||||
this.add(rippleGroup);
|
||||
|
||||
rippleGroup.beforeUpdate = function () {
|
||||
this.attr(symbol.getScale());
|
||||
};
|
||||
this.updateData(data, idx);
|
||||
}
|
||||
|
||||
var effectSymbolProto = EffectSymbol.prototype;
|
||||
|
||||
effectSymbolProto.stopEffectAnimation = function () {
|
||||
this.childAt(1).removeAll();
|
||||
};
|
||||
|
||||
effectSymbolProto.startEffectAnimation = function (
|
||||
period, brushType, rippleScale, effectOffset, z, zlevel
|
||||
) {
|
||||
var symbolType = this._symbolType;
|
||||
var color = this._color;
|
||||
|
||||
var rippleGroup = this.childAt(1);
|
||||
|
||||
for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) {
|
||||
var ripplePath = symbolUtil.createSymbol(
|
||||
symbolType, -0.5, -0.5, 1, 1, color
|
||||
);
|
||||
ripplePath.attr({
|
||||
style: {
|
||||
stroke: brushType === 'stroke' ? color : null,
|
||||
fill: brushType === 'fill' ? color : null,
|
||||
strokeNoScale: true
|
||||
},
|
||||
z2: 99,
|
||||
silent: true,
|
||||
scale: [1, 1],
|
||||
z: z,
|
||||
zlevel: zlevel
|
||||
});
|
||||
|
||||
var delay = -i / EFFECT_RIPPLE_NUMBER * period + effectOffset;
|
||||
// TODO Configurable period
|
||||
ripplePath.animate('', true)
|
||||
.when(period, {
|
||||
scale: [rippleScale, rippleScale]
|
||||
})
|
||||
.delay(delay)
|
||||
.start();
|
||||
ripplePath.animateStyle(true)
|
||||
.when(period, {
|
||||
opacity: 0
|
||||
})
|
||||
.delay(delay)
|
||||
.start();
|
||||
|
||||
rippleGroup.add(ripplePath);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Highlight symbol
|
||||
*/
|
||||
effectSymbolProto.highlight = function () {
|
||||
this.trigger('emphasis');
|
||||
};
|
||||
|
||||
/**
|
||||
* Downplay symbol
|
||||
*/
|
||||
effectSymbolProto.downplay = function () {
|
||||
this.trigger('normal');
|
||||
};
|
||||
|
||||
/**
|
||||
* Update symbol properties
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
*/
|
||||
effectSymbolProto.updateData = function (data, idx) {
|
||||
var seriesModel = data.hostModel;
|
||||
|
||||
this.childAt(0).updateData(data, idx);
|
||||
|
||||
var rippleGroup = this.childAt(1);
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var symbolType = data.getItemVisual(idx, 'symbol');
|
||||
var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
|
||||
rippleGroup.attr('scale', symbolSize);
|
||||
|
||||
rippleGroup.traverse(function (ripplePath) {
|
||||
ripplePath.attr({
|
||||
fill: color
|
||||
});
|
||||
});
|
||||
|
||||
var symbolOffset = itemModel.getShallow('symbolOffset');
|
||||
if (symbolOffset) {
|
||||
var pos = rippleGroup.position;
|
||||
pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
|
||||
pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
|
||||
}
|
||||
rippleGroup.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0;
|
||||
|
||||
this._symbolType = symbolType;
|
||||
this._color = color;
|
||||
|
||||
var showEffectOn = seriesModel.get('showEffectOn');
|
||||
var rippleScale = itemModel.get('rippleEffect.scale');
|
||||
var brushType = itemModel.get('rippleEffect.brushType');
|
||||
var effectPeriod = itemModel.get('rippleEffect.period') * 1000;
|
||||
var effectOffset = idx / data.count();
|
||||
var z = itemModel.getShallow('z') || 0;
|
||||
var zlevel = itemModel.getShallow('zlevel') || 0;
|
||||
|
||||
this.stopEffectAnimation();
|
||||
if (showEffectOn === 'render') {
|
||||
this.startEffectAnimation(
|
||||
effectPeriod, brushType, rippleScale, effectOffset, z, zlevel
|
||||
);
|
||||
}
|
||||
var symbol = this.childAt(0);
|
||||
function onEmphasis() {
|
||||
symbol.trigger('emphasis');
|
||||
if (showEffectOn !== 'render') {
|
||||
this.startEffectAnimation(
|
||||
effectPeriod, brushType, rippleScale, effectOffset, z, zlevel
|
||||
);
|
||||
}
|
||||
}
|
||||
function onNormal() {
|
||||
symbol.trigger('normal');
|
||||
if (showEffectOn !== 'render') {
|
||||
this.stopEffectAnimation();
|
||||
}
|
||||
}
|
||||
this.on('mouseover', onEmphasis, this)
|
||||
.on('mouseout', onNormal, this)
|
||||
.on('emphasis', onEmphasis, this)
|
||||
.on('normal', onNormal, this);
|
||||
};
|
||||
|
||||
effectSymbolProto.fadeOut = function (cb) {
|
||||
this.off('mouseover').off('mouseout').off('emphasis').off('normal');
|
||||
cb && cb();
|
||||
};
|
||||
|
||||
zrUtil.inherits(EffectSymbol, Group);
|
||||
|
||||
return EffectSymbol;
|
||||
});
|
||||
109
vendors/echarts/src/chart/helper/LargeSymbolDraw.js
vendored
Normal file
109
vendors/echarts/src/chart/helper/LargeSymbolDraw.js
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var LargeSymbolPath = graphic.extendShape({
|
||||
shape: {
|
||||
points: null,
|
||||
sizes: null
|
||||
},
|
||||
|
||||
symbolProxy: null,
|
||||
|
||||
buildPath: function (path, shape) {
|
||||
var points = shape.points;
|
||||
var sizes = shape.sizes;
|
||||
|
||||
var symbolProxy = this.symbolProxy;
|
||||
var symbolProxyShape = symbolProxy.shape;
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
var pt = points[i];
|
||||
var size = sizes[i];
|
||||
if (size[0] < 4) {
|
||||
// Optimize for small symbol
|
||||
path.rect(
|
||||
pt[0] - size[0] / 2, pt[1] - size[1] / 2,
|
||||
size[0], size[1]
|
||||
);
|
||||
}
|
||||
else {
|
||||
symbolProxyShape.x = pt[0] - size[0] / 2;
|
||||
symbolProxyShape.y = pt[1] - size[1] / 2;
|
||||
symbolProxyShape.width = size[0];
|
||||
symbolProxyShape.height = size[1];
|
||||
|
||||
symbolProxy.buildPath(path, symbolProxyShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function LargeSymbolDraw() {
|
||||
this.group = new graphic.Group();
|
||||
|
||||
this._symbolEl = new LargeSymbolPath({
|
||||
silent: true
|
||||
});
|
||||
}
|
||||
|
||||
var largeSymbolProto = LargeSymbolDraw.prototype;
|
||||
|
||||
/**
|
||||
* Update symbols draw by new data
|
||||
* @param {module:echarts/data/List} data
|
||||
*/
|
||||
largeSymbolProto.updateData = function (data) {
|
||||
this.group.removeAll();
|
||||
|
||||
var symbolEl = this._symbolEl;
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
|
||||
symbolEl.setShape({
|
||||
points: data.mapArray(data.getItemLayout),
|
||||
sizes: data.mapArray(
|
||||
function (idx) {
|
||||
var size = data.getItemVisual(idx, 'symbolSize');
|
||||
if (!zrUtil.isArray(size)) {
|
||||
size = [size, size];
|
||||
}
|
||||
return size;
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
// Create symbolProxy to build path for each data
|
||||
symbolEl.symbolProxy = symbolUtil.createSymbol(
|
||||
data.getVisual('symbol'), 0, 0, 0, 0
|
||||
);
|
||||
// Use symbolProxy setColor method
|
||||
symbolEl.setColor = symbolEl.symbolProxy.setColor;
|
||||
|
||||
symbolEl.useStyle(
|
||||
seriesModel.getModel('itemStyle.normal').getItemStyle(['color'])
|
||||
);
|
||||
|
||||
var visualColor = data.getVisual('color');
|
||||
if (visualColor) {
|
||||
symbolEl.setColor(visualColor);
|
||||
}
|
||||
|
||||
// Add back
|
||||
this.group.add(this._symbolEl);
|
||||
};
|
||||
|
||||
largeSymbolProto.updateLayout = function (seriesModel) {
|
||||
var data = seriesModel.getData();
|
||||
this._symbolEl.setShape({
|
||||
points: data.mapArray(data.getItemLayout)
|
||||
});
|
||||
};
|
||||
|
||||
largeSymbolProto.remove = function () {
|
||||
this.group.removeAll();
|
||||
};
|
||||
|
||||
return LargeSymbolDraw;
|
||||
});
|
||||
313
vendors/echarts/src/chart/helper/Line.js
vendored
Normal file
313
vendors/echarts/src/chart/helper/Line.js
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/Line
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
var vector = require('zrender/core/vector');
|
||||
// var matrix = require('zrender/core/matrix');
|
||||
var LinePath = require('./LinePath');
|
||||
var graphic = require('../../util/graphic');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var numberUtil = require('../../util/number');
|
||||
|
||||
var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol'];
|
||||
function makeSymbolTypeKey(symbolCategory) {
|
||||
return '_' + symbolCategory + 'Type';
|
||||
}
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function createSymbol(name, lineData, idx) {
|
||||
var color = lineData.getItemVisual(idx, 'color');
|
||||
var symbolType = lineData.getItemVisual(idx, name);
|
||||
var symbolSize = lineData.getItemVisual(idx, name + 'Size');
|
||||
|
||||
if (!symbolType || symbolType === 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zrUtil.isArray(symbolSize)) {
|
||||
symbolSize = [symbolSize, symbolSize];
|
||||
}
|
||||
var symbolPath = symbolUtil.createSymbol(
|
||||
symbolType, -symbolSize[0] / 2, -symbolSize[1] / 2,
|
||||
symbolSize[0], symbolSize[1], color
|
||||
);
|
||||
symbolPath.name = name;
|
||||
|
||||
return symbolPath;
|
||||
}
|
||||
|
||||
function createLine(points) {
|
||||
var line = new LinePath({
|
||||
name: 'line'
|
||||
});
|
||||
setLinePoints(line.shape, points);
|
||||
return line;
|
||||
}
|
||||
|
||||
function setLinePoints(targetShape, points) {
|
||||
var p1 = points[0];
|
||||
var p2 = points[1];
|
||||
var cp1 = points[2];
|
||||
targetShape.x1 = p1[0];
|
||||
targetShape.y1 = p1[1];
|
||||
targetShape.x2 = p2[0];
|
||||
targetShape.y2 = p2[1];
|
||||
targetShape.percent = 1;
|
||||
|
||||
if (cp1) {
|
||||
targetShape.cpx1 = cp1[0];
|
||||
targetShape.cpy1 = cp1[1];
|
||||
}
|
||||
}
|
||||
|
||||
function updateSymbolAndLabelBeforeLineUpdate () {
|
||||
var lineGroup = this;
|
||||
var symbolFrom = lineGroup.childOfName('fromSymbol');
|
||||
var symbolTo = lineGroup.childOfName('toSymbol');
|
||||
var label = lineGroup.childOfName('label');
|
||||
// Quick reject
|
||||
if (!symbolFrom && !symbolTo && label.ignore) {
|
||||
return;
|
||||
}
|
||||
|
||||
var invScale = 1;
|
||||
var parentNode = this.parent;
|
||||
while (parentNode) {
|
||||
if (parentNode.scale) {
|
||||
invScale /= parentNode.scale[0];
|
||||
}
|
||||
parentNode = parentNode.parent;
|
||||
}
|
||||
|
||||
var line = lineGroup.childOfName('line');
|
||||
// If line not changed
|
||||
// FIXME Parent scale changed
|
||||
if (!this.__dirty && !line.__dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
var percent = line.shape.percent;
|
||||
var fromPos = line.pointAt(0);
|
||||
var toPos = line.pointAt(percent);
|
||||
|
||||
var d = vector.sub([], toPos, fromPos);
|
||||
vector.normalize(d, d);
|
||||
|
||||
if (symbolFrom) {
|
||||
symbolFrom.attr('position', fromPos);
|
||||
var tangent = line.tangentAt(0);
|
||||
symbolFrom.attr('rotation', Math.PI / 2 - Math.atan2(
|
||||
tangent[1], tangent[0]
|
||||
));
|
||||
symbolFrom.attr('scale', [invScale * percent, invScale * percent]);
|
||||
}
|
||||
if (symbolTo) {
|
||||
symbolTo.attr('position', toPos);
|
||||
var tangent = line.tangentAt(1);
|
||||
symbolTo.attr('rotation', -Math.PI / 2 - Math.atan2(
|
||||
tangent[1], tangent[0]
|
||||
));
|
||||
symbolTo.attr('scale', [invScale * percent, invScale * percent]);
|
||||
}
|
||||
|
||||
if (!label.ignore) {
|
||||
label.attr('position', toPos);
|
||||
|
||||
var textPosition;
|
||||
var textAlign;
|
||||
var textVerticalAlign;
|
||||
|
||||
var distance = 5 * invScale;
|
||||
// End
|
||||
if (label.__position === 'end') {
|
||||
textPosition = [d[0] * distance + toPos[0], d[1] * distance + toPos[1]];
|
||||
textAlign = d[0] > 0.8 ? 'left' : (d[0] < -0.8 ? 'right' : 'center');
|
||||
textVerticalAlign = d[1] > 0.8 ? 'top' : (d[1] < -0.8 ? 'bottom' : 'middle');
|
||||
}
|
||||
// Middle
|
||||
else if (label.__position === 'middle') {
|
||||
var halfPercent = percent / 2;
|
||||
var tangent = line.tangentAt(halfPercent);
|
||||
var n = [tangent[1], -tangent[0]];
|
||||
var cp = line.pointAt(halfPercent);
|
||||
if (n[1] > 0) {
|
||||
n[0] = -n[0];
|
||||
n[1] = -n[1];
|
||||
}
|
||||
textPosition = [cp[0] + n[0] * distance, cp[1] + n[1] * distance];
|
||||
textAlign = 'center';
|
||||
textVerticalAlign = 'bottom';
|
||||
var rotation = -Math.atan2(tangent[1], tangent[0]);
|
||||
if (toPos[0] < fromPos[0]) {
|
||||
rotation = Math.PI + rotation;
|
||||
}
|
||||
label.attr('rotation', rotation);
|
||||
}
|
||||
// Start
|
||||
else {
|
||||
textPosition = [-d[0] * distance + fromPos[0], -d[1] * distance + fromPos[1]];
|
||||
textAlign = d[0] > 0.8 ? 'right' : (d[0] < -0.8 ? 'left' : 'center');
|
||||
textVerticalAlign = d[1] > 0.8 ? 'bottom' : (d[1] < -0.8 ? 'top' : 'middle');
|
||||
}
|
||||
label.attr({
|
||||
style: {
|
||||
// Use the user specified text align and baseline first
|
||||
textVerticalAlign: label.__verticalAlign || textVerticalAlign,
|
||||
textAlign: label.__textAlign || textAlign
|
||||
},
|
||||
position: textPosition,
|
||||
scale: [invScale, invScale]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
* @alias {module:echarts/chart/helper/Line}
|
||||
*/
|
||||
function Line(lineData, idx) {
|
||||
graphic.Group.call(this);
|
||||
|
||||
this._createLine(lineData, idx);
|
||||
}
|
||||
|
||||
var lineProto = Line.prototype;
|
||||
|
||||
// Update symbol position and rotation
|
||||
lineProto.beforeUpdate = updateSymbolAndLabelBeforeLineUpdate;
|
||||
|
||||
lineProto._createLine = function (lineData, idx) {
|
||||
var seriesModel = lineData.hostModel;
|
||||
var linePoints = lineData.getItemLayout(idx);
|
||||
|
||||
var line = createLine(linePoints);
|
||||
line.shape.percent = 0;
|
||||
graphic.initProps(line, {
|
||||
shape: {
|
||||
percent: 1
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
|
||||
this.add(line);
|
||||
|
||||
var label = new graphic.Text({
|
||||
name: 'label'
|
||||
});
|
||||
this.add(label);
|
||||
|
||||
zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
|
||||
var symbol = createSymbol(symbolCategory, lineData, idx);
|
||||
// symbols must added after line to make sure
|
||||
// it will be updated after line#update.
|
||||
// Or symbol position and rotation update in line#beforeUpdate will be one frame slow
|
||||
this.add(symbol);
|
||||
this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory);
|
||||
}, this);
|
||||
|
||||
this._updateCommonStl(lineData, idx);
|
||||
};
|
||||
|
||||
lineProto.updateData = function (lineData, idx) {
|
||||
var seriesModel = lineData.hostModel;
|
||||
|
||||
var line = this.childOfName('line');
|
||||
var linePoints = lineData.getItemLayout(idx);
|
||||
var target = {
|
||||
shape: {}
|
||||
};
|
||||
setLinePoints(target.shape, linePoints);
|
||||
graphic.updateProps(line, target, seriesModel, idx);
|
||||
|
||||
zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) {
|
||||
var symbolType = lineData.getItemVisual(idx, symbolCategory);
|
||||
var key = makeSymbolTypeKey(symbolCategory);
|
||||
// Symbol changed
|
||||
if (this[key] !== symbolType) {
|
||||
var symbol = createSymbol(symbolCategory, lineData, idx);
|
||||
this.remove(this.childOfName(symbolCategory));
|
||||
this.add(symbol);
|
||||
}
|
||||
this[key] = symbolType;
|
||||
}, this);
|
||||
|
||||
this._updateCommonStl(lineData, idx);
|
||||
};
|
||||
|
||||
lineProto._updateCommonStl = function (lineData, idx) {
|
||||
var seriesModel = lineData.hostModel;
|
||||
|
||||
var line = this.childOfName('line');
|
||||
var itemModel = lineData.getItemModel(idx);
|
||||
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var textStyleModel = labelModel.getModel('textStyle');
|
||||
var labelHoverModel = itemModel.getModel('label.emphasis');
|
||||
var textStyleHoverModel = labelHoverModel.getModel('textStyle');
|
||||
|
||||
var defaultText = numberUtil.round(seriesModel.getRawValue(idx));
|
||||
if (isNaN(defaultText)) {
|
||||
// Use name
|
||||
defaultText = lineData.getName(idx);
|
||||
}
|
||||
line.useStyle(zrUtil.extend(
|
||||
{
|
||||
strokeNoScale: true,
|
||||
fill: 'none',
|
||||
stroke: lineData.getItemVisual(idx, 'color')
|
||||
},
|
||||
itemModel.getModel('lineStyle.normal').getLineStyle()
|
||||
));
|
||||
line.hoverStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle();
|
||||
var defaultColor = lineData.getItemVisual(idx, 'color') || '#000';
|
||||
var label = this.childOfName('label');
|
||||
// label.afterUpdate = lineAfterUpdate;
|
||||
label.setStyle({
|
||||
text: labelModel.get('show')
|
||||
? zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'normal', lineData.dataType),
|
||||
defaultText
|
||||
)
|
||||
: '',
|
||||
textFont: textStyleModel.getFont(),
|
||||
fill: textStyleModel.getTextColor() || defaultColor
|
||||
});
|
||||
label.hoverStyle = {
|
||||
text: labelHoverModel.get('show')
|
||||
? zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'emphasis', lineData.dataType),
|
||||
defaultText
|
||||
)
|
||||
: '',
|
||||
textFont: textStyleHoverModel.getFont(),
|
||||
fill: textStyleHoverModel.getTextColor() || defaultColor
|
||||
};
|
||||
label.__textAlign = textStyleModel.get('align');
|
||||
label.__verticalAlign = textStyleModel.get('baseline');
|
||||
label.__position = labelModel.get('position');
|
||||
|
||||
label.ignore = !label.style.text && !label.hoverStyle.text;
|
||||
|
||||
graphic.setHoverStyle(this);
|
||||
};
|
||||
|
||||
lineProto.updateLayout = function (lineData, idx) {
|
||||
var points = lineData.getItemLayout(idx);
|
||||
var linePath = this.childOfName('line');
|
||||
setLinePoints(linePath.shape, points);
|
||||
linePath.dirty(true);
|
||||
};
|
||||
|
||||
lineProto.setLinePoints = function (points) {
|
||||
var linePath = this.childOfName('line');
|
||||
setLinePoints(linePath.shape, points);
|
||||
linePath.dirty();
|
||||
};
|
||||
|
||||
zrUtil.inherits(Line, graphic.Group);
|
||||
|
||||
return Line;
|
||||
});
|
||||
85
vendors/echarts/src/chart/helper/LineDraw.js
vendored
Normal file
85
vendors/echarts/src/chart/helper/LineDraw.js
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/LineDraw
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var LineGroup = require('./Line');
|
||||
|
||||
|
||||
function isPointNaN(pt) {
|
||||
return isNaN(pt[0]) || isNaN(pt[1]);
|
||||
}
|
||||
function lineNeedsDraw(pts) {
|
||||
return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
|
||||
}
|
||||
/**
|
||||
* @alias module:echarts/component/marker/LineDraw
|
||||
* @constructor
|
||||
*/
|
||||
function LineDraw(ctor) {
|
||||
this._ctor = ctor || LineGroup;
|
||||
this.group = new graphic.Group();
|
||||
}
|
||||
|
||||
var lineDrawProto = LineDraw.prototype;
|
||||
|
||||
/**
|
||||
* @param {module:echarts/data/List} lineData
|
||||
*/
|
||||
lineDrawProto.updateData = function (lineData) {
|
||||
|
||||
var oldLineData = this._lineData;
|
||||
var group = this.group;
|
||||
var LineCtor = this._ctor;
|
||||
|
||||
lineData.diff(oldLineData)
|
||||
.add(function (idx) {
|
||||
if (!lineNeedsDraw(lineData.getItemLayout(idx))) {
|
||||
return;
|
||||
}
|
||||
var lineGroup = new LineCtor(lineData, idx);
|
||||
|
||||
lineData.setItemGraphicEl(idx, lineGroup);
|
||||
|
||||
group.add(lineGroup);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var lineGroup = oldLineData.getItemGraphicEl(oldIdx);
|
||||
if (!lineNeedsDraw(lineData.getItemLayout(newIdx))) {
|
||||
group.remove(lineGroup);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lineGroup) {
|
||||
lineGroup = new LineCtor(lineData, newIdx);
|
||||
}
|
||||
else {
|
||||
lineGroup.updateData(lineData, newIdx);
|
||||
}
|
||||
|
||||
lineData.setItemGraphicEl(newIdx, lineGroup);
|
||||
|
||||
group.add(lineGroup);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
group.remove(oldLineData.getItemGraphicEl(idx));
|
||||
})
|
||||
.execute();
|
||||
|
||||
this._lineData = lineData;
|
||||
};
|
||||
|
||||
lineDrawProto.updateLayout = function () {
|
||||
var lineData = this._lineData;
|
||||
lineData.eachItemGraphicEl(function (el, idx) {
|
||||
el.updateLayout(lineData, idx);
|
||||
}, this);
|
||||
};
|
||||
|
||||
lineDrawProto.remove = function () {
|
||||
this.group.removeAll();
|
||||
};
|
||||
|
||||
return LineDraw;
|
||||
});
|
||||
52
vendors/echarts/src/chart/helper/LinePath.js
vendored
Normal file
52
vendors/echarts/src/chart/helper/LinePath.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Line path for bezier and straight line draw
|
||||
*/
|
||||
define(function (require) {
|
||||
var graphic = require('../../util/graphic');
|
||||
var vec2 = require('zrender/core/vector');
|
||||
|
||||
var straightLineProto = graphic.Line.prototype;
|
||||
var bezierCurveProto = graphic.BezierCurve.prototype;
|
||||
|
||||
function isLine(shape) {
|
||||
return shape.cpx1 == null || shape.cpy1 == null;
|
||||
}
|
||||
|
||||
return graphic.extendShape({
|
||||
|
||||
type: 'ec-line',
|
||||
|
||||
style: {
|
||||
stroke: '#000',
|
||||
fill: null
|
||||
},
|
||||
|
||||
shape: {
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: 0,
|
||||
y2: 0,
|
||||
percent: 1,
|
||||
cpx1: null,
|
||||
cpy1: null
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
(isLine(shape) ? straightLineProto : bezierCurveProto).buildPath(ctx, shape);
|
||||
},
|
||||
|
||||
pointAt: function (t) {
|
||||
return isLine(this.shape)
|
||||
? straightLineProto.pointAt.call(this, t)
|
||||
: bezierCurveProto.pointAt.call(this, t);
|
||||
},
|
||||
|
||||
tangentAt: function (t) {
|
||||
var shape = this.shape;
|
||||
var p = isLine(shape)
|
||||
? [shape.x2 - shape.x1, shape.y2 - shape.y1]
|
||||
: bezierCurveProto.tangentAt.call(this, t);
|
||||
return vec2.normalize(p, p);
|
||||
}
|
||||
});
|
||||
});
|
||||
265
vendors/echarts/src/chart/helper/Symbol.js
vendored
Normal file
265
vendors/echarts/src/chart/helper/Symbol.js
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/Symbol
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
var graphic = require('../../util/graphic');
|
||||
var numberUtil = require('../../util/number');
|
||||
|
||||
function normalizeSymbolSize(symbolSize) {
|
||||
if (!zrUtil.isArray(symbolSize)) {
|
||||
symbolSize = [+symbolSize, +symbolSize];
|
||||
}
|
||||
return symbolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @alias {module:echarts/chart/helper/Symbol}
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
*/
|
||||
function Symbol(data, idx) {
|
||||
graphic.Group.call(this);
|
||||
|
||||
this.updateData(data, idx);
|
||||
}
|
||||
|
||||
var symbolProto = Symbol.prototype;
|
||||
|
||||
function driftSymbol(dx, dy) {
|
||||
this.parent.drift(dx, dy);
|
||||
}
|
||||
|
||||
symbolProto._createSymbol = function (symbolType, data, idx) {
|
||||
// Remove paths created before
|
||||
this.removeAll();
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
|
||||
var symbolPath = symbolUtil.createSymbol(
|
||||
symbolType, -0.5, -0.5, 1, 1, color
|
||||
);
|
||||
|
||||
symbolPath.attr({
|
||||
z2: 100,
|
||||
culling: true,
|
||||
scale: [0, 0]
|
||||
});
|
||||
// Rewrite drift method
|
||||
symbolPath.drift = driftSymbol;
|
||||
|
||||
var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
|
||||
|
||||
graphic.initProps(symbolPath, {
|
||||
scale: size
|
||||
}, seriesModel, idx);
|
||||
|
||||
this._symbolType = symbolType;
|
||||
|
||||
this.add(symbolPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop animation
|
||||
* @param {boolean} toLastFrame
|
||||
*/
|
||||
symbolProto.stopSymbolAnimation = function (toLastFrame) {
|
||||
this.childAt(0).stopAnimation(toLastFrame);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get scale(aka, current symbol size).
|
||||
* Including the change caused by animation
|
||||
*/
|
||||
symbolProto.getScale = function () {
|
||||
return this.childAt(0).scale;
|
||||
};
|
||||
|
||||
/**
|
||||
* Highlight symbol
|
||||
*/
|
||||
symbolProto.highlight = function () {
|
||||
this.childAt(0).trigger('emphasis');
|
||||
};
|
||||
|
||||
/**
|
||||
* Downplay symbol
|
||||
*/
|
||||
symbolProto.downplay = function () {
|
||||
this.childAt(0).trigger('normal');
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} zlevel
|
||||
* @param {number} z
|
||||
*/
|
||||
symbolProto.setZ = function (zlevel, z) {
|
||||
var symbolPath = this.childAt(0);
|
||||
symbolPath.zlevel = zlevel;
|
||||
symbolPath.z = z;
|
||||
};
|
||||
|
||||
symbolProto.setDraggable = function (draggable) {
|
||||
var symbolPath = this.childAt(0);
|
||||
symbolPath.draggable = draggable;
|
||||
symbolPath.cursor = draggable ? 'move' : 'pointer';
|
||||
};
|
||||
|
||||
/**
|
||||
* Update symbol properties
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
*/
|
||||
symbolProto.updateData = function (data, idx) {
|
||||
var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
|
||||
var seriesModel = data.hostModel;
|
||||
var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
|
||||
if (symbolType !== this._symbolType) {
|
||||
this._createSymbol(symbolType, data, idx);
|
||||
}
|
||||
else {
|
||||
var symbolPath = this.childAt(0);
|
||||
graphic.updateProps(symbolPath, {
|
||||
scale: symbolSize
|
||||
}, seriesModel, idx);
|
||||
}
|
||||
this._updateCommon(data, idx, symbolSize);
|
||||
|
||||
this._seriesModel = seriesModel;
|
||||
};
|
||||
|
||||
// Update common properties
|
||||
var normalStyleAccessPath = ['itemStyle', 'normal'];
|
||||
var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
|
||||
var normalLabelAccessPath = ['label', 'normal'];
|
||||
var emphasisLabelAccessPath = ['label', 'emphasis'];
|
||||
|
||||
symbolProto._updateCommon = function (data, idx, symbolSize) {
|
||||
var symbolPath = this.childAt(0);
|
||||
var seriesModel = data.hostModel;
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
|
||||
// Reset style
|
||||
if (symbolPath.type !== 'image') {
|
||||
symbolPath.useStyle({
|
||||
strokeNoScale: true
|
||||
});
|
||||
}
|
||||
var elStyle = symbolPath.style;
|
||||
|
||||
var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();
|
||||
|
||||
symbolPath.rotation = (itemModel.getShallow('symbolRotate') || 0) * Math.PI / 180 || 0;
|
||||
|
||||
var symbolOffset = itemModel.getShallow('symbolOffset');
|
||||
if (symbolOffset) {
|
||||
var pos = symbolPath.position;
|
||||
pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
|
||||
pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
|
||||
}
|
||||
|
||||
symbolPath.setColor(color);
|
||||
|
||||
zrUtil.extend(
|
||||
elStyle,
|
||||
// Color must be excluded.
|
||||
// Because symbol provide setColor individually to set fill and stroke
|
||||
normalItemStyleModel.getItemStyle(['color'])
|
||||
);
|
||||
|
||||
var opacity = data.getItemVisual(idx, 'opacity');
|
||||
if (opacity != null) {
|
||||
elStyle.opacity = opacity;
|
||||
}
|
||||
|
||||
var labelModel = itemModel.getModel(normalLabelAccessPath);
|
||||
var hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
|
||||
|
||||
// Get last value dim
|
||||
var dimensions = data.dimensions.slice();
|
||||
var valueDim;
|
||||
var dataType;
|
||||
while (dimensions.length && (
|
||||
valueDim = dimensions.pop(),
|
||||
dataType = data.getDimensionInfo(valueDim).type,
|
||||
dataType === 'ordinal' || dataType === 'time'
|
||||
)) {} // jshint ignore:line
|
||||
|
||||
if (valueDim != null && labelModel.get('show')) {
|
||||
graphic.setText(elStyle, labelModel, color);
|
||||
elStyle.text = zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'normal'),
|
||||
data.get(valueDim, idx)
|
||||
);
|
||||
}
|
||||
else {
|
||||
elStyle.text = '';
|
||||
}
|
||||
|
||||
if (valueDim != null && hoverLabelModel.getShallow('show')) {
|
||||
graphic.setText(hoverStyle, hoverLabelModel, color);
|
||||
hoverStyle.text = zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(idx, 'emphasis'),
|
||||
data.get(valueDim, idx)
|
||||
);
|
||||
}
|
||||
else {
|
||||
hoverStyle.text = '';
|
||||
}
|
||||
|
||||
var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
|
||||
|
||||
symbolPath.off('mouseover')
|
||||
.off('mouseout')
|
||||
.off('emphasis')
|
||||
.off('normal');
|
||||
|
||||
graphic.setHoverStyle(symbolPath, hoverStyle);
|
||||
|
||||
if (itemModel.getShallow('hoverAnimation')) {
|
||||
var onEmphasis = function() {
|
||||
var ratio = size[1] / size[0];
|
||||
this.animateTo({
|
||||
scale: [
|
||||
Math.max(size[0] * 1.1, size[0] + 3),
|
||||
Math.max(size[1] * 1.1, size[1] + 3 * ratio)
|
||||
]
|
||||
}, 400, 'elasticOut');
|
||||
};
|
||||
var onNormal = function() {
|
||||
this.animateTo({
|
||||
scale: size
|
||||
}, 400, 'elasticOut');
|
||||
};
|
||||
symbolPath.on('mouseover', onEmphasis)
|
||||
.on('mouseout', onNormal)
|
||||
.on('emphasis', onEmphasis)
|
||||
.on('normal', onNormal);
|
||||
}
|
||||
};
|
||||
|
||||
symbolProto.fadeOut = function (cb) {
|
||||
var symbolPath = this.childAt(0);
|
||||
// Avoid trigger hoverAnimation when fading
|
||||
symbolPath.off('mouseover')
|
||||
.off('mouseout')
|
||||
.off('emphasis')
|
||||
.off('normal');
|
||||
// Not show text when animating
|
||||
symbolPath.style.text = '';
|
||||
graphic.updateProps(symbolPath, {
|
||||
scale: [0, 0]
|
||||
}, this._seriesModel, this.dataIndex, cb);
|
||||
};
|
||||
|
||||
zrUtil.inherits(Symbol, graphic.Group);
|
||||
|
||||
return Symbol;
|
||||
});
|
||||
111
vendors/echarts/src/chart/helper/SymbolDraw.js
vendored
Normal file
111
vendors/echarts/src/chart/helper/SymbolDraw.js
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/SymbolDraw
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var Symbol = require('./Symbol');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @alias module:echarts/chart/helper/SymbolDraw
|
||||
* @param {module:zrender/graphic/Group} [symbolCtor]
|
||||
*/
|
||||
function SymbolDraw(symbolCtor) {
|
||||
this.group = new graphic.Group();
|
||||
|
||||
this._symbolCtor = symbolCtor || Symbol;
|
||||
}
|
||||
|
||||
var symbolDrawProto = SymbolDraw.prototype;
|
||||
|
||||
function symbolNeedsDraw(data, idx, isIgnore) {
|
||||
var point = data.getItemLayout(idx);
|
||||
return point && !isNaN(point[0]) && !isNaN(point[1]) && !(isIgnore && isIgnore(idx))
|
||||
&& data.getItemVisual(idx, 'symbol') !== 'none';
|
||||
}
|
||||
/**
|
||||
* Update symbols draw by new data
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {Array.<boolean>} [isIgnore]
|
||||
*/
|
||||
symbolDrawProto.updateData = function (data, isIgnore) {
|
||||
var group = this.group;
|
||||
var seriesModel = data.hostModel;
|
||||
var oldData = this._data;
|
||||
|
||||
var SymbolCtor = this._symbolCtor;
|
||||
|
||||
data.diff(oldData)
|
||||
.add(function (newIdx) {
|
||||
var point = data.getItemLayout(newIdx);
|
||||
if (symbolNeedsDraw(data, newIdx, isIgnore)) {
|
||||
var symbolEl = new SymbolCtor(data, newIdx);
|
||||
symbolEl.attr('position', point);
|
||||
data.setItemGraphicEl(newIdx, symbolEl);
|
||||
group.add(symbolEl);
|
||||
}
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var symbolEl = oldData.getItemGraphicEl(oldIdx);
|
||||
var point = data.getItemLayout(newIdx);
|
||||
if (!symbolNeedsDraw(data, newIdx, isIgnore)) {
|
||||
group.remove(symbolEl);
|
||||
return;
|
||||
}
|
||||
if (!symbolEl) {
|
||||
symbolEl = new SymbolCtor(data, newIdx);
|
||||
symbolEl.attr('position', point);
|
||||
}
|
||||
else {
|
||||
symbolEl.updateData(data, newIdx);
|
||||
graphic.updateProps(symbolEl, {
|
||||
position: point
|
||||
}, seriesModel);
|
||||
}
|
||||
|
||||
// Add back
|
||||
group.add(symbolEl);
|
||||
|
||||
data.setItemGraphicEl(newIdx, symbolEl);
|
||||
})
|
||||
.remove(function (oldIdx) {
|
||||
var el = oldData.getItemGraphicEl(oldIdx);
|
||||
el && el.fadeOut(function () {
|
||||
group.remove(el);
|
||||
});
|
||||
})
|
||||
.execute();
|
||||
|
||||
this._data = data;
|
||||
};
|
||||
|
||||
symbolDrawProto.updateLayout = function () {
|
||||
var data = this._data;
|
||||
if (data) {
|
||||
// Not use animation
|
||||
data.eachItemGraphicEl(function (el, idx) {
|
||||
el.attr('position', data.getItemLayout(idx));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
symbolDrawProto.remove = function (enableAnimation) {
|
||||
var group = this.group;
|
||||
var data = this._data;
|
||||
if (data) {
|
||||
if (enableAnimation) {
|
||||
data.eachItemGraphicEl(function (el) {
|
||||
el.fadeOut(function () {
|
||||
group.remove(el);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
group.removeAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return SymbolDraw;
|
||||
});
|
||||
215
vendors/echarts/src/chart/helper/WhiskerBoxDraw.js
vendored
Normal file
215
vendors/echarts/src/chart/helper/WhiskerBoxDraw.js
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @module echarts/chart/helper/Symbol
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var graphic = require('../../util/graphic');
|
||||
var Path = require('zrender/graphic/Path');
|
||||
|
||||
var WhiskerPath = Path.extend({
|
||||
|
||||
type: 'whiskerInBox',
|
||||
|
||||
shape: {},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
for (var i in shape) {
|
||||
if (i.indexOf('ends') === 0) {
|
||||
var pts = shape[i];
|
||||
ctx.moveTo(pts[0][0], pts[0][1]);
|
||||
ctx.lineTo(pts[1][0], pts[1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @alias {module:echarts/chart/helper/WhiskerBox}
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
* @param {Function} styleUpdater
|
||||
* @param {boolean} isInit
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
*/
|
||||
function WhiskerBox(data, idx, styleUpdater, isInit) {
|
||||
graphic.Group.call(this);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @readOnly
|
||||
*/
|
||||
this.bodyIndex;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @readOnly
|
||||
*/
|
||||
this.whiskerIndex;
|
||||
|
||||
/**
|
||||
* @type {Function}
|
||||
*/
|
||||
this.styleUpdater = styleUpdater;
|
||||
|
||||
this._createContent(data, idx, isInit);
|
||||
|
||||
this.updateData(data, idx, isInit);
|
||||
|
||||
/**
|
||||
* Last series model.
|
||||
* @type {module:echarts/model/Series}
|
||||
*/
|
||||
this._seriesModel;
|
||||
}
|
||||
|
||||
var whiskerBoxProto = WhiskerBox.prototype;
|
||||
|
||||
whiskerBoxProto._createContent = function (data, idx, isInit) {
|
||||
var itemLayout = data.getItemLayout(idx);
|
||||
var constDim = itemLayout.chartLayout === 'horizontal' ? 1 : 0;
|
||||
var count = 0;
|
||||
|
||||
// Whisker element.
|
||||
this.add(new graphic.Polygon({
|
||||
shape: {
|
||||
points: isInit
|
||||
? transInit(itemLayout.bodyEnds, constDim, itemLayout)
|
||||
: itemLayout.bodyEnds
|
||||
},
|
||||
style: {strokeNoScale: true},
|
||||
z2: 100
|
||||
}));
|
||||
this.bodyIndex = count++;
|
||||
|
||||
// Box element.
|
||||
var whiskerEnds = zrUtil.map(itemLayout.whiskerEnds, function (ends) {
|
||||
return isInit ? transInit(ends, constDim, itemLayout) : ends;
|
||||
});
|
||||
this.add(new WhiskerPath({
|
||||
shape: makeWhiskerEndsShape(whiskerEnds),
|
||||
style: {strokeNoScale: true},
|
||||
z2: 100
|
||||
}));
|
||||
this.whiskerIndex = count++;
|
||||
};
|
||||
|
||||
function transInit(points, dim, itemLayout) {
|
||||
return zrUtil.map(points, function (point) {
|
||||
point = point.slice();
|
||||
point[dim] = itemLayout.initBaseline;
|
||||
return point;
|
||||
});
|
||||
}
|
||||
|
||||
function makeWhiskerEndsShape(whiskerEnds) {
|
||||
// zr animation only support 2-dim array.
|
||||
var shape = {};
|
||||
zrUtil.each(whiskerEnds, function (ends, i) {
|
||||
shape['ends' + i] = ends;
|
||||
});
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update symbol properties
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {number} idx
|
||||
*/
|
||||
whiskerBoxProto.updateData = function (data, idx, isInit) {
|
||||
var seriesModel = this._seriesModel = data.hostModel;
|
||||
var itemLayout = data.getItemLayout(idx);
|
||||
var updateMethod = graphic[isInit ? 'initProps' : 'updateProps'];
|
||||
// this.childAt(this.bodyIndex).stopAnimation(true);
|
||||
// this.childAt(this.whiskerIndex).stopAnimation(true);
|
||||
updateMethod(
|
||||
this.childAt(this.bodyIndex),
|
||||
{shape: {points: itemLayout.bodyEnds}},
|
||||
seriesModel, idx
|
||||
);
|
||||
updateMethod(
|
||||
this.childAt(this.whiskerIndex),
|
||||
{shape: makeWhiskerEndsShape(itemLayout.whiskerEnds)},
|
||||
seriesModel, idx
|
||||
);
|
||||
|
||||
this.styleUpdater.call(null, this, data, idx);
|
||||
};
|
||||
|
||||
zrUtil.inherits(WhiskerBox, graphic.Group);
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @alias module:echarts/chart/helper/WhiskerBoxDraw
|
||||
*/
|
||||
function WhiskerBoxDraw(styleUpdater) {
|
||||
this.group = new graphic.Group();
|
||||
this.styleUpdater = styleUpdater;
|
||||
}
|
||||
|
||||
var whiskerBoxDrawProto = WhiskerBoxDraw.prototype;
|
||||
|
||||
/**
|
||||
* Update symbols draw by new data
|
||||
* @param {module:echarts/data/List} data
|
||||
*/
|
||||
whiskerBoxDrawProto.updateData = function (data) {
|
||||
var group = this.group;
|
||||
var oldData = this._data;
|
||||
var styleUpdater = this.styleUpdater;
|
||||
|
||||
data.diff(oldData)
|
||||
.add(function (newIdx) {
|
||||
if (data.hasValue(newIdx)) {
|
||||
var symbolEl = new WhiskerBox(data, newIdx, styleUpdater, true);
|
||||
data.setItemGraphicEl(newIdx, symbolEl);
|
||||
group.add(symbolEl);
|
||||
}
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var symbolEl = oldData.getItemGraphicEl(oldIdx);
|
||||
|
||||
// Empty data
|
||||
if (!data.hasValue(newIdx)) {
|
||||
group.remove(symbolEl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!symbolEl) {
|
||||
symbolEl = new WhiskerBox(data, newIdx, styleUpdater);
|
||||
}
|
||||
else {
|
||||
symbolEl.updateData(data, newIdx);
|
||||
}
|
||||
|
||||
// Add back
|
||||
group.add(symbolEl);
|
||||
|
||||
data.setItemGraphicEl(newIdx, symbolEl);
|
||||
})
|
||||
.remove(function (oldIdx) {
|
||||
var el = oldData.getItemGraphicEl(oldIdx);
|
||||
el && group.remove(el);
|
||||
})
|
||||
.execute();
|
||||
|
||||
this._data = data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove symbols.
|
||||
* @param {module:echarts/data/List} data
|
||||
*/
|
||||
whiskerBoxDrawProto.remove = function () {
|
||||
var group = this.group;
|
||||
var data = this._data;
|
||||
this._data = null;
|
||||
data && data.eachItemGraphicEl(function (el) {
|
||||
el && group.remove(el);
|
||||
});
|
||||
};
|
||||
|
||||
return WhiskerBoxDraw;
|
||||
});
|
||||
68
vendors/echarts/src/chart/helper/createGraphFromNodeEdge.js
vendored
Normal file
68
vendors/echarts/src/chart/helper/createGraphFromNodeEdge.js
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
define(function (require) {
|
||||
|
||||
var List = require('../../data/List');
|
||||
var Graph = require('../../data/Graph');
|
||||
var linkList = require('../../data/helper/linkList');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
var CoordinateSystem = require('../../CoordinateSystem');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var createListFromArray = require('./createListFromArray');
|
||||
|
||||
return function (nodes, edges, hostModel, directed, beforeLink) {
|
||||
var graph = new Graph(directed);
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
graph.addNode(zrUtil.retrieve(
|
||||
// Id, name, dataIndex
|
||||
nodes[i].id, nodes[i].name, i
|
||||
), i);
|
||||
}
|
||||
|
||||
var linkNameList = [];
|
||||
var validEdges = [];
|
||||
for (var i = 0; i < edges.length; i++) {
|
||||
var link = edges[i];
|
||||
var source = link.source;
|
||||
var target = link.target;
|
||||
// addEdge may fail when source or target not exists
|
||||
if (graph.addEdge(source, target, i)) {
|
||||
validEdges.push(link);
|
||||
linkNameList.push(zrUtil.retrieve(link.id, source + ' > ' + target));
|
||||
}
|
||||
}
|
||||
|
||||
var coordSys = hostModel.get('coordinateSystem');
|
||||
var nodeData;
|
||||
if (coordSys === 'cartesian2d' || coordSys === 'polar') {
|
||||
nodeData = createListFromArray(nodes, hostModel, hostModel.ecModel);
|
||||
}
|
||||
else {
|
||||
// FIXME
|
||||
var coordSysCtor = CoordinateSystem.get(coordSys);
|
||||
// FIXME
|
||||
var dimensionNames = completeDimensions(
|
||||
((coordSysCtor && coordSysCtor.type !== 'view') ? (coordSysCtor.dimensions || []) : []).concat(['value']),
|
||||
nodes
|
||||
);
|
||||
nodeData = new List(dimensionNames, hostModel);
|
||||
nodeData.initData(nodes);
|
||||
}
|
||||
|
||||
var edgeData = new List(['value'], hostModel);
|
||||
edgeData.initData(validEdges, linkNameList);
|
||||
|
||||
beforeLink && beforeLink(nodeData, edgeData);
|
||||
|
||||
linkList({
|
||||
mainData: nodeData,
|
||||
struct: graph,
|
||||
structAttr: 'graph',
|
||||
datas: {node: nodeData, edge: edgeData},
|
||||
datasAttr: {node: 'data', edge: 'edgeData'}
|
||||
});
|
||||
|
||||
// Update dataIndex of nodes and edges because invalid edge may be removed
|
||||
graph.update();
|
||||
|
||||
return graph;
|
||||
};
|
||||
});
|
||||
92
vendors/echarts/src/chart/helper/createGraphFromNodeMatrix.js
vendored
Normal file
92
vendors/echarts/src/chart/helper/createGraphFromNodeMatrix.js
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
define(function (require) {
|
||||
|
||||
var List = require('../../data/List');
|
||||
var Graph = require('../../data/Graph');
|
||||
var linkList = require('../../data/helper/linkList');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
var CoordinateSystem = require('../../CoordinateSystem');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var createListFromArray = require('./createListFromArray');
|
||||
|
||||
/**
|
||||
* 从邻接矩阵生成
|
||||
* ```
|
||||
* TARGET
|
||||
* -1--2--3--4--5-
|
||||
* 1| x x x x x
|
||||
* 2| x x x x x
|
||||
* 3| x x x x x SOURCE
|
||||
* 4| x x x x x
|
||||
* 5| x x x x x
|
||||
* ```
|
||||
*
|
||||
* @param {Array.<Object>} nodes 节点信息
|
||||
* @param {Array} matrix 邻接矩阵
|
||||
* @param {module:echarts/model/Series}
|
||||
* @param {boolean} directed 是否是有向图
|
||||
* @return {module:echarts/data/Graph}
|
||||
*/
|
||||
return function (nodes, matrix, hostModel, directed) {
|
||||
var graph = new Graph(directed);
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
graph.addNode(zrUtil.retrieve(
|
||||
// Id, name, dataIndex
|
||||
nodes[i].id, nodes[i].name, i
|
||||
), i);
|
||||
}
|
||||
|
||||
var size = matrix.length;
|
||||
var links = [];
|
||||
var linkCount = 0;
|
||||
for (var i = 0; i < size; i++) {
|
||||
for (var j = 0; j < size; j++) {
|
||||
var val = matrix[i][j];
|
||||
if (val === 0) {
|
||||
continue;
|
||||
}
|
||||
var n1 = graph.nodes[i];
|
||||
var n2 = graph.nodes[j];
|
||||
var edge = graph.addEdge(n1, n2, linkCount);
|
||||
if (edge) {
|
||||
linkCount++;
|
||||
links.push({
|
||||
value: val
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var coordSys = hostModel.get('coordinateSystem');
|
||||
var nodeData;
|
||||
if (coordSys === 'cartesian2d' || coordSys === 'polar') {
|
||||
nodeData = createListFromArray(nodes, hostModel, hostModel.ecModel);
|
||||
}
|
||||
else {
|
||||
// FIXME
|
||||
var coordSysCtor = CoordinateSystem.get(coordSys);
|
||||
// FIXME
|
||||
var dimensionNames = completeDimensions(
|
||||
((coordSysCtor && coordSysCtor.type !== 'view') ? (coordSysCtor.dimensions || []) : []).concat(['value']),
|
||||
nodes
|
||||
);
|
||||
nodeData = new List(dimensionNames, hostModel);
|
||||
nodeData.initData(nodes);
|
||||
}
|
||||
var edgeData = new List(['value'], hostModel);
|
||||
|
||||
edgeData.initData(links);
|
||||
|
||||
linkList({
|
||||
mainData: nodeData,
|
||||
struct: graph,
|
||||
structAttr: 'graph',
|
||||
datas: {node: nodeData, edge: edgeData},
|
||||
datasAttr: {node: 'data', edge: 'edgeData'}
|
||||
});
|
||||
|
||||
// Update dataIndex of nodes and edges because invalid edge may be removed
|
||||
graph.update();
|
||||
|
||||
return graph;
|
||||
};
|
||||
});
|
||||
229
vendors/echarts/src/chart/helper/createListFromArray.js
vendored
Normal file
229
vendors/echarts/src/chart/helper/createListFromArray.js
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var List = require('../../data/List');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var modelUtil = require('../../util/model');
|
||||
var CoordinateSystem = require('../../CoordinateSystem');
|
||||
var getDataItemValue = modelUtil.getDataItemValue;
|
||||
var converDataValue = modelUtil.converDataValue;
|
||||
|
||||
function firstDataNotNull(data) {
|
||||
var i = 0;
|
||||
while (i < data.length && data[i] == null) {
|
||||
i++;
|
||||
}
|
||||
return data[i];
|
||||
}
|
||||
function ifNeedCompleteOrdinalData(data) {
|
||||
var sampleItem = firstDataNotNull(data);
|
||||
return sampleItem != null
|
||||
&& !zrUtil.isArray(getDataItemValue(sampleItem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a list from option data
|
||||
*/
|
||||
function createListFromArray(data, seriesModel, ecModel) {
|
||||
// If data is undefined
|
||||
data = data || [];
|
||||
|
||||
if (!zrUtil.isArray(data)) {
|
||||
throw new Error('Invalid data.');
|
||||
}
|
||||
|
||||
var coordSysName = seriesModel.get('coordinateSystem');
|
||||
var creator = creators[coordSysName];
|
||||
var registeredCoordSys = CoordinateSystem.get(coordSysName);
|
||||
// FIXME
|
||||
var result = creator && creator(data, seriesModel, ecModel);
|
||||
var dimensions = result && result.dimensions;
|
||||
if (!dimensions) {
|
||||
// Get dimensions from registered coordinate system
|
||||
dimensions = (registeredCoordSys && registeredCoordSys.dimensions) || ['x', 'y'];
|
||||
dimensions = completeDimensions(dimensions, data, dimensions.concat(['value']));
|
||||
}
|
||||
var categoryAxisModel = result && result.categoryAxisModel;
|
||||
var categories;
|
||||
|
||||
var categoryDimIndex = dimensions[0].type === 'ordinal'
|
||||
? 0 : (dimensions[1].type === 'ordinal' ? 1 : -1);
|
||||
|
||||
var list = new List(dimensions, seriesModel);
|
||||
|
||||
var nameList = createNameList(result, data);
|
||||
|
||||
var dimValueGetter = (categoryAxisModel && ifNeedCompleteOrdinalData(data))
|
||||
? function (itemOpt, dimName, dataIndex, dimIndex) {
|
||||
// Use dataIndex as ordinal value in categoryAxis
|
||||
return dimIndex === categoryDimIndex
|
||||
? dataIndex
|
||||
: converDataValue(getDataItemValue(itemOpt), dimensions[dimIndex]);
|
||||
}
|
||||
: function (itemOpt, dimName, dataIndex, dimIndex) {
|
||||
var value = getDataItemValue(itemOpt);
|
||||
var val = converDataValue(value && value[dimIndex], dimensions[dimIndex]);
|
||||
if (categoryDimIndex === dimIndex) {
|
||||
// If given value is a category string
|
||||
if (typeof val === 'string') {
|
||||
// Lazy get categories
|
||||
categories = categories || categoryAxisModel.getCategories();
|
||||
val = zrUtil.indexOf(categories, val);
|
||||
if (val < 0 && !isNaN(val)) {
|
||||
// In case some one write '1', '2' istead of 1, 2
|
||||
val = +val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
list.initData(data, nameList, dimValueGetter);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function isStackable(axisType) {
|
||||
return axisType !== 'category' && axisType !== 'time';
|
||||
}
|
||||
|
||||
function getDimTypeByAxis(axisType) {
|
||||
return axisType === 'category'
|
||||
? 'ordinal'
|
||||
: axisType === 'time'
|
||||
? 'time'
|
||||
: 'float';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creaters for each coord system.
|
||||
* @return {Object} {dimensions, categoryAxisModel};
|
||||
*/
|
||||
var creators = {
|
||||
|
||||
cartesian2d: function (data, seriesModel, ecModel) {
|
||||
var xAxisModel = ecModel.getComponent('xAxis', seriesModel.get('xAxisIndex'));
|
||||
var yAxisModel = ecModel.getComponent('yAxis', seriesModel.get('yAxisIndex'));
|
||||
if (!xAxisModel || !yAxisModel) {
|
||||
throw new Error('Axis option not found');
|
||||
}
|
||||
|
||||
var xAxisType = xAxisModel.get('type');
|
||||
var yAxisType = yAxisModel.get('type');
|
||||
|
||||
var dimensions = [
|
||||
{
|
||||
name: 'x',
|
||||
type: getDimTypeByAxis(xAxisType),
|
||||
stackable: isStackable(xAxisType)
|
||||
},
|
||||
{
|
||||
name: 'y',
|
||||
// If two category axes
|
||||
type: getDimTypeByAxis(yAxisType),
|
||||
stackable: isStackable(yAxisType)
|
||||
}
|
||||
];
|
||||
|
||||
var isXAxisCateogry = xAxisType === 'category';
|
||||
|
||||
completeDimensions(dimensions, data, ['x', 'y', 'z']);
|
||||
|
||||
return {
|
||||
dimensions: dimensions,
|
||||
categoryIndex: isXAxisCateogry ? 0 : 1,
|
||||
categoryAxisModel: isXAxisCateogry
|
||||
? xAxisModel
|
||||
: (yAxisType === 'category' ? yAxisModel : null)
|
||||
};
|
||||
},
|
||||
|
||||
polar: function (data, seriesModel, ecModel) {
|
||||
var polarIndex = seriesModel.get('polarIndex') || 0;
|
||||
|
||||
var axisFinder = function (axisModel) {
|
||||
return axisModel.get('polarIndex') === polarIndex;
|
||||
};
|
||||
|
||||
var angleAxisModel = ecModel.findComponents({
|
||||
mainType: 'angleAxis', filter: axisFinder
|
||||
})[0];
|
||||
var radiusAxisModel = ecModel.findComponents({
|
||||
mainType: 'radiusAxis', filter: axisFinder
|
||||
})[0];
|
||||
|
||||
if (!angleAxisModel || !radiusAxisModel) {
|
||||
throw new Error('Axis option not found');
|
||||
}
|
||||
|
||||
var radiusAxisType = radiusAxisModel.get('type');
|
||||
var angleAxisType = angleAxisModel.get('type');
|
||||
|
||||
var dimensions = [
|
||||
{
|
||||
name: 'radius',
|
||||
type: getDimTypeByAxis(radiusAxisType),
|
||||
stackable: isStackable(radiusAxisType)
|
||||
},
|
||||
{
|
||||
name: 'angle',
|
||||
type: getDimTypeByAxis(angleAxisType),
|
||||
stackable: isStackable(angleAxisType)
|
||||
}
|
||||
];
|
||||
var isAngleAxisCateogry = angleAxisType === 'category';
|
||||
|
||||
completeDimensions(dimensions, data, ['radius', 'angle', 'value']);
|
||||
|
||||
return {
|
||||
dimensions: dimensions,
|
||||
categoryIndex: isAngleAxisCateogry ? 1 : 0,
|
||||
categoryAxisModel: isAngleAxisCateogry
|
||||
? angleAxisModel
|
||||
: (radiusAxisType === 'category' ? radiusAxisModel : null)
|
||||
};
|
||||
},
|
||||
|
||||
geo: function (data, seriesModel, ecModel) {
|
||||
// TODO Region
|
||||
// 多个散点图系列在同一个地区的时候
|
||||
return {
|
||||
dimensions: completeDimensions([
|
||||
{name: 'lng'},
|
||||
{name: 'lat'}
|
||||
], data, ['lng', 'lat', 'value'])
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function createNameList(result, data) {
|
||||
var nameList = [];
|
||||
|
||||
if (result && result.categoryAxisModel) {
|
||||
// FIXME Two category axis
|
||||
var categories = result.categoryAxisModel.getCategories();
|
||||
if (categories) {
|
||||
var dataLen = data.length;
|
||||
// Ordered data is given explicitly like
|
||||
// [[3, 0.2], [1, 0.3], [2, 0.15]]
|
||||
// or given scatter data,
|
||||
// pick the category
|
||||
if (zrUtil.isArray(data[0]) && data[0].length > 1) {
|
||||
nameList = [];
|
||||
for (var i = 0; i < dataLen; i++) {
|
||||
nameList[i] = categories[data[i][result.categoryIndex || 0]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
nameList = categories.slice(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nameList;
|
||||
}
|
||||
|
||||
return createListFromArray;
|
||||
|
||||
});
|
||||
140
vendors/echarts/src/chart/helper/whiskerBoxCommon.js
vendored
Normal file
140
vendors/echarts/src/chart/helper/whiskerBoxCommon.js
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var List = require('../../data/List');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
var WhiskerBoxDraw = require('../helper/WhiskerBoxDraw');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
function getItemValue(item) {
|
||||
return item.value == null ? item : item.value;
|
||||
}
|
||||
|
||||
var seriesModelMixin = {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
_baseAxisDim: null,
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getInitialData: function (option, ecModel) {
|
||||
// When both types of xAxis and yAxis are 'value', layout is
|
||||
// needed to be specified by user. Otherwise, layout can be
|
||||
// judged by which axis is category.
|
||||
|
||||
var categories;
|
||||
|
||||
var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex'));
|
||||
var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex'));
|
||||
var xAxisType = xAxisModel.get('type');
|
||||
var yAxisType = yAxisModel.get('type');
|
||||
var addOrdinal;
|
||||
|
||||
// FIXME
|
||||
// 考虑时间轴
|
||||
|
||||
if (xAxisType === 'category') {
|
||||
option.layout = 'horizontal';
|
||||
categories = xAxisModel.getCategories();
|
||||
addOrdinal = true;
|
||||
}
|
||||
else if (yAxisType === 'category') {
|
||||
option.layout = 'vertical';
|
||||
categories = yAxisModel.getCategories();
|
||||
addOrdinal = true;
|
||||
}
|
||||
else {
|
||||
option.layout = option.layout || 'horizontal';
|
||||
}
|
||||
|
||||
this._baseAxisDim = option.layout === 'horizontal' ? 'x' : 'y';
|
||||
|
||||
var data = option.data;
|
||||
var dimensions = this.dimensions = ['base'].concat(this.valueDimensions);
|
||||
completeDimensions(dimensions, data);
|
||||
|
||||
var list = new List(dimensions, this);
|
||||
list.initData(data, categories ? categories.slice() : null, function (dataItem, dimName, idx, dimIdx) {
|
||||
var value = getItemValue(dataItem);
|
||||
return addOrdinal ? (dimName === 'base' ? idx : value[dimIdx - 1]) : value[dimIdx];
|
||||
});
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
/**
|
||||
* Used by Gird.
|
||||
* @param {string} axisDim 'x' or 'y'
|
||||
* @return {Array.<string>} dimensions on the axis.
|
||||
*/
|
||||
coordDimToDataDim: function (axisDim) {
|
||||
var dims = this.valueDimensions.slice();
|
||||
var baseDim = ['base'];
|
||||
var map = {
|
||||
horizontal: {x: baseDim, y: dims},
|
||||
vertical: {x: dims, y: baseDim}
|
||||
};
|
||||
return map[this.get('layout')][axisDim];
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @param {string|number} dataDim
|
||||
* @return {string} coord dimension
|
||||
*/
|
||||
dataDimToCoordDim: function (dataDim) {
|
||||
var dim;
|
||||
|
||||
zrUtil.each(['x', 'y'], function (coordDim, index) {
|
||||
var dataDims = this.coordDimToDataDim(coordDim);
|
||||
if (zrUtil.indexOf(dataDims, dataDim) >= 0) {
|
||||
dim = coordDim;
|
||||
}
|
||||
}, this);
|
||||
|
||||
return dim;
|
||||
},
|
||||
|
||||
/**
|
||||
* If horizontal, base axis is x, otherwise y.
|
||||
* @override
|
||||
*/
|
||||
getBaseAxis: function () {
|
||||
var dim = this._baseAxisDim;
|
||||
return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis;
|
||||
}
|
||||
};
|
||||
|
||||
var viewMixin = {
|
||||
|
||||
init: function () {
|
||||
/**
|
||||
* Old data.
|
||||
* @private
|
||||
* @type {module:echarts/chart/helper/WhiskerBoxDraw}
|
||||
*/
|
||||
var whiskerBoxDraw = this._whiskerBoxDraw = new WhiskerBoxDraw(
|
||||
this.getStyleUpdater()
|
||||
);
|
||||
this.group.add(whiskerBoxDraw.group);
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
this._whiskerBoxDraw.updateData(seriesModel.getData());
|
||||
},
|
||||
|
||||
remove: function (ecModel) {
|
||||
this._whiskerBoxDraw.remove();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
seriesModelMixin: seriesModelMixin,
|
||||
viewMixin: viewMixin
|
||||
};
|
||||
});
|
||||
23
vendors/echarts/src/chart/line.js
vendored
Normal file
23
vendors/echarts/src/chart/line.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./line/LineSeries');
|
||||
require('./line/LineView');
|
||||
|
||||
echarts.registerVisualCoding('chart', zrUtil.curry(
|
||||
require('../visual/symbol'), 'line', 'circle', 'line'
|
||||
));
|
||||
echarts.registerLayout(zrUtil.curry(
|
||||
require('../layout/points'), 'line'
|
||||
));
|
||||
|
||||
// Down sample after filter
|
||||
echarts.registerProcessor('statistic', zrUtil.curry(
|
||||
require('../processor/dataSample'), 'line'
|
||||
));
|
||||
|
||||
// In case developer forget to include grid component
|
||||
require('../component/grid');
|
||||
});
|
||||
74
vendors/echarts/src/chart/line/LineSeries.js
vendored
Normal file
74
vendors/echarts/src/chart/line/LineSeries.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var createListFromArray = require('../helper/createListFromArray');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
|
||||
return SeriesModel.extend({
|
||||
|
||||
type: 'series.line',
|
||||
|
||||
dependencies: ['grid', 'polar'],
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
return createListFromArray(option.data, this, ecModel);
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
coordinateSystem: 'cartesian2d',
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
// stack: null
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
polarIndex: 0,
|
||||
|
||||
// If clip the overflow value
|
||||
clipOverflow: true,
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
position: 'top'
|
||||
}
|
||||
},
|
||||
// itemStyle: {
|
||||
// normal: {},
|
||||
// emphasis: {}
|
||||
// },
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 2,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
// areaStyle: {},
|
||||
|
||||
smooth: false,
|
||||
smoothMonotone: null,
|
||||
// 拐点图形类型
|
||||
symbol: 'emptyCircle',
|
||||
// 拐点图形大小
|
||||
symbolSize: 4,
|
||||
// 拐点图形旋转控制
|
||||
symbolRotate: null,
|
||||
|
||||
// 是否显示 symbol, 只有在 tooltip hover 的时候显示
|
||||
showSymbol: true,
|
||||
// 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
|
||||
showAllSymbol: false,
|
||||
|
||||
// 是否连接断点
|
||||
connectNulls: false,
|
||||
|
||||
// 数据过滤,'average', 'max', 'min', 'sum'
|
||||
sampling: 'none',
|
||||
|
||||
animationEasing: 'linear'
|
||||
}
|
||||
});
|
||||
});
|
||||
550
vendors/echarts/src/chart/line/LineView.js
vendored
Normal file
550
vendors/echarts/src/chart/line/LineView.js
vendored
Normal file
@@ -0,0 +1,550 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var SymbolDraw = require('../helper/SymbolDraw');
|
||||
var Symbol = require('../helper/Symbol');
|
||||
var lineAnimationDiff = require('./lineAnimationDiff');
|
||||
var graphic = require('../../util/graphic');
|
||||
|
||||
var polyHelper = require('./poly');
|
||||
|
||||
var ChartView = require('../../view/Chart');
|
||||
|
||||
function isPointsSame(points1, points2) {
|
||||
if (points1.length !== points2.length) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < points1.length; i++) {
|
||||
var p1 = points1[i];
|
||||
var p2 = points2[i];
|
||||
if (p1[0] !== p2[0] || p1[1] !== p2[1]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSmooth(smooth) {
|
||||
return typeof (smooth) === 'number' ? smooth : (smooth ? 0.3 : 0);
|
||||
}
|
||||
|
||||
function getAxisExtentWithGap(axis) {
|
||||
var extent = axis.getGlobalExtent();
|
||||
if (axis.onBand) {
|
||||
// Remove extra 1px to avoid line miter in clipped edge
|
||||
var halfBandWidth = axis.getBandWidth() / 2 - 1;
|
||||
var dir = extent[1] > extent[0] ? 1 : -1;
|
||||
extent[0] += dir * halfBandWidth;
|
||||
extent[1] -= dir * halfBandWidth;
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
function sign(val) {
|
||||
return val >= 0 ? 1 : -1;
|
||||
}
|
||||
/**
|
||||
* @param {module:echarts/coord/cartesian/Cartesian2D|module:echarts/coord/polar/Polar} coordSys
|
||||
* @param {module:echarts/data/List} data
|
||||
* @param {Array.<Array.<number>>} points
|
||||
* @private
|
||||
*/
|
||||
function getStackedOnPoints(coordSys, data) {
|
||||
var baseAxis = coordSys.getBaseAxis();
|
||||
var valueAxis = coordSys.getOtherAxis(baseAxis);
|
||||
var valueStart = baseAxis.onZero
|
||||
? 0 : valueAxis.scale.getExtent()[0];
|
||||
|
||||
var valueDim = valueAxis.dim;
|
||||
|
||||
var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0;
|
||||
|
||||
return data.mapArray([valueDim], function (val, idx) {
|
||||
var stackedOnSameSign;
|
||||
var stackedOn = data.stackedOn;
|
||||
// Find first stacked value with same sign
|
||||
while (stackedOn &&
|
||||
sign(stackedOn.get(valueDim, idx)) === sign(val)
|
||||
) {
|
||||
stackedOnSameSign = stackedOn;
|
||||
break;
|
||||
}
|
||||
var stackedData = [];
|
||||
stackedData[baseDataOffset] = data.get(baseAxis.dim, idx);
|
||||
stackedData[1 - baseDataOffset] = stackedOnSameSign
|
||||
? stackedOnSameSign.get(valueDim, idx, true) : valueStart;
|
||||
|
||||
return coordSys.dataToPoint(stackedData);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function queryDataIndex(data, payload) {
|
||||
if (payload.dataIndex != null) {
|
||||
return payload.dataIndex;
|
||||
}
|
||||
else if (payload.name != null) {
|
||||
return data.indexOfName(payload.name);
|
||||
}
|
||||
}
|
||||
|
||||
function createGridClipShape(cartesian, hasAnimation, seriesModel) {
|
||||
var xExtent = getAxisExtentWithGap(cartesian.getAxis('x'));
|
||||
var yExtent = getAxisExtentWithGap(cartesian.getAxis('y'));
|
||||
var isHorizontal = cartesian.getBaseAxis().isHorizontal();
|
||||
|
||||
var x = Math.min(xExtent[0], xExtent[1]);
|
||||
var y = Math.min(yExtent[0], yExtent[1]);
|
||||
var width = Math.max(xExtent[0], xExtent[1]) - x;
|
||||
var height = Math.max(yExtent[0], yExtent[1]) - y;
|
||||
var lineWidth = seriesModel.get('lineStyle.normal.width') || 2;
|
||||
// Expand clip shape to avoid clipping when line value exceeds axis
|
||||
var expandSize = seriesModel.get('clipOverflow') ? lineWidth / 2 : Math.max(width, height);
|
||||
if (isHorizontal) {
|
||||
y -= expandSize;
|
||||
height += expandSize * 2;
|
||||
}
|
||||
else {
|
||||
x -= expandSize;
|
||||
width += expandSize * 2;
|
||||
}
|
||||
|
||||
var clipPath = new graphic.Rect({
|
||||
shape: {
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
});
|
||||
|
||||
if (hasAnimation) {
|
||||
clipPath.shape[isHorizontal ? 'width' : 'height'] = 0;
|
||||
graphic.initProps(clipPath, {
|
||||
shape: {
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
}, seriesModel);
|
||||
}
|
||||
|
||||
return clipPath;
|
||||
}
|
||||
|
||||
function createPolarClipShape(polar, hasAnimation, seriesModel) {
|
||||
var angleAxis = polar.getAngleAxis();
|
||||
var radiusAxis = polar.getRadiusAxis();
|
||||
|
||||
var radiusExtent = radiusAxis.getExtent();
|
||||
var angleExtent = angleAxis.getExtent();
|
||||
|
||||
var RADIAN = Math.PI / 180;
|
||||
|
||||
var clipPath = new graphic.Sector({
|
||||
shape: {
|
||||
cx: polar.cx,
|
||||
cy: polar.cy,
|
||||
r0: radiusExtent[0],
|
||||
r: radiusExtent[1],
|
||||
startAngle: -angleExtent[0] * RADIAN,
|
||||
endAngle: -angleExtent[1] * RADIAN,
|
||||
clockwise: angleAxis.inverse
|
||||
}
|
||||
});
|
||||
|
||||
if (hasAnimation) {
|
||||
clipPath.shape.endAngle = -angleExtent[0] * RADIAN;
|
||||
graphic.initProps(clipPath, {
|
||||
shape: {
|
||||
endAngle: -angleExtent[1] * RADIAN
|
||||
}
|
||||
}, seriesModel);
|
||||
}
|
||||
|
||||
return clipPath;
|
||||
}
|
||||
|
||||
function createClipShape(coordSys, hasAnimation, seriesModel) {
|
||||
return coordSys.type === 'polar'
|
||||
? createPolarClipShape(coordSys, hasAnimation, seriesModel)
|
||||
: createGridClipShape(coordSys, hasAnimation, seriesModel);
|
||||
}
|
||||
|
||||
return ChartView.extend({
|
||||
|
||||
type: 'line',
|
||||
|
||||
init: function () {
|
||||
var lineGroup = new graphic.Group();
|
||||
|
||||
var symbolDraw = new SymbolDraw();
|
||||
this.group.add(symbolDraw.group);
|
||||
|
||||
this._symbolDraw = symbolDraw;
|
||||
this._lineGroup = lineGroup;
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var group = this.group;
|
||||
var data = seriesModel.getData();
|
||||
var lineStyleModel = seriesModel.getModel('lineStyle.normal');
|
||||
var areaStyleModel = seriesModel.getModel('areaStyle.normal');
|
||||
|
||||
var points = data.mapArray(data.getItemLayout, true);
|
||||
|
||||
var isCoordSysPolar = coordSys.type === 'polar';
|
||||
var prevCoordSys = this._coordSys;
|
||||
|
||||
var symbolDraw = this._symbolDraw;
|
||||
var polyline = this._polyline;
|
||||
var polygon = this._polygon;
|
||||
|
||||
var lineGroup = this._lineGroup;
|
||||
|
||||
var hasAnimation = seriesModel.get('animation');
|
||||
|
||||
var isAreaChart = !areaStyleModel.isEmpty();
|
||||
var stackedOnPoints = getStackedOnPoints(coordSys, data);
|
||||
|
||||
var showSymbol = seriesModel.get('showSymbol');
|
||||
|
||||
var isSymbolIgnore = showSymbol && !isCoordSysPolar && !seriesModel.get('showAllSymbol')
|
||||
&& this._getSymbolIgnoreFunc(data, coordSys);
|
||||
|
||||
// Remove temporary symbols
|
||||
var oldData = this._data;
|
||||
oldData && oldData.eachItemGraphicEl(function (el, idx) {
|
||||
if (el.__temp) {
|
||||
group.remove(el);
|
||||
oldData.setItemGraphicEl(idx, null);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove previous created symbols if showSymbol changed to false
|
||||
if (!showSymbol) {
|
||||
symbolDraw.remove();
|
||||
}
|
||||
|
||||
group.add(lineGroup);
|
||||
|
||||
// Initialization animation or coordinate system changed
|
||||
if (
|
||||
!(polyline && prevCoordSys.type === coordSys.type)
|
||||
) {
|
||||
showSymbol && symbolDraw.updateData(data, isSymbolIgnore);
|
||||
|
||||
polyline = this._newPolyline(points, coordSys, hasAnimation);
|
||||
if (isAreaChart) {
|
||||
polygon = this._newPolygon(
|
||||
points, stackedOnPoints,
|
||||
coordSys, hasAnimation
|
||||
);
|
||||
}
|
||||
lineGroup.setClipPath(createClipShape(coordSys, true, seriesModel));
|
||||
}
|
||||
else {
|
||||
if (isAreaChart && !polygon) {
|
||||
// If areaStyle is added
|
||||
polygon = this._newPolygon(
|
||||
points, stackedOnPoints,
|
||||
coordSys, hasAnimation
|
||||
);
|
||||
}
|
||||
else if (polygon && !isAreaChart) {
|
||||
// If areaStyle is removed
|
||||
lineGroup.remove(polygon);
|
||||
polygon = this._polygon = null;
|
||||
}
|
||||
|
||||
// Update clipPath
|
||||
lineGroup.setClipPath(createClipShape(coordSys, false, seriesModel));
|
||||
|
||||
// Always update, or it is wrong in the case turning on legend
|
||||
// because points are not changed
|
||||
showSymbol && symbolDraw.updateData(data, isSymbolIgnore);
|
||||
|
||||
// Stop symbol animation and sync with line points
|
||||
// FIXME performance?
|
||||
data.eachItemGraphicEl(function (el) {
|
||||
el.stopAnimation(true);
|
||||
});
|
||||
|
||||
// In the case data zoom triggerred refreshing frequently
|
||||
// Data may not change if line has a category axis. So it should animate nothing
|
||||
if (!isPointsSame(this._stackedOnPoints, stackedOnPoints)
|
||||
|| !isPointsSame(this._points, points)
|
||||
) {
|
||||
if (hasAnimation) {
|
||||
this._updateAnimation(
|
||||
data, stackedOnPoints, coordSys, api
|
||||
);
|
||||
}
|
||||
else {
|
||||
polyline.setShape({
|
||||
points: points
|
||||
});
|
||||
polygon && polygon.setShape({
|
||||
points: points,
|
||||
stackedOnPoints: stackedOnPoints
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
polyline.useStyle(zrUtil.defaults(
|
||||
// Use color in lineStyle first
|
||||
lineStyleModel.getLineStyle(),
|
||||
{
|
||||
fill: 'none',
|
||||
stroke: data.getVisual('color'),
|
||||
lineJoin: 'bevel'
|
||||
}
|
||||
));
|
||||
|
||||
var smooth = seriesModel.get('smooth');
|
||||
smooth = getSmooth(seriesModel.get('smooth'));
|
||||
polyline.setShape({
|
||||
smooth: smooth,
|
||||
smoothMonotone: seriesModel.get('smoothMonotone'),
|
||||
connectNulls: seriesModel.get('connectNulls')
|
||||
});
|
||||
|
||||
if (polygon) {
|
||||
var stackedOn = data.stackedOn;
|
||||
var stackedOnSmooth = 0;
|
||||
|
||||
polygon.useStyle(zrUtil.defaults(
|
||||
areaStyleModel.getAreaStyle(),
|
||||
{
|
||||
fill: data.getVisual('color'),
|
||||
opacity: 0.7,
|
||||
lineJoin: 'bevel'
|
||||
}
|
||||
));
|
||||
|
||||
if (stackedOn) {
|
||||
var stackedOnSeries = stackedOn.hostModel;
|
||||
stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth'));
|
||||
}
|
||||
|
||||
polygon.setShape({
|
||||
smooth: smooth,
|
||||
stackedOnSmooth: stackedOnSmooth,
|
||||
smoothMonotone: seriesModel.get('smoothMonotone'),
|
||||
connectNulls: seriesModel.get('connectNulls')
|
||||
});
|
||||
}
|
||||
|
||||
this._data = data;
|
||||
// Save the coordinate system for transition animation when data changed
|
||||
this._coordSys = coordSys;
|
||||
this._stackedOnPoints = stackedOnPoints;
|
||||
this._points = points;
|
||||
},
|
||||
|
||||
highlight: function (seriesModel, ecModel, api, payload) {
|
||||
var data = seriesModel.getData();
|
||||
var dataIndex = queryDataIndex(data, payload);
|
||||
|
||||
if (dataIndex != null && dataIndex >= 0) {
|
||||
var symbol = data.getItemGraphicEl(dataIndex);
|
||||
if (!symbol) {
|
||||
// Create a temporary symbol if it is not exists
|
||||
var pt = data.getItemLayout(dataIndex);
|
||||
symbol = new Symbol(data, dataIndex, api);
|
||||
symbol.position = pt;
|
||||
symbol.setZ(
|
||||
seriesModel.get('zlevel'),
|
||||
seriesModel.get('z')
|
||||
);
|
||||
symbol.ignore = isNaN(pt[0]) || isNaN(pt[1]);
|
||||
symbol.__temp = true;
|
||||
data.setItemGraphicEl(dataIndex, symbol);
|
||||
|
||||
// Stop scale animation
|
||||
symbol.stopSymbolAnimation(true);
|
||||
|
||||
this.group.add(symbol);
|
||||
}
|
||||
symbol.highlight();
|
||||
}
|
||||
else {
|
||||
// Highlight whole series
|
||||
ChartView.prototype.highlight.call(
|
||||
this, seriesModel, ecModel, api, payload
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
downplay: function (seriesModel, ecModel, api, payload) {
|
||||
var data = seriesModel.getData();
|
||||
var dataIndex = queryDataIndex(data, payload);
|
||||
if (dataIndex != null && dataIndex >= 0) {
|
||||
var symbol = data.getItemGraphicEl(dataIndex);
|
||||
if (symbol) {
|
||||
if (symbol.__temp) {
|
||||
data.setItemGraphicEl(dataIndex, null);
|
||||
this.group.remove(symbol);
|
||||
}
|
||||
else {
|
||||
symbol.downplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Downplay whole series
|
||||
ChartView.prototype.downplay.call(
|
||||
this, seriesModel, ecModel, api, payload
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:zrender/container/Group} group
|
||||
* @param {Array.<Array.<number>>} points
|
||||
* @private
|
||||
*/
|
||||
_newPolyline: function (points) {
|
||||
var polyline = this._polyline;
|
||||
// Remove previous created polyline
|
||||
if (polyline) {
|
||||
this._lineGroup.remove(polyline);
|
||||
}
|
||||
|
||||
polyline = new polyHelper.Polyline({
|
||||
shape: {
|
||||
points: points
|
||||
},
|
||||
silent: true,
|
||||
z2: 10
|
||||
});
|
||||
|
||||
this._lineGroup.add(polyline);
|
||||
|
||||
this._polyline = polyline;
|
||||
|
||||
return polyline;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:zrender/container/Group} group
|
||||
* @param {Array.<Array.<number>>} stackedOnPoints
|
||||
* @param {Array.<Array.<number>>} points
|
||||
* @private
|
||||
*/
|
||||
_newPolygon: function (points, stackedOnPoints) {
|
||||
var polygon = this._polygon;
|
||||
// Remove previous created polygon
|
||||
if (polygon) {
|
||||
this._lineGroup.remove(polygon);
|
||||
}
|
||||
|
||||
polygon = new polyHelper.Polygon({
|
||||
shape: {
|
||||
points: points,
|
||||
stackedOnPoints: stackedOnPoints
|
||||
},
|
||||
silent: true
|
||||
});
|
||||
|
||||
this._lineGroup.add(polygon);
|
||||
|
||||
this._polygon = polygon;
|
||||
return polygon;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_getSymbolIgnoreFunc: function (data, coordSys) {
|
||||
var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
|
||||
// `getLabelInterval` is provided by echarts/component/axis
|
||||
if (categoryAxis && categoryAxis.isLabelIgnored) {
|
||||
return zrUtil.bind(categoryAxis.isLabelIgnored, categoryAxis);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
// FIXME Two value axis
|
||||
_updateAnimation: function (data, stackedOnPoints, coordSys, api) {
|
||||
var polyline = this._polyline;
|
||||
var polygon = this._polygon;
|
||||
var seriesModel = data.hostModel;
|
||||
|
||||
var diff = lineAnimationDiff(
|
||||
this._data, data,
|
||||
this._stackedOnPoints, stackedOnPoints,
|
||||
this._coordSys, coordSys
|
||||
);
|
||||
polyline.shape.points = diff.current;
|
||||
|
||||
graphic.updateProps(polyline, {
|
||||
shape: {
|
||||
points: diff.next
|
||||
}
|
||||
}, seriesModel);
|
||||
|
||||
if (polygon) {
|
||||
polygon.setShape({
|
||||
points: diff.current,
|
||||
stackedOnPoints: diff.stackedOnCurrent
|
||||
});
|
||||
graphic.updateProps(polygon, {
|
||||
shape: {
|
||||
points: diff.next,
|
||||
stackedOnPoints: diff.stackedOnNext
|
||||
}
|
||||
}, seriesModel);
|
||||
}
|
||||
|
||||
var updatedDataInfo = [];
|
||||
var diffStatus = diff.status;
|
||||
|
||||
for (var i = 0; i < diffStatus.length; i++) {
|
||||
var cmd = diffStatus[i].cmd;
|
||||
if (cmd === '=') {
|
||||
var el = data.getItemGraphicEl(diffStatus[i].idx1);
|
||||
if (el) {
|
||||
updatedDataInfo.push({
|
||||
el: el,
|
||||
ptIdx: i // Index of points
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (polyline.animators && polyline.animators.length) {
|
||||
polyline.animators[0].during(function () {
|
||||
for (var i = 0; i < updatedDataInfo.length; i++) {
|
||||
var el = updatedDataInfo[i].el;
|
||||
el.attr('position', polyline.shape.points[updatedDataInfo[i].ptIdx]);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
remove: function (ecModel) {
|
||||
var group = this.group;
|
||||
var oldData = this._data;
|
||||
this._lineGroup.removeAll();
|
||||
this._symbolDraw.remove(true);
|
||||
// Remove temporary created elements when highlighting
|
||||
oldData && oldData.eachItemGraphicEl(function (el, idx) {
|
||||
if (el.__temp) {
|
||||
group.remove(el);
|
||||
oldData.setItemGraphicEl(idx, null);
|
||||
}
|
||||
});
|
||||
|
||||
this._polyline =
|
||||
this._polygon =
|
||||
this._coordSys =
|
||||
this._points =
|
||||
this._stackedOnPoints =
|
||||
this._data = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
209
vendors/echarts/src/chart/line/lineAnimationDiff.js
vendored
Normal file
209
vendors/echarts/src/chart/line/lineAnimationDiff.js
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
define(function (require) {
|
||||
|
||||
// var arrayDiff = require('zrender/core/arrayDiff');
|
||||
// 'zrender/core/arrayDiff' has been used before, but it did
|
||||
// not do well in performance when roam with fixed dataZoom window.
|
||||
|
||||
function sign(val) {
|
||||
return val >= 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
function getStackedOnPoint(coordSys, data, idx) {
|
||||
var baseAxis = coordSys.getBaseAxis();
|
||||
var valueAxis = coordSys.getOtherAxis(baseAxis);
|
||||
var valueStart = baseAxis.onZero
|
||||
? 0 : valueAxis.scale.getExtent()[0];
|
||||
|
||||
var valueDim = valueAxis.dim;
|
||||
var baseDataOffset = valueDim === 'x' || valueDim === 'radius' ? 1 : 0;
|
||||
|
||||
var stackedOnSameSign;
|
||||
var stackedOn = data.stackedOn;
|
||||
var val = data.get(valueDim, idx);
|
||||
// Find first stacked value with same sign
|
||||
while (stackedOn &&
|
||||
sign(stackedOn.get(valueDim, idx)) === sign(val)
|
||||
) {
|
||||
stackedOnSameSign = stackedOn;
|
||||
break;
|
||||
}
|
||||
var stackedData = [];
|
||||
stackedData[baseDataOffset] = data.get(baseAxis.dim, idx);
|
||||
stackedData[1 - baseDataOffset] = stackedOnSameSign
|
||||
? stackedOnSameSign.get(valueDim, idx, true) : valueStart;
|
||||
|
||||
return coordSys.dataToPoint(stackedData);
|
||||
}
|
||||
|
||||
// function convertToIntId(newIdList, oldIdList) {
|
||||
// // Generate int id instead of string id.
|
||||
// // Compare string maybe slow in score function of arrDiff
|
||||
|
||||
// // Assume id in idList are all unique
|
||||
// var idIndicesMap = {};
|
||||
// var idx = 0;
|
||||
// for (var i = 0; i < newIdList.length; i++) {
|
||||
// idIndicesMap[newIdList[i]] = idx;
|
||||
// newIdList[i] = idx++;
|
||||
// }
|
||||
// for (var i = 0; i < oldIdList.length; i++) {
|
||||
// var oldId = oldIdList[i];
|
||||
// // Same with newIdList
|
||||
// if (idIndicesMap[oldId]) {
|
||||
// oldIdList[i] = idIndicesMap[oldId];
|
||||
// }
|
||||
// else {
|
||||
// oldIdList[i] = idx++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
function diffData(oldData, newData) {
|
||||
var diffResult = [];
|
||||
|
||||
newData.diff(oldData)
|
||||
.add(function (idx) {
|
||||
diffResult.push({cmd: '+', idx: idx});
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
diffResult.push({cmd: '=', idx: oldIdx, idx1: newIdx});
|
||||
})
|
||||
.remove(function (idx) {
|
||||
diffResult.push({cmd: '-', idx: idx});
|
||||
})
|
||||
.execute();
|
||||
|
||||
return diffResult;
|
||||
}
|
||||
|
||||
return function (
|
||||
oldData, newData,
|
||||
oldStackedOnPoints, newStackedOnPoints,
|
||||
oldCoordSys, newCoordSys
|
||||
) {
|
||||
var diff = diffData(oldData, newData);
|
||||
|
||||
// var newIdList = newData.mapArray(newData.getId);
|
||||
// var oldIdList = oldData.mapArray(oldData.getId);
|
||||
|
||||
// convertToIntId(newIdList, oldIdList);
|
||||
|
||||
// // FIXME One data ?
|
||||
// diff = arrayDiff(oldIdList, newIdList);
|
||||
|
||||
var currPoints = [];
|
||||
var nextPoints = [];
|
||||
// Points for stacking base line
|
||||
var currStackedPoints = [];
|
||||
var nextStackedPoints = [];
|
||||
|
||||
var status = [];
|
||||
var sortedIndices = [];
|
||||
var rawIndices = [];
|
||||
var dims = newCoordSys.dimensions;
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
var diffItem = diff[i];
|
||||
var pointAdded = true;
|
||||
|
||||
// FIXME, animation is not so perfect when dataZoom window moves fast
|
||||
// Which is in case remvoing or add more than one data in the tail or head
|
||||
switch (diffItem.cmd) {
|
||||
case '=':
|
||||
var currentPt = oldData.getItemLayout(diffItem.idx);
|
||||
var nextPt = newData.getItemLayout(diffItem.idx1);
|
||||
// If previous data is NaN, use next point directly
|
||||
if (isNaN(currentPt[0]) || isNaN(currentPt[1])) {
|
||||
currentPt = nextPt.slice();
|
||||
}
|
||||
currPoints.push(currentPt);
|
||||
nextPoints.push(nextPt);
|
||||
|
||||
currStackedPoints.push(oldStackedOnPoints[diffItem.idx]);
|
||||
nextStackedPoints.push(newStackedOnPoints[diffItem.idx1]);
|
||||
|
||||
rawIndices.push(newData.getRawIndex(diffItem.idx1));
|
||||
break;
|
||||
case '+':
|
||||
var idx = diffItem.idx;
|
||||
currPoints.push(
|
||||
oldCoordSys.dataToPoint([
|
||||
newData.get(dims[0], idx, true), newData.get(dims[1], idx, true)
|
||||
])
|
||||
);
|
||||
|
||||
nextPoints.push(newData.getItemLayout(idx).slice());
|
||||
|
||||
currStackedPoints.push(
|
||||
getStackedOnPoint(oldCoordSys, newData, idx)
|
||||
);
|
||||
nextStackedPoints.push(newStackedOnPoints[idx]);
|
||||
|
||||
rawIndices.push(newData.getRawIndex(idx));
|
||||
break;
|
||||
case '-':
|
||||
var idx = diffItem.idx;
|
||||
var rawIndex = oldData.getRawIndex(idx);
|
||||
// Data is replaced. In the case of dynamic data queue
|
||||
// FIXME FIXME FIXME
|
||||
if (rawIndex !== idx) {
|
||||
currPoints.push(oldData.getItemLayout(idx));
|
||||
nextPoints.push(newCoordSys.dataToPoint([
|
||||
oldData.get(dims[0], idx, true), oldData.get(dims[1], idx, true)
|
||||
]));
|
||||
|
||||
currStackedPoints.push(oldStackedOnPoints[idx]);
|
||||
nextStackedPoints.push(
|
||||
getStackedOnPoint(
|
||||
newCoordSys, oldData, idx
|
||||
)
|
||||
);
|
||||
|
||||
rawIndices.push(rawIndex);
|
||||
}
|
||||
else {
|
||||
pointAdded = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Original indices
|
||||
if (pointAdded) {
|
||||
status.push(diffItem);
|
||||
sortedIndices.push(sortedIndices.length);
|
||||
}
|
||||
}
|
||||
|
||||
// Diff result may be crossed if all items are changed
|
||||
// Sort by data index
|
||||
sortedIndices.sort(function (a, b) {
|
||||
return rawIndices[a] - rawIndices[b];
|
||||
});
|
||||
|
||||
var sortedCurrPoints = [];
|
||||
var sortedNextPoints = [];
|
||||
|
||||
var sortedCurrStackedPoints = [];
|
||||
var sortedNextStackedPoints = [];
|
||||
|
||||
var sortedStatus = [];
|
||||
for (var i = 0; i < sortedIndices.length; i++) {
|
||||
var idx = sortedIndices[i];
|
||||
sortedCurrPoints[i] = currPoints[idx];
|
||||
sortedNextPoints[i] = nextPoints[idx];
|
||||
|
||||
sortedCurrStackedPoints[i] = currStackedPoints[idx];
|
||||
sortedNextStackedPoints[i] = nextStackedPoints[idx];
|
||||
|
||||
sortedStatus[i] = status[idx];
|
||||
}
|
||||
|
||||
return {
|
||||
current: sortedCurrPoints,
|
||||
next: sortedNextPoints,
|
||||
|
||||
stackedOnCurrent: sortedCurrStackedPoints,
|
||||
stackedOnNext: sortedNextStackedPoints,
|
||||
|
||||
status: sortedStatus
|
||||
};
|
||||
};
|
||||
});
|
||||
250
vendors/echarts/src/chart/line/poly.js
vendored
Normal file
250
vendors/echarts/src/chart/line/poly.js
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
// Poly path support NaN point
|
||||
define(function (require) {
|
||||
|
||||
var Path = require('zrender/graphic/Path');
|
||||
var vec2 = require('zrender/core/vector');
|
||||
|
||||
var vec2Min = vec2.min;
|
||||
var vec2Max = vec2.max;
|
||||
|
||||
var scaleAndAdd = vec2.scaleAndAdd;
|
||||
var v2Copy = vec2.copy;
|
||||
|
||||
// Temporary variable
|
||||
var v = [];
|
||||
var cp0 = [];
|
||||
var cp1 = [];
|
||||
|
||||
function isPointNull(p) {
|
||||
return isNaN(p[0]) || isNaN(p[1]);
|
||||
}
|
||||
|
||||
function drawSegment(
|
||||
ctx, points, start, segLen, allLen,
|
||||
dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
|
||||
) {
|
||||
var prevIdx = 0;
|
||||
var idx = start;
|
||||
for (var k = 0; k < segLen; k++) {
|
||||
var p = points[idx];
|
||||
if (idx >= allLen || idx < 0) {
|
||||
break;
|
||||
}
|
||||
if (isPointNull(p)) {
|
||||
if (connectNulls) {
|
||||
idx += dir;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx === start) {
|
||||
ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
|
||||
v2Copy(cp0, p);
|
||||
}
|
||||
else {
|
||||
if (smooth > 0) {
|
||||
var nextIdx = idx + dir;
|
||||
var nextP = points[nextIdx];
|
||||
if (connectNulls) {
|
||||
// Find next point not null
|
||||
while (nextP && isPointNull(points[nextIdx])) {
|
||||
nextIdx += dir;
|
||||
nextP = points[nextIdx];
|
||||
}
|
||||
}
|
||||
|
||||
var ratioNextSeg = 0.5;
|
||||
var prevP = points[prevIdx];
|
||||
var nextP = points[nextIdx];
|
||||
// Last point
|
||||
if (!nextP || isPointNull(nextP)) {
|
||||
v2Copy(cp1, p);
|
||||
}
|
||||
else {
|
||||
// If next data is null in not connect case
|
||||
if (isPointNull(nextP) && !connectNulls) {
|
||||
nextP = p;
|
||||
}
|
||||
|
||||
vec2.sub(v, nextP, prevP);
|
||||
|
||||
var lenPrevSeg;
|
||||
var lenNextSeg;
|
||||
if (smoothMonotone === 'x' || smoothMonotone === 'y') {
|
||||
var dim = smoothMonotone === 'x' ? 0 : 1;
|
||||
lenPrevSeg = Math.abs(p[dim] - prevP[dim]);
|
||||
lenNextSeg = Math.abs(p[dim] - nextP[dim]);
|
||||
}
|
||||
else {
|
||||
lenPrevSeg = vec2.dist(p, prevP);
|
||||
lenNextSeg = vec2.dist(p, nextP);
|
||||
}
|
||||
|
||||
// Use ratio of seg length
|
||||
ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);
|
||||
|
||||
scaleAndAdd(cp1, p, v, -smooth * (1 - ratioNextSeg));
|
||||
}
|
||||
// Smooth constraint
|
||||
vec2Min(cp0, cp0, smoothMax);
|
||||
vec2Max(cp0, cp0, smoothMin);
|
||||
vec2Min(cp1, cp1, smoothMax);
|
||||
vec2Max(cp1, cp1, smoothMin);
|
||||
|
||||
ctx.bezierCurveTo(
|
||||
cp0[0], cp0[1],
|
||||
cp1[0], cp1[1],
|
||||
p[0], p[1]
|
||||
);
|
||||
// cp0 of next segment
|
||||
scaleAndAdd(cp0, p, v, smooth * ratioNextSeg);
|
||||
}
|
||||
else {
|
||||
ctx.lineTo(p[0], p[1]);
|
||||
}
|
||||
}
|
||||
|
||||
prevIdx = idx;
|
||||
idx += dir;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
function getBoundingBox(points, smoothConstraint) {
|
||||
var ptMin = [Infinity, Infinity];
|
||||
var ptMax = [-Infinity, -Infinity];
|
||||
if (smoothConstraint) {
|
||||
for (var i = 0; i < points.length; i++) {
|
||||
var pt = points[i];
|
||||
if (pt[0] < ptMin[0]) { ptMin[0] = pt[0]; }
|
||||
if (pt[1] < ptMin[1]) { ptMin[1] = pt[1]; }
|
||||
if (pt[0] > ptMax[0]) { ptMax[0] = pt[0]; }
|
||||
if (pt[1] > ptMax[1]) { ptMax[1] = pt[1]; }
|
||||
}
|
||||
}
|
||||
return {
|
||||
min: smoothConstraint ? ptMin : ptMax,
|
||||
max: smoothConstraint ? ptMax : ptMin
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Polyline: Path.extend({
|
||||
|
||||
type: 'ec-polyline',
|
||||
|
||||
shape: {
|
||||
points: [],
|
||||
|
||||
smooth: 0,
|
||||
|
||||
smoothConstraint: true,
|
||||
|
||||
smoothMonotone: null,
|
||||
|
||||
connectNulls: false
|
||||
},
|
||||
|
||||
style: {
|
||||
fill: null,
|
||||
|
||||
stroke: '#000'
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
var points = shape.points;
|
||||
|
||||
var i = 0;
|
||||
var len = points.length;
|
||||
|
||||
var result = getBoundingBox(points, shape.smoothConstraint);
|
||||
|
||||
if (shape.connectNulls) {
|
||||
// Must remove first and last null values avoid draw error in polygon
|
||||
for (; len > 0; len--) {
|
||||
if (!isPointNull(points[len - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < len; i++) {
|
||||
if (!isPointNull(points[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i < len) {
|
||||
i += drawSegment(
|
||||
ctx, points, i, len, len,
|
||||
1, result.min, result.max, shape.smooth,
|
||||
shape.smoothMonotone, shape.connectNulls
|
||||
) + 1;
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
Polygon: Path.extend({
|
||||
|
||||
type: 'ec-polygon',
|
||||
|
||||
shape: {
|
||||
points: [],
|
||||
|
||||
// Offset between stacked base points and points
|
||||
stackedOnPoints: [],
|
||||
|
||||
smooth: 0,
|
||||
|
||||
stackedOnSmooth: 0,
|
||||
|
||||
smoothConstraint: true,
|
||||
|
||||
smoothMonotone: null,
|
||||
|
||||
connectNulls: false
|
||||
},
|
||||
|
||||
buildPath: function (ctx, shape) {
|
||||
var points = shape.points;
|
||||
var stackedOnPoints = shape.stackedOnPoints;
|
||||
|
||||
var i = 0;
|
||||
var len = points.length;
|
||||
var smoothMonotone = shape.smoothMonotone;
|
||||
var bbox = getBoundingBox(points, shape.smoothConstraint);
|
||||
var stackedOnBBox = getBoundingBox(stackedOnPoints, shape.smoothConstraint);
|
||||
|
||||
if (shape.connectNulls) {
|
||||
// Must remove first and last null values avoid draw error in polygon
|
||||
for (; len > 0; len--) {
|
||||
if (!isPointNull(points[len - 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < len; i++) {
|
||||
if (!isPointNull(points[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (i < len) {
|
||||
var k = drawSegment(
|
||||
ctx, points, i, len, len,
|
||||
1, bbox.min, bbox.max, shape.smooth,
|
||||
smoothMonotone, shape.connectNulls
|
||||
);
|
||||
drawSegment(
|
||||
ctx, stackedOnPoints, i + k - 1, k, len,
|
||||
-1, stackedOnBBox.min, stackedOnBBox.max, shape.stackedOnSmooth,
|
||||
smoothMonotone, shape.connectNulls
|
||||
);
|
||||
i += k + 1;
|
||||
|
||||
ctx.closePath();
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
15
vendors/echarts/src/chart/lines.js
vendored
Normal file
15
vendors/echarts/src/chart/lines.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
define(function (require) {
|
||||
|
||||
require('./lines/LinesSeries');
|
||||
require('./lines/LinesView');
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
echarts.registerLayout(
|
||||
require('./lines/linesLayout')
|
||||
);
|
||||
|
||||
echarts.registerVisualCoding(
|
||||
'chart', zrUtil.curry(require('../visual/seriesColor'), 'lines', 'lineStyle')
|
||||
);
|
||||
});
|
||||
117
vendors/echarts/src/chart/lines/LinesSeries.js
vendored
Normal file
117
vendors/echarts/src/chart/lines/LinesSeries.js
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
define(function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var List = require('../../data/List');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var CoordinateSystem = require('../../CoordinateSystem');
|
||||
|
||||
return SeriesModel.extend({
|
||||
|
||||
type: 'series.lines',
|
||||
|
||||
dependencies: ['grid', 'polar'],
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var fromDataArr = [];
|
||||
var toDataArr = [];
|
||||
var lineDataArr = [];
|
||||
zrUtil.each(option.data, function (opt) {
|
||||
fromDataArr.push(opt[0]);
|
||||
toDataArr.push(opt[1]);
|
||||
lineDataArr.push(zrUtil.extend(
|
||||
zrUtil.extend({}, zrUtil.isArray(opt[0]) ? null : opt[0]),
|
||||
zrUtil.isArray(opt[1]) ? null : opt[1]
|
||||
));
|
||||
});
|
||||
|
||||
// var coordSys = option.coordinateSystem;
|
||||
// if (coordSys !== 'cartesian2d' && coordSys !== 'geo') {
|
||||
// throw new Error('Coordinate system can only be cartesian2d or geo in lines');
|
||||
// }
|
||||
|
||||
// var dimensions = coordSys === 'geo' ? ['lng', 'lat'] : ['x', 'y'];
|
||||
var coordSys = CoordinateSystem.get(option.coordinateSystem);
|
||||
if (!coordSys) {
|
||||
throw new Error('Invalid coordinate system');
|
||||
}
|
||||
var dimensions = coordSys.dimensions;
|
||||
|
||||
var fromData = new List(dimensions, this);
|
||||
var toData = new List(dimensions, this);
|
||||
var lineData = new List(['value'], this);
|
||||
|
||||
function geoCoordGetter(item, dim, dataIndex, dimIndex) {
|
||||
return item.coord && item.coord[dimIndex];
|
||||
}
|
||||
|
||||
fromData.initData(fromDataArr, null, geoCoordGetter);
|
||||
toData.initData(toDataArr, null, geoCoordGetter);
|
||||
lineData.initData(lineDataArr);
|
||||
|
||||
this.fromData = fromData;
|
||||
this.toData = toData;
|
||||
|
||||
return lineData;
|
||||
},
|
||||
|
||||
formatTooltip: function (dataIndex) {
|
||||
var fromName = this.fromData.getName(dataIndex);
|
||||
var toName = this.toData.getName(dataIndex);
|
||||
return fromName + ' > ' + toName;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
coordinateSystem: 'geo',
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
// Cartesian coordinate system
|
||||
xAxisIndex: 0,
|
||||
yAxisIndex: 0,
|
||||
|
||||
// Geo coordinate system
|
||||
geoIndex: 0,
|
||||
|
||||
// symbol: null,
|
||||
// symbolSize: 10,
|
||||
// symbolRotate: null,
|
||||
|
||||
effect: {
|
||||
show: false,
|
||||
period: 4,
|
||||
symbol: 'circle',
|
||||
symbolSize: 3,
|
||||
// Length of trail, 0 - 1
|
||||
trailLength: 0.2
|
||||
// Same with lineStyle.normal.color
|
||||
// color
|
||||
},
|
||||
|
||||
large: false,
|
||||
// Available when large is true
|
||||
largeThreshold: 2000,
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
show: false,
|
||||
position: 'end'
|
||||
// distance: 5,
|
||||
// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
|
||||
}
|
||||
},
|
||||
// itemStyle: {
|
||||
// normal: {
|
||||
// }
|
||||
// },
|
||||
lineStyle: {
|
||||
normal: {
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
66
vendors/echarts/src/chart/lines/LinesView.js
vendored
Normal file
66
vendors/echarts/src/chart/lines/LinesView.js
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
define(function (require) {
|
||||
|
||||
var LineDraw = require('../helper/LineDraw');
|
||||
var EffectLine = require('../helper/EffectLine');
|
||||
var Line = require('../helper/Line');
|
||||
|
||||
require('../../echarts').extendChartView({
|
||||
|
||||
type: 'lines',
|
||||
|
||||
init: function () {},
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var data = seriesModel.getData();
|
||||
var lineDraw = this._lineDraw;
|
||||
|
||||
var hasEffect = seriesModel.get('effect.show');
|
||||
if (hasEffect !== this._hasEffet) {
|
||||
if (lineDraw) {
|
||||
lineDraw.remove();
|
||||
}
|
||||
lineDraw = this._lineDraw = new LineDraw(
|
||||
hasEffect ? EffectLine : Line
|
||||
);
|
||||
this._hasEffet = hasEffect;
|
||||
}
|
||||
|
||||
var zlevel = seriesModel.get('zlevel');
|
||||
var trailLength = seriesModel.get('effect.trailLength');
|
||||
|
||||
var zr = api.getZr();
|
||||
// Avoid the drag cause ghost shadow
|
||||
// FIXME Better way ?
|
||||
zr.painter.getLayer(zlevel).clear(true);
|
||||
// Config layer with motion blur
|
||||
if (this._lastZlevel != null) {
|
||||
zr.configLayer(this._lastZlevel, {
|
||||
motionBlur: false
|
||||
});
|
||||
}
|
||||
if (hasEffect && trailLength) {
|
||||
zr.configLayer(zlevel, {
|
||||
motionBlur: true,
|
||||
lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0)
|
||||
});
|
||||
}
|
||||
|
||||
this.group.add(lineDraw.group);
|
||||
|
||||
lineDraw.updateData(data);
|
||||
|
||||
this._lastZlevel = zlevel;
|
||||
},
|
||||
|
||||
updateLayout: function (seriesModel, ecModel, api) {
|
||||
this._lineDraw.updateLayout();
|
||||
// Not use motion when dragging or zooming
|
||||
var zr = api.getZr();
|
||||
zr.painter.getLayer(this._lastZlevel).clear(true);
|
||||
},
|
||||
|
||||
remove: function (ecModel, api) {
|
||||
this._lineDraw && this._lineDraw.remove(api, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
32
vendors/echarts/src/chart/lines/linesLayout.js
vendored
Normal file
32
vendors/echarts/src/chart/lines/linesLayout.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
define(function (require) {
|
||||
|
||||
return function (ecModel) {
|
||||
ecModel.eachSeriesByType('lines', function (seriesModel) {
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var fromData = seriesModel.fromData;
|
||||
var toData = seriesModel.toData;
|
||||
var lineData = seriesModel.getData();
|
||||
|
||||
var dims = coordSys.dimensions;
|
||||
fromData.each(dims, function (x, y, idx) {
|
||||
fromData.setItemLayout(idx, coordSys.dataToPoint([x, y]));
|
||||
});
|
||||
toData.each(dims, function (x, y, idx) {
|
||||
toData.setItemLayout(idx, coordSys.dataToPoint([x, y]));
|
||||
});
|
||||
lineData.each(function (idx) {
|
||||
var p1 = fromData.getItemLayout(idx);
|
||||
var p2 = toData.getItemLayout(idx);
|
||||
var curveness = lineData.getItemModel(idx).get('lineStyle.normal.curveness');
|
||||
var cp1;
|
||||
if (curveness > 0) {
|
||||
cp1 = [
|
||||
(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness,
|
||||
(p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness
|
||||
];
|
||||
}
|
||||
lineData.setItemLayout(idx, [p1, p2, cp1]);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
34
vendors/echarts/src/chart/map.js
vendored
Normal file
34
vendors/echarts/src/chart/map.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./map/MapSeries');
|
||||
|
||||
require('./map/MapView');
|
||||
|
||||
require('../action/geoRoam');
|
||||
|
||||
require('../coord/geo/geoCreator');
|
||||
|
||||
echarts.registerLayout(require('./map/mapSymbolLayout'));
|
||||
|
||||
echarts.registerVisualCoding('chart', require('./map/mapVisual'));
|
||||
|
||||
echarts.registerProcessor('statistic', require('./map/mapDataStatistic'));
|
||||
|
||||
echarts.registerPreprocessor(require('./map/backwardCompat'));
|
||||
|
||||
require('../action/createDataSelectAction')('map', [{
|
||||
type: 'mapToggleSelect',
|
||||
event: 'mapselectchanged',
|
||||
method: 'toggleSelected'
|
||||
}, {
|
||||
type: 'mapSelect',
|
||||
event: 'mapselected',
|
||||
method: 'select'
|
||||
}, {
|
||||
type: 'mapUnSelect',
|
||||
event: 'mapunselected',
|
||||
method: 'unSelect'
|
||||
}]);
|
||||
});
|
||||
190
vendors/echarts/src/chart/map/MapSeries.js
vendored
Normal file
190
vendors/echarts/src/chart/map/MapSeries.js
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
define(function (require) {
|
||||
|
||||
var List = require('../../data/List');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
|
||||
var formatUtil = require('../../util/format');
|
||||
var encodeHTML = formatUtil.encodeHTML;
|
||||
var addCommas = formatUtil.addCommas;
|
||||
|
||||
var dataSelectableMixin = require('../../component/helper/selectableMixin');
|
||||
|
||||
var geoCreator = require('../../coord/geo/geoCreator');
|
||||
|
||||
var MapSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.map',
|
||||
|
||||
/**
|
||||
* Only first map series of same mapType will drawMap
|
||||
* @type {boolean}
|
||||
*/
|
||||
needsDrawMap: false,
|
||||
|
||||
/**
|
||||
* Group of all map series with same mapType
|
||||
* @type {boolean}
|
||||
*/
|
||||
seriesGroup: [],
|
||||
|
||||
init: function (option) {
|
||||
|
||||
option = this._fillOption(option, option.map);
|
||||
this.option = option;
|
||||
|
||||
MapSeries.superApply(this, 'init', arguments);
|
||||
|
||||
this.updateSelectedMap(option.data);
|
||||
},
|
||||
|
||||
getInitialData: function (option) {
|
||||
var dimensions = completeDimensions(['value'], option.data || []);
|
||||
|
||||
var list = new List(dimensions, this);
|
||||
|
||||
list.initData(option.data);
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
mergeOption: function (newOption) {
|
||||
if (newOption.data) {
|
||||
newOption = this._fillOption(newOption, this.option.map);
|
||||
}
|
||||
|
||||
MapSeries.superCall(this, 'mergeOption', newOption);
|
||||
|
||||
this.updateSelectedMap(this.option.data);
|
||||
},
|
||||
|
||||
_fillOption: function (option, mapName) {
|
||||
// Shallow clone
|
||||
option = zrUtil.extend({}, option);
|
||||
|
||||
option.data = geoCreator.getFilledRegions(option.data, mapName);
|
||||
|
||||
return option;
|
||||
},
|
||||
|
||||
getRawValue: function (dataIndex) {
|
||||
// Use value stored in data instead because it is calculated from multiple series
|
||||
// FIXME Provide all value of multiple series ?
|
||||
return this._data.get('value', dataIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get model of region
|
||||
* @param {string} name
|
||||
* @return {module:echarts/model/Model}
|
||||
*/
|
||||
getRegionModel: function (regionName) {
|
||||
var data = this.getData();
|
||||
return data.getItemModel(data.indexOfName(regionName));
|
||||
},
|
||||
|
||||
/**
|
||||
* Map tooltip formatter
|
||||
*
|
||||
* @param {number} dataIndex
|
||||
*/
|
||||
formatTooltip: function (dataIndex) {
|
||||
var data = this._data;
|
||||
var formattedValue = addCommas(this.getRawValue(dataIndex));
|
||||
var name = data.getName(dataIndex);
|
||||
|
||||
var seriesGroup = this.seriesGroup;
|
||||
var seriesNames = [];
|
||||
for (var i = 0; i < seriesGroup.length; i++) {
|
||||
if (!isNaN(seriesGroup[i].getRawValue(dataIndex))) {
|
||||
seriesNames.push(
|
||||
encodeHTML(seriesGroup[i].name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return seriesNames.join(', ') + '<br />'
|
||||
+ name + ' : ' + formattedValue;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
// 一级层叠
|
||||
zlevel: 0,
|
||||
// 二级层叠
|
||||
z: 2,
|
||||
coordinateSystem: 'geo',
|
||||
// 各省的 map 暂时都用中文
|
||||
map: 'china',
|
||||
|
||||
// 'center' | 'left' | 'right' | 'x%' | {number}
|
||||
left: 'center',
|
||||
// 'center' | 'top' | 'bottom' | 'x%' | {number}
|
||||
top: 'center',
|
||||
// right
|
||||
// bottom
|
||||
// width:
|
||||
// height // 自适应
|
||||
|
||||
// 数值合并方式,默认加和,可选为:
|
||||
// 'sum' | 'average' | 'max' | 'min'
|
||||
// mapValueCalculation: 'sum',
|
||||
// 地图数值计算结果小数精度
|
||||
// mapValuePrecision: 0,
|
||||
// 显示图例颜色标识(系列标识的小圆点),图例开启时有效
|
||||
showLegendSymbol: true,
|
||||
// 选择模式,默认关闭,可选single,multiple
|
||||
// selectedMode: false,
|
||||
dataRangeHoverLink: true,
|
||||
// 是否开启缩放及漫游模式
|
||||
// roam: false,
|
||||
|
||||
// Default on center of map
|
||||
center: null,
|
||||
|
||||
zoom: 1,
|
||||
|
||||
scaleLimit: null,
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
show: false,
|
||||
textStyle: {
|
||||
color: '#000'
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: 'rgb(100,0,0)'
|
||||
}
|
||||
}
|
||||
},
|
||||
// scaleLimit: null,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// color: 各异,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#444',
|
||||
areaColor: '#eee'
|
||||
},
|
||||
// 也是选中样式
|
||||
emphasis: {
|
||||
areaColor: 'rgba(255,215, 0, 0.8)'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setZoom: function (zoom) {
|
||||
this.option.zoom = zoom;
|
||||
},
|
||||
|
||||
setCenter: function (center) {
|
||||
this.option.center = center;
|
||||
}
|
||||
});
|
||||
|
||||
zrUtil.mixin(MapSeries, dataSelectableMixin);
|
||||
|
||||
return MapSeries;
|
||||
});
|
||||
132
vendors/echarts/src/chart/map/MapView.js
vendored
Normal file
132
vendors/echarts/src/chart/map/MapView.js
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
define(function (require) {
|
||||
|
||||
// var zrUtil = require('zrender/core/util');
|
||||
var graphic = require('../../util/graphic');
|
||||
|
||||
var MapDraw = require('../../component/helper/MapDraw');
|
||||
|
||||
require('../../echarts').extendChartView({
|
||||
|
||||
type: 'map',
|
||||
|
||||
render: function (mapModel, ecModel, api, payload) {
|
||||
// Not render if it is an toggleSelect action from self
|
||||
if (payload && payload.type === 'mapToggleSelect'
|
||||
&& payload.from === this.uid
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
var group = this.group;
|
||||
group.removeAll();
|
||||
// Not update map if it is an roam action from self
|
||||
if (!(payload && payload.type === 'geoRoam'
|
||||
&& payload.component === 'series'
|
||||
&& payload.name === mapModel.name)) {
|
||||
|
||||
if (mapModel.needsDrawMap) {
|
||||
var mapDraw = this._mapDraw || new MapDraw(api, true);
|
||||
group.add(mapDraw.group);
|
||||
|
||||
mapDraw.draw(mapModel, ecModel, api, this, payload);
|
||||
|
||||
this._mapDraw = mapDraw;
|
||||
}
|
||||
else {
|
||||
// Remove drawed map
|
||||
this._mapDraw && this._mapDraw.remove();
|
||||
this._mapDraw = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var mapDraw = this._mapDraw;
|
||||
mapDraw && group.add(mapDraw.group);
|
||||
}
|
||||
|
||||
mapModel.get('showLegendSymbol') && ecModel.getComponent('legend')
|
||||
&& this._renderSymbols(mapModel, ecModel, api);
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this._mapDraw && this._mapDraw.remove();
|
||||
this._mapDraw = null;
|
||||
this.group.removeAll();
|
||||
},
|
||||
|
||||
_renderSymbols: function (mapModel, ecModel, api) {
|
||||
var data = mapModel.getData();
|
||||
var group = this.group;
|
||||
|
||||
data.each('value', function (value, idx) {
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var layout = data.getItemLayout(idx);
|
||||
|
||||
if (!layout || !layout.point) {
|
||||
// Not exists in map
|
||||
return;
|
||||
}
|
||||
|
||||
var point = layout.point;
|
||||
var offset = layout.offset;
|
||||
|
||||
var circle = new graphic.Circle({
|
||||
style: {
|
||||
fill: data.getVisual('color')
|
||||
},
|
||||
shape: {
|
||||
cx: point[0] + offset * 9,
|
||||
cy: point[1],
|
||||
r: 3
|
||||
},
|
||||
silent: true,
|
||||
z2: 10
|
||||
});
|
||||
|
||||
// First data on the same region
|
||||
if (!offset) {
|
||||
var labelText = data.getName(idx);
|
||||
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var hoverLabelModel = itemModel.getModel('label.emphasis');
|
||||
|
||||
var textStyleModel = labelModel.getModel('textStyle');
|
||||
var hoverTextStyleModel = hoverLabelModel.getModel('textStyle');
|
||||
|
||||
var polygonGroups = data.getItemGraphicEl(idx);
|
||||
circle.setStyle({
|
||||
textPosition: 'bottom'
|
||||
});
|
||||
|
||||
var onEmphasis = function () {
|
||||
circle.setStyle({
|
||||
text: hoverLabelModel.get('show') ? labelText : '',
|
||||
textFill: hoverTextStyleModel.getTextColor(),
|
||||
textFont: hoverTextStyleModel.getFont()
|
||||
});
|
||||
};
|
||||
|
||||
var onNormal = function () {
|
||||
circle.setStyle({
|
||||
text: labelModel.get('show') ? labelText : '',
|
||||
textFill: textStyleModel.getTextColor(),
|
||||
textFont: textStyleModel.getFont()
|
||||
});
|
||||
};
|
||||
|
||||
polygonGroups.on('mouseover', onEmphasis)
|
||||
.on('mouseout', onNormal)
|
||||
.on('emphasis', onEmphasis)
|
||||
.on('normal', onNormal);
|
||||
|
||||
onNormal();
|
||||
}
|
||||
|
||||
group.add(circle);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
86
vendors/echarts/src/chart/map/backwardCompat.js
vendored
Normal file
86
vendors/echarts/src/chart/map/backwardCompat.js
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var geoProps = [
|
||||
'x', 'y', 'x2', 'y2', 'width', 'height', 'map', 'roam', 'center', 'zoom', 'scaleLimit', 'label', 'itemStyle'
|
||||
];
|
||||
|
||||
var geoCoordsMap = {};
|
||||
|
||||
function createGeoFromMap(mapSeriesOpt) {
|
||||
var geoOpt = {};
|
||||
zrUtil.each(geoProps, function (propName) {
|
||||
if (mapSeriesOpt[propName] != null) {
|
||||
geoOpt[propName] = mapSeriesOpt[propName];
|
||||
}
|
||||
});
|
||||
return geoOpt;
|
||||
}
|
||||
return function (option) {
|
||||
// Save geoCoord
|
||||
var mapSeries = [];
|
||||
zrUtil.each(option.series, function (seriesOpt) {
|
||||
if (seriesOpt.type === 'map') {
|
||||
mapSeries.push(seriesOpt);
|
||||
}
|
||||
zrUtil.extend(geoCoordsMap, seriesOpt.geoCoord);
|
||||
});
|
||||
|
||||
var newCreatedGeoOptMap = {};
|
||||
zrUtil.each(mapSeries, function (seriesOpt) {
|
||||
seriesOpt.map = seriesOpt.map || seriesOpt.mapType;
|
||||
// Put x, y, width, height, x2, y2 in the top level
|
||||
zrUtil.defaults(seriesOpt, seriesOpt.mapLocation);
|
||||
if (seriesOpt.markPoint) {
|
||||
var markPoint = seriesOpt.markPoint;
|
||||
// Convert name or geoCoord in markPoint to lng and lat
|
||||
// For example
|
||||
// { name: 'xxx', value: 10} Or
|
||||
// { geoCoord: [lng, lat], value: 10} to
|
||||
// { name: 'xxx', value: [lng, lat, 10]}
|
||||
markPoint.data = zrUtil.map(markPoint.data, function (dataOpt) {
|
||||
if (!zrUtil.isArray(dataOpt.value)) {
|
||||
var geoCoord;
|
||||
if (dataOpt.geoCoord) {
|
||||
geoCoord = dataOpt.geoCoord;
|
||||
}
|
||||
else if (dataOpt.name) {
|
||||
geoCoord = geoCoordsMap[dataOpt.name];
|
||||
}
|
||||
var newValue = geoCoord ? [geoCoord[0], geoCoord[1]] : [NaN, NaN];
|
||||
if (dataOpt.value != null) {
|
||||
newValue.push(dataOpt.value);
|
||||
}
|
||||
dataOpt.value = newValue;
|
||||
}
|
||||
return dataOpt;
|
||||
});
|
||||
// Convert map series which only has markPoint without data to scatter series
|
||||
// FIXME
|
||||
if (!(seriesOpt.data && seriesOpt.data.length)) {
|
||||
if (!option.geo) {
|
||||
option.geo = [];
|
||||
}
|
||||
else if (!zrUtil.isArray(option.geo)) {
|
||||
option.geo = [option.geo];
|
||||
}
|
||||
|
||||
// Use same geo if multiple map series has same map type
|
||||
var geoOpt = newCreatedGeoOptMap[seriesOpt.map];
|
||||
if (!geoOpt) {
|
||||
geoOpt = newCreatedGeoOptMap[seriesOpt.map] = createGeoFromMap(seriesOpt);
|
||||
option.geo.push(geoOpt);
|
||||
}
|
||||
|
||||
var scatterSeries = seriesOpt.markPoint;
|
||||
scatterSeries.type = option.effect && option.effect.show ? 'effectScatter' : 'scatter';
|
||||
scatterSeries.coordinateSystem = 'geo';
|
||||
scatterSeries.geoIndex = zrUtil.indexOf(option.geo, geoOpt);
|
||||
scatterSeries.name = seriesOpt.name;
|
||||
|
||||
option.series.splice(zrUtil.indexOf(option.series, seriesOpt), 1, scatterSeries);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
80
vendors/echarts/src/chart/map/mapDataStatistic.js
vendored
Normal file
80
vendors/echarts/src/chart/map/mapDataStatistic.js
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
// FIXME 公用?
|
||||
/**
|
||||
* @param {Array.<module:echarts/data/List>} datas
|
||||
* @param {string} statisticsType 'average' 'sum'
|
||||
* @inner
|
||||
*/
|
||||
function dataStatistics(datas, statisticsType) {
|
||||
var dataNameMap = {};
|
||||
var dims = ['value'];
|
||||
|
||||
for (var i = 0; i < datas.length; i++) {
|
||||
datas[i].each(dims, function (value, idx) {
|
||||
var name = datas[i].getName(idx);
|
||||
dataNameMap[name] = dataNameMap[name] || [];
|
||||
if (!isNaN(value)) {
|
||||
dataNameMap[name].push(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return datas[0].map(dims, function (value, idx) {
|
||||
var name = datas[0].getName(idx);
|
||||
var sum = 0;
|
||||
var min = Infinity;
|
||||
var max = -Infinity;
|
||||
var len = dataNameMap[name].length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
min = Math.min(min, dataNameMap[name][i]);
|
||||
max = Math.max(max, dataNameMap[name][i]);
|
||||
sum += dataNameMap[name][i];
|
||||
}
|
||||
var result;
|
||||
if (statisticsType === 'min') {
|
||||
result = min;
|
||||
}
|
||||
else if (statisticsType === 'max') {
|
||||
result = max;
|
||||
}
|
||||
else if (statisticsType === 'average') {
|
||||
result = sum / len;
|
||||
}
|
||||
else {
|
||||
result = sum;
|
||||
}
|
||||
return len === 0 ? NaN : result;
|
||||
});
|
||||
}
|
||||
|
||||
return function (ecModel) {
|
||||
var seriesGroupByMapType = {};
|
||||
ecModel.eachSeriesByType('map', function (seriesModel) {
|
||||
var mapType = seriesModel.get('map');
|
||||
seriesGroupByMapType[mapType] = seriesGroupByMapType[mapType] || [];
|
||||
seriesGroupByMapType[mapType].push(seriesModel);
|
||||
});
|
||||
|
||||
zrUtil.each(seriesGroupByMapType, function (seriesList, mapType) {
|
||||
var data = dataStatistics(
|
||||
zrUtil.map(seriesList, function (seriesModel) {
|
||||
return seriesModel.getData();
|
||||
}),
|
||||
seriesList[0].get('mapValueCalculation')
|
||||
);
|
||||
|
||||
seriesList[0].seriesGroup = [];
|
||||
|
||||
seriesList[0].setData(data);
|
||||
|
||||
// FIXME Put where?
|
||||
for (var i = 0; i < seriesList.length; i++) {
|
||||
seriesList[i].seriesGroup = seriesList;
|
||||
seriesList[i].needsDrawMap = i === 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
59
vendors/echarts/src/chart/map/mapSymbolLayout.js
vendored
Normal file
59
vendors/echarts/src/chart/map/mapSymbolLayout.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
return function (ecModel) {
|
||||
|
||||
var processedMapType = {};
|
||||
|
||||
ecModel.eachSeriesByType('map', function (mapSeries) {
|
||||
var mapType = mapSeries.get('map');
|
||||
if (processedMapType[mapType]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var mapSymbolOffsets = {};
|
||||
|
||||
zrUtil.each(mapSeries.seriesGroup, function (subMapSeries) {
|
||||
var geo = subMapSeries.coordinateSystem;
|
||||
var data = subMapSeries.getData();
|
||||
if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) {
|
||||
data.each('value', function (value, idx) {
|
||||
var name = data.getName(idx);
|
||||
var region = geo.getRegion(name);
|
||||
|
||||
// No region or no value
|
||||
// In MapSeries data regions will be filled with NaN
|
||||
// If they are not in the series.data array.
|
||||
// So here must validate if value is NaN
|
||||
if (!region || isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = mapSymbolOffsets[name] || 0;
|
||||
|
||||
var point = geo.dataToPoint(region.center);
|
||||
|
||||
mapSymbolOffsets[name] = offset + 1;
|
||||
|
||||
data.setItemLayout(idx, {
|
||||
point: point,
|
||||
offset: offset
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Show label of those region not has legendSymbol(which is offset 0)
|
||||
var data = mapSeries.getData();
|
||||
data.each(function (idx) {
|
||||
var name = data.getName(idx);
|
||||
var layout = data.getItemLayout(idx) || {};
|
||||
layout.showLabel = !mapSymbolOffsets[name];
|
||||
data.setItemLayout(idx, layout);
|
||||
});
|
||||
|
||||
processedMapType[mapType] = true;
|
||||
});
|
||||
};
|
||||
});
|
||||
17
vendors/echarts/src/chart/map/mapVisual.js
vendored
Normal file
17
vendors/echarts/src/chart/map/mapVisual.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
define(function (require) {
|
||||
return function (ecModel) {
|
||||
ecModel.eachSeriesByType('map', function (seriesModel) {
|
||||
var colorList = seriesModel.get('color');
|
||||
var itemStyleModel = seriesModel.getModel('itemStyle.normal');
|
||||
|
||||
var areaColor = itemStyleModel.get('areaColor');
|
||||
var color = itemStyleModel.get('color')
|
||||
|| colorList[seriesModel.seriesIndex % colorList.length];
|
||||
|
||||
seriesModel.getData().setVisual({
|
||||
'areaColor': areaColor,
|
||||
'color': color
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
12
vendors/echarts/src/chart/parallel.js
vendored
Normal file
12
vendors/echarts/src/chart/parallel.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
define(function (require) {
|
||||
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('../component/parallel');
|
||||
|
||||
require('./parallel/ParallelSeries');
|
||||
require('./parallel/ParallelView');
|
||||
|
||||
echarts.registerVisualCoding('chart', require('./parallel/parallelVisual'));
|
||||
|
||||
});
|
||||
119
vendors/echarts/src/chart/parallel/ParallelSeries.js
vendored
Normal file
119
vendors/echarts/src/chart/parallel/ParallelSeries.js
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
define(function(require) {
|
||||
|
||||
var List = require('../../data/List');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var SeriesModel = require('../../model/Series');
|
||||
|
||||
return SeriesModel.extend({
|
||||
|
||||
type: 'series.parallel',
|
||||
|
||||
dependencies: ['parallel'],
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var parallelModel = ecModel.getComponent(
|
||||
'parallel', this.get('parallelIndex')
|
||||
);
|
||||
var dimensions = parallelModel.dimensions;
|
||||
var parallelAxisIndices = parallelModel.parallelAxisIndex;
|
||||
|
||||
var rawData = option.data;
|
||||
|
||||
var dimensionsInfo = zrUtil.map(dimensions, function (dim, index) {
|
||||
var axisModel = ecModel.getComponent(
|
||||
'parallelAxis', parallelAxisIndices[index]
|
||||
);
|
||||
if (axisModel.get('type') === 'category') {
|
||||
translateCategoryValue(axisModel, dim, rawData);
|
||||
return {name: dim, type: 'ordinal'};
|
||||
}
|
||||
else {
|
||||
return dim;
|
||||
}
|
||||
});
|
||||
|
||||
var list = new List(dimensionsInfo, this);
|
||||
list.initData(rawData);
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
/**
|
||||
* User can get data raw indices on 'axisAreaSelected' event received.
|
||||
*
|
||||
* @public
|
||||
* @param {string} activeState 'active' or 'inactive' or 'normal'
|
||||
* @return {Array.<number>} Raw indices
|
||||
*/
|
||||
getRawIndicesByActiveState: function (activeState) {
|
||||
var coordSys = this.coordinateSystem;
|
||||
var data = this.getData();
|
||||
var indices = [];
|
||||
|
||||
coordSys.eachActiveState(data, function (theActiveState, dataIndex) {
|
||||
if (activeState === theActiveState) {
|
||||
indices.push(data.getRawIndex(dataIndex));
|
||||
}
|
||||
});
|
||||
|
||||
return indices;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0, // 一级层叠
|
||||
z: 2, // 二级层叠
|
||||
|
||||
coordinateSystem: 'parallel',
|
||||
parallelIndex: 0,
|
||||
|
||||
// FIXME 尚无用
|
||||
label: {
|
||||
normal: {
|
||||
show: false
|
||||
// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
|
||||
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
|
||||
// 'inside'|'left'|'right'|'top'|'bottom'
|
||||
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
|
||||
},
|
||||
emphasis: {
|
||||
show: false
|
||||
// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
|
||||
// position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
|
||||
// 'inside'|'left'|'right'|'top'|'bottom'
|
||||
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
|
||||
}
|
||||
},
|
||||
|
||||
inactiveOpacity: 0.05,
|
||||
activeOpacity: 1,
|
||||
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 2,
|
||||
opacity: 0.45,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
// smooth: false
|
||||
|
||||
animationEasing: 'linear'
|
||||
}
|
||||
});
|
||||
|
||||
function translateCategoryValue(axisModel, dim, rawData) {
|
||||
var axisData = axisModel.get('data');
|
||||
var numberDim = +dim.replace('dim', '');
|
||||
|
||||
if (axisData && axisData.length) {
|
||||
zrUtil.each(rawData, function (dataItem) {
|
||||
if (!dataItem) {
|
||||
return;
|
||||
}
|
||||
var index = zrUtil.indexOf(axisData, dataItem[numberDim]);
|
||||
dataItem[numberDim] = index >= 0 ? index : NaN;
|
||||
});
|
||||
}
|
||||
// FIXME
|
||||
// 如果没有设置axis data, 应自动算出,或者提示。
|
||||
}
|
||||
});
|
||||
200
vendors/echarts/src/chart/parallel/ParallelView.js
vendored
Normal file
200
vendors/echarts/src/chart/parallel/ParallelView.js
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var ParallelView = require('../../view/Chart').extend({
|
||||
|
||||
type: 'parallel',
|
||||
|
||||
init: function () {
|
||||
|
||||
/**
|
||||
* @type {module:zrender/container/Group}
|
||||
* @private
|
||||
*/
|
||||
this._dataGroup = new graphic.Group();
|
||||
|
||||
this.group.add(this._dataGroup);
|
||||
/**
|
||||
* @type {module:echarts/data/List}
|
||||
*/
|
||||
this._data;
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
render: function (seriesModel, ecModel, api, payload) {
|
||||
|
||||
var dataGroup = this._dataGroup;
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var dimensions = coordSys.dimensions;
|
||||
|
||||
data.diff(oldData)
|
||||
.add(add)
|
||||
.update(update)
|
||||
.remove(remove)
|
||||
.execute();
|
||||
|
||||
// Update style
|
||||
data.eachItemGraphicEl(function (elGroup, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var lineStyleModel = itemModel.getModel('lineStyle.normal');
|
||||
elGroup.eachChild(function (child) {
|
||||
child.useStyle(zrUtil.extend(
|
||||
lineStyleModel.getLineStyle(),
|
||||
{
|
||||
fill: null,
|
||||
stroke: data.getItemVisual(idx, 'color'),
|
||||
opacity: data.getItemVisual(idx, 'opacity')
|
||||
}
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
// First create
|
||||
if (!this._data) {
|
||||
dataGroup.setClipPath(createGridClipShape(
|
||||
coordSys, seriesModel, function () {
|
||||
dataGroup.removeClipPath();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
this._data = data;
|
||||
|
||||
function add(newDataIndex) {
|
||||
var values = data.getValues(dimensions, newDataIndex);
|
||||
var elGroup = new graphic.Group();
|
||||
dataGroup.add(elGroup);
|
||||
|
||||
eachAxisPair(
|
||||
values, dimensions, coordSys,
|
||||
function (pointPair, pairIndex) {
|
||||
// FIXME
|
||||
// init animation
|
||||
if (pointPair) {
|
||||
elGroup.add(createEl(pointPair));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
data.setItemGraphicEl(newDataIndex, elGroup);
|
||||
}
|
||||
|
||||
function update(newDataIndex, oldDataIndex) {
|
||||
var values = data.getValues(dimensions, newDataIndex);
|
||||
var elGroup = oldData.getItemGraphicEl(oldDataIndex);
|
||||
var newEls = [];
|
||||
var elGroupIndex = 0;
|
||||
|
||||
eachAxisPair(
|
||||
values, dimensions, coordSys,
|
||||
function (pointPair, pairIndex) {
|
||||
var el = elGroup.childAt(elGroupIndex++);
|
||||
|
||||
if (pointPair && !el) {
|
||||
newEls.push(createEl(pointPair));
|
||||
}
|
||||
else if (pointPair) {
|
||||
graphic.updateProps(el, {
|
||||
shape: {
|
||||
points: pointPair
|
||||
}
|
||||
}, seriesModel, newDataIndex);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Remove redundent els
|
||||
for (var i = elGroup.childCount() - 1; i >= elGroupIndex; i--) {
|
||||
elGroup.remove(elGroup.childAt(i));
|
||||
}
|
||||
|
||||
// Add new els
|
||||
for (var i = 0, len = newEls.length; i < len; i++) {
|
||||
elGroup.add(newEls[i]);
|
||||
}
|
||||
|
||||
data.setItemGraphicEl(newDataIndex, elGroup);
|
||||
}
|
||||
|
||||
function remove(oldDataIndex) {
|
||||
var elGroup = oldData.getItemGraphicEl(oldDataIndex);
|
||||
dataGroup.remove(elGroup);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
remove: function () {
|
||||
this._dataGroup && this._dataGroup.removeAll();
|
||||
this._data = null;
|
||||
}
|
||||
});
|
||||
|
||||
function createGridClipShape(coordSys, seriesModel, cb) {
|
||||
var parallelModel = coordSys.model;
|
||||
var rect = coordSys.getRect();
|
||||
var rectEl = new graphic.Rect({
|
||||
shape: {
|
||||
x: rect.x,
|
||||
y: rect.y,
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
}
|
||||
});
|
||||
var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height';
|
||||
rectEl.setShape(dim, 0);
|
||||
graphic.initProps(rectEl, {
|
||||
shape: {
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
}
|
||||
}, seriesModel, cb);
|
||||
return rectEl;
|
||||
}
|
||||
|
||||
function eachAxisPair(values, dimensions, coordSys, cb) {
|
||||
for (var i = 0, len = dimensions.length - 1; i < len; i++) {
|
||||
var dimA = dimensions[i];
|
||||
var dimB = dimensions[i + 1];
|
||||
var valueA = values[i];
|
||||
var valueB = values[i + 1];
|
||||
|
||||
cb(
|
||||
(isEmptyValue(valueA, coordSys.getAxis(dimA).type)
|
||||
|| isEmptyValue(valueB, coordSys.getAxis(dimB).type)
|
||||
)
|
||||
? null
|
||||
: [
|
||||
coordSys.dataToPoint(valueA, dimA),
|
||||
coordSys.dataToPoint(valueB, dimB)
|
||||
],
|
||||
i
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function createEl(pointPair) {
|
||||
return new graphic.Polyline({
|
||||
shape: {points: pointPair},
|
||||
silent: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// FIXME
|
||||
// 公用方法?
|
||||
function isEmptyValue(val, axisType) {
|
||||
return axisType === 'category'
|
||||
? val == null
|
||||
: (val == null || isNaN(val)); // axisType === 'value'
|
||||
}
|
||||
|
||||
return ParallelView;
|
||||
});
|
||||
37
vendors/echarts/src/chart/parallel/parallelVisual.js
vendored
Normal file
37
vendors/echarts/src/chart/parallel/parallelVisual.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
define(function (require) {
|
||||
|
||||
/**
|
||||
* @payload
|
||||
* @property {string} parallelAxisId
|
||||
* @property {Array.<number>} extent
|
||||
*/
|
||||
return function (ecModel, payload) {
|
||||
|
||||
ecModel.eachSeriesByType('parallel', function (seriesModel) {
|
||||
|
||||
var itemStyleModel = seriesModel.getModel('itemStyle.normal');
|
||||
var globalColors = ecModel.get('color');
|
||||
|
||||
var color = itemStyleModel.get('color')
|
||||
|| globalColors[seriesModel.seriesIndex % globalColors.length];
|
||||
var inactiveOpacity = seriesModel.get('inactiveOpacity');
|
||||
var activeOpacity = seriesModel.get('activeOpacity');
|
||||
var lineStyle = seriesModel.getModel('lineStyle.normal').getLineStyle();
|
||||
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
var data = seriesModel.getData();
|
||||
|
||||
var opacityMap = {
|
||||
normal: lineStyle.opacity,
|
||||
active: activeOpacity,
|
||||
inactive: inactiveOpacity
|
||||
};
|
||||
|
||||
coordSys.eachActiveState(data, function (activeState, dataIndex) {
|
||||
data.setItemVisual(dataIndex, 'opacity', opacityMap[activeState]);
|
||||
});
|
||||
|
||||
data.setVisual('color', color);
|
||||
});
|
||||
};
|
||||
});
|
||||
34
vendors/echarts/src/chart/pie.js
vendored
Normal file
34
vendors/echarts/src/chart/pie.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
require('./pie/PieSeries');
|
||||
require('./pie/PieView');
|
||||
|
||||
require('../action/createDataSelectAction')('pie', [{
|
||||
type: 'pieToggleSelect',
|
||||
event: 'pieselectchanged',
|
||||
method: 'toggleSelected'
|
||||
}, {
|
||||
type: 'pieSelect',
|
||||
event: 'pieselected',
|
||||
method: 'select'
|
||||
}, {
|
||||
type: 'pieUnSelect',
|
||||
event: 'pieunselected',
|
||||
method: 'unSelect'
|
||||
}]);
|
||||
|
||||
echarts.registerVisualCoding(
|
||||
'chart', zrUtil.curry(require('../visual/dataColor'), 'pie')
|
||||
);
|
||||
|
||||
echarts.registerLayout(zrUtil.curry(
|
||||
require('./pie/pieLayout'), 'pie'
|
||||
));
|
||||
|
||||
echarts.registerProcessor(
|
||||
'filter', zrUtil.curry(require('../processor/dataFilter'), 'pie')
|
||||
);
|
||||
});
|
||||
146
vendors/echarts/src/chart/pie/PieSeries.js
vendored
Normal file
146
vendors/echarts/src/chart/pie/PieSeries.js
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var List = require('../../data/List');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var modelUtil = require('../../util/model');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
|
||||
var dataSelectableMixin = require('../../component/helper/selectableMixin');
|
||||
|
||||
var PieSeries = require('../../echarts').extendSeriesModel({
|
||||
|
||||
type: 'series.pie',
|
||||
|
||||
// Overwrite
|
||||
init: function (option) {
|
||||
PieSeries.superApply(this, 'init', arguments);
|
||||
|
||||
// Enable legend selection for each data item
|
||||
// Use a function instead of direct access because data reference may changed
|
||||
this.legendDataProvider = function () {
|
||||
return this._dataBeforeProcessed;
|
||||
};
|
||||
|
||||
this.updateSelectedMap(option.data);
|
||||
|
||||
this._defaultLabelLine(option);
|
||||
},
|
||||
|
||||
// Overwrite
|
||||
mergeOption: function (newOption) {
|
||||
PieSeries.superCall(this, 'mergeOption', newOption);
|
||||
this.updateSelectedMap(this.option.data);
|
||||
},
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var dimensions = completeDimensions(['value'], option.data);
|
||||
var list = new List(dimensions, this);
|
||||
list.initData(option.data);
|
||||
return list;
|
||||
},
|
||||
|
||||
// Overwrite
|
||||
getDataParams: function (dataIndex) {
|
||||
var data = this._data;
|
||||
var params = PieSeries.superCall(this, 'getDataParams', dataIndex);
|
||||
var sum = data.getSum('value');
|
||||
// FIXME toFixed?
|
||||
//
|
||||
// Percent is 0 if sum is 0
|
||||
params.percent = !sum ? 0 : +(data.get('value', dataIndex) / sum * 100).toFixed(2);
|
||||
|
||||
params.$vars.push('percent');
|
||||
return params;
|
||||
},
|
||||
|
||||
_defaultLabelLine: function (option) {
|
||||
// Extend labelLine emphasis
|
||||
modelUtil.defaultEmphasis(option.labelLine, ['show']);
|
||||
|
||||
var labelLineNormalOpt = option.labelLine.normal;
|
||||
var labelLineEmphasisOpt = option.labelLine.emphasis;
|
||||
// Not show label line if `label.normal.show = false`
|
||||
labelLineNormalOpt.show = labelLineNormalOpt.show
|
||||
&& option.label.normal.show;
|
||||
labelLineEmphasisOpt.show = labelLineEmphasisOpt.show
|
||||
&& option.label.emphasis.show;
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
legendHoverLink: true,
|
||||
|
||||
hoverAnimation: true,
|
||||
// 默认全局居中
|
||||
center: ['50%', '50%'],
|
||||
radius: [0, '75%'],
|
||||
// 默认顺时针
|
||||
clockwise: true,
|
||||
startAngle: 90,
|
||||
// 最小角度改为0
|
||||
minAngle: 0,
|
||||
// 选中是扇区偏移量
|
||||
selectedOffset: 10,
|
||||
|
||||
// If use strategy to avoid label overlapping
|
||||
avoidLabelOverlap: true,
|
||||
// 选择模式,默认关闭,可选single,multiple
|
||||
// selectedMode: false,
|
||||
// 南丁格尔玫瑰图模式,'radius'(半径) | 'area'(面积)
|
||||
// roseType: null,
|
||||
|
||||
label: {
|
||||
normal: {
|
||||
// If rotate around circle
|
||||
rotate: false,
|
||||
show: true,
|
||||
// 'outer', 'inside', 'center'
|
||||
position: 'outer'
|
||||
// formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调
|
||||
// textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
|
||||
// distance: 当position为inner时有效,为label位置到圆心的距离与圆半径(环状图为内外半径和)的比例系数
|
||||
},
|
||||
emphasis: {}
|
||||
},
|
||||
// Enabled when label.normal.position is 'outer'
|
||||
labelLine: {
|
||||
normal: {
|
||||
show: true,
|
||||
// 引导线两段中的第一段长度
|
||||
length: 15,
|
||||
// 引导线两段中的第二段长度
|
||||
length2: 15,
|
||||
smooth: false,
|
||||
lineStyle: {
|
||||
// color: 各异,
|
||||
width: 1,
|
||||
type: 'solid'
|
||||
}
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
// color: 各异,
|
||||
borderColor: 'rgba(0,0,0,0)',
|
||||
borderWidth: 1
|
||||
},
|
||||
emphasis: {
|
||||
// color: 各异,
|
||||
borderColor: 'rgba(0,0,0,0)',
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
|
||||
animationEasing: 'cubicOut',
|
||||
|
||||
data: []
|
||||
}
|
||||
});
|
||||
|
||||
zrUtil.mixin(PieSeries, dataSelectableMixin);
|
||||
|
||||
return PieSeries;
|
||||
});
|
||||
362
vendors/echarts/src/chart/pie/PieView.js
vendored
Normal file
362
vendors/echarts/src/chart/pie/PieView.js
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
/**
|
||||
* @param {module:echarts/model/Series} seriesModel
|
||||
* @param {boolean} hasAnimation
|
||||
* @inner
|
||||
*/
|
||||
function updateDataSelected(uid, seriesModel, hasAnimation, api) {
|
||||
var data = seriesModel.getData();
|
||||
var dataIndex = this.dataIndex;
|
||||
var name = data.getName(dataIndex);
|
||||
var selectedOffset = seriesModel.get('selectedOffset');
|
||||
|
||||
api.dispatchAction({
|
||||
type: 'pieToggleSelect',
|
||||
from: uid,
|
||||
name: name,
|
||||
seriesId: seriesModel.id
|
||||
});
|
||||
|
||||
data.each(function (idx) {
|
||||
toggleItemSelected(
|
||||
data.getItemGraphicEl(idx),
|
||||
data.getItemLayout(idx),
|
||||
seriesModel.isSelected(data.getName(idx)),
|
||||
selectedOffset,
|
||||
hasAnimation
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {module:zrender/graphic/Sector} el
|
||||
* @param {Object} layout
|
||||
* @param {boolean} isSelected
|
||||
* @param {number} selectedOffset
|
||||
* @param {boolean} hasAnimation
|
||||
* @inner
|
||||
*/
|
||||
function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) {
|
||||
var midAngle = (layout.startAngle + layout.endAngle) / 2;
|
||||
|
||||
var dx = Math.cos(midAngle);
|
||||
var dy = Math.sin(midAngle);
|
||||
|
||||
var offset = isSelected ? selectedOffset : 0;
|
||||
var position = [dx * offset, dy * offset];
|
||||
|
||||
hasAnimation
|
||||
// animateTo will stop revious animation like update transition
|
||||
? el.animate()
|
||||
.when(200, {
|
||||
position: position
|
||||
})
|
||||
.start('bounceOut')
|
||||
: el.attr('position', position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Piece of pie including Sector, Label, LabelLine
|
||||
* @constructor
|
||||
* @extends {module:zrender/graphic/Group}
|
||||
*/
|
||||
function PiePiece(data, idx) {
|
||||
|
||||
graphic.Group.call(this);
|
||||
|
||||
var sector = new graphic.Sector({
|
||||
z2: 2
|
||||
});
|
||||
var polyline = new graphic.Polyline();
|
||||
var text = new graphic.Text();
|
||||
this.add(sector);
|
||||
this.add(polyline);
|
||||
this.add(text);
|
||||
|
||||
this.updateData(data, idx, true);
|
||||
|
||||
// Hover to change label and labelLine
|
||||
function onEmphasis() {
|
||||
polyline.ignore = polyline.hoverIgnore;
|
||||
text.ignore = text.hoverIgnore;
|
||||
}
|
||||
function onNormal() {
|
||||
polyline.ignore = polyline.normalIgnore;
|
||||
text.ignore = text.normalIgnore;
|
||||
}
|
||||
this.on('emphasis', onEmphasis)
|
||||
.on('normal', onNormal)
|
||||
.on('mouseover', onEmphasis)
|
||||
.on('mouseout', onNormal);
|
||||
}
|
||||
|
||||
var piePieceProto = PiePiece.prototype;
|
||||
|
||||
function getLabelStyle(data, idx, state, labelModel, labelPosition) {
|
||||
var textStyleModel = labelModel.getModel('textStyle');
|
||||
var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
|
||||
return {
|
||||
fill: textStyleModel.getTextColor()
|
||||
|| (isLabelInside ? '#fff' : data.getItemVisual(idx, 'color')),
|
||||
opacity: data.getItemVisual(idx, 'opacity'),
|
||||
textFont: textStyleModel.getFont(),
|
||||
text: zrUtil.retrieve(
|
||||
data.hostModel.getFormattedLabel(idx, state), data.getName(idx)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
piePieceProto.updateData = function (data, idx, firstCreate) {
|
||||
|
||||
var sector = this.childAt(0);
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var layout = data.getItemLayout(idx);
|
||||
var sectorShape = zrUtil.extend({}, layout);
|
||||
sectorShape.label = null;
|
||||
if (firstCreate) {
|
||||
sector.setShape(sectorShape);
|
||||
sector.shape.endAngle = layout.startAngle;
|
||||
graphic.updateProps(sector, {
|
||||
shape: {
|
||||
endAngle: layout.endAngle
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
}
|
||||
else {
|
||||
graphic.updateProps(sector, {
|
||||
shape: sectorShape
|
||||
}, seriesModel, idx);
|
||||
}
|
||||
|
||||
// Update common style
|
||||
var itemStyleModel = itemModel.getModel('itemStyle');
|
||||
var visualColor = data.getItemVisual(idx, 'color');
|
||||
|
||||
sector.useStyle(
|
||||
zrUtil.defaults(
|
||||
{
|
||||
fill: visualColor
|
||||
},
|
||||
itemStyleModel.getModel('normal').getItemStyle()
|
||||
)
|
||||
);
|
||||
sector.hoverStyle = itemStyleModel.getModel('emphasis').getItemStyle();
|
||||
|
||||
// Toggle selected
|
||||
toggleItemSelected(
|
||||
this,
|
||||
data.getItemLayout(idx),
|
||||
itemModel.get('selected'),
|
||||
seriesModel.get('selectedOffset'),
|
||||
seriesModel.get('animation')
|
||||
);
|
||||
|
||||
function onEmphasis() {
|
||||
// Sector may has animation of updating data. Force to move to the last frame
|
||||
// Or it may stopped on the wrong shape
|
||||
sector.stopAnimation(true);
|
||||
sector.animateTo({
|
||||
shape: {
|
||||
r: layout.r + 10
|
||||
}
|
||||
}, 300, 'elasticOut');
|
||||
}
|
||||
function onNormal() {
|
||||
sector.stopAnimation(true);
|
||||
sector.animateTo({
|
||||
shape: {
|
||||
r: layout.r
|
||||
}
|
||||
}, 300, 'elasticOut');
|
||||
}
|
||||
sector.off('mouseover').off('mouseout').off('emphasis').off('normal');
|
||||
if (itemModel.get('hoverAnimation')) {
|
||||
sector
|
||||
.on('mouseover', onEmphasis)
|
||||
.on('mouseout', onNormal)
|
||||
.on('emphasis', onEmphasis)
|
||||
.on('normal', onNormal);
|
||||
}
|
||||
|
||||
this._updateLabel(data, idx);
|
||||
|
||||
graphic.setHoverStyle(this);
|
||||
};
|
||||
|
||||
piePieceProto._updateLabel = function (data, idx) {
|
||||
|
||||
var labelLine = this.childAt(1);
|
||||
var labelText = this.childAt(2);
|
||||
|
||||
var seriesModel = data.hostModel;
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var layout = data.getItemLayout(idx);
|
||||
var labelLayout = layout.label;
|
||||
var visualColor = data.getItemVisual(idx, 'color');
|
||||
|
||||
graphic.updateProps(labelLine, {
|
||||
shape: {
|
||||
points: labelLayout.linePoints || [
|
||||
[labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y], [labelLayout.x, labelLayout.y]
|
||||
]
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
|
||||
graphic.updateProps(labelText, {
|
||||
style: {
|
||||
x: labelLayout.x,
|
||||
y: labelLayout.y
|
||||
}
|
||||
}, seriesModel, idx);
|
||||
labelText.attr({
|
||||
style: {
|
||||
textVerticalAlign: labelLayout.verticalAlign,
|
||||
textAlign: labelLayout.textAlign,
|
||||
textFont: labelLayout.font
|
||||
},
|
||||
rotation: labelLayout.rotation,
|
||||
origin: [labelLayout.x, labelLayout.y],
|
||||
z2: 10
|
||||
});
|
||||
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var labelHoverModel = itemModel.getModel('label.emphasis');
|
||||
var labelLineModel = itemModel.getModel('labelLine.normal');
|
||||
var labelLineHoverModel = itemModel.getModel('labelLine.emphasis');
|
||||
var labelPosition = labelModel.get('position') || labelHoverModel.get('position');
|
||||
|
||||
labelText.setStyle(getLabelStyle(data, idx, 'normal', labelModel, labelPosition));
|
||||
|
||||
labelText.ignore = labelText.normalIgnore = !labelModel.get('show');
|
||||
labelText.hoverIgnore = !labelHoverModel.get('show');
|
||||
|
||||
labelLine.ignore = labelLine.normalIgnore = !labelLineModel.get('show');
|
||||
labelLine.hoverIgnore = !labelLineHoverModel.get('show');
|
||||
|
||||
// Default use item visual color
|
||||
labelLine.setStyle({
|
||||
stroke: visualColor,
|
||||
opacity: data.getItemVisual(idx, 'opacity')
|
||||
});
|
||||
labelLine.setStyle(labelLineModel.getModel('lineStyle').getLineStyle());
|
||||
|
||||
labelText.hoverStyle = getLabelStyle(data, idx, 'emphasis', labelHoverModel, labelPosition);
|
||||
labelLine.hoverStyle = labelLineHoverModel.getModel('lineStyle').getLineStyle();
|
||||
|
||||
var smooth = labelLineModel.get('smooth');
|
||||
if (smooth && smooth === true) {
|
||||
smooth = 0.4;
|
||||
}
|
||||
labelLine.setShape({
|
||||
smooth: smooth
|
||||
});
|
||||
};
|
||||
|
||||
zrUtil.inherits(PiePiece, graphic.Group);
|
||||
|
||||
|
||||
// Pie view
|
||||
var Pie = require('../../view/Chart').extend({
|
||||
|
||||
type: 'pie',
|
||||
|
||||
init: function () {
|
||||
var sectorGroup = new graphic.Group();
|
||||
this._sectorGroup = sectorGroup;
|
||||
},
|
||||
|
||||
render: function (seriesModel, ecModel, api, payload) {
|
||||
if (payload && (payload.from === this.uid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
var group = this.group;
|
||||
|
||||
var hasAnimation = ecModel.get('animation');
|
||||
var isFirstRender = !oldData;
|
||||
|
||||
var onSectorClick = zrUtil.curry(
|
||||
updateDataSelected, this.uid, seriesModel, hasAnimation, api
|
||||
);
|
||||
|
||||
var selectedMode = seriesModel.get('selectedMode');
|
||||
|
||||
data.diff(oldData)
|
||||
.add(function (idx) {
|
||||
var piePiece = new PiePiece(data, idx);
|
||||
if (isFirstRender) {
|
||||
piePiece.eachChild(function (child) {
|
||||
child.stopAnimation(true);
|
||||
});
|
||||
}
|
||||
|
||||
selectedMode && piePiece.on('click', onSectorClick);
|
||||
|
||||
data.setItemGraphicEl(idx, piePiece);
|
||||
|
||||
group.add(piePiece);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var piePiece = oldData.getItemGraphicEl(oldIdx);
|
||||
|
||||
piePiece.updateData(data, newIdx);
|
||||
|
||||
piePiece.off('click');
|
||||
selectedMode && piePiece.on('click', onSectorClick);
|
||||
group.add(piePiece);
|
||||
data.setItemGraphicEl(newIdx, piePiece);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
var piePiece = oldData.getItemGraphicEl(idx);
|
||||
group.remove(piePiece);
|
||||
})
|
||||
.execute();
|
||||
|
||||
if (hasAnimation && isFirstRender && data.count() > 0) {
|
||||
var shape = data.getItemLayout(0);
|
||||
var r = Math.max(api.getWidth(), api.getHeight()) / 2;
|
||||
|
||||
var removeClipPath = zrUtil.bind(group.removeClipPath, group);
|
||||
group.setClipPath(this._createClipPath(
|
||||
shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, seriesModel
|
||||
));
|
||||
}
|
||||
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
_createClipPath: function (
|
||||
cx, cy, r, startAngle, clockwise, cb, seriesModel
|
||||
) {
|
||||
var clipPath = new graphic.Sector({
|
||||
shape: {
|
||||
cx: cx,
|
||||
cy: cy,
|
||||
r0: 0,
|
||||
r: r,
|
||||
startAngle: startAngle,
|
||||
endAngle: startAngle,
|
||||
clockwise: clockwise
|
||||
}
|
||||
});
|
||||
|
||||
graphic.initProps(clipPath, {
|
||||
shape: {
|
||||
endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
|
||||
}
|
||||
}, seriesModel, cb);
|
||||
|
||||
return clipPath;
|
||||
}
|
||||
});
|
||||
|
||||
return Pie;
|
||||
});
|
||||
227
vendors/echarts/src/chart/pie/labelLayout.js
vendored
Normal file
227
vendors/echarts/src/chart/pie/labelLayout.js
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
// FIXME emphasis label position is not same with normal label position
|
||||
define(function (require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var textContain = require('zrender/contain/text');
|
||||
|
||||
function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight) {
|
||||
list.sort(function (a, b) {
|
||||
return a.y - b.y;
|
||||
});
|
||||
|
||||
// 压
|
||||
function shiftDown(start, end, delta, dir) {
|
||||
for (var j = start; j < end; j++) {
|
||||
list[j].y += delta;
|
||||
if (j > start
|
||||
&& j + 1 < end
|
||||
&& list[j + 1].y > list[j].y + list[j].height
|
||||
) {
|
||||
shiftUp(j, delta / 2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
shiftUp(end - 1, delta / 2);
|
||||
}
|
||||
|
||||
// 弹
|
||||
function shiftUp(end, delta) {
|
||||
for (var j = end; j >= 0; j--) {
|
||||
list[j].y -= delta;
|
||||
if (j > 0
|
||||
&& list[j].y > list[j - 1].y + list[j - 1].height
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function changeX(list, isDownList, cx, cy, r, dir) {
|
||||
var lastDeltaX = dir > 0
|
||||
? isDownList // 右侧
|
||||
? Number.MAX_VALUE // 下
|
||||
: 0 // 上
|
||||
: isDownList // 左侧
|
||||
? Number.MAX_VALUE // 下
|
||||
: 0; // 上
|
||||
|
||||
for (var i = 0, l = list.length; i < l; i++) {
|
||||
// Not change x for center label
|
||||
if (list[i].position === 'center') {
|
||||
continue;
|
||||
}
|
||||
var deltaY = Math.abs(list[i].y - cy);
|
||||
var length = list[i].len;
|
||||
var length2 = list[i].len2;
|
||||
var deltaX = (deltaY < r + length)
|
||||
? Math.sqrt(
|
||||
(r + length + length2) * (r + length + length2)
|
||||
- deltaY * deltaY
|
||||
)
|
||||
: Math.abs(list[i].x - cx);
|
||||
if (isDownList && deltaX >= lastDeltaX) {
|
||||
// 右下,左下
|
||||
deltaX = lastDeltaX - 10;
|
||||
}
|
||||
if (!isDownList && deltaX <= lastDeltaX) {
|
||||
// 右上,左上
|
||||
deltaX = lastDeltaX + 10;
|
||||
}
|
||||
|
||||
list[i].x = cx + deltaX * dir;
|
||||
lastDeltaX = deltaX;
|
||||
}
|
||||
}
|
||||
|
||||
var lastY = 0;
|
||||
var delta;
|
||||
var len = list.length;
|
||||
var upList = [];
|
||||
var downList = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
delta = list[i].y - lastY;
|
||||
if (delta < 0) {
|
||||
shiftDown(i, len, -delta, dir);
|
||||
}
|
||||
lastY = list[i].y + list[i].height;
|
||||
}
|
||||
if (viewHeight - lastY < 0) {
|
||||
shiftUp(len - 1, lastY - viewHeight);
|
||||
}
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (list[i].y >= cy) {
|
||||
downList.push(list[i]);
|
||||
}
|
||||
else {
|
||||
upList.push(list[i]);
|
||||
}
|
||||
}
|
||||
changeX(upList, false, cx, cy, r, dir);
|
||||
changeX(downList, true, cx, cy, r, dir);
|
||||
}
|
||||
|
||||
function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight) {
|
||||
var leftList = [];
|
||||
var rightList = [];
|
||||
for (var i = 0; i < labelLayoutList.length; i++) {
|
||||
if (labelLayoutList[i].x < cx) {
|
||||
leftList.push(labelLayoutList[i]);
|
||||
}
|
||||
else {
|
||||
rightList.push(labelLayoutList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight);
|
||||
adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight);
|
||||
|
||||
for (var i = 0; i < labelLayoutList.length; i++) {
|
||||
var linePoints = labelLayoutList[i].linePoints;
|
||||
if (linePoints) {
|
||||
var dist = linePoints[1][0] - linePoints[2][0];
|
||||
if (labelLayoutList[i].x < cx) {
|
||||
linePoints[2][0] = labelLayoutList[i].x + 3;
|
||||
}
|
||||
else {
|
||||
linePoints[2][0] = labelLayoutList[i].x - 3;
|
||||
}
|
||||
linePoints[1][1] = linePoints[2][1] = labelLayoutList[i].y;
|
||||
linePoints[1][0] = linePoints[2][0] + dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return function (seriesModel, r, viewWidth, viewHeight) {
|
||||
var data = seriesModel.getData();
|
||||
var labelLayoutList = [];
|
||||
var cx;
|
||||
var cy;
|
||||
var hasLabelRotate = false;
|
||||
|
||||
data.each(function (idx) {
|
||||
var layout = data.getItemLayout(idx);
|
||||
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
// Use position in normal or emphasis
|
||||
var labelPosition = labelModel.get('position') || itemModel.get('label.emphasis.position');
|
||||
|
||||
var labelLineModel = itemModel.getModel('labelLine.normal');
|
||||
var labelLineLen = labelLineModel.get('length');
|
||||
var labelLineLen2 = labelLineModel.get('length2');
|
||||
|
||||
var midAngle = (layout.startAngle + layout.endAngle) / 2;
|
||||
var dx = Math.cos(midAngle);
|
||||
var dy = Math.sin(midAngle);
|
||||
|
||||
var textX;
|
||||
var textY;
|
||||
var linePoints;
|
||||
var textAlign;
|
||||
|
||||
cx = layout.cx;
|
||||
cy = layout.cy;
|
||||
|
||||
var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner';
|
||||
if (labelPosition === 'center') {
|
||||
textX = layout.cx;
|
||||
textY = layout.cy;
|
||||
textAlign = 'center';
|
||||
}
|
||||
else {
|
||||
var x1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dx : layout.r * dx) + cx;
|
||||
var y1 = (isLabelInside ? (layout.r + layout.r0) / 2 * dy : layout.r * dy) + cy;
|
||||
|
||||
textX = x1 + dx * 3;
|
||||
textY = y1 + dy * 3;
|
||||
|
||||
if (!isLabelInside) {
|
||||
// For roseType
|
||||
var x2 = x1 + dx * (labelLineLen + r - layout.r);
|
||||
var y2 = y1 + dy * (labelLineLen + r - layout.r);
|
||||
var x3 = x2 + ((dx < 0 ? -1 : 1) * labelLineLen2);
|
||||
var y3 = y2;
|
||||
|
||||
textX = x3 + (dx < 0 ? -5 : 5);
|
||||
textY = y3;
|
||||
linePoints = [[x1, y1], [x2, y2], [x3, y3]];
|
||||
}
|
||||
|
||||
textAlign = isLabelInside ? 'center' : (dx > 0 ? 'left' : 'right');
|
||||
}
|
||||
var font = labelModel.getModel('textStyle').getFont();
|
||||
|
||||
var labelRotate = labelModel.get('rotate')
|
||||
? (dx < 0 ? -midAngle + Math.PI : -midAngle) : 0;
|
||||
var text = seriesModel.getFormattedLabel(idx, 'normal')
|
||||
|| data.getName(idx);
|
||||
var textRect = textContain.getBoundingRect(
|
||||
text, font, textAlign, 'top'
|
||||
);
|
||||
hasLabelRotate = !!labelRotate;
|
||||
layout.label = {
|
||||
x: textX,
|
||||
y: textY,
|
||||
position: labelPosition,
|
||||
height: textRect.height,
|
||||
len: labelLineLen,
|
||||
len2: labelLineLen2,
|
||||
linePoints: linePoints,
|
||||
textAlign: textAlign,
|
||||
verticalAlign: 'middle',
|
||||
font: font,
|
||||
rotation: labelRotate
|
||||
};
|
||||
|
||||
// Not layout the inside label
|
||||
if (!isLabelInside) {
|
||||
labelLayoutList.push(layout.label);
|
||||
}
|
||||
});
|
||||
if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) {
|
||||
avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight);
|
||||
}
|
||||
};
|
||||
});
|
||||
123
vendors/echarts/src/chart/pie/pieLayout.js
vendored
Normal file
123
vendors/echarts/src/chart/pie/pieLayout.js
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// TODO minAngle
|
||||
|
||||
define(function (require) {
|
||||
|
||||
var numberUtil = require('../../util/number');
|
||||
var parsePercent = numberUtil.parsePercent;
|
||||
var labelLayout = require('./labelLayout');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var PI2 = Math.PI * 2;
|
||||
var RADIAN = Math.PI / 180;
|
||||
|
||||
return function (seriesType, ecModel, api) {
|
||||
ecModel.eachSeriesByType(seriesType, function (seriesModel) {
|
||||
var center = seriesModel.get('center');
|
||||
var radius = seriesModel.get('radius');
|
||||
|
||||
if (!zrUtil.isArray(radius)) {
|
||||
radius = [0, radius];
|
||||
}
|
||||
if (!zrUtil.isArray(center)) {
|
||||
center = [center, center];
|
||||
}
|
||||
|
||||
var width = api.getWidth();
|
||||
var height = api.getHeight();
|
||||
var size = Math.min(width, height);
|
||||
var cx = parsePercent(center[0], width);
|
||||
var cy = parsePercent(center[1], height);
|
||||
var r0 = parsePercent(radius[0], size / 2);
|
||||
var r = parsePercent(radius[1], size / 2);
|
||||
|
||||
var data = seriesModel.getData();
|
||||
|
||||
var startAngle = -seriesModel.get('startAngle') * RADIAN;
|
||||
|
||||
var minAngle = seriesModel.get('minAngle') * RADIAN;
|
||||
|
||||
var sum = data.getSum('value');
|
||||
// Sum may be 0
|
||||
var unitRadian = Math.PI / (sum || data.count()) * 2;
|
||||
|
||||
var clockwise = seriesModel.get('clockwise');
|
||||
|
||||
var roseType = seriesModel.get('roseType');
|
||||
|
||||
// [0...max]
|
||||
var extent = data.getDataExtent('value');
|
||||
extent[0] = 0;
|
||||
|
||||
// In the case some sector angle is smaller than minAngle
|
||||
var restAngle = PI2;
|
||||
var valueSumLargerThanMinAngle = 0;
|
||||
|
||||
var currentAngle = startAngle;
|
||||
|
||||
var dir = clockwise ? 1 : -1;
|
||||
data.each('value', function (value, idx) {
|
||||
var angle;
|
||||
// FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样?
|
||||
if (roseType !== 'area') {
|
||||
angle = sum === 0 ? unitRadian : (value * unitRadian);
|
||||
}
|
||||
else {
|
||||
angle = PI2 / (data.count() || 1);
|
||||
}
|
||||
|
||||
if (angle < minAngle) {
|
||||
angle = minAngle;
|
||||
restAngle -= minAngle;
|
||||
}
|
||||
else {
|
||||
valueSumLargerThanMinAngle += value;
|
||||
}
|
||||
|
||||
var endAngle = currentAngle + dir * angle;
|
||||
data.setItemLayout(idx, {
|
||||
angle: angle,
|
||||
startAngle: currentAngle,
|
||||
endAngle: endAngle,
|
||||
clockwise: clockwise,
|
||||
cx: cx,
|
||||
cy: cy,
|
||||
r0: r0,
|
||||
r: roseType
|
||||
? numberUtil.linearMap(value, extent, [r0, r])
|
||||
: r
|
||||
});
|
||||
|
||||
currentAngle = endAngle;
|
||||
}, true);
|
||||
|
||||
// Some sector is constrained by minAngle
|
||||
// Rest sectors needs recalculate angle
|
||||
if (restAngle < PI2) {
|
||||
// Average the angle if rest angle is not enough after all angles is
|
||||
// Constrained by minAngle
|
||||
if (restAngle <= 1e-3) {
|
||||
var angle = PI2 / data.count();
|
||||
data.each(function (idx) {
|
||||
var layout = data.getItemLayout(idx);
|
||||
layout.startAngle = startAngle + dir * idx * angle;
|
||||
layout.endAngle = startAngle + dir * (idx + 1) * angle;
|
||||
});
|
||||
}
|
||||
else {
|
||||
unitRadian = restAngle / valueSumLargerThanMinAngle;
|
||||
currentAngle = startAngle;
|
||||
data.each('value', function (value, idx) {
|
||||
var layout = data.getItemLayout(idx);
|
||||
var angle = layout.angle === minAngle
|
||||
? minAngle : value * unitRadian;
|
||||
layout.startAngle = currentAngle;
|
||||
layout.endAngle = currentAngle + dir * angle;
|
||||
currentAngle += angle;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
labelLayout(seriesModel, r, width, height);
|
||||
});
|
||||
};
|
||||
});
|
||||
25
vendors/echarts/src/chart/radar.js
vendored
Normal file
25
vendors/echarts/src/chart/radar.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var echarts = require('../echarts');
|
||||
|
||||
// Must use radar component
|
||||
require('../component/radar');
|
||||
|
||||
require('./radar/RadarSeries');
|
||||
require('./radar/RadarView');
|
||||
|
||||
echarts.registerVisualCoding(
|
||||
'chart', zrUtil.curry(require('../visual/dataColor'), 'radar')
|
||||
);
|
||||
echarts.registerVisualCoding('chart', zrUtil.curry(
|
||||
require('../visual/symbol'), 'radar', 'circle', null
|
||||
));
|
||||
echarts.registerLayout(require('./radar/radarLayout'));
|
||||
|
||||
echarts.registerProcessor(
|
||||
'filter', zrUtil.curry(require('../processor/dataFilter'), 'radar')
|
||||
);
|
||||
|
||||
echarts.registerPreprocessor(require('./radar/backwardCompat'));
|
||||
});
|
||||
75
vendors/echarts/src/chart/radar/RadarSeries.js
vendored
Normal file
75
vendors/echarts/src/chart/radar/RadarSeries.js
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var SeriesModel = require('../../model/Series');
|
||||
var List = require('../../data/List');
|
||||
var completeDimensions = require('../../data/helper/completeDimensions');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
var RadarSeries = SeriesModel.extend({
|
||||
|
||||
type: 'series.radar',
|
||||
|
||||
dependencies: ['radar'],
|
||||
|
||||
|
||||
// Overwrite
|
||||
init: function (option) {
|
||||
RadarSeries.superApply(this, 'init', arguments);
|
||||
|
||||
// Enable legend selection for each data item
|
||||
// Use a function instead of direct access because data reference may changed
|
||||
this.legendDataProvider = function () {
|
||||
return this._dataBeforeProcessed;
|
||||
};
|
||||
},
|
||||
|
||||
getInitialData: function (option, ecModel) {
|
||||
var data = option.data || [];
|
||||
var dimensions = completeDimensions(
|
||||
[], data, [], 'indicator_'
|
||||
);
|
||||
var list = new List(dimensions, this);
|
||||
list.initData(data);
|
||||
return list;
|
||||
},
|
||||
|
||||
formatTooltip: function (dataIndex) {
|
||||
var value = this.getRawValue(dataIndex);
|
||||
var coordSys = this.coordinateSystem;
|
||||
var indicatorAxes = coordSys.getIndicatorAxes();
|
||||
return this._data.getName(dataIndex) + '<br />'
|
||||
+ zrUtil.map(indicatorAxes, function (axis, idx) {
|
||||
return axis.name + ' : ' + value[idx];
|
||||
}).join('<br />');
|
||||
},
|
||||
|
||||
defaultOption: {
|
||||
zlevel: 0,
|
||||
z: 2,
|
||||
coordinateSystem: 'radar',
|
||||
legendHoverLink: true,
|
||||
radarIndex: 0,
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 2,
|
||||
type: 'solid'
|
||||
}
|
||||
},
|
||||
label: {
|
||||
normal: {
|
||||
position: 'top'
|
||||
}
|
||||
},
|
||||
// areaStyle: {
|
||||
// },
|
||||
// itemStyle: {}
|
||||
symbol: 'emptyCircle',
|
||||
symbolSize: 4
|
||||
// symbolRotate: null
|
||||
}
|
||||
});
|
||||
|
||||
return RadarSeries;
|
||||
});
|
||||
219
vendors/echarts/src/chart/radar/RadarView.js
vendored
Normal file
219
vendors/echarts/src/chart/radar/RadarView.js
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
define(function (require) {
|
||||
|
||||
var graphic = require('../../util/graphic');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var symbolUtil = require('../../util/symbol');
|
||||
|
||||
function normalizeSymbolSize(symbolSize) {
|
||||
if (!zrUtil.isArray(symbolSize)) {
|
||||
symbolSize = [+symbolSize, +symbolSize];
|
||||
}
|
||||
return symbolSize;
|
||||
}
|
||||
return require('../../echarts').extendChartView({
|
||||
type: 'radar',
|
||||
|
||||
render: function (seriesModel, ecModel, api) {
|
||||
var polar = seriesModel.coordinateSystem;
|
||||
var group = this.group;
|
||||
|
||||
var data = seriesModel.getData();
|
||||
var oldData = this._data;
|
||||
|
||||
function createSymbol(data, idx) {
|
||||
var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
if (symbolType === 'none') {
|
||||
return;
|
||||
}
|
||||
var symbolPath = symbolUtil.createSymbol(
|
||||
symbolType, -0.5, -0.5, 1, 1, color
|
||||
);
|
||||
symbolPath.attr({
|
||||
style: {
|
||||
strokeNoScale: true
|
||||
},
|
||||
z2: 100,
|
||||
scale: normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'))
|
||||
});
|
||||
return symbolPath;
|
||||
}
|
||||
|
||||
function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) {
|
||||
// Simply rerender all
|
||||
symbolGroup.removeAll();
|
||||
for (var i = 0; i < newPoints.length - 1; i++) {
|
||||
var symbolPath = createSymbol(data, idx);
|
||||
if (symbolPath) {
|
||||
symbolPath.__dimIdx = i;
|
||||
if (oldPoints[i]) {
|
||||
symbolPath.attr('position', oldPoints[i]);
|
||||
graphic[isInit ? 'initProps' : 'updateProps'](
|
||||
symbolPath, {
|
||||
position: newPoints[i]
|
||||
}, seriesModel, idx
|
||||
);
|
||||
}
|
||||
else {
|
||||
symbolPath.attr('position', newPoints[i]);
|
||||
}
|
||||
symbolGroup.add(symbolPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getInitialPoints(points) {
|
||||
return zrUtil.map(points, function (pt) {
|
||||
return [polar.cx, polar.cy];
|
||||
});
|
||||
}
|
||||
data.diff(oldData)
|
||||
.add(function (idx) {
|
||||
var points = data.getItemLayout(idx);
|
||||
if (!points) {
|
||||
return;
|
||||
}
|
||||
var polygon = new graphic.Polygon();
|
||||
var polyline = new graphic.Polyline();
|
||||
var target = {
|
||||
shape: {
|
||||
points: points
|
||||
}
|
||||
};
|
||||
polygon.shape.points = getInitialPoints(points);
|
||||
polyline.shape.points = getInitialPoints(points);
|
||||
graphic.initProps(polygon, target, seriesModel, idx);
|
||||
graphic.initProps(polyline, target, seriesModel, idx);
|
||||
|
||||
var itemGroup = new graphic.Group();
|
||||
var symbolGroup = new graphic.Group();
|
||||
itemGroup.add(polyline);
|
||||
itemGroup.add(polygon);
|
||||
itemGroup.add(symbolGroup);
|
||||
|
||||
updateSymbols(
|
||||
polyline.shape.points, points, symbolGroup, data, idx, true
|
||||
);
|
||||
|
||||
data.setItemGraphicEl(idx, itemGroup);
|
||||
})
|
||||
.update(function (newIdx, oldIdx) {
|
||||
var itemGroup = oldData.getItemGraphicEl(oldIdx);
|
||||
var polyline = itemGroup.childAt(0);
|
||||
var polygon = itemGroup.childAt(1);
|
||||
var symbolGroup = itemGroup.childAt(2);
|
||||
var target = {
|
||||
shape: {
|
||||
points: data.getItemLayout(newIdx)
|
||||
}
|
||||
};
|
||||
if (!target.shape.points) {
|
||||
return;
|
||||
}
|
||||
updateSymbols(
|
||||
polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false
|
||||
);
|
||||
|
||||
graphic.updateProps(polyline, target, seriesModel);
|
||||
graphic.updateProps(polygon, target, seriesModel);
|
||||
|
||||
data.setItemGraphicEl(newIdx, itemGroup);
|
||||
})
|
||||
.remove(function (idx) {
|
||||
group.remove(oldData.getItemGraphicEl(idx));
|
||||
})
|
||||
.execute();
|
||||
|
||||
data.eachItemGraphicEl(function (itemGroup, idx) {
|
||||
var itemModel = data.getItemModel(idx);
|
||||
var polyline = itemGroup.childAt(0);
|
||||
var polygon = itemGroup.childAt(1);
|
||||
var symbolGroup = itemGroup.childAt(2);
|
||||
var color = data.getItemVisual(idx, 'color');
|
||||
|
||||
group.add(itemGroup);
|
||||
|
||||
polyline.useStyle(
|
||||
zrUtil.extend(
|
||||
itemModel.getModel('lineStyle.normal').getLineStyle(),
|
||||
{
|
||||
fill: 'none',
|
||||
stroke: color
|
||||
}
|
||||
)
|
||||
);
|
||||
polyline.hoverStyle = itemModel.getModel('lineStyle.emphasis').getLineStyle();
|
||||
|
||||
var areaStyleModel = itemModel.getModel('areaStyle.normal');
|
||||
var hoverAreaStyleModel = itemModel.getModel('areaStyle.emphasis');
|
||||
var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty();
|
||||
var hoverPolygonIgnore = hoverAreaStyleModel.isEmpty() && hoverAreaStyleModel.parentModel.isEmpty();
|
||||
|
||||
hoverPolygonIgnore = hoverPolygonIgnore && polygonIgnore;
|
||||
polygon.ignore = polygonIgnore;
|
||||
|
||||
polygon.useStyle(
|
||||
zrUtil.defaults(
|
||||
areaStyleModel.getAreaStyle(),
|
||||
{
|
||||
fill: color,
|
||||
opacity: 0.7
|
||||
}
|
||||
)
|
||||
);
|
||||
polygon.hoverStyle = hoverAreaStyleModel.getAreaStyle();
|
||||
|
||||
var itemStyle = itemModel.getModel('itemStyle.normal').getItemStyle(['color']);
|
||||
var itemHoverStyle = itemModel.getModel('itemStyle.emphasis').getItemStyle();
|
||||
var labelModel = itemModel.getModel('label.normal');
|
||||
var labelHoverModel = itemModel.getModel('label.emphasis');
|
||||
symbolGroup.eachChild(function (symbolPath) {
|
||||
symbolPath.setStyle(itemStyle);
|
||||
symbolPath.hoverStyle = zrUtil.clone(itemHoverStyle);
|
||||
|
||||
var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx);
|
||||
graphic.setText(symbolPath.style, labelModel, color);
|
||||
symbolPath.setStyle({
|
||||
text: labelModel.get('show') ? zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(
|
||||
idx, 'normal', null, symbolPath.__dimIdx
|
||||
),
|
||||
defaultText
|
||||
) : ''
|
||||
});
|
||||
|
||||
graphic.setText(symbolPath.hoverStyle, labelHoverModel, color);
|
||||
symbolPath.hoverStyle.text = labelHoverModel.get('show') ? zrUtil.retrieve(
|
||||
seriesModel.getFormattedLabel(
|
||||
idx, 'emphasis', null, symbolPath.__dimIdx
|
||||
),
|
||||
defaultText
|
||||
) : '';
|
||||
});
|
||||
|
||||
function onEmphasis() {
|
||||
polygon.attr('ignore', hoverPolygonIgnore);
|
||||
}
|
||||
|
||||
function onNormal() {
|
||||
polygon.attr('ignore', polygonIgnore);
|
||||
}
|
||||
|
||||
itemGroup.off('mouseover').off('mouseout').off('normal').off('emphasis');
|
||||
itemGroup.on('emphasis', onEmphasis)
|
||||
.on('mouseover', onEmphasis)
|
||||
.on('normal', onNormal)
|
||||
.on('mouseout', onNormal);
|
||||
|
||||
graphic.setHoverStyle(itemGroup);
|
||||
});
|
||||
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this.group.removeAll();
|
||||
this._data = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
36
vendors/echarts/src/chart/radar/backwardCompat.js
vendored
Normal file
36
vendors/echarts/src/chart/radar/backwardCompat.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Backward compat for radar chart in 2
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
return function (option) {
|
||||
var polarOptArr = option.polar;
|
||||
if (polarOptArr) {
|
||||
if (!zrUtil.isArray(polarOptArr)) {
|
||||
polarOptArr = [polarOptArr];
|
||||
}
|
||||
var polarNotRadar = [];
|
||||
zrUtil.each(polarOptArr, function (polarOpt, idx) {
|
||||
if (polarOpt.indicator) {
|
||||
if (polarOpt.type && !polarOpt.shape) {
|
||||
polarOpt.shape = polarOpt.type;
|
||||
}
|
||||
option.radar = option.radar || [];
|
||||
if (!zrUtil.isArray(option.radar)) {
|
||||
option.radar = [option.radar];
|
||||
}
|
||||
option.radar.push(polarOpt);
|
||||
}
|
||||
else {
|
||||
polarNotRadar.push(polarOpt);
|
||||
}
|
||||
});
|
||||
option.polar = polarNotRadar;
|
||||
}
|
||||
zrUtil.each(option.series, function (seriesOpt) {
|
||||
if (seriesOpt.type === 'radar' && seriesOpt.polarIndex) {
|
||||
seriesOpt.radarIndex = seriesOpt.polarIndex;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
28
vendors/echarts/src/chart/radar/radarLayout.js
vendored
Normal file
28
vendors/echarts/src/chart/radar/radarLayout.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
define(function (require) {
|
||||
|
||||
return function (ecModel, api) {
|
||||
ecModel.eachSeriesByType('radar', function (seriesModel) {
|
||||
var data = seriesModel.getData();
|
||||
var points = [];
|
||||
var coordSys = seriesModel.coordinateSystem;
|
||||
if (!coordSys) {
|
||||
return;
|
||||
}
|
||||
|
||||
function pointsConverter(val, idx) {
|
||||
points[idx] = points[idx] || [];
|
||||
points[idx][i] = coordSys.dataToPoint(val, i);
|
||||
}
|
||||
for (var i = 0; i < coordSys.getIndicatorAxes().length; i++) {
|
||||
var dim = data.dimensions[i];
|
||||
data.each(dim, pointsConverter);
|
||||
}
|
||||
|
||||
data.each(function (idx) {
|
||||
// Close polygon
|
||||
points[idx][0] && points[idx].push(points[idx][0].slice());
|
||||
data.setItemLayout(idx, points[idx]);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user