提交 979fe862 编写于 作者: P pah100

Merge branch 'dev-3.0.0' of https://github.com/ecomfe/echarts into dev-3.0.0

......@@ -24,13 +24,13 @@ define(function (require) {
var coordinateSystemType = seriesModel.get('coordinateSystem');
if (coordinateSystemType === 'cartesian2d') {
this._renderCartesian(seriesModel, ecModel, api);
this._renderOnCartesian(seriesModel, ecModel, api);
}
return this.group;
},
_renderCartesian: function (seriesModel, ecModel, api) {
_renderOnCartesian: function (seriesModel, ecModel, api) {
var group = this.group;
var data = seriesModel.getData();
var oldData = this._data;
......@@ -39,7 +39,7 @@ define(function (require) {
var baseAxis = cartesian.getBaseAxis();
var isHorizontal = baseAxis.isHorizontal();
var enableAnimation = ecModel.get('animation');
var enableAnimation = seriesModel.get('animation');
var barBorderWidthQuery = ['itemStyle', 'normal', 'barBorderWidth'];
......@@ -153,12 +153,12 @@ define(function (require) {
var labelModel = itemModel.getModel('label.normal');
var hoverLabelModel = itemModel.getModel('label.emphasis');
var labelText = seriesModel.getFormattedLabel(idx, 'normal')
|| data.getRawValue(idx);
var rectStyle = rect.style;
if (labelModel.get('show')) {
setLabel(
rectStyle, labelModel, color, labelText, labelPositionOutside
rectStyle, labelModel, color,
seriesModel.getFormattedLabel(idx, 'normal') || data.getRawValue(idx),
labelPositionOutside
);
}
else {
......@@ -166,7 +166,9 @@ define(function (require) {
}
if (hoverLabelModel.get('show')) {
setLabel(
hoverStyle, hoverLabelModel, color, labelText, labelPositionOutside
hoverStyle, hoverLabelModel, color,
seriesModel.getFormattedLabel(idx, 'emphasis') || data.getRawValue(idx),
labelPositionOutside
);
}
else {
......
......@@ -29,6 +29,8 @@ define(function (require) {
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) {
......
......@@ -17,6 +17,7 @@ define(function (require) {
echarts.registerLayout(require('./graph/simpleLayout'));
echarts.registerLayout(require('./graph/circularLayout'));
echarts.registerLayout(require('./graph/forceLayout'));
// Graph view coordinate system
echarts.registerCoordinateSystem('graphView', {
......
......@@ -112,6 +112,14 @@ define(function (require) {
layout: null,
// Configuration of force
force: {
initLayout: null,
repulsion: 50,
gravity: 0.1,
edgeLength: 30
},
x: 'center',
y: 'center',
x2: null,
......@@ -122,8 +130,9 @@ define(function (require) {
symbol: 'circle',
symbolSize: 10,
// roam: false,
draggable: false,
roam: false,
roamDetail: {
x: 0,
y: 0,
......
......@@ -62,7 +62,6 @@ define(function (require) {
});
});
// Save the original lineWidth
data.graph.eachEdge(function (edge) {
edge.__lineWidth = edge.getModel('lineStyle.normal').get('width');
......@@ -80,6 +79,42 @@ define(function (require) {
this._updateNodeAndLinkScale();
this._updateController(seriesModel, coordSys, api);
clearTimeout(this._layoutTimeout);
var forceLayout = seriesModel.forceLayout;
if (forceLayout) {
this._startForceLayoutIteration(forceLayout);
}
// Update draggable
data.eachItemGraphicEl(function (el, idx) {
var draggable = data.getItemModel(idx).get('draggable');
if (draggable && forceLayout) {
el.on('drag', function () {
forceLayout.warmUp();
forceLayout.setFixed(idx);
// Write position back to layout
data.setItemLayout(idx, el.position);
}).on('dragend', function () {
forceLayout.setUnfixed(idx);
});
}
else {
el.off('drag');
}
el.setDraggable(draggable);
}, this);
},
_startForceLayoutIteration: function (forceLayout) {
var self = this;
(function step() {
forceLayout.step(function (stopped) {
self.updateLayout();
!stopped && (self._layoutTimeout = setTimeout(step, 16));
});
})();
},
_updateController: function (seriesModel, coordSys, api) {
......
define(function (require) {
var circularLayoutHelper = require('./circularLayoutHelper');
return function (ecModel, api) {
ecModel.eachSeriesByType('graph', function (seriesModel) {
if (seriesModel.get('layout') === 'circular') {
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 unitAngle = Math.PI * 2 / nodeData.getSum('value');
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 * value / 2;
node.setLayout([
r * Math.cos(angle) + cx,
r * Math.sin(angle) + cy
]);
angle += unitAngle * value / 2;
});
graph.eachEdge(function (edge) {
var curveness = edge.getModel().get('lineStyle.normal.curveness');
var p1 = edge.node1.getLayout();
var p2 = edge.node2.getLayout();
var cp1;
if (curveness > 0) {
cp1 = [cx, cy];
}
edge.setLayout([p1, p2, cp1]);
});
circularLayoutHelper(seriesModel);
}
});
};
......
define(function (require) {
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 = edge.node1.getLayout();
var p2 = edge.node2.getLayout();
var cp1;
if (curveness > 0) {
cp1 = [cx, cy];
}
edge.setLayout([p1, p2, cp1]);
});
};
});
\ No newline at end of file
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.995;
cb && cb(nodes, edges, friction < 0.01);
}
};
};
});
\ No newline at end of file
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) {
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;
}
});
};
});
\ No newline at end of file
define(function (require) {
var simpleLayoutHelper = require('./simpleLayoutHelper');
return function (ecModel, api) {
ecModel.eachSeriesByType('graph', function (seriesModel) {
var layout = seriesModel.get('layout');
if (!layout || layout === 'none') {
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')]);
});
graph.eachEdge(function (edge) {
var curveness = edge.getModel().get('lineStyle.normal.curveness');
var p1 = edge.node1.getLayout();
var p2 = edge.node2.getLayout();
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
];
}
edge.setLayout([p1, p2, cp1]);
});
simpleLayoutHelper(seriesModel);
}
});
};
......
define(function (require) {
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')]);
});
graph.eachEdge(function (edge) {
var curveness = edge.getModel().get('lineStyle.normal.curveness') || 0;
var p1 = edge.node1.getLayout();
var p2 = edge.node2.getLayout();
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
];
}
edge.setLayout([p1, p2, cp1]);
});
};
});
\ No newline at end of file
define(function (require) {
require('./heatmap/HeatmapSeries');
require('./heatmap/HeatmapView');
});
\ No newline at end of file
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,
// No blur
// Available when heatmap is on geo
blurSize: 0
}
});
});
\ No newline at end of file
define(function (require) {
var graphic = require('../../util/graphic');
return require('../../echarts').extendChartView({
type: 'heatmap',
render: function (seriesModel, ecModel, api) {
var coordSys = seriesModel.coordinateSystem;
if (coordSys.type === 'cartesian2d') {
this._renderOnCartesian(coordSys, seriesModel, ecModel, api);
}
else if (coordSys.type === 'geo') {
this._renderOnGeo(coordSys, seriesModel, ecModel, api);
}
},
_renderOnCartesian: function (cartesian, seriesModel, ecModel, api) {
var xAxis = cartesian.getAxis('x');
var yAxis = cartesian.getAxis('y');
var group = this.group;
group.removeAll();
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]);
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')
}
});
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 = data.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, ecModel, api) {
}
});
});
\ No newline at end of file
......@@ -51,6 +51,8 @@ define(function (require) {
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) {
......@@ -68,6 +70,7 @@ define(function (require) {
symbol = symbolUtil.createSymbol(
symbolType, -0.5, -0.5, 1, 1, color
);
symbol.ignore = true;
symbol.z2 = 100;
this._symbolType = symbolType;
this._period = period;
......
......@@ -36,7 +36,10 @@ define(function (require) {
function createLine(points) {
var line = new LinePath({
name: 'line'
name: 'line',
style: {
strokeNoScale: true
}
});
setLinePoints(line.shape, points);
return line;
......
......@@ -29,6 +29,10 @@ define(function (require) {
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();
......@@ -47,6 +51,8 @@ define(function (require) {
z2: 100,
scale: [0, 0]
});
// Rewrite drift method
symbolPath.drift = driftSymbol;
var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
......@@ -99,6 +105,12 @@ define(function (require) {
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
......
......@@ -19,6 +19,11 @@ define(function (require) {
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
......@@ -33,26 +38,21 @@ define(function (require) {
data.diff(oldData)
.add(function (newIdx) {
if (
data.hasValue(newIdx) && !(isIgnore && isIgnore(newIdx))
&& data.getItemVisual(newIdx, 'symbol') !== 'none'
) {
var point = data.getItemLayout(newIdx);
if (symbolNeedsDraw(data, newIdx, isIgnore)) {
var symbolEl = new SymbolCtor(data, newIdx);
symbolEl.attr('position', data.getItemLayout(newIdx));
symbolEl.attr('position', point);
data.setItemGraphicEl(newIdx, symbolEl);
group.add(symbolEl);
}
})
.update(function (newIdx, oldIdx) {
var symbolEl = oldData.getItemGraphicEl(oldIdx);
// Empty data
if (!data.hasValue(newIdx) || (isIgnore && isIgnore(newIdx))
|| data.getItemVisual(newIdx, 'symbol') === 'none'
) {
var point = data.getItemLayout(newIdx);
if (!symbolNeedsDraw(data, newIdx, isIgnore)) {
group.remove(symbolEl);
return;
}
var point = data.getItemLayout(newIdx);
if (!symbolEl) {
symbolEl = new SymbolCtor(data, newIdx);
symbolEl.attr('position', point);
......
......@@ -4,18 +4,23 @@ define(function (require) {
var Graph = require('../../data/Graph');
var linkList = require('../../data/helper/linkList');
var completeDimensions = require('../../data/helper/completeDimensions');
var zrUtil = require('zrender/core/util');
return function (nodes, edges, hostModel, directed) {
var graph = new Graph(directed);
for (var i = 0; i < nodes.length; i++) {
graph.addNode(nodes[i].id || nodes[i].name, i);
graph.addNode(zrUtil.retrieve(nodes[i].id, nodes[i].name), i);
}
var linkNameList = [];
var validEdges = [];
for (var i = 0; i < edges.length; i++) {
var link = edges[i];
linkNameList[i] = link.id || link.source + ' - ' + link.target;
graph.addEdge(link.source, link.target, i);
// addEdge may fail when source or target not exists
if (graph.addEdge(link.source, link.target, i)) {
validEdges.push(link);
linkNameList.push(zrUtil.retrieve(link.id, link.source + ' - ' + link.target));
}
}
// FIXME
......@@ -25,11 +30,13 @@ define(function (require) {
var edgeData = new List(['value'], hostModel);
nodeData.initData(nodes);
edgeData.initData(edges, linkNameList);
edgeData.initData(validEdges, linkNameList);
graph.setEdgeData(edgeData);
linkList.linkToGraph(nodeData, graph);
// Update dataIndex of nodes and edges because invalid edge may be removed
graph.update();
return graph;
};
......
......@@ -187,7 +187,7 @@ define(function(require) {
var lineGroup = this._lineGroup;
var hasAnimation = ecModel.get('animation');
var hasAnimation = seriesModel.get('animation');
var isAreaChart = !areaStyleModel.isEmpty();
var stackedOnPoints = getStackedOnPoints(coordSys, data);
......@@ -329,7 +329,7 @@ define(function(require) {
data.setItemGraphicEl(dataIndex, symbol);
// Stop scale animation
symbol.stopAnimation(true);
symbol.stopSymbolAnimation(true);
this.group.add(symbol);
}
......
......@@ -214,10 +214,13 @@ define(function (require) {
data.getItemLayout(idx),
itemModel.get('selected'),
seriesModel.get('selectedOffset'),
seriesModel.ecModel.get('animation')
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
......@@ -225,6 +228,7 @@ define(function (require) {
}, 300, 'elasticOut');
}
function onNormal() {
sector.stopAnimation(true);
sector.animateTo({
shape: {
r: layout.r
......
......@@ -5,6 +5,7 @@ define(function (require) {
var echarts = require('../../echarts');
var VisualMapping = require('../../visual/VisualMapping');
var zrUtil = require('zrender/core/util');
echarts.registerVisualCoding('component', function (ecModel) {
ecModel.eachComponent('dataRange', function (dataRangeModel) {
......@@ -13,8 +14,29 @@ define(function (require) {
});
function processSingleDataRange(dataRangeModel, ecModel) {
var visualMappings = dataRangeModel.targetVisuals;
var visualTypesMap = {};
var colorFuncsMap = {};
zrUtil.each(['inRange', 'outOfRange'], function (state) {
var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
var colorFunc = zrUtil.filter(zrUtil.map(visualTypes, function (visualType) {
return visualMappings[state][visualType].getColorMapper;
}), function (func) {
return !!func;
})[0];
visualTypesMap[state] = visualTypes;
colorFuncsMap[state] = colorFunc;
});
// Cache color func
function colorFunc(value, out) {
var valueState = dataRangeModel.getValueState(value);
var colorFunc = colorFuncsMap[valueState];
// PENDING
return colorFunc && colorFunc(value, out);
}
dataRangeModel.eachTargetSeries(function (seriesModel) {
var visualMappings = dataRangeModel.targetVisuals;
var data = seriesModel.getData();
var dimension = dataRangeModel.getDataDimension(data);
var dataIndex;
......@@ -27,11 +49,14 @@ define(function (require) {
data.setItemVisual(dataIndex, key, value);
}
data.setVisual('colorFunc', colorFunc);
data.each([dimension], function (value, index) {
// For performance consideration, do not use curry.
dataIndex = index;
var mappings = visualMappings[dataRangeModel.getValueState(value)];
var visualTypes = VisualMapping.prepareVisualTypes(mappings);
var valueState = dataRangeModel.getValueState(value);
var mappings = visualMappings[valueState];
var visualTypes = visualTypesMap[valueState];
for (var i = 0, len = visualTypes.length; i < len; i++) {
var type = visualTypes[i];
mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual);
......
......@@ -120,6 +120,10 @@ define(function (require) {
var rectWidth = rect.width;
var rectHeight = rect.height;
switch (position) {
case 'inside':
x = rect.x + rectWidth / 2 - domWidth / 2;
y = rect.y + rectHeight / 2 - domHeight / 2;
break;
case 'top':
x = rect.x + rectWidth / 2 - domWidth / 2;
y = rect.y - domHeight - gap;
......@@ -463,8 +467,8 @@ define(function (require) {
var moveAnimation = axisPointerType !== 'cross';
if (axisPointerType === 'cross') {
moveGridLine('x', point, cartesian.getAxis('y').getExtent());
moveGridLine('y', point, cartesian.getAxis('x').getExtent());
moveGridLine('x', point, cartesian.getAxis('y').getGlobalExtent());
moveGridLine('y', point, cartesian.getAxis('x').getGlobalExtent());
this._updateCrossText(cartesian, point, axisPointerModel);
}
......
......@@ -107,16 +107,18 @@ define(function(require, factory) {
// Minus label size
if (gridModel.get('containLabel')) {
each(axesList, function (axis) {
var labelUnionRect = getLabelUnionRect(axis);
if (labelUnionRect) {
var dim = axis.isHorizontal() ? 'height' : 'width';
var margin = axis.model.get('axisLabel.margin');
gridRect[dim] -= labelUnionRect[dim] + margin;
if (axis.position === 'top') {
gridRect.y += labelUnionRect.height + margin;
}
else if (axis.position === 'left') {
gridRect.x += labelUnionRect.width + margin;
if (!axis.model.get('axisLabel.inside')) {
var labelUnionRect = getLabelUnionRect(axis);
if (labelUnionRect) {
var dim = axis.isHorizontal() ? 'height' : 'width';
var margin = axis.model.get('axisLabel.margin');
gridRect[dim] -= labelUnionRect[dim] + margin;
if (axis.position === 'top') {
gridRect.y += labelUnionRect.height + margin;
}
else if (axis.position === 'left') {
gridRect.x += labelUnionRect.width + margin;
}
}
}
});
......
......@@ -81,8 +81,13 @@ define(function(require) {
graphProto.addNode = function (id, dataIndex) {
var nodesMap = this._nodesMap;
// Assign dataIndex as id if not exists
if (id == null) {
id = dataIndex;
}
if (nodesMap[id]) {
return nodesMap[id];
return;
}
var node = new Node(id, dataIndex);
......@@ -94,6 +99,15 @@ define(function(require) {
return node;
};
/**
* Get node by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto.getNodeByIndex = function (dataIndex) {
var rawIdx = this.data.getRawIndex(dataIndex);
return this.nodes[rawIdx];
};
/**
* Get node by id
* @param {string} id
......@@ -114,10 +128,10 @@ define(function(require) {
var nodesMap = this._nodesMap;
var edgesMap = this._edgesMap;
if (typeof n1 == 'string') {
if (!(n1 instanceof Node)) {
n1 = nodesMap[n1];
}
if (typeof n2 == 'string') {
if (!(n2 instanceof Node)) {
n2 = nodesMap[n2];
}
if (!n1 || !n2) {
......@@ -125,8 +139,9 @@ define(function(require) {
}
var key = n1.id + '-' + n2.id;
// PENDING
if (edgesMap[key]) {
return edgesMap[key];
return;
}
var edge = new Edge(n1, n2, dataIndex);
......@@ -148,16 +163,25 @@ define(function(require) {
};
/**
* Get edge by two nodes
* Get edge by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto.getEdgeByIndex = function (dataIndex) {
var rawIdx = this.edgeData.getRawIndex(dataIndex);
return this.edges[rawIdx];
};
/**
* Get edge by two linked nodes
* @param {module:echarts/data/Graph.Node|string} n1
* @param {module:echarts/data/Graph.Node|string} n2
* @return {module:echarts/data/Graph.Edge}
*/
graphProto.getEdge = function (n1, n2) {
if (typeof(n1) !== 'string') {
if (n1 instanceof Node) {
n1 = n1.id;
}
if (typeof(n2) !== 'string') {
if (n2 instanceof Node) {
n2 = n2.id;
}
......@@ -214,7 +238,7 @@ define(function(require) {
graphProto.breadthFirstTraverse = function (
cb, startNode, direction, context
) {
if (typeof(startNode) === 'string') {
if (!startNode instanceof Node) {
startNode = this._nodesMap[startNode];
}
if (!startNode) {
......@@ -254,11 +278,11 @@ define(function(require) {
};
// TODO
graphProto.depthFirstTraverse = function (
cb, startNode, direction, context
) {
// graphProto.depthFirstTraverse = function (
// cb, startNode, direction, context
// ) {
};
// };
// Filter update
graphProto.update = function () {
......@@ -326,7 +350,7 @@ define(function(require) {
/**
* @type {string}
*/
this.id = id || '';
this.id = id == null ? '' : id;
/**
* @type {Array.<module:echarts/data/Graph.Edge>}
......
......@@ -73,7 +73,8 @@ define(function (require) {
* @private
*/
this._zr = zrender.init(dom, {
renderer: opts.renderer || 'canvas'
renderer: opts.renderer || 'canvas',
devicePixelRatio: opts.devicePixelRatio
});
/**
......@@ -736,6 +737,9 @@ define(function (require) {
chart.id = idBase++;
instances[chart.id] = chart;
dom.setAttribute &&
dom.setAttribute(DOM_ATTRIBUTE_KEY, chart.id);
// Connecting
zrUtil.each(eventActionMap, function (actionType, eventType) {
// FIXME
......
......@@ -31,8 +31,7 @@ define(function (require) {
var sub = domain[1] - domain[0];
if (sub === 0) {
// FIXME
return range[0];
return (range[0] + range[1]) / 2;
}
var t = (val - domain[0]) / sub;
......
......@@ -96,6 +96,29 @@ define(function (require) {
applyVisual: defaultApplyColor,
/**
* Create a mapper function
* @return {Function}
*/
getColorMapper: function () {
var visual = isCategory(this)
? this.option.visual
: zrUtil.map(this.option.visual, zrUtil.parse);
return isCategory(this)
? function (value) {
return getVisualForCategory(this, visual, this._normalizeData(value));
}
: function (value, out) {
// If output rgb array
// which will be much faster and useful in pixel manipulation
var returnRGBArray = !!out;
out = zrColor.fastMapToColor(
this._normalizeData(value), visual, out
);
return returnRGBArray ? out : zrUtil.stringify(out, 'rgba');
};
},
// value:
// (1) {number}
// (2) {Array.<number>} Represents a interval, for colorStops.
......@@ -113,7 +136,7 @@ define(function (require) {
this._normalizeData(value[1])
];
// For creating graduate color list.
// For creating gradient color list.
return zrColor.mapIntervalToColor(value, visual);
}
else {
......
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/dat.gui.min.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/parser/gexf',
'echarts/chart/graph',
'echarts/component/title',
'echarts/component/legend',
'echarts/component/geo',
'echarts/component/tooltip',
'echarts/component/dataRange'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
function createNodes(count) {
var nodes = [];
for (var i = 0; i < count; i++) {
nodes.push({
id: i
});
}
return nodes;
}
function createEdges(count) {
var edges = [];
if (count === 2) {
return [[0, 1]];
}
for (var i = 0; i < count; i++) {
edges.push([i, (i + 1) % count]);
}
return edges;
}
var datas = [];
for (var i = 0; i < 16; i++) {
datas.push({
nodes: createNodes(i + 2),
edges: createEdges(i + 2)
});
}
chart.setOption({
series: datas.map(function (item, idx) {
return {
type: 'graph',
layout: 'force',
animation: false,
data: item.nodes,
x: (idx % 4) * 25 + '%',
y: Math.floor(idx / 4) * 25 + '%',
width: '25%',
height: '25%',
force: {
// initLayout: 'circular'
// gravity: 0
repulsion: 100,
edgeLength: 5
},
edges: item.edges.map(function (e) {
return {
source: e[0],
target: e[1]
};
})
};
})
});
});
</script>
</body>
</html>
\ No newline at end of file
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/dat.gui.min.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/parser/gexf',
'echarts/chart/graph',
'echarts/component/title',
'echarts/component/legend',
'echarts/component/geo',
'echarts/component/tooltip',
'echarts/component/dataRange'
], function (echarts, gexf) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
$.get('./data/les-miserables.gexf', function (xml) {
var graph = gexf.parse(xml);
var categories = [];
for (var i = 0; i < 9; i++) {
categories[i] = {
name: '类目' + i
};
}
graph.nodes.forEach(function (node) {
node.itemStyle = null;
node.symbolSize = 10;
node.value = node.symbolSize;
node.label.normal.show = node.symbolSize > 30;
node.category = node.attributes['modularity_class'];
node.x = node.y = null;
});
chart.setOption({
legend: [{
// selectedMode: 'single',
data: categories.map(function (a) {
return a.name;
})
}],
animationDurationUpdate: 1500,
animationEasingUpdate: 'quinticInOut',
series : [
{
name: 'Les Miserables',
type: 'graph',
layout: 'force',
data: graph.nodes,
links: graph.links,
categories: categories,
animation: false,
roam: true,
draggable: true,
force: {
repulsion: 100
},
label: {
normal: {
position: 'right'
}
}
}
]
});
var config = {
layout: 'none'
};
var gui = new dat.GUI();
gui.add(config, 'layout', ['none', 'circular'])
.onChange(function (value) {
chart.setOption({
series: [{
name: 'Les Miserables',
layout: value
}]
});
});
});
});
</script>
</body>
</html>
\ No newline at end of file
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/dat.gui.min.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/parser/gexf',
'echarts/chart/graph',
'echarts/component/title',
'echarts/component/legend',
'echarts/component/geo',
'echarts/component/tooltip',
'echarts/component/dataRange'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'), null, {
renderer: 'canvas'
});
var data = [];
var edges = [];
chart.setOption({
series: [{
type: 'graph',
layout: 'force',
animation: false,
data: data,
force: {
// initLayout: 'circular'
// gravity: 0
repulsion: 100,
edgeLength: 5
},
edges: edges
}]
});
setInterval(function () {
data.push({
id: data.length
});
var source = Math.round((data.length - 1) * Math.random());
var target = Math.round((data.length - 1) * Math.random());
if (source !== target) {
edges.push({
source: source,
target: target
});
}
chart.setOption({
series: [{
data: data,
edges: edges
}]
});
console.log('nodes: ' + data.length);
console.log('links: ' + data.length);
}, 500);
});
</script>
</body>
</html>
\ No newline at end of file
......@@ -64,7 +64,7 @@
}
},
animationDurationUpdate: 1500,
animationEasing: 'quinticInOut',
animationEasingUpdate: 'quinticInOut',
series : [
{
name: 'Les Miserables',
......
<html>
<head>
<meta charset="utf-8">
<script src="esl.js"></script>
<script src="config.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<div id="main"></div>
<script>
require([
'echarts',
'echarts/chart/heatmap',
'echarts/component/legend',
'echarts/component/dataRange',
'echarts/component/grid',
'echarts/component/polar',
'echarts/component/tooltip'
], function (echarts) {
var chart = echarts.init(document.getElementById('main'));
var hours = ['12a', '1a', '2a', '3a', '4a', '5a', '6a',
'7a', '8a', '9a','10a','11a',
'12p', '1p', '2p', '3p', '4p', '5p',
'6p', '7p', '8p', '9p', '10p', '11p'];
var days = ['Saturday', 'Friday', 'Thursday',
'Wednesday', 'Tuesday', 'Monday', 'Sunday'];
var data = [[0,0,5],[0,1,1],[0,2,0],[0,3,0],[0,4,0],[0,5,0],[0,6,0],[0,7,0],[0,8,0],[0,9,0],[0,10,0],[0,11,2],[0,12,4],[0,13,1],[0,14,1],[0,15,3],[0,16,4],[0,17,6],[0,18,4],[0,19,4],[0,20,3],[0,21,3],[0,22,2],[0,23,5],[1,0,7],[1,1,0],[1,2,0],[1,3,0],[1,4,0],[1,5,0],[1,6,0],[1,7,0],[1,8,0],[1,9,0],[1,10,5],[1,11,2],[1,12,2],[1,13,6],[1,14,9],[1,15,11],[1,16,6],[1,17,7],[1,18,8],[1,19,12],[1,20,5],[1,21,5],[1,22,7],[1,23,2],[2,0,1],[2,1,1],[2,2,0],[2,3,0],[2,4,0],[2,5,0],[2,6,0],[2,7,0],[2,8,0],[2,9,0],[2,10,3],[2,11,2],[2,12,1],[2,13,9],[2,14,8],[2,15,10],[2,16,6],[2,17,5],[2,18,5],[2,19,5],[2,20,7],[2,21,4],[2,22,2],[2,23,4],[3,0,7],[3,1,3],[3,2,0],[3,3,0],[3,4,0],[3,5,0],[3,6,0],[3,7,0],[3,8,1],[3,9,0],[3,10,5],[3,11,4],[3,12,7],[3,13,14],[3,14,13],[3,15,12],[3,16,9],[3,17,5],[3,18,5],[3,19,10],[3,20,6],[3,21,4],[3,22,4],[3,23,1],[4,0,1],[4,1,3],[4,2,0],[4,3,0],[4,4,0],[4,5,1],[4,6,0],[4,7,0],[4,8,0],[4,9,2],[4,10,4],[4,11,4],[4,12,2],[4,13,4],[4,14,4],[4,15,14],[4,16,12],[4,17,1],[4,18,8],[4,19,5],[4,20,3],[4,21,7],[4,22,3],[4,23,0],[5,0,2],[5,1,1],[5,2,0],[5,3,3],[5,4,0],[5,5,0],[5,6,0],[5,7,0],[5,8,2],[5,9,0],[5,10,4],[5,11,1],[5,12,5],[5,13,10],[5,14,5],[5,15,7],[5,16,11],[5,17,6],[5,18,0],[5,19,5],[5,20,3],[5,21,4],[5,22,2],[5,23,0],[6,0,1],[6,1,0],[6,2,0],[6,3,0],[6,4,0],[6,5,0],[6,6,0],[6,7,0],[6,8,0],[6,9,0],[6,10,1],[6,11,0],[6,12,2],[6,13,1],[6,14,3],[6,15,4],[6,16,0],[6,17,0],[6,18,0],[6,19,0],[6,20,1],[6,21,2],[6,22,2],[6,23,6]];
data = data.map(function (item) {
return [item[1], item[0], item[2]];
});
chart.setOption({
tooltip: {
position: 'top'
},
animation: false,
grid: {
height: 300
},
xAxis: {
type: 'category',
data: hours
},
yAxis: {
type: 'category',
data: days
},
dataRange: {
min: 0,
max: 10,
// calculable: true,
range: [1, 10],
color: ['darkgreen','lightgreen']
},
series: [{
name: 'Punch Card',
type: 'heatmap',
data: data,
label: {
normal: {
show: true
}
},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
});
});
</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.
先完成此消息的编辑!
想要评论请 注册