提交 e3b6dd3f 编写于 作者: P pah100

add parallel

上级 0181bc07
define(function (require) {
require('./parallel/ParallelSeries');
require('./parallel/ParallelView');
});
\ No newline at end of file
define(function(require) {
var createListFromArray = require('../helper/createListFromArray');
var SeriesModel = require('../../model/Series');
return SeriesModel.extend({
type: 'series.parallel',
dependencies: ['parallel'],
getInitialData: function (option, ecModel) {
return createListFromArray(option.data, this, ecModel);
},
defaultOption: {
zlevel: 0, // 一级层叠
z: 2, // 二级层叠
coordinateSystem: 'parallel',
parallelIndex: 0,
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
}
},
itemStyle: {
normal: {
// color: 各异
},
emphasis: {
// color: 各异,
}
},
lineStyle: {
normal: {
width: 2,
type: 'solid',
shadowColor: 'rgba(0,0,0,0)', //默认透明
shadowBlur: 0,
shadowOffsetX: 0,
shadowOffsetY: 0
}
},
// areaStyle: {
// },
// smooth: false,
// 拐点图形类型
symbol: 'emptyCircle',
// 拐点图形大小
symbolSize: 4,
// 拐点图形旋转控制
// symbolRotate: null,
// 标志图形默认只有主轴显示(随主轴标签间隔隐藏策略)
showAllSymbol: false
}
});
});
\ No newline at end of file
define(function (require) {
var graphic = require('../../util/graphic');
var zrUtil = require('zrender/core/util');
var ParallelView = require('../../view/Chart').extend({
type: 'pie',
init: function () {
this._dataGroup = new graphic.Group();
},
render: function (seriesModel, ecModel, api, payload) {
var data = seriesModel.getData();
var oldData = this._data;
var dataGroup = this._dataGroup;
var group = this.group;
var coordSys = seriesModel.coordinateSystem;
var dimensions = coordSys.dimensions;
var hasAnimation = ecModel.get('animation');
var isFirstRender = !oldData;
var lineStyleModel = seriesModel.getModel('lineStyle.normal');
var lineStyle = lineStyleModel.getLineStyle();
// var onSectorClick = zrUtil.curry(
// updateDataSelected, this.uid, seriesModel, hasAnimation, api
// );
// var selectedMode = seriesModel.get('selectedMode');
data.diff(oldData)
.add(function (dataIndex) {
var values = data.getValues(dimensions, dataIndex);
var els = createEls(
dataGroup, values, dimensions, coordSys,
lineStyle, hasAnimation && !isFirstRender
);
data.setItemGraphicEl(dataIndex, els);
})
.update(function (newDataIndex, oldDataIndex) {
// var els = oldData.getItemGraphicEl(oldDataIndex);
// var values = data.getValues(dimensions, newDataIndex);
// updateEls(
// els, dataGroup, values, dimensions, coordSys, lineStyle
// );
// api.updateGraphicEl(sector, {
// points: layout
// });
// api.updateGraphicEl(labelLine, {
// shape: {
// points: labelLayout.linePoints
// }
// });
// api.updateGraphicEl(labelText, {
// style: {
// x: labelLayout.x,
// y: labelLayout.y
// },
// rotation: labelLayout.rotation
// });
// // Set none animating style
// labelText.setStyle({
// textAlign: labelLayout.textAlign,
// textBaseline: labelLayout.textBaseline,
// textFont: labelLayout.font
// });
// sectorGroup.add(sector);
// data.setItemGraphicEl(newDataIndex, sector);
// group.add(labelLine);
// group.add(labelText);
})
.remove(function (idx) {
// var sector = oldData.getItemGraphicEl(idx);
// sectorGroup.remove(sector);
})
.execute();
// Make sure data els is on top of labels
group.remove(dataGroup);
group.add(dataGroup);
this._updateAll(data, seriesModel);
this._data = data;
},
_updateAll: function (data, seriesModel, hasAnimation) {
// var selectedOffset = seriesModel.get('selectedOffset');
// data.eachItemGraphicEl(function (sector, idx) {
// var itemModel = data.getItemModel(idx);
// var itemStyleModel = itemModel.getModel('itemStyle');
// var visualColor = data.getItemVisual(idx, 'color');
// sector.setStyle(
// zrUtil.extend(
// {
// fill: visualColor
// },
// itemStyleModel.getModel('normal').getItemStyle()
// )
// );
// graphic.setHoverStyle(
// sector,
// itemStyleModel.getModel('emphasis').getItemStyle()
// );
// // Set label style
// var labelText = sector.__labelText;
// var labelLine = sector.__labelLine;
// var labelModel = itemModel.getModel('label.normal');
// var textStyleModel = labelModel.getModel('textStyle');
// var labelPosition = labelModel.get('position');
// var isLabelInside = labelPosition === 'inside';
// labelText.setStyle({
// fill: textStyleModel.get('color')
// || isLabelInside ? '#fff' : visualColor,
// text: seriesModel.getFormattedLabel(idx, 'normal')
// || data.getName(idx),
// textFont: textStyleModel.getFont()
// });
// labelText.attr('ignore', !labelModel.get('show'));
// // Default use item visual color
// labelLine.attr('ignore', !itemModel.get('labelLine.show'));
// labelLine.setStyle({
// stroke: visualColor
// });
// labelLine.setStyle(itemModel.getModel('labelLine').getLineStyle());
// toggleItemSelected(
// sector,
// data.getItemLayout(idx),
// itemModel.get('selected'),
// selectedOffset,
// hasAnimation
// );
// });
},
dispose: function () {}
});
function createEls(dataGroup, values, dimensions, coordSys, lineStyle) {
// FIXME
// init animation
var els = [];
for (var i = 0, len = dimensions.length - 1; i < len; i++) {
var points = [
coordSys.dataToPoint(values[i], dimensions[i]),
coordSys.dataToPoint(values[i + 1], dimensions[i + 1])
];
dataGroup.add(els[i] = new graphic.Polyline({
points: points,
style: lineStyle
}));
}
return els;
}
// function updateEls(els, values, dimensions, coordSys) {
// // FIXME
// // update animation
// var els = [];
// for (var i = 0, len = dimensions.length - 1; i < len; i++) {
// var points = [
// coordSys.dataToPoint(values[i], dimensions[i]),
// coordSys.dataToPoint(values[i + 1], dimensions[i + 1])
// ];
// dataGroup.add(els[i] = new graphic.Polyline({
// points: points,
// style: lineStyle
// }));
// api.updateGraphicEl(sector, {
// points: layout
// });
// }
// return els;
// }
function getElProp() {
}
return ParallelView;
});
\ No newline at end of file
define(function (require) {
var zrUtil = require('zrender/core/util');
var graphic = require('../../util/graphic');
var EPSILON = 1e-4;
var PI2 = Math.PI * 2;
var PI = Math.PI;
/**
* @param {module:zrender/container/Group} group
* @param {Object} axisModel
* @param {Object} opt Standard axis parameters.
* @param {Array.<number>} opt.position [x, y]
* @param {number} opt.rotation by radian
* @param {number} opt.tickDirection 1 or -1
* @param {number} opt.labelDirection 1 or -1
* @param {string} [opt.axisName] default get from axisModel.
* @param {number} [opt.lableRotation] by degree, default get from axisModel.
* @param {number} [opt.lableInterval] Default label interval when label
* interval from model is null or 'auto'.
* @param {number} [opt.isCartesian=false]
* @param {number} [opt.z2=0]
*/
var AxisBuilder = function (axisModel, opt) {
/**
* @readOnly
*/
this.opt = opt;
/**
* @readOnly
*/
this.axisModel = axisModel;
/**
* @readOnly
*/
this.group = new graphic.Group({
position: opt.position.slice(),
rotation: opt.rotation,
z2: opt.z2
});
};
AxisBuilder.prototype = {
constructor: AxisBuilder,
hasBuilder: function (name) {
return !!builders[name];
},
add: function (name) {
builders[name].call(this);
},
getGroup: function () {
return this.group;
},
/**
* @inner
*/
_getExtent: function () {
var opt = this.opt;
var extent = this.axisModel.axis.getExtent();
opt.offset = 0;
// FIXME
// 修正axisExtent不统一
if (opt.isCartesian) {
var min = Math.min(extent[0], extent[1]);
var max = Math.max(extent[0], extent[1]);
opt.offset = min;
extent = [0, max - opt.offset];
}
return extent;
}
};
var builders = {
/**
* @private
*/
axisLine: function () {
var axisModel = this.axisModel;
var extent = this._getExtent();
this.group.add(new graphic.Line({
shape: {
x1: extent[0],
y1: 0,
x2: extent[1],
y2: 0
},
style: zrUtil.extend(
{lineCap: 'round'},
axisModel.getModel('axisLine.lineStyle').getLineStyle()
),
silent: true,
z2: 1
}));
},
/**
* @private
*/
axisTick: function () {
var axisModel = this.axisModel;
var axis = axisModel.axis;
var tickModel = axisModel.getModel('axisTick');
var opt = this.opt;
var lineStyleModel = tickModel.getModel('lineStyle');
var tickLen = tickModel.get('length');
var tickInterval = getInterval(tickModel, opt);
var ticksCoords = axis.getTicksCoords();
var tickLines = [];
for (var i = 0; i < ticksCoords.length; i++) {
// Only ordinal scale support tick interval
if (ifIgnoreOnTick(axis, i, tickInterval)) {
// ??? 检查 计算正确?(因为offset)
continue;
}
var tickCoord = ticksCoords[i] - opt.offset;
// Tick line
tickLines.push(new graphic.Line(graphic.subPixelOptimizeLine({
shape: {
x1: tickCoord,
y1: 0,
x2: tickCoord,
y2: opt.tickDirection * tickLen
},
style: {
lineWidth: lineStyleModel.get('width')
},
silent: true
})));
}
this.group.add(graphic.mergePath(tickLines, {
style: lineStyleModel.getLineStyle(),
silent: true
}));
},
/**
* @param {module:echarts/coord/cartesian/AxisModel} axisModel
* @param {module:echarts/coord/cartesian/GridModel} gridModel
* @private
*/
axisLabel: function () {
var opt = this.opt;
var axisModel = this.axisModel;
var axis = axisModel.axis;
var labelModel = axisModel.getModel('axisLabel');
var textStyleModel = labelModel.getModel('textStyle');
var labelMargin = labelModel.get('margin');
var ticks = axis.scale.getTicks();
var labels = axisModel.formatLabels(axis.scale.getTicksLabels());
// Special label rotate.
var labelRotation = opt.labelRotation;
if (labelRotation == null) {
labelRotation = labelModel.get('rotate') || 0;
}
// To radian.
labelRotation = labelRotation * PI / 180;
var labelLayout = innerTextLayout(opt, labelRotation);
for (var i = 0; i < ticks.length; i++) {
if (ifIgnoreOnTick(axis, i, opt.labelInterval)) {
continue;
}
var tickCoord = axis.dataToCoord(ticks[i]) - opt.offset;
var pos = [tickCoord, opt.labelDirection * labelMargin];
this.group.add(new graphic.Text({
style: {
x: pos[0],
y: pos[1],
text: labels[i],
textAlign: labelLayout.textAlign,
textBaseline: labelLayout.textBaseline,
textFont: textStyleModel.getFont(),
fill: textStyleModel.get('color')
},
rotation: labelLayout.rotation,
origin: pos,
silent: true
}));
}
},
/**
* @private
*/
axisName: function () {
var opt = this.opt;
var axisModel = this.axisModel;
var name = this.opt.name;
// If name is '', do not get name from axisMode.
if (name == null) {
name = axisModel.get('name');
}
if (!name) {
return;
}
var nameLocation = axisModel.get('nameLocation');
var textStyleModel = axisModel.getModel('nameTextStyle');
var gap = axisModel.get('nameGap') || 0;
var position = opt.position;
var extent = this._getExtent();
var textX = nameLocation == 'start'
? position[0] - gap
: position[0] + extent[1] + gap;
var textY = position[1];
var labelLayout;
if (nameLocation === 'middle') {
labelLayout = innerTextLayout(opt, opt.rotation);
}
else {
labelLayout = endTextLayout(opt, nameLocation);
}
this.group.add(new graphic.Text({
style: {
text: name,
textFont: textStyleModel.getFont(),
fill: textStyleModel.get('color')
|| axisModel.get('axisLine.lineStyle.color'),
textAlign: labelLayout.textAlign,
textBaseline: labelLayout.textBaseline
},
position: [textX, textY],
silent: true,
z2: 1
}));
}
};
/**
* @inner
*/
function innerTextLayout(opt, textRotation) {
var labelDirection = opt.labelDirection;
var rotationDiff = remRadian(textRotation - opt.rotation);
var textAlign;
var textBaseline;
if (isAroundZero(rotationDiff)) { // Label is parallel with axis line.
textBaseline = labelDirection > 0 ? 'top' : 'bottom';
textAlign = 'center';
}
else if (isAroundZero(rotationDiff - PI)) { // Label is inverse parallel with axis line.
textBaseline = labelDirection > 0 ? 'bottom' : 'top';
textAlign = 'center';
}
else {
textBaseline = 'middle';
if (rotationDiff > 0 && rotationDiff < PI) {
textAlign = labelDirection > 0 ? 'right' : 'left';
}
else {
textAlign = labelDirection > 0 ? 'left' : 'right';
}
}
return {
rotation: rotationDiff,
textAlign: textAlign,
textBaseline: textBaseline
};
}
/**
* @inner
*/
function endTextLayout(opt, textPosition) {
var rotationDiff = remRadian(-opt.rotation);
var textAlign;
var textBaseline;
if (isAroundZero(rotationDiff - PI / 2)) {
textBaseline = textPosition === 'start' ? 'top' : 'bottom';
textAlign = 'center';
}
else if (isAroundZero(rotationDiff - PI * 1.5)) {
textBaseline = textPosition === 'start' ? 'bottom' : 'top';
textAlign = 'center';
}
else {
textBaseline = 'middle';
if (rotationDiff < PI * 1.5 && rotationDiff > PI / 2) {
textAlign = textPosition === 'start' ? 'left' : 'right';
}
else {
textAlign = textPosition === 'start' ? 'right' : 'left';
}
}
return {
rotation: rotationDiff,
textAlign: textAlign,
textBaseline: textBaseline
};
}
/**
* @inner
*/
function ifIgnoreOnTick(axis, i, interval) {
return axis.scale.type === 'ordinal'
&& (typeof interval === 'function')
&& !interval(i, axis.scale.getItem(i))
|| i % (interval + 1);
}
/**
* @inner
*/
function getInterval(model, opt) {
var interval = model.get('interval');
if (interval == null || interval == 'auto') {
interval = opt.labelInterval;
}
return interval;
}
/**
* @inner
*/
function isAroundZero(val) {
return val > -EPSILON && val < EPSILON;
}
/**
* @inner
*/
function remRadian(radian) {
// To 0 - 2 * PI, considering negative radian.
return (radian % PI2 + PI2) % PI2;
}
return AxisBuilder;
});
\ No newline at end of file
define(function (require) {
var zrUtil = require('zrender/core/util');
var AxisBuilder = require('./AxisBuilder');
var elementList = ['axisLine', 'axisLabel', 'axisTick', 'axisName'];
var AxisView = require('../../echarts').extendComponentView({
type: 'parallelAxis',
render: function (axisModel, ecModel) {
this.group.removeAll();
if (!axisModel.get('show')) {
return;
}
var coordSys = ecModel.getComponent('parallel', axisModel.get('parallelIndex'));
var axisBuilder = new AxisBuilder(coordSys.getAxisLayout(axisModel.axis.dim));
zrUtil.each(elementList, function (name) {
if (axisModel.get(name +'.show')) {
axisBuilder.add(name);
}
}, this);
this.group.add(axisBuilder.getGroup());
}
});
return AxisView;
});
\ No newline at end of file
define(function(require) {
require('../coord/parallel/parallelCreator');
require('./parallelAxis');
var echarts = require('../echarts');
// Parallel view
echarts.extendComponentView({
type: 'parallel'
});
echarts.registerPreprocessor(require('../preprocessor/parallel'));
});
\ No newline at end of file
define(function(require) {
require('../coord/parallel/parallelCreator');
require('./axis/ParallelAxisView');
});
\ No newline at end of file
define(function(require) {
var ComponentModel = require('../../model/Component');
var defaultOption = require('../axisDefault');
var zrUtil = require('zrender/core/util');
function mergeDefault(axisOption, ecModel) {
var axisType = axisOption.type + 'Axis';
zrUtil.merge(axisOption, ecModel.get(axisType));
zrUtil.merge(axisOption, ecModel.getTheme().get(axisType));
zrUtil.merge(axisOption, defaultOption[axisType]);
}
var AxisModel = ComponentModel.extend({
type: 'parallelAxis',
/**
* @type {module:echarts/coord/parallel/Axis}
*/
axis: null,
defaultOption: {
type: 'value',
parallelIndex: null
},
init: function (axisOption, parentModel, ecModel) {
zrUtil.merge(axisOption, this.getDefaultOption(), false);
mergeDefault(axisOption, ecModel);
},
/**
* @public
* @param {boolean} needs Whether axis needs cross zero.
*/
setNeedsCrossZero: function (needs) {
this.option.scale = !needs;
},
/**
* @public
*/
setParallelIndex: function (parallelIndex) {
this.option.parallelIndex = parallelIndex;
}
});
zrUtil.merge(AxisModel.prototype, require('../axisModelCommonMixin'));
return AxisModel;
});
\ No newline at end of file
/**
* Parallel Coordinates
* <https://en.wikipedia.org/wiki/Parallel_coordinates>
*/
define(function(require) {
var layout = require('../../util/layout');
var axisHelper = require('../../coord/axisHelper');
var zrUtil = require('zrender/core/util');
var ParallelAxis = require('./ParallelAxis');
var matrix = require('zrender/core/matrix');
var vector = require('zrender/core/vector');
var each = zrUtil.each;
var PI = Math.PI;
function Parallel(parallelModel, ecModel, api) {
/**
* key: dimension
* @type {Object.<string, module:echarts/coord/parallel/Axis>}
* @private
*/
this._axesMap = {};
/**
* key: dimension
* value: {position: [], rotation, }
* @type {Object.<string, Object>}
* @private
*/
this._axesLayout = {};
/**
* Always follow axis order.
* @type {Array.<number>}
* @readOnly
*/
this.dimensions = parallelModel.get('dimensions');
/**
* @type {module:zrender/core/BoundingRect}
*/
this._rect;
this._init(parallelModel, ecModel, api);
this.resize(parallelModel, api);
}
Parallel.prototype = {
type: 'parallel',
constructor: Parallel,
/**
* Initialize cartesian coordinate systems
* @private
*/
_init: function (parallelModel, ecModel, api) {
var dimensions = parallelModel.get('dimensions');
var axisIndices = parallelModel.get('parallelAxisIndex');
each(axisIndices, function (axisIndex, idx) {
var axisModel = ecModel.getComponent('parallelAxis', axisIndex);
var parallelIndex = axisModel.get('parallelIndex');
if (ecModel.getComponent('parallel', parallelIndex) !== parallelModel) {
// FIXME
// api.log('Axis should not be shared among coordinate systems!');
return;
}
var dim = dimensions[idx];
var axis = this._axesMap[dim] = new ParallelAxis(
dim,
axisHelper.createScaleByModel(axisModel),
[0, 0],
axisModel.get('type')
);
var isCategory = axis.type === 'category';
axis.onBand = isCategory && axisModel.get('boundaryGap');
axis.inverse = axisModel.get('inverse');
// Inject axis into axisModel
axisModel.axis = axis;
// Inject axisModel into axis
axis.model = axisModel;
axisHelper.niceScaleExtent(axis, axisModel);
}, this);
},
/**
* Resize the parallel coordinate system.
* @param {module:echarts/coord/parallel/ParallelModel} parallelModel
* @param {module:echarts/ExtensionAPI} api
*/
resize: function (parallelModel, api) {
this._rect = layout.parsePositionInfo(
{
x: parallelModel.get('x'),
y: parallelModel.get('y'),
x2: parallelModel.get('x2'),
y2: parallelModel.get('y2'),
width: parallelModel.get('width'),
height: parallelModel.get('height')
},
{
width: api.getWidth(),
height: api.getHeight()
}
);
this._layoutAxes(parallelModel);
},
/**
* @private
*/
_layoutAxes: function (parallelModel) {
var rect = this._rect;
var layout = parallelModel.get('layout');
var axes = this._axesMap;
var dimensions = this.dimensions;
var size = [rect.width, rect.height];
var sizeIdx = layout === 'horizontal' ? 0 : 1;
var layoutLength = size[sizeIdx];
var axisLength = size[1 - sizeIdx];
var axisExtent = [0, axisLength];
each(axes, function (axis) {
var idx = axis.inverse ? 1 : 0;
axis.setExtent(axisExtent[idx], axisExtent[1 - idx]);
});
each(dimensions, function (dim, idx) {
var axis = axes[dim];
var pos = layoutLength * idx / (dimensions.length - 1);
var inverse = axis.inverse ? 'inverse' : 'forward';
var positionTable = {
horizontal: {
x: pos,
y: {forward: layoutLength, inverse: 0}
},
vertical: {
x: {forward: 0, inverse: layoutLength},
y: pos
}
};
var rotationTable = {
horizontal: {forward: PI / 2, inverse: PI * 1.5},
vertical: {forward: 0, inverse: PI}
};
var position = [
positionTable[layout]['x'][inverse] + rect.x,
positionTable[layout]['y'][inverse] + rect.y
];
var rotation = rotationTable[layout][inverse];
var transform = matrix.create();
matrix.rotate(transform, transform, rotation);
matrix.translate(transform, transform, position);
// TODO
// tick等排布信息。
// TODO
// 根据axis order 更新 dimensions顺序。
this._axesLayout[dim] = {
position: position,
rotation: rotation,
transform: transform
};
}, this);
},
/**
* Convert a dim value of a single item of series data to Point.
* @param {*} value
* @param {string} dim
* @return {Array}
*/
dataToPoint: function (value, dim) {
return this.axisCoordToPoint(
this._axesMap[dim].dataToCoord(value),
dim
);
},
/**
* Convert coords of each axis to Point.
* Return point. For example: [10, 20]
* @param {Array.<number>} coords
* @param {string} dim
* @return {Array.<number>}
*/
axisCoordToPoint: function (coord, dim) {
var axisLayout = this._axesLayout[dim];
var point = [0, coord];
vector.applyTransform(point, point, axisLayout.transform);
return point;
},
/**
* Get axis layout.
*/
getAxisLayout: function (dim) {
return zrUtil.clone(this._axesLayout[dim], true);
}
};
return Parallel;
});
\ No newline at end of file
define(function (require) {
var zrUtil = require('zrender/core/util');
var Axis = require('../Axis');
/**
* @constructor module:echarts/coord/parallel/ParallelAxis
* @extends {module:echarts/coord/Axis}
* @param {string} dim
* @param {*} scale
* @param {Array.<number>} coordExtent
* @param {string} axisType
*/
var ParallelAxis = function (dim, scale, coordExtent, axisType) {
Axis.call(this, dim, scale, coordExtent);
/**
* Axis type
* - 'category'
* - 'value'
* - 'time'
* - 'log'
* @type {string}
*/
this.type = axisType || 'value';
};
ParallelAxis.prototype = {
constructor: ParallelAxis,
/**
* Axis model
* @param {module:echarts/coord/parallel/AxisModel}
*/
model: null
};
zrUtil.inherits(ParallelAxis, Axis);
return ParallelAxis;
});
\ No newline at end of file
define(function(require) {
var zrUtil = require('zrender/core/util');
require('./AxisModel');
require('../../echarts').extendComponentModel({
type: 'parallel',
/**
* @type {module:echarts/coord/parallel/Parallel}
*/
coordinateSystem: null,
defaultOption: {
show: false,
dimensions: 5, // {number} 表示 dim数,如设为 3 会自动转化成 ['dim0', 'dim1', 'dim2']
// {Array.<string>} 表示哪些dim,如 ['dim3', 'dim2']
parallelAxisIndex: null, // {Array.<number>} 表示引用哪些axis,如 [2, 1, 4]
// {Object} 表示 mapping,如{dim1: 3, dim3: 1, others: 0},others不设则自动取0
zlevel: 0, // 一级层叠
z: 0, // 二级层叠
x: 80,
y: 60,
x2: 80,
y2: 60,
layout: 'horizontal', // 'horizontal' or 'vertical'
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 0,
borderColor: '#ccc'
},
/**
* @override
*/
mergeOption: function (newOption) {
var thisOption = this.option;
newOption && zrUtil.merge(thisOption, newOption);
var parallelAxisIndex = thisOption.parallelAxisIndex;
var dimensions = thisOption.dimensions;
dimensions = completeDimensions(dimensions);
parallelAxisIndex = completeParallelAxisIndexByMapping(
parallelAxisIndex, dimensions
);
parallelAxisIndex = completeParallelAxisIndexWhenNone(
parallelAxisIndex, dimensions
);
thisOption.dimensions = dimensions;
thisOption.parallelAxisIndex = parallelAxisIndex;
}
});
function completeDimensions(dimensions) {
// If dimensions is not array, represents dimension count.
// Generate dimensions by dimension count.
if (!zrUtil.isArray(dimensions)) {
var count = dimensions;
dimensions = [];
for (var i = 0; i < count; i++) {
dimensions.push('dim' + i);
}
}
return dimensions;
}
function completeParallelAxisIndexByMapping(parallelAxisIndex, dimensions) {
// If parallelAxisIndex is {}, represents mapping.
// like: {dim1: 3, dim3: 1, others: 0}
// Generate parallelAxisIndex by mapping.
if (zrUtil.isObject(parallelAxisIndex)
&& !zrUtil.isArray(parallelAxisIndex)
) {
var mapping = parallelAxisIndex;
parallelAxisIndex = [];
var otherAxisIndex = 0; // Others default 0.
zrUtil.each(mapping, function (axisIndex, dim) {
var dimIndex = zrUtil.indexOf(dimensions, dim);
if (dimIndex >= 0) {
parallelAxisIndex[dimIndex] = dim;
}
else if (dim === 'others') {
otherAxisIndex = axisIndex;
}
});
// Complete others.
zrUtil.each(parallelAxisIndex, function (axisIndex, idx) {
if (axisIndex == null) {
parallelAxisIndex[idx] = otherAxisIndex;
}
});
}
return parallelAxisIndex;
}
function completeParallelAxisIndexWhenNone(parallelAxisIndex, dimensions) {
if (!zrUtil.isObject(parallelAxisIndex)
|| !zrUtil.isArray(parallelAxisIndex)
) {
parallelAxisIndex = [];
}
if (parallelAxisIndex.length !== dimensions.length) {
// TODO
}
return parallelAxisIndex;
}
});
\ No newline at end of file
/**
* Parallel coordinate system creater.
*/
define(function(require) {
var Parallel = require('./Parallel');
function create(ecModel, api) {
var coordSysList = [];
ecModel.eachComponent('parallel', function (parallelModel, idx) {
var coordSys = new Parallel(parallelModel, ecModel, api);
coordSys.name = 'parallel_' + idx;
coordSys.resize(parallelModel, api);
parallelModel.coordinateSystem = coordSys;
coordSysList.push(coordSys);
});
// Inject the coordinateSystems into seriesModel
ecModel.eachSeries(function (seriesModel) {
if (seriesModel.get('coordinateSystem') === 'parallel') {
var parallelIndex = seriesModel.get('parallelIndex');
seriesModel.coordinateSystem = coordSysList[parallelIndex];
}
});
return coordSysList;
}
require('../../CoordinateSystem').register('parallel', {create: create});
});
\ No newline at end of file
......@@ -12,10 +12,10 @@ define(function (require) {
? Array : global.Int32Array;
var dataCtors = {
float: Float32Array,
int: Int32Array,
'float': Float32Array,
'int': Int32Array,
// Ordinal data type can be string or int
ordinal: Array,
'ordinal': Array,
'number': Array
};
......@@ -346,6 +346,29 @@ define(function (require) {
return value;
};
/**
* Get value for multi dimensions.
* @param {Array.<string>} [dimensions] If ignored, using all dimensions.
* @param {number} idx
* @param {boolean} stack
* @return {number}
*/
listProto.getValues = function (dimensions, idx, stack) {
var values = [];
if (!zrUtil.isArray(dimensions)) {
stack = idx;
idx = dimensions;
dimensions = this.dimensions;
}
for (var i = 0, len = dimensions.length; i < len; i++) {
values.push(this.get(dimensions[i], idx, stack));
}
return values;
};
/**
* If value is NaN. Inlcuding '-'
* @param {string} dim
......@@ -869,20 +892,32 @@ define(function (require) {
};
/**
* @param {number} idx
* @param {module:zrender/Element} el
* @param {module:zrender/Element|Array.<module:zrender/Element>} el
*/
listProto.setItemGraphicEl = function (idx, el) {
var hostModel = this.hostModel;
if (zrUtil.isArray(el)) {
zrUtil.each(el, function (singleEl) {
addIndexToGraphicEl(singleEl, idx, hostModel);
});
}
else {
addIndexToGraphicEl(el, idx, hostModel);
}
this._graphicEls[idx] = el;
};
function addIndexToGraphicEl(el, dataIndex, hostModel) {
// Add data index and series index for indexing the data by element
// Useful in tooltip
el.dataIndex = idx;
el.dataIndex = dataIndex;
el.seriesIndex = hostModel && hostModel.seriesIndex;
if (el.type === 'group') {
el.traverse(setItemDataAndSeriesIndex, el);
}
this._graphicEls[idx] = el;
};
}
/**
* @param {number} idx
......
define(function (require) {
var zrUtil = require('zrender/core/util');
// TODO
//
// parallelAxis: [ // 根据dim需求自动补全 parallelAxis,自动赋值已有axisoption。
// // 找出所有引用axis的 parallel option,来决定如何补全。
// // 但是这步在这里做比较难,在后面做比较麻烦。
// {
// axisLine: [],
// axisLabel: []
// }
// ],
// parallel: [ // 如果没有写parallel则自动创建。FIXME 是不是应该强制用户写,自动创建埋bug?
// {
// dimensions: 3 // number表示 count, 根据dimensionCount创建 []。
// ['dim1', 'dim3'], //
//
// parallelAxisIndex: [3, 1], // TODO 如果不设置则根据parallelAxisMap创建此项,
// // 如果没有parallelAxisMap则顺序引用。
// // TODO 如果设置了 parallelAxisIndex 则此项无效。
// { // 根据parallelAxisMap创建 []
// dim1: 3
// dim3: 1
// others: 0 // 不配other也取parallelAxis[0]。
// }
// }
// ],
// series: [
// {
// parallelIndex: 0, // 缺省则0
// data: [
// [22, 23, 34, 6, 19],
// [22, 23, 34, 6, 19]
// ]
// }
// ]
return function (option) {
// Create a parallel coordinate if not exists.
if (option.parallel) {
return;
}
var hasParallelSeries = false;
zrUtil.each(option.series, function (seriesOpt) {
if (seriesOpt && seriesOpt.type === 'parallel') {
hasParallelSeries = true;
}
});
if (hasParallelSeries) {
option.parallel = [{}];
}
};
});
\ No newline at end of file
<html>
<head>
<meta charset="utf-8">
<script src="./esl.js"></script>
<script src="./config.js"></script>
<link rel="stylesheet" href="./reset.css">
</head>
<body>
<style>
body {
background: #000;
}
</style>
<div id="main"></div>
<script>
// Schema:
// date,AQIindex,PM2.5,PM10,CO,NO2,SO2
var schema = [
{name: 'date', index: 0, text: ''},
{name: 'AQIindex', index: 1, text: 'AQI指数'},
{name: 'PM25', index: 2, text: 'PM2.5'},
{name: 'PM10', index: 3, text: 'PM10'},
{name: 'CO', index: 4, text: '一氧化碳(CO)'},
{name: 'NO2', index: 5, text: '二氧化氮(NO2)'},
{name: 'SO2', index: 6, text: '二氧化硫(SO2)'}
];
require([
'data/aqi/BJdata',
'data/aqi/GZdata',
'data/aqi/SHdata',
'echarts',
'echarts/chart/parallel',
// 'echarts/component/legend',
'echarts/component/parallel',
], function (dataBJ, dataGZ, dataSH, echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
var itemStyle = {
normal: {
opacity: 0.8,
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
};
var axis = {
type: 'value',
name: 'AQI指数',
nameLocation: 'end',
nameGap: 20,
nameTextStyle: {
color: '#fff',
fontSize: 20
},
axisTick: {
lineStyle: {
color: '#777'
}
},
splitLine: {
show: false
},
axisLabel: {
textStyle: {
color: '#fff'
}
}
};
var dimensions = 5;
var parallelAxis = [];
var parallelAxisIndex = [];
for (var i = 0; i < dimensions.length; i++) {
parallelAxis.push(axis);
parallelAxisIndex.push(i);
}
chart.setOption({
color: [
'#dd4444', '#fec42c', '#80F1BE'
],
legend: {
y: 'top',
data: ['北京', '上海', '广州'],
textStyle: {
color: '#fff',
fontSize: 20
}
},
grid: {
x: '10%',
x2: 200,
y: '15%',
y2: '10%'
},
tooltip: {
padding: 10,
backgroundColor: '#222',
borderColor: '#777',
borderWidth: 1,
formatter: function (obj) {
var value = obj[0].value;
return '<div style="border-bottom: 1px solid rgba(255,255,255,.3); font-size: 18px;padding-bottom: 7px;margin-bottom: 7px">'
+ obj[0].seriesName + ' ' + value[0] + '日:'
+ value[7]
+ '</div>'
+ schema[1].text + '' + value[1] + '<br>'
+ schema[2].text + '' + value[2] + '<br>'
+ schema[3].text + '' + value[3] + '<br>'
+ schema[4].text + '' + value[4] + '<br>'
+ schema[5].text + '' + value[5] + '<br>'
+ schema[6].text + '' + value[6] + '<br>';
}
},
parallelAxis: parallelAxis,
parallel: {
dimensions: dimensions,
parallelAxisIndex: parallelAxisIndex
},
series: [
{
name: '北京',
type: 'parallel',
itemStyle: itemStyle,
data: dataBJ
},
{
name: '上海',
type: 'parallel',
itemStyle: itemStyle,
data: dataSH
},
{
name: '广州',
type: 'parallel',
itemStyle: itemStyle,
data: dataGZ
}
]
});
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册