提交 0dc78665 编写于 作者: L lang

Interactive legend

上级 20bc4281
......@@ -22,7 +22,7 @@ define(function(require) {
Polyline: require('zrender/graphic/shape/Polyline'),
Rectangle: require('zrender/graphic/shape/Rectangle'),
Rect: require('zrender/graphic/shape/Rectangle'),
/**
* Create a path element from path data string
......
......@@ -5,6 +5,8 @@ define(function (require) {
type: 'bar',
render: function (seriesModel, ecModel, api) {
this.group.clear();
var coordinateSystemType = seriesModel.get('coordinateSystem');
if (coordinateSystemType === 'cartesian2d') {
......@@ -18,7 +20,7 @@ define(function (require) {
seriesModel.getData().each(function (dataItem) {
var layout = dataItem.layout;
var rect = new api.Rectangle({
var rect = new api.Rect({
shape: {
x: layout.x,
y: layout.y,
......
......@@ -4,8 +4,10 @@ define(function(require) {
// Grid view
require('../echarts').extendComponentView({
render: function (gridModel, ecModel) {
render: function (gridModel, ecModel, api) {
this.group.add(new api.Rectangle({
}));
}
});
});
\ No newline at end of file
......@@ -3,6 +3,7 @@ define(function(require) {
'use strict';
var List = require('../../data/List');
var zrUtil = require('zrender/core/util');
return require('../../echarts').extendComponentModel({
......@@ -13,7 +14,27 @@ define(function(require) {
option.selected = option.selected || {};
this._data = List.fromArray(option.data);
var list = new List();
zrUtil.each(option.data, function (dataItem) {
if (typeof dataItem === 'string') {
list.append(dataItem, {});
}
else {
list.append(dataItem.name, dataItem);
}
});
/**
* @type {Array.<string>}
* @private
*/
this._seriesNames = zrUtil.map(ecModel.getSeriesAll(), function (series) {
return series.name;
});
this._data = list;
this._stack = [];
},
/**
......@@ -37,12 +58,24 @@ define(function(require) {
this.option.selected[name] = false;
},
/**
* @param {string} name
*/
toggleSelected: function (name) {
var selected = this.option.selected;
if (! (name in selected)) {
selected[name] = true;
}
selected[name] = !selected[name];
},
/**
* @param {string} name
*/
isSelected: function (name) {
var selected = this.option.selected;
return !((name in selected) && selected[name]);
return !((name in selected) && !selected[name])
&& this._seriesNames.indexOf(name) >= 0
},
defaultOption: {
......
define(function (require) {
var numberUtil = require('../../util/number');
return require('../../echarts').extendComponentView({
type: 'legend',
render: function (legendModel, ecModel, api) {
var itemGap = legendModel.get('itemGap');
var padding = numberUtil.normalizeCssArray(
legendModel.get('padding')
);
var orient = legendModel.get('orient');
var group = this.group;
group.clear();
group.position = [
numberUtil.parsePercent(
legendModel.get('x'), api.getWidth()
),
numberUtil.parsePercent(
legendModel.get('y'), api.getHeight()
)
];
var x = 0;
var y = 0;
legendModel.getData().each(function (dataItem) {
var series = ecModel.getSeriesByName(dataItem.name);
var color = ecModel.getVisual('color');
var symbol = ecModel.getVisual('symbol');
var seriesName = dataItem.name;
var seriesModel = ecModel.getSeriesByName(seriesName);
var color = legendModel.isSelected(seriesName)
? seriesModel.getVisual('color')
: '#ccc';
var symbol = seriesModel.getVisual('symbol');
var width = 20;
var height = 10;
var rect = new api.Rect({
shape: {
x: x,
y: y,
width: width,
height: height
},
style: {
fill: color
}
});
var text = new api.Text({
style: {
text: dataItem.name,
x: x + width + 5,
y: y,
fill: '#000',
textAlign: 'left',
textBaseline: 'top'
}
});
var textRect = text.getBoundingRect();
if (orient === 'horizontal') {
x += width + 5 + textRect.width + itemGap;
}
else {
y += Math.max(height, textRect.height) + itemGap;
}
group.add(rect);
group.add(text);
rect.on('click', function () {
legendModel.toggleSelected(seriesName);
api.update();
});
});
var groupRect = group.getBoundingRect();
group.position[0] -= groupRect.width / 2;
}
});
});
\ No newline at end of file
......@@ -63,14 +63,14 @@ define(function(require) {
* 添加一个新的节点
* @param {*} [option] 存储的数据
*/
Graph.prototype.addNode = function (option) {
var name = option.name;
Graph.prototype.addNode = function (name, option) {
if (this._nodesMap[name]) {
return this._nodesMap[name];
}
var node = new Graph.Node(option);
node.name = name;
this.nodes.push(node);
......@@ -328,11 +328,13 @@ define(function(require) {
*/
Graph.prototype.clone = function () {
var graph = new Graph(this._directed);
for (var i = 0; i < this.nodes.length; i++) {
graph.addNode(this.nodes[i].name, this.nodes[i].data);
var nodes = this.nodes;
var edges = this.edges;
for (var i = 0; i < nodes.length; i++) {
graph.addNode(nodes[i].name, nodes[i].data);
}
for (var i = 0; i < this.edges.length; i++) {
var e = this.edges[i];
for (var i = 0; i < edges.length; i++) {
var e = edges[i];
graph.addEdge(e.node1.name, e.node2.name, e.data);
}
return graph;
......
......@@ -35,7 +35,7 @@ define(function(require) {
dimension: 1,
init: function (option, parentModel, ecModel, dataIndex) {
init: function (option, parentModel, dataIndex) {
/**
* @type {string}
......@@ -57,7 +57,7 @@ define(function(require) {
* @private
* @readOnly
*/
this.rawIndex = dataIndex || 0;
this.dataIndex = dataIndex || 0;
},
/**
......@@ -66,7 +66,7 @@ define(function(require) {
getX: function () {
// Use idx as x if data is 1d
// Usually when xAxis is category axis
return this.dimension === 1 ? this.rawIndex : this._value[0];
return this.dimension === 1 ? this.dataIndex : this._value[0];
},
/**
......@@ -132,13 +132,21 @@ define(function(require) {
* @param {number} value
*/
setValue: function (value) {
this._value[this.dimensino] = value
this._value[this.dimension] = value
},
clone: function () {
var entry = new Entry(
this.option, this.parentModel, this.dataIndex
);
entry.dimension = this.dimension;
return entry;
}
});
function List() {
this.elements = this.elements || [];
this.elements = [];
// Depth and properties is useful in nested Array.
// For example in eventRiver, data structure is a nested 2d array as following
......@@ -210,8 +218,27 @@ define(function(require) {
}
},
/**
* @param {string} name
* @param {*} option
*/
append: function (name, option) {
var elements = this.elements;
var el = new Entry(option, null, elements.length);
el.name = name;
elements.push(el);
return el;
},
clone: function () {
// Clone
var list = new List();
var elements = this.elements;
for (var i = 0; i < elements.length; i++) {
list.elements.push(elements[i].clone());
}
list.depth = this.depth;
list.properties = this.properties;
return list;
}
};
......@@ -230,7 +257,7 @@ define(function(require) {
var list = new List();
// Normalize data
list.elements = zrUtil.map(data, function (dataItem, index) {
var entry = new Entry(dataItem, parentModel, null, index);
var entry = new Entry(dataItem, parentModel, index);
entry.dimension = dimension || 1;
return entry;
});
......
......@@ -3,6 +3,8 @@
*
* @module echarts/data/Tree
* @author Yi Shen(https://www.github.com/pissang)
*
* TODO clone
*/
define(function(require) {
......
/**
* TODO processor的优先级
* TODO restore
* TODO setTheme
* restore
* setTheme
* stack
*/
define(function (require) {
......@@ -30,25 +31,76 @@ define(function (require) {
var ECharts = function (dom, theme, opts) {
opts = opts || {};
/**
* @type {module:zrender/ZRender}
* @private
*/
this._zr = zrender.init(dom, {
renderer: opts.renderer || 'canvas'
});
/**
* @type {Object}
* @private
*/
this._theme = zrUtil.clone(theme);
/**
* @type {Array.<module:echarts/view/Chart>}
* @private
*/
this._chartsList = [];
/**
* @type {Object.<string, module:echarts/view/Chart>}
* @private
*/
this._chartsMap = {};
/**
* @type {Array.<module:echarts/view/Component>}
* @private
*/
this._componentsList = [];
/**
* @type {Object.<string, module:echarts/view/Component>}
* @private
*/
this._componentsMap = {};
/**
* @type {module:echarts/api/ExtensionAPI}
* @private
*/
this._extensionAPI = new ExtensionAPI(this);
/**
* @type {module:echarts/CoordinateSystem}
* @private
*/
this._coordinateSystem = new CoordinateSystemManager();
/**
* Layout instances
* @type {Array}
* @private
*/
this._layouts = zrUtil.map(layoutClasses, function (Layout) {
return new Layout();
});
/**
* @type {boolean}
* @private
*/
this._needsUpdate = false;
this._zr.animation.on('frame', function () {
if (this._needsUpdate) {
this.updateImmediately();
}
}, this);
};
ECharts.prototype = {
......@@ -99,6 +151,7 @@ define(function (require) {
},
update: function () {
this._needsUpdate = true;
},
updateImmediately: function () {
......@@ -106,6 +159,8 @@ define(function (require) {
ecModel.restore();
ecModel.save();
this._processData(ecModel);
this._coordinateSystem.update(ecModel, this._extensionAPI);
......@@ -115,6 +170,8 @@ define(function (require) {
this._doLayout(ecModel);
this._doRender(ecModel);
this._needsUpdate = false;
},
resize: function () {
......@@ -256,7 +313,6 @@ define(function (require) {
/**
* Render each chart and component
*
*/
_doRender: function (ecModel) {
var api = this._extensionAPI;
......
......@@ -31,11 +31,23 @@ define(function (require) {
this.option = {};
/**
* @type {Array}
* @private
*/
this._stack = [];
/**
* @type {Array.<module:echarts/model/Model}
* @private
*/
this._components = [];
/**
* @type {Object.<string, module:echarts/model/Model>}
* @private
*/
this._components = {};
this._componentsMap = {};
/**
* @type {Array.<module:echarts/model/Model}
......@@ -109,6 +121,7 @@ define(function (require) {
return seriesModel.option;
});
var componentsMap = this._componentsMap;
var components = this._components;
for (var name in newOption) {
var componentOption = newOption[name];
......@@ -128,11 +141,11 @@ define(function (require) {
if (! (componentOption instanceof Array)) {
componentOption = [componentOption];
}
if (! components[name]) {
components[name] = [];
if (! componentsMap[name]) {
componentsMap[name] = [];
}
for (var i = 0; i < componentOption.length; i++) {
var componentModel = components[name][i];
var componentModel = componentsMap[name][i];
if (componentModel) {
componentModel.mergeOption(
componentOption[i], this
......@@ -142,7 +155,8 @@ define(function (require) {
componentModel = ComponentModel.create(
name, componentOption[i], this
);
components[name][i] = componentModel;
componentsMap[name][i] = componentModel;
components.push(componentModel);
}
if (componentModel) {
// 同步 Option
......@@ -170,16 +184,25 @@ define(function (require) {
* @return {module:echarts/model/Component}
*/
getComponent: function (type, idx) {
var list = this._components[type];
var list = this._componentsMap[type];
if (list) {
return list[idx || 0];
}
},
/**
* @param {string} type
* @param {Function} cb
* @param {*} context
*/
eachComponent: function (type, cb, context) {
zrUtil.each(this._components[type], cb, context);
zrUtil.each(this._componentsMap[type], cb, context);
},
/**
* @param {string} name
* @return {Array.<module:echarts/model/Series>}
*/
getSeriesByName: function (name) {
return this._seriesMap[name];
},
......@@ -206,15 +229,55 @@ define(function (require) {
* @return {Array.<module:echarts/model/Series>}
*/
getSeriesAll: function () {
return this._series;
return this._series.slice();
},
/**
* @param {Function} cb
* @param {*} context
*/
eachSeries: function (cb, context) {
zrUtil.each(this._series, cb, context);
},
/**
* @param {Function} cb
* @param {*} context
*/
filterSeries: function (cb, context) {
this._series = zrUtil.filter(this._series, cb, context);
},
save: function () {
this._stack.push({
series: this._series.slice()
});
var components = this._components;
var series = this._series;
var i;
for (i = 0; i < components.length; i++) {
components[i].save();
}
for (i = 0; i < series.length; i++) {
series[i].save();
}
},
restore: function () {
if (this._stack.length) {
this._series = this._stack.pop().series;
}
var components = this._components;
var series = this._series;
var i;
for (i = 0; i < components.length; i++) {
components[i].restore();
}
for (i = 0; i < series.length; i++) {
series[i].restore();
}
}
});
......
......@@ -104,6 +104,8 @@ define(function (require) {
this._visual[key] = val;
},
save: function () {},
restore: function () {},
// Pending
......
......@@ -25,13 +25,22 @@ define(function(require) {
init: function (seriesOption, parentModel, ecModel, seriesIndex) {
/**
* @type {number}
*/
this.seriesIndex = seriesIndex;
zrUtil.merge(seriesOption, ecModel.getTheme().get(this.type));
zrUtil.merge(seriesOption, this.defaultOption);
/**
* @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
* @private
*/
this._data = this.getInitialData(seriesOption);
this._stack = [];
},
mergeOption: function (newSeriesOption) {
......@@ -46,6 +55,18 @@ define(function(require) {
getData: function () {
return this._data;
},
save: function () {
this._stack.push({
data: this._data.clone()
});
},
restore: function () {
if (this._stack.length) {
this._data = this._stack.pop().data;
}
}
});
......
......@@ -40,6 +40,19 @@ define(function (require) {
* @return {number}
*/
function parsePercent(percent, all) {
switch (percent) {
case 'center':
percent = '50%';
break;
case 'left':
case 'top':
percent = '0%';
break;
case 'right':
case 'bottom':
percent = '100%';
break;
}
if (typeof percent === 'string') {
if (_trim(percent).match(/%$/)) {
return parseFloat(percent) / 100 * all;
......@@ -51,10 +64,36 @@ define(function (require) {
return +percent;
}
/**
* Normalize css liked array configuration
* e.g.
* 3 => [3, 3, 3, 3]
* [4, 2] => [4, 2, 4, 2]
* [4, 3, 2] => [4, 3, 2, 3]
* @param {number|Array.<number>} val
*/
function normalizeCssArray(val) {
var len = val.length;
if (typeof (val) === 'number') {
return [val, val, val, val];
}
else if (len === 2) {
// vertical | horizontal
return [val[0], val[1], val[0], val[1]];
}
else if (len === 3) {
// top | horizontal | bottom
return [val[0], val[1], val[2], val[1]];
}
return val;
}
return {
linearMap: linearMap,
parsePercent: parsePercent
parsePercent: parsePercent,
normalizeCssArray: normalizeCssArray
}
});
\ No newline at end of file
define(function (require) {
return function (ecModel) {
ecModel.eachSeries(function (seriesModel, idx) {
ecModel.eachSeries(function (seriesModel) {
var colorList = ecModel.get('color');
seriesModel.setVisual(
'color', seriesModel.get('itemStyle.normal.color') || colorList[idx]
'color', seriesModel.get('itemStyle.normal.color')
|| colorList[seriesModel.seriesIndex]
);
});
}
......
......@@ -19,11 +19,15 @@
var chart = echarts.init(document.getElementById('main'));
var xAxisData = [];
var data = [];
var data1 = [];
var data2 = [];
var data3 = [];
for (var i = 0; i < 10000; i++) {
for (var i = 0; i < 20; i++) {
xAxisData.push(Math.random());
data.push(Math.random());
data1.push(Math.random());
data2.push(Math.random());
data3.push(Math.random());
}
console.profile('setOption');
......@@ -33,10 +37,13 @@
name: 'bar',
itemStyle: {
normal: {
color: 'blue'
// color: 'blue'
}
}
}]
}, 'bar2', 'bar3'],
selected: {
'bar': false
}
},
xAxis: {
// data: ['类目1', '类目2', '类目3', '类目4', '类目5',]
......@@ -48,7 +55,17 @@
name: 'bar',
type: 'bar',
// data: [0, 1, 2, 3, 4]
data: data
data: data1
}, {
name: 'bar2',
type: 'bar',
// data: [0, 1, 2, 3, 4]
data: data2
}, {
name: 'bar3',
type: 'bar',
// data: [0, 1, 2, 3, 4]
data: data3
}]
});
console.profileEnd('setOption');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册