提交 675251e2 编写于 作者: S sushuang

Fix scatter stream.

Modify coord.dataToPoint.
Fix large and incremental detection.
上级 b42e8a5a
import * as graphic from '../../util/graphic';
import * as lineContain from 'zrender/src/contain/line';
import * as quadraticContain from 'zrender/src/contain/quadratic';
export default graphic.extendShape({
shape: {
polyline: false,
curveness: 0,
segs: []
},
buildPath: function (path, shape) {
var segs = shape.segs;
var curveness = shape.curveness;
if (shape.polyline) {
for (var i = 0; i < segs.length;) {
var count = segs[i++];
if (count > 0) {
path.moveTo(segs[i++], segs[i++]);
for (var k = 1; k < count; k++) {
path.lineTo(segs[i++], segs[i++]);
}
}
}
}
else {
for (var i = 0; i < segs.length;) {
var x0 = segs[i++];
var y0 = segs[i++];
var x1 = segs[i++];
var y1 = segs[i++];
path.moveTo(x0, y0);
if (curveness > 0) {
var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;
path.quadraticCurveTo(x2, y2, x1, y1);
}
else {
path.lineTo(x1, y1);
}
}
}
},
findDataIndex: function (x, y) {
// var shape = this.shape;
// var segs = shape.segs;
// var isPolyline = shape.polyline;
// var lineWidth = Math.max(this.style.lineWidth, 1);
// Not consider transform
// for (var i = 0; i < segs.length; i++) {
// var seg = segs[i];
// if (isPolyline) {
// for (var j = 1; j < seg.length; j++) {
// if (lineContain.containStroke(
// seg[j - 1][0], seg[j - 1][1], seg[j][0], seg[j][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// }
// else {
// if (seg.length > 2) {
// if (quadraticContain.containStroke(
// seg[0][0], seg[0][1], seg[2][0], seg[2][1], seg[1][0], seg[1][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// else {
// if (lineContain.containStroke(
// seg[0][0], seg[0][1], seg[1][0], seg[1][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// }
// }
return -1;
}
});
\ No newline at end of file
// TODO Batch by color
import * as graphic from '../../util/graphic';
import LargeLineShape from './LargeLine';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
// import * as lineContain from 'zrender/src/contain/line';
// import * as quadraticContain from 'zrender/src/contain/quadratic';
var LargeLineShape = graphic.extendShape({
shape: {
polyline: false,
curveness: 0,
segs: []
},
buildPath: function (path, shape) {
var segs = shape.segs;
var curveness = shape.curveness;
if (shape.polyline) {
for (var i = 0; i < segs.length;) {
var count = segs[i++];
if (count > 0) {
path.moveTo(segs[i++], segs[i++]);
for (var k = 1; k < count; k++) {
path.lineTo(segs[i++], segs[i++]);
}
}
}
}
else {
for (var i = 0; i < segs.length;) {
var x0 = segs[i++];
var y0 = segs[i++];
var x1 = segs[i++];
var y1 = segs[i++];
path.moveTo(x0, y0);
if (curveness > 0) {
var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;
path.quadraticCurveTo(x2, y2, x1, y1);
}
else {
path.lineTo(x1, y1);
}
}
}
},
findDataIndex: function (x, y) {
// TODO
// support incremental
// ???
// Typed array support
// var shape = this.shape;
// var segs = shape.segs;
// var isPolyline = shape.polyline;
// var lineWidth = Math.max(this.style.lineWidth, 1);
// // TODO ???
// // Not consider transform
// for (var i = 0; i < segs.length; i++) {
// var seg = segs[i];
// if (isPolyline) {
// for (var j = 1; j < seg.length; j++) {
// if (lineContain.containStroke(
// seg[j - 1][0], seg[j - 1][1], seg[j][0], seg[j][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// }
// else {
// if (seg.length > 2) {
// if (quadraticContain.containStroke(
// seg[0][0], seg[0][1], seg[2][0], seg[2][1], seg[1][0], seg[1][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// else {
// if (lineContain.containStroke(
// seg[0][0], seg[0][1], seg[1][0], seg[1][1], lineWidth, x, y
// )) {
// return i;
// }
// }
// }
// }
return -1;
}
});
function LargeLineDraw() {
this.group = new graphic.Group();
......@@ -20,41 +109,36 @@ largeLineProto.updateData = function (data) {
this.group.removeAll();
var lineEl = this._lineEl;
var seriesModel = data.hostModel;
lineEl.setShape({
segs: data.mapArray(data.getItemLayout)
segs: data.getLayout('linesPoints')
});
this._setCommon(data, seriesModel);
this._setCommon(data);
// Add back
this.group.add(lineEl);
};
largeLineProto.updateLayout = function (seriesModel) {
var data = seriesModel.getData();
this._lineEl.setShape({
segs: data.mapArray(data.getItemLayout)
});
};
/**
* @override
*/
largeLineProto.incrementalPrepareRender = function (data) {
this._setCommon(data, data.hostModel);
largeLineProto.incrementalPrepareUpdate = function (data) {
this.group.removeAll();
this._setCommon(data, true);
this._clearIncremental();
!this._incremental && this.group.add(
this._incremental = new IncrementalDisplayable()
);
if (!this._incremental) {
this._incremental = new IncrementalDisplayable();
}
this.group.add(this._incremental);
};
/**
* @override
*/
largeLineProto.incrementalRender = function (taskParams, data) {
largeLineProto.incrementalUpdate = function (taskParams, data) {
this._lineEl.setShape({
segs: data.getLayout('linesPoints')
});
......@@ -70,16 +154,17 @@ largeLineProto.remove = function () {
this.group.removeAll();
};
largeLineProto._setCommon = function (data, seriesModel, isIncremental) {
largeLineProto._setCommon = function (data, isIncremental) {
var lineEl = this._lineEl;
var hostModel = data.hostModel;
lineEl.setShape({
polyline: seriesModel.get('polyline'),
curveness: seriesModel.get('lineStyle.normal.curveness')
polyline: hostModel.get('polyline'),
curveness: hostModel.get('lineStyle.normal.curveness')
});
lineEl.useStyle(
seriesModel.getModel('lineStyle.normal').getLineStyle()
hostModel.getModel('lineStyle.normal').getLineStyle()
);
var visualColor = data.getVisual('color');
......@@ -91,7 +176,7 @@ largeLineProto._setCommon = function (data, seriesModel, isIncremental) {
if (!isIncremental) {
// Enable tooltip
// PENDING May have performance issue when path is extremely large
lineEl.seriesIndex = seriesModel.seriesIndex;
lineEl.seriesIndex = hostModel.seriesIndex;
lineEl.on('mousemove', function (e) {
lineEl.dataIndex = null;
var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY);
......
......@@ -2,6 +2,7 @@
import * as graphic from '../../util/graphic';
import {createSymbol} from '../../util/symbol';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
var LargeSymbolPath = graphic.extendShape({
......@@ -15,27 +16,32 @@ var LargeSymbolPath = graphic.extendShape({
buildPath: function (path, shape) {
var points = shape.points;
var sizes = shape.sizes;
var size = shape.size;
var symbolProxy = this.symbolProxy;
var symbolProxyShape = symbolProxy.shape;
for (var i = 0; i < points.length; i++) {
var pt = points[i];
for (var i = 0; i < points.length;) {
var x = points[i++];
var y = points[i++];
if (isNaN(pt[0]) || isNaN(pt[1])) {
if (isNaN(x) || isNaN(y)) {
continue;
}
var size = sizes[i];
if (sizes) {
size = sizes[i];
}
if (size[0] < 4) {
// Optimize for small symbol
path.rect(
pt[0] - size[0] / 2, pt[1] - size[1] / 2,
x - size[0] / 2, y - size[1] / 2,
size[0], size[1]
);
}
else {
symbolProxyShape.x = pt[0] - size[0] / 2;
symbolProxyShape.y = pt[1] - size[1] / 2;
symbolProxyShape.x = x - size[0] / 2;
symbolProxyShape.y = y - size[1] / 2;
symbolProxyShape.width = size[0];
symbolProxyShape.height = size[1];
......@@ -45,23 +51,29 @@ var LargeSymbolPath = graphic.extendShape({
},
findDataIndex: function (x, y) {
var shape = this.shape;
var points = shape.points;
var sizes = shape.sizes;
// Not consider transform
// Treat each element as a rect
// top down traverse
for (var i = points.length - 1; i >= 0; i--) {
var pt = points[i];
var size = sizes[i];
var x0 = pt[0] - size[0] / 2;
var y0 = pt[1] - size[1] / 2;
if (x >= x0 && y >= y0 && x <= x0 + size[0] && y <= y0 + size[1]) {
// i is dataIndex
return i;
}
}
// TODO
// support incremental, Typed array.
// TODO ???
// Consider transform
// var shape = this.shape;
// var points = shape.points;
// var sizes = shape.sizes;
// // Not consider transform
// // Treat each element as a rect
// // top down traverse
// for (var i = points.length - 1; i >= 0; i--) {
// var pt = points[i];
// var size = sizes[i];
// var x0 = pt[0] - size[0] / 2;
// var y0 = pt[1] - size[1] / 2;
// if (x >= x0 && y >= y0 && x <= x0 + size[0] && y <= y0 + size[1]) {
// // i is dataIndex
// return i;
// }
// }
return -1;
}
......@@ -84,23 +96,50 @@ var largeSymbolProto = LargeSymbolDraw.prototype;
*/
largeSymbolProto.updateData = function (data) {
this.group.removeAll();
var symbolEl = this._symbolEl;
var seriesModel = data.hostModel;
this._setCommon(data);
symbolEl.setShape({
points: data.mapArray(data.getItemLayout),
sizes: data.mapArray(
// Add back
this.group.add(symbolEl);
};
largeSymbolProto.incrementalPrepareUpdate = function (data) {
this.group.removeAll();
this._setCommon(data, true);
this._clearIncremental();
if (!this._incremental) {
this._incremental = new IncrementalDisplayable();
}
this.group.add(this._incremental);
};
largeSymbolProto.incrementalUpdate = function (taskParams, data) {
this._symbolEl.setShape({
points: data.getLayout('symbolPoints')
});
this._incremental.addDisplayable(this._symbolEl, true);
};
largeSymbolProto._setCommon = function (data, isIncremental) {
var symbolEl = this._symbolEl;
var hostModel = data.hostModel;
if (data.hasItemVisual.symbolSize) {
// TODO typed array?
symbolEl.setShape('sizes', data.mapArray(
function (idx) {
var size = data.getItemVisual(idx, 'symbolSize');
if (!(size instanceof Array)) {
size = [size, size];
}
return size;
return (size instanceof Array) ? size : [size, size];
}
)
});
));
}
else {
var size = data.getVisual('symbolSize');
symbolEl.setShape('size', (size instanceof Array) ? size : [size, size]);
}
// Create symbolProxy to build path for each data
symbolEl.symbolProxy = createSymbol(
......@@ -110,7 +149,7 @@ largeSymbolProto.updateData = function (data) {
symbolEl.setColor = symbolEl.symbolProxy.setColor;
symbolEl.useStyle(
seriesModel.getModel('itemStyle.normal').getItemStyle(['color'])
hostModel.getModel('itemStyle.normal').getItemStyle(['color'])
);
var visualColor = data.getVisual('color');
......@@ -118,31 +157,32 @@ largeSymbolProto.updateData = function (data) {
symbolEl.setColor(visualColor);
}
// Enable tooltip
// PENDING May have performance issue when path is extremely large
symbolEl.seriesIndex = seriesModel.seriesIndex;
symbolEl.on('mousemove', function (e) {
symbolEl.dataIndex = null;
var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);
if (dataIndex >= 0) {
// Provide dataIndex for tooltip
symbolEl.dataIndex = dataIndex;
}
});
// Add back
this.group.add(symbolEl);
};
largeSymbolProto.updateLayout = function (seriesModel) {
var data = seriesModel.getData();
this._symbolEl.setShape({
points: data.mapArray(data.getItemLayout)
});
if (!isIncremental) {
// Enable tooltip
// PENDING May have performance issue when path is extremely large
symbolEl.seriesIndex = hostModel.seriesIndex;
symbolEl.on('mousemove', function (e) {
symbolEl.dataIndex = null;
var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY);
if (dataIndex >= 0) {
// Provide dataIndex for tooltip
symbolEl.dataIndex = dataIndex;
}
});
}
};
largeSymbolProto.remove = function () {
this._clearIncremental();
this._incremental = null;
this.group.removeAll();
};
largeSymbolProto._clearIncremental = function () {
var incremental = this._incremental;
if (incremental) {
incremental.clearDisplaybles();
}
};
export default LargeSymbolDraw;
\ No newline at end of file
......@@ -4,7 +4,7 @@
import * as graphic from '../../util/graphic';
import LineGroup from './Line';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
// import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
/**
* @alias module:echarts/component/marker/LineDraw
......@@ -77,6 +77,7 @@ function doUpdate(lineDraw, oldLineData, newLineData, oldIdx, newIdx, seriesScop
lineDraw.group.add(itemEl);
}
// ???
lineDrawProto.updateLayout = function () {
var lineData = this._lineData;
lineData.eachItemGraphicEl(function (el, idx) {
......@@ -84,26 +85,27 @@ lineDrawProto.updateLayout = function () {
}, this);
};
lineDrawProto.incrementalPrepareRender = function (lineData) {
this._seriesScope = makeSeriesScope(this);
this._lineData = lineData;
this._clearIncremental();
// lineDrawProto.incrementalPrepareRender = function (lineData) {
// this._seriesScope = makeSeriesScope(this);
// this._lineData = lineData;
// this._clearIncremental();
!this._incremental && this.group.add(
this._incremental = new IncrementalDisplayable()
);
};
// !this._incremental && this.group.add(
// this._incremental = new IncrementalDisplayable()
// );
// };
lineDrawProto.incrementalRender = function (taskParams, lineData) {
for (var idx = taskParams.start; idx < taskParams.end; idx++) {
var itemLayout = lineData.getItemLayout(idx);
// lineDrawProto.incrementalRender = function (taskParams, lineData) {
// for (var idx = taskParams.start; idx < taskParams.end; idx++) {
// var itemLayout = lineData.getItemLayout(idx);
if (lineNeedsDraw(itemLayout)) {
var el = new this._ctor(lineData, idx, this._seriesScope);
this._incremental.addDisplayable(el, true);
}
}
};
// if (lineNeedsDraw(itemLayout)) {
// // ??? IncrementalDisplayable do not support Group.
// var el = new this._ctor(lineData, idx, this._seriesScope);
// this._incremental.addDisplayable(el, true);
// }
// }
// };
function makeSeriesScope(lineData) {
var hostModel = lineData.hostModel;
......@@ -111,8 +113,7 @@ function makeSeriesScope(lineData) {
lineStyle: hostModel.getModel('lineStyle.normal').getLineStyle(),
hoverLineStyle: hostModel.getModel('lineStyle.emphasis').getLineStyle(),
labelModel: hostModel.getModel('label.normal'),
hoverLabelModel: hostModel.getModel('label.emphasis'),
isLargeMode: hostModel.get('large')
hoverLabelModel: hostModel.getModel('label.emphasis')
};
}
......
// Temp.
import SymbolClz from './Symbol';
import IncrementalDisplayble from 'zrender/src/graphic/IncrementalDisplayable';
import * as graphic from '../../util/graphic';
/**
* @constructor
*/
function SymbolDraw(symbolCtor) {
var group = this.group = new graphic.Group();
group.add(this._root = new IncrementalDisplayble());
this._symbolCtor = symbolCtor || SymbolClz;
}
var symbolDrawProto = SymbolDraw.prototype;
function symbolNeedsDraw(data, idx, isIgnore) {
var point = data.getItemLayout(idx);
// Is an object
// if (point && point.hasOwnProperty('point')) {
// point = point.point;
// }
return point && !isNaN(point[0]) && !isNaN(point[1]) && !(isIgnore && isIgnore(idx))
&& data.getItemVisual(idx, 'symbol') !== 'none';
}
symbolDrawProto.updateData = function (data, isIgnore) {
var seriesModel = this._seriesModel = data.hostModel;
this._isIgnore = isIgnore;
doRender(this, seriesModel, isIgnore);
};
function doRender(self, seriesModel, isIgnore) {
var root = self._root;
var data = seriesModel.getData();
var seriesModel = data.hostModel;
var SymbolCtor = self._symbolCtor;
var seriesScope = self._seriesScope = {
itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']),
hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(),
symbolRotate: seriesModel.get('symbolRotate'),
symbolOffset: seriesModel.get('symbolOffset'),
hoverAnimation: seriesModel.get('hoverAnimation'),
labelModel: seriesModel.getModel('label.normal'),
hoverLabelModel: seriesModel.getModel('label.emphasis'),
cursorStyle: seriesModel.get('cursor')
};
root.clearDisplaybles();
var dataEachTask = data.createEachTask(function (newIdx) {
var point = data.getItemLayout(newIdx);
var color = data.getItemVisual(newIdx, 'color');
if (symbolNeedsDraw(data, newIdx, isIgnore)) {
// var symbolEl = new SymbolCtor(data, newIdx, seriesScope);
// symbolEl.attr('position', point);
// ??? not a good interface? which must ensure data index
// corresponding implicitly.
// ??? group?
var symbolEl = new graphic.Circle({
shape: {
r: 1 + Math.random() * 1
},
style: {
fill: color,
blend: 'lighter'
},
position: point
});
data.setItemGraphicEl(newIdx, symbolEl);
root.addDisplayable(symbolEl, true);
}
});
// ??? updateViewBase should not be here?
seriesModel.pipeTask(dataEachTask, 'render');
}
// ???
symbolDrawProto.updateView = function () {
if (this._seriesModel) {
doRender(this, this._seriesModel, this._isIgnore);
}
};
symbolDrawProto.remove = function (enableAnimation) {
var root = this._root;
root && root.clearDisplaybles();
this.group.removeAll();
};
export default SymbolDraw;
\ No newline at end of file
......@@ -4,6 +4,7 @@
import * as graphic from '../../util/graphic';
import SymbolClz from './Symbol';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
/**
* @constructor
......@@ -18,14 +19,10 @@ function SymbolDraw(symbolCtor) {
var symbolDrawProto = SymbolDraw.prototype;
function symbolNeedsDraw(data, idx, isIgnore) {
var point = data.getItemLayout(idx);
// Is an object
// if (point && point.hasOwnProperty('point')) {
// point = point.point;
// }
return point && !isNaN(point[0]) && !isNaN(point[1]) && !(isIgnore && isIgnore(idx))
&& data.getItemVisual(idx, 'symbol') !== 'none';
function symbolNeedsDraw(data, point, idx, isIgnore) {
return point && !isNaN(point[0]) && !isNaN(point[1])
&& !(isIgnore && isIgnore(idx))
&& data.getItemVisual(idx, 'symbol') !== 'none';
}
/**
* Update symbols draw by new data
......@@ -36,25 +33,14 @@ symbolDrawProto.updateData = function (data, isIgnore) {
var group = this.group;
var seriesModel = data.hostModel;
var oldData = this._data;
var SymbolCtor = this._symbolCtor;
var seriesScope = {
itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']),
hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(),
symbolRotate: seriesModel.get('symbolRotate'),
symbolOffset: seriesModel.get('symbolOffset'),
hoverAnimation: seriesModel.get('hoverAnimation'),
labelModel: seriesModel.getModel('label.normal'),
hoverLabelModel: seriesModel.getModel('label.emphasis'),
cursorStyle: seriesModel.get('cursor')
};
var seriesScope = makeSeriesScope(data);
data.diff(oldData)
.add(function (newIdx) {
var point = data.getItemLayout(newIdx);
if (symbolNeedsDraw(data, newIdx, isIgnore)) {
if (symbolNeedsDraw(data, point, newIdx, isIgnore)) {
var symbolEl = new SymbolCtor(data, newIdx, seriesScope);
symbolEl.attr('position', point);
data.setItemGraphicEl(newIdx, symbolEl);
......@@ -64,7 +50,7 @@ symbolDrawProto.updateData = function (data, isIgnore) {
.update(function (newIdx, oldIdx) {
var symbolEl = oldData.getItemGraphicEl(oldIdx);
var point = data.getItemLayout(newIdx);
if (!symbolNeedsDraw(data, newIdx, isIgnore)) {
if (!symbolNeedsDraw(data, point, newIdx, isIgnore)) {
group.remove(symbolEl);
return;
}
......@@ -95,26 +81,7 @@ symbolDrawProto.updateData = function (data, isIgnore) {
this._data = data;
};
symbolDrawProto.progress = function (data) {
var group = this.group;
var seriesModel = data.hostModel;
var oldData = this._data;
var SymbolCtor = this._symbolCtor;
var seriesScope = {
itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']),
hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(),
symbolRotate: seriesModel.get('symbolRotate'),
symbolOffset: seriesModel.get('symbolOffset'),
hoverAnimation: seriesModel.get('hoverAnimation'),
labelModel: seriesModel.getModel('label.normal'),
hoverLabelModel: seriesModel.getModel('label.emphasis'),
cursorStyle: seriesModel.get('cursor')
};
};
// ??? remove
symbolDrawProto.updateLayout = function () {
var data = this._data;
if (data) {
......@@ -126,7 +93,30 @@ symbolDrawProto.updateLayout = function () {
}
};
// symbolDrawProto.incrementalPrepareUpdate = function (data) {
// this._seriesScope = makeSeriesScope(data);
// this._clearIncremental();
// !this._incremental && this.group.add(
// this._incremental = new IncrementalDisplayable()
// );
// };
// symbolDrawProto.incrementalUpdate = function (taskParams, data) {
// for (var idx = taskParams.start; idx < taskParams.end; idx++) {
// var point = data.getItemLayout(idx);
// // ??? IncrementalDisplayable do not support Group.
// symbolNeedsDraw(data, point, idx) && this._incremental.addDisplayable(
// new this._symbolCtor(data, idx, this._seriesScope),
// true
// );
// }
// };
symbolDrawProto.remove = function (enableAnimation) {
this._clearIncremental();
this._incremental = null;
var group = this.group;
var data = this._data;
if (data) {
......@@ -143,4 +133,25 @@ symbolDrawProto.remove = function (enableAnimation) {
}
};
symbolDrawProto._clearIncremental = function () {
var incremental = this._incremental;
if (incremental) {
incremental.clearDisplaybles();
}
};
function makeSeriesScope(data) {
var seriesModel = data.hostModel;
return {
itemStyle: seriesModel.getModel('itemStyle.normal').getItemStyle(['color']),
hoverItemStyle: seriesModel.getModel('itemStyle.emphasis').getItemStyle(),
symbolRotate: seriesModel.get('symbolRotate'),
symbolOffset: seriesModel.get('symbolOffset'),
hoverAnimation: seriesModel.get('hoverAnimation'),
labelModel: seriesModel.getModel('label.normal'),
hoverLabelModel: seriesModel.getModel('label.emphasis'),
cursorStyle: seriesModel.get('cursor')
};
}
export default SymbolDraw;
\ No newline at end of file
import {makeInner} from '../../util/model';
/**
* @return {string} If large mode changed, return string 'reset';
*/
export default function () {
var inner = makeInner();
return function (seriesModel) {
var fields = inner(seriesModel);
var pipelineContext = seriesModel.pipelineContext;
var originalLarge = fields.large;
var originalIncremental = fields.incrementalRender;
var large = fields.large = pipelineContext.large;
var incremental = fields.incrementalRender = pipelineContext.incrementalRender;
return ((originalLarge ^ large) || (originalIncremental ^ incremental)) && 'reset';
};
}
......@@ -7,8 +7,8 @@ import CoordinateSystem from '../../CoordinateSystem';
var globalObj = typeof window === 'undefined' ? global : window;
var Uint32Array = globalObj.Uint32Array || Array;
var Float64Array = globalObj.Float64Array || Array;
var Uint32Arr = globalObj.Uint32Array || Array;
var Float64Arr = globalObj.Float64Array || Array;
// Convert [ [{coord: []}, {coord: []}] ]
// to [ { coords: [[]] } ]
......@@ -111,8 +111,8 @@ var LinesSeries = SeriesModel.extend({
if (typeof data[0] === 'number') {
var len = data.length;
// Store offset and len of each segment
var coordsOffsetAndLenStorage = new Uint32Array(len);
var coordsStorage = new Float64Array(len);
var coordsOffsetAndLenStorage = new Uint32Arr(len);
var coordsStorage = new Float64Arr(len);
var coordsCursor = 0;
var offsetCursor = 0;
var dataCount = 0;
......
......@@ -14,8 +14,6 @@ export default echarts.extendChartView({
init: function () {},
render: function (seriesModel, ecModel, api) {
this.remove(ecModel, api);
var data = seriesModel.getData();
var lineDraw = this._updateLineDraw(data, seriesModel);
......@@ -61,44 +59,41 @@ export default echarts.extendChartView({
this._lastZlevel = zlevel;
},
updateLayout: function (seriesModel, ecModel, api) {
this._lineDraw.updateLayout();
this._clearLayer(api);
},
incrementalPrepareRender: function (seriesModel, ecModel, api) {
this.remove(ecModel, api);
var data = seriesModel.getData();
var lineDraw = this._updateLineDraw(data, seriesModel);
lineDraw.incrementalPrepareRender(data);
lineDraw.incrementalPrepareUpdate(data);
this._clearLayer(api);
},
incrementalRender: function (taskParams, seriesModel, ecModel) {
this._lineDraw.incrementalRender(taskParams, seriesModel.getData());
this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData());
},
_updateLineDraw: function (data, seriesModel) {
var lineDraw = this._lineDraw;
var hasEffect = this._showEffect(seriesModel);
var isPolyline = !!seriesModel.get('polyline');
var isLarge = !!seriesModel.get('large')
&& data.count() >= seriesModel.get('largeThreshold');
var pipelineContext = seriesModel.pipelineContext;
var isLargeDraw = pipelineContext.large || pipelineContext.incrementalRender;
if (__DEV__) {
if (hasEffect && isLarge) {
if (hasEffect && isLargeDraw) {
console.warn('Large lines not support effect');
}
}
if (hasEffect !== this._hasEffet
if (!lineDraw
|| hasEffect !== this._hasEffet
|| isPolyline !== this._isPolyline
|| isLarge !== this._isLarge
|| isLargeDraw !== this._isLargeDraw
) {
if (lineDraw) {
lineDraw.remove();
}
lineDraw = this._lineDraw = isLarge
lineDraw = this._lineDraw = isLargeDraw
? new LargeLineDraw()
: new LineDraw(
isPolyline
......@@ -107,7 +102,7 @@ export default echarts.extendChartView({
);
this._hasEffet = hasEffect;
this._isPolyline = isPolyline;
this._isLarge = isLarge;
this._isLargeDraw = isLargeDraw;
}
this.group.add(lineDraw.group);
......@@ -130,6 +125,7 @@ export default echarts.extendChartView({
remove: function (ecModel, api) {
this._lineDraw && this._lineDraw.remove(api, true);
this._lineDraw = null;
// Clear motion when lineDraw is removed
var zr = api.getZr();
var isSvg = zr.painter.getType() === 'svg';
......
import createRenderPlanner from '../helper/createRenderPlanner';
export default {
seriesType: 'lines',
reset: function (seriesModel, ecModel) {
plan: createRenderPlanner(),
reset: function (seriesModel) {
var coordSys = seriesModel.coordinateSystem;
var isPolyline = seriesModel.get('polyline');
var isLarge = seriesModel.get('large');
var isLarge = seriesModel.pipelineContext.large;
function progress(params, lineData) {
var lineCoords = [];
......@@ -29,7 +34,7 @@ export default {
points[offset++] = len;
}
for (var k = 0; k < len; k++) {
pt = coordSys.dataToPoint(lineCoords[k], pt);
pt = coordSys.dataToPoint(lineCoords[k], null, pt);
points[offset++] = pt[0];
points[offset++] = pt[1];
}
......
import * as echarts from '../../echarts';
import SymbolDraw from '../helper/SymbolDraw';
import LargeSymbolDraw from '../helper/LargeSymbolDraw';
import StreamSymbolDraw from '../helper/StreamSymbolDraw';
echarts.extendChartView({
type: 'scatter',
init: function () {
this._normalSymbolDraw = new SymbolDraw();
this._largeSymbolDraw = new LargeSymbolDraw();
this._streamSymbolDraw = new StreamSymbolDraw();
},
render: function (seriesModel, ecModel, api) {
var data = seriesModel.getData();
var group = this.group;
var symbolDraw = seriesModel.get('large') && data.count() > seriesModel.get('largeThreshold')
? this._largeSymbolDraw
: this._normalSymbolDraw;
this._symbolDraw = symbolDraw;
var symbolDraw = this._updateSymbolDraw(data, seriesModel);
symbolDraw.updateData(data);
group.add(symbolDraw.group);
this._lasySymbolDrawGroup && group.remove(this._lasySymbolDrawGroup);
},
this._lasySymbolDrawGroup = symbolDraw.group;
incrementalPrepareRender: function (seriesModel, ecModel, api) {
var data = seriesModel.getData();
var symbolDraw = this._updateSymbolDraw(data, seriesModel);
symbolDraw.incrementalPrepareUpdate(data);
},
updateLayout: function (seriesModel) {
// ??? do not support updateLayout in stream
this._symbolDraw.updateLayout(seriesModel);
incrementalRender: function (taskParams, seriesModel, ecModel) {
this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData());
},
updateView: function (seriesModel) {
this._symbolDraw.updateView(seriesModel);
_updateSymbolDraw: function (data, seriesModel) {
var symbolDraw = this._symbolDraw;
var pipelineContext = seriesModel.pipelineContext;
var isLargeDraw = pipelineContext.large || pipelineContext.incrementalRender;
if (!symbolDraw || isLargeDraw !== this._isLargeDraw) {
symbolDraw && symbolDraw.remove();
symbolDraw = this._symbolDraw = isLargeDraw
? new LargeSymbolDraw()
: new SymbolDraw();
this._isLargeDraw = isLargeDraw;
}
this.group.add(symbolDraw.group);
return symbolDraw;
},
remove: function (ecModel, api) {
this._symbolDraw && this._symbolDraw.remove(api, true);
this._symbolDraw = null;
},
dispose: function () {}
......
......@@ -3,6 +3,8 @@ import * as zrUtil from 'zrender/src/core/util';
import * as visualSolution from '../../visual/visualSolution';
import VisualMapping from '../../visual/VisualMapping';
// ???! visualmap progress.
echarts.registerVisual(echarts.PRIORITY.VISUAL.COMPONENT, function (ecModel) {
ecModel.eachComponent('visualMap', function (visualMapModel) {
processSingleVisualMap(visualMapModel, ecModel);
......
......@@ -32,14 +32,16 @@
* + axisPointerEnabled {boolean}
*
* + dataToPoint {Function}: mandatory
* @param {Array.<*>} data
* @param {boolean} [clamp=false]
* @param {*|Array.<*>} data
* @param {*} Defined by the coordinate system itself
* @param {Array.<*>} out
* @return {Array.<number>} point Point in global pixel coordinate system.
*
* + pointToData {Function}: mandatory
* @param {Array.<number>} point Point in global pixel coordinate system.
* @param {boolean} [clamp=false]
* @return {Array.<*>} data
* @param {*} Defined by the coordinate system itself
* @param {Array.<*>} out
* @return {*|Array.<*>} data
*
* + containPoint {Function}: mandatory
* @param {Array.<number>} point Point in global pixel coordinate system.
......
......@@ -57,7 +57,7 @@ Cartesian2D.prototype = {
* @param {Array.<number>} out
* @return {Array.<number>}
*/
dataToPoint: function (data, out) {
dataToPoint: function (data, reserved, out) {
var xAxis = this.getAxis('x');
var yAxis = this.getAxis('y');
out = out || [];
......
......@@ -194,12 +194,6 @@ var List = function (dimensions, hostModel) {
this._count = 0;
/**
* @type {number}
* @private
*/
this._chunkSize;
/**
* Data storage
* @type {Object.<key, Array.<TypedArray|Array>>}
......@@ -249,6 +243,13 @@ var List = function (dimensions, hostModel) {
*/
this._itemVisuals = [];
/**
* Key: visual type, Value: boolean
* @type {Object}
* @readOnly
*/
this.hasItemVisual = {};
/**
* Item layout properties after layout
* @type {Array.<Object>}
......@@ -287,6 +288,12 @@ var List = function (dimensions, hostModel) {
* @private
*/
this._extent;
/**
* @type {Object}
* @private
*/
this._extentEnds;
};
var listProto = List.prototype;
......@@ -421,10 +428,52 @@ listProto._initDataFromProvider = function (start, end) {
// Reset cached extent
this._extent = {};
this._extentEnds = {};
// Create more chunk storage.
var chunkIndex = this._chunkCount;
var volume = chunkIndex * chunkSize;
// var chunkIndex = this._chunkCount;
// var volume = chunkIndex * chunkSize;
// for (var i = 0; i < dimensions.length; i++) {
// var dim = dimensions[i];
// var dimInfo = dimensionInfoMap[dim];
// if (dimInfo.otherDims.itemName === 0) {
// nameDimIdx = i;
// }
// var DataCtor = dataCtors[dimInfo.type];
// if (!storage[dim]) {
// storage[dim] = [];
// }
// if (storage[dim][chunkIndex]) {
// var resizeChunkArray = storage[dim][chunkIndex];
// var newSize;
// if (volume < end) {
// newSize = chunkSize;
// }
// else {
// newStore = end - chunkIndex * chunkSize;
// }
// var newStore = new DataCtor(newSize);
// for (var i = 0; i < resizeChunkArray.length; i++) {
// newStore[i] = resizeChunkArray[i];
// }
// storage[dim][chunkIndex] = newStore;
// }
// }
// Create new chunks
// for (var k = volume; k < end; k += chunkSize) {
// for (var i = 0; i < dimensions.length; i++) {
// var dim = dimensions[i];
// var dimInfo = dimensionInfoMap[dim];
// var DataCtor = dataCtors[dimInfo.type];
// storage[dim][this._chunkCount] = new DataCtor(Math.min(end - k, chunkSize));
// }
// this._chunkCount++;
// }
var chunkCount = this._chunkCount;
var lastChunkIndex = chunkCount - 1;
for (var i = 0; i < dimensions.length; i++) {
var dim = dimensions[i];
......@@ -437,33 +486,22 @@ listProto._initDataFromProvider = function (start, end) {
if (!storage[dim]) {
storage[dim] = [];
}
if (storage[dim][chunkIndex]) {
var resizeChunkArray = storage[dim][chunkIndex];
var newSize;
if (volume < end) {
newSize = chunkSize;
}
else {
newStore = end - chunkIndex * chunkSize;
}
var newStore = new DataCtor(newSize);
for (var i = 0; i < resizeChunkArray.length; i++) {
newStore[i] = resizeChunkArray[i];
var resizeChunkArray = storage[dim][lastChunkIndex];
if (resizeChunkArray && resizeChunkArray.length < chunkSize) {
var newStore = new DataCtor(Math.min(end - lastChunkIndex * chunkSize, chunkSize));
// The cost of the copy is probably inconsiderable
// within the initial chunkSize.
for (var j = 0; j < resizeChunkArray.length; j++) {
newStore[j] = resizeChunkArray[j];
}
storage[dim][chunkIndex] = newStore;
storage[dim][lastChunkIndex] = newStore;
}
}
// Create new chunks
for (var k = volume; k < end; k += chunkSize) {
for (var i = 0; i < dimensions.length; i++) {
var dim = dimensions[i];
var dimInfo = dimensionInfoMap[dim];
var DataCtor = dataCtors[dimInfo.type];
storage[dim][this._chunkCount] = new DataCtor(Math.min(end - k, chunkSize));
// Create new chunks.
for (var k = chunkCount * chunkSize; k < end; k += chunkSize) {
storage[dim].push(new DataCtor(Math.min(end - k, chunkSize)));
}
this._chunkCount++;
this._chunkCount = storage[dim].length;
}
for (var idx = start; idx < end; idx++) {
......@@ -513,7 +551,6 @@ listProto._initDataFromProvider = function (start, end) {
}
}
this._count = end;
};
......@@ -623,35 +660,43 @@ listProto.hasValue = function (idx) {
* @param {Function} filter
*/
listProto.getDataExtent = function (dim, stack, filter) {
// Consider the stream or append data cases: If at the begining the data
// is empty or little, the extent should not be simply cached.
dim = this.getDimension(dim);
var dimData = this._storage[dim];
var dimInfo = this.getDimensionInfo(dim);
stack = (dimInfo && dimInfo.stackable) && stack;
var dimExtent = (this._extent || (this._extent = {}))[dim + (!!stack)];
var value;
if (dimExtent) {
return dimExtent;
}
if (!dimData) {
return [Infinity, -Infinity];
}
var dimInfo = this.getDimensionInfo(dim);
stack = (dimInfo && dimInfo.stackable) && stack;
var cacheName = dim + (!!stack);
var dimExtent = this._extent[cacheName];
var dimExtentEnd = this._extentEnds[cacheName] || 0;
var currEnd = this.count();
// Assume that dimExtentEnd > currEnd will never happen.
// When data appended, dimExtenEnd < currEnd.
if (dimExtent && dimExtentEnd === currEnd) {
return dimExtent;
}
var min = Infinity;
var max = -Infinity;
// var isOrdinal = dimInfo.type === 'ordinal';
for (var i = 0, len = this.count(); i < len; i++) {
value = this.get(dim, i, stack);
// FIXME
// if (isOrdinal && typeof value === 'string') {
// value = zrUtil.indexOf(dimData, value);
// }
dimExtent && (min = dimExtent[0], max = dimExtent[1]);
for (var i = dimExtentEnd; i < currEnd; i++) {
var value = this.get(dim, i, stack);
if (!filter || filter(value, dim, i)) {
value < min && (min = value);
value > max && (max = value);
}
}
return (this._extent[dim + !!stack] = [min, max]);
this._extentEnds[cacheName] = currEnd;
return (this._extent[cacheName] = [min, max]);
};
/**
......@@ -944,6 +989,7 @@ listProto.filterSelf = function (dimensions, cb, stack, context) {
// Reset data extent
this._extent = {};
this._extentEnds = {};
return this;
};
......@@ -1246,17 +1292,20 @@ listProto.getItemVisual = function (idx, key, ignoreParent) {
*/
listProto.setItemVisual = function (idx, key, value) {
var itemVisual = this._itemVisuals[idx] || {};
var hasItemVisual = this.hasItemVisual;
this._itemVisuals[idx] = itemVisual;
if (isObject(key)) {
for (var name in key) {
if (key.hasOwnProperty(name)) {
itemVisual[name] = key[name];
hasItemVisual[name] = true;
}
}
return;
}
itemVisual[key] = value;
hasItemVisual[key] = true;
};
/**
......@@ -1265,6 +1314,7 @@ listProto.setItemVisual = function (idx, key, value) {
listProto.clearAllVisual = function () {
this._visual = {};
this._itemVisuals = [];
this.hasItemVisual = {};
};
var setItemDataAndSeriesIndex = function (child) {
......@@ -1338,7 +1388,8 @@ listProto.cloneShallow = function (list) {
}
if (this._extent) {
list._extent = zrUtil.extend({}, this._extent);
list._extent = zrUtil.clone(this._extent);
list._extentEnds = zrUtil.clone(this._extentEnds);
}
return list;
......
......@@ -264,7 +264,6 @@ echartsProto._onframe = function () {
var remainTime = TEST_FRAME_REMAIN_TIME;
var scheduler = this._scheduler;
var ecModel = this._model;
if (scheduler.unfinished) {
scheduler.unfinished = false;
do {
......@@ -273,13 +272,15 @@ echartsProto._onframe = function () {
scheduler.performSeriesTasks(ecModel);
// Currently dataProcessorFuncs do not check threshold.
scheduler.performStageTasks(dataProcessorFuncs, ecModel);
scheduler.performDataProcessorTasks(dataProcessorFuncs, ecModel);
scheduler.updateModes(ecModel);
// ???! coordSys create
// this._coordSysMgr.update();
// console.log('------------- ec frame visual -------------', remainTime);
scheduler.performStageTasks(visualFuncs, ecModel);
scheduler.performVisualTasks(visualFuncs, ecModel);
render(this, this._model, this._api, 'none');
......@@ -771,7 +772,9 @@ var updateMethods = {
// ??? if some processor do not use task, it should also process in progress,
// otherwise, consider data extent, both dependent.
scheduler.performStageTasks(dataProcessorFuncs, ecModel, payload);
scheduler.performDataProcessorTasks(dataProcessorFuncs, ecModel, payload);
scheduler.updateModes(ecModel);
stackSeriesData.call(this, ecModel);
......@@ -779,7 +782,7 @@ var updateMethods = {
coordSysMgr.update(ecModel, api);
clearColorPalette(ecModel);
scheduler.performStageTasks(visualFuncs, ecModel, payload);
scheduler.performVisualTasks(visualFuncs, ecModel, payload);
render(this, ecModel, api, payload);
......@@ -859,8 +862,8 @@ var updateMethods = {
});
// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
// this._scheduler.performStageTasks(visualFuncs, ecModel, payload, 'layout', true);
this._scheduler.performStageTasks(
// this._scheduler.performVisualTasks(visualFuncs, ecModel, payload, 'layout', true);
this._scheduler.performVisualTasks(
visualFuncs, ecModel, payload, {setDirty: true, seriesModels: seriesModels}
);
......@@ -886,7 +889,7 @@ var updateMethods = {
clearColorPalette(ecModel);
// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
this._scheduler.performStageTasks(visualFuncs, ecModel, payload, {setDirty: true});
this._scheduler.performVisualTasks(visualFuncs, ecModel, payload, {setDirty: true});
render(this, this._model, this._api, payload);
......@@ -910,7 +913,7 @@ var updateMethods = {
clearColorPalette(ecModel);
// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
this._scheduler.performStageTasks(visualFuncs, ecModel, payload, {visualType: 'visual', setDirty: true});
this._scheduler.performVisualTasks(visualFuncs, ecModel, payload, {visualType: 'visual', setDirty: true});
render(this, this._model, this._api, payload);
......@@ -932,8 +935,8 @@ var updateMethods = {
ChartView.markUpdateMethod(payload, 'updateLayout');
// Keep pipe to the exist pipeline because it depends on the render task of the full pipeline.
// this._scheduler.performStageTasks(visualFuncs, ecModel, payload, 'layout', true);
this._scheduler.performStageTasks(visualFuncs, ecModel, payload, {setDirty: true});
// this._scheduler.performVisualTasks(visualFuncs, ecModel, payload, 'layout', true);
this._scheduler.performVisualTasks(visualFuncs, ecModel, payload, {setDirty: true});
render(this, this._model, this._api, payload);
......@@ -1012,6 +1015,9 @@ echartsProto.resize = function (opts) {
optionChanged && ecModel.settingTask.dirty();
// ???
// can not visual???
ecModel.eachComponent(function (model, componentType) {
optionChanged && model.settingTask.dirty();
model.dataInitTask && model.dataInitTask.dirty();
......@@ -1398,16 +1404,9 @@ function renderSeries(ecIns, ecModel, api, payload, dirtySeriesModels) {
chartView.__alive = true;
var renderTask = chartView.renderTask;
var performInfo = scheduler.getPerformInfo(renderTask, seriesModel);
var renderTaskCtx = renderTask.context;
payload !== 'none' && (renderTaskCtx.payload = payload);
var incremental = performInfo.incremental;
if (dirtySeriesModels || incremental ^ renderTaskCtx.incremental) {
renderTask.dirty();
}
renderTask.context.incremental = incremental;
unfinished |= renderTask.perform(performInfo);
payload !== 'none' && (renderTask.context.payload = payload);
dirtySeriesModels && renderTask.dirty();
unfinished |= renderTask.perform(scheduler.getPerformArgs(renderTask));
chartView.group.silent = !!seriesModel.get('silent');
......
import {map} from 'zrender/src/core/util';
import createRenderPlanner from '../chart/helper/createRenderPlanner';
export default function (seriesType) {
return {
seriesType: seriesType,
reset: function (seriesModel, ecModel, api) {
plan: createRenderPlanner(),
reset: function (seriesModel) {
var data = seriesModel.getData();
var coordSys = seriesModel.coordinateSystem;
var pipelineContext = seriesModel.pipelineContext;
var isLargeRender = pipelineContext.large || pipelineContext.incrementalRender;
if (!coordSys) {
return;
}
var dims = map(coordSys.dimensions, function (dim) {
return data.getDimension(seriesModel.coordDimToDataDim(dim)[0]);
});
}).slice(0, 2);
var dimLen = dims.length;
var dataEach = dims.length === 1
? function (data, idx) {
var x = data.get(dims[0], idx);
// Also {Array.<number>}, not undefined to avoid if...else... statement
data.setItemLayout(idx, isNaN(x) ? [NaN, NaN] : coordSys.dataToPoint(x));
}
: dims.length === 2
? function (data, idx) {
var x = data.get(dims[0], idx);
var y = data.get(dims[1], idx);
// Also {Array.<number>}, not undefined to avoid if...else... statement
data.setItemLayout(
idx, (isNaN(x) || isNaN(y)) ? [NaN, NaN] : coordSys.dataToPoint([x, y])
);
function progress(params, seriesModel) {
var segCount = params.end - params.start;
var points = isLargeRender && new Float32Array(segCount * dimLen);
for (var i = params.start, offset = 0, tmpIn = [], tmpOut = []; i < params.end; i++) {
var point;
if (dimLen === 1) {
var x = data.get(dims[0], i);
point = isNaN(x) && coordSys.dataToPoint(x, null, tmpOut);
}
else {
var x = tmpIn[0] = data.get(dims[0], i);
var y = tmpIn[1] = data.get(dims[1], i);
// Also {Array.<number>}, not undefined to avoid if...else... statement
point = !isNaN(x) && !isNaN(y) && coordSys.dataToPoint(tmpIn, tmpOut);
}
if (isLargeRender) {
points[offset++] = point ? point[0] : NaN;
points[offset++] = point ? point[1] : NaN;
}
else {
data.setItemLayout(i, point || [NaN, NaN]);
}
}
: null;
return {dataEach: dataEach};
isLargeRender && data.setLayout('symbolPoints', points);
}
return dimLen && {progress: progress};
}
};
}
......@@ -371,8 +371,16 @@ var SeriesModel = ComponentModel.extend({
/**
* Convinient for override in extended class.
* @protected
* @type {Function}
*/
banIncremental: null,
/**
* @public
* @readOnly
* @type {Object}
*/
banIncremental: null
pipelineContext: null
});
......
......@@ -36,21 +36,41 @@ function Scheduler(ecInstance, api) {
var proto = Scheduler.prototype;
// If seriesModel provided, incremental threshold is check by series data.
proto.getPerformInfo = function (task, seriesModel) {
proto.getPerformArgs = function (task, isBlock) {
// For overall task
if (!task.__pipelineId) {
return;
}
var pipeline = this._pipelineMap.get(task.__pipelineId);
if (seriesModel) {
pipeline.thresholdFail = seriesModel.getData().count() < pipeline.threshold;
}
var incremental = pipeline.incremental
&& task.__idxInPipeline > pipeline.bockIndex
&& !pipeline.thresholdFail;
var pCtx = pipeline.context;
var incremental = !isBlock
&& pipeline.incrementalEnabled
&& (!pCtx || pCtx.incrementalRender)
&& task.__idxInPipeline > pipeline.bockIndex;
return {incremental: incremental, step: incremental ? pipeline.step : null};
return {step: incremental ? pipeline.step : null};
};
/**
* Current, progressive rendering starts from visual and layout.
* Always detect render mode in the same stage, avoiding that incorrect
* detection caused by data filtering.
*/
proto.updateModes = function (ecModel) {
var pipelineMap = this._pipelineMap;
ecModel.eachSeries(function (seriesModel) {
var pipeline = pipelineMap.get(seriesModel.uid);
var data = seriesModel.getData();
var dataLen = data.count();
var incrementalRender = pipeline.incrementalEnabled && dataLen >= pipeline.threshold;
var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold');
seriesModel.pipelineContext = pipeline.context = {
incrementalRender: incrementalRender,
large: large
};
});
};
proto.restorePipelines = function (ecModel) {
......@@ -65,7 +85,7 @@ proto.restorePipelines = function (ecModel) {
head: dataTask,
tail: dataTask,
threshold: seriesModel.get('progressiveThreshold'),
incremental: progressive
incrementalEnabled: progressive
&& !(seriesModel.banIncremental && seriesModel.banIncremental()),
bockIndex: -1,
step: progressive || 700, // ??? Temporarily number
......@@ -102,13 +122,21 @@ proto.prepareView = function (view, model, ecModel, api) {
pipe(this, model, renderTask);
};
proto.performDataProcessorTasks = function (stageHandlers, ecModel, payload) {
performStageTasks(this, stageHandlers, ecModel, payload);
};
// opt
// opt.visualType: 'visual' or 'layout'
// opt.setDirty
proto.performStageTasks = function (stageHandlers, ecModel, payload, opt) {
proto.performVisualTasks = function (stageHandlers, ecModel, payload, opt) {
performStageTasks(this, stageHandlers, ecModel, payload, {block: true});
};
function performStageTasks(scheduler, stageHandlers, ecModel, payload, opt) {
opt = opt || {};
var unfinished;
var scheduler = this;
each(stageHandlers, function (stageHandler, idx) {
if (opt.visualType && opt.visualType !== stageHandler.visualType) {
......@@ -124,7 +152,7 @@ proto.performStageTasks = function (stageHandlers, ecModel, payload, opt) {
overallTask.dirty();
}
overallTask.context.payload = payload;
unfinished |= overallTask.perform(scheduler.getPerformInfo(overallTask));
unfinished |= overallTask.perform(scheduler.getPerformArgs(overallTask, opt.block));
}
else if (seriesTaskMap) {
opt.seriesModels
......@@ -144,16 +172,17 @@ proto.performStageTasks = function (stageHandlers, ecModel, payload, opt) {
unfinished = true;
}
else {
var performInfo = scheduler.getPerformInfo(task, opt.dontCheckThreshold ? null : seriesModel);
performInfo.skip = !stageHandler.processRawSeries && ecModel.isSeriesFiltered(seriesModel);
var performArgs = scheduler.getPerformArgs(task, opt.block);
// ??? chck skip necessary.
performArgs.skip = !stageHandler.processRawSeries && ecModel.isSeriesFiltered(seriesModel);
task.context.payload = payload;
unfinished |= task.perform(performInfo);
unfinished |= task.perform(performArgs);
}
}
});
scheduler.unfinished |= unfinished;
};
}
proto.performSeriesTasks = function (ecModel) {
var unfinished;
......@@ -199,12 +228,14 @@ function createSeriesStageTask(scheduler, stageHandler, stageHandlerRecord, ecMo
if (!task) {
task = createTask({
reset: seriesTaskReset,
plan: seriesTaskPlan,
count: seriesTaskCount
}, {
model: seriesModel,
ecModel: ecModel,
api: api,
useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
plan: stageHandler.plan,
reset: stageHandler.reset
});
seriesTaskMap.set(pipelineId, task);
......@@ -250,7 +281,15 @@ function createOverallStageTask(scheduler, stageHandler, stageHandlerRecord, ecM
}
function overallTaskReset(context) {
context.overallReset(context.ecModel, context.api, context.payload);
context.overallReset(
context.ecModel, context.api, context.payload
);
}
function seriesTaskPlan(context) {
return context.plan && context.plan(
context.model, context.ecModel, context.api, context.payload
);
}
function seriesTaskReset(context) {
......
......@@ -13,6 +13,7 @@ export function createTask(define, context) {
* @constructor
* @param {Object} define
* @param {Function} define.reset Custom reset
* @param {Function} [define.plan] Returns 'reset' indicate reset immediately.
* @param {Function} [define.count] count is used to determin data task.
* @param {Object} [context]
*/
......@@ -20,6 +21,7 @@ function Task(define, context) {
define = define || {};
this._reset = define.reset;
this._plan = define.plan;
this._count = define.count;
this._dirty = true;
......@@ -35,7 +37,13 @@ var taskProto = Task.prototype;
* @param {number} [performArgs.skip] Skip customer perform call.
*/
taskProto.perform = function (performArgs) {
if (this._dirty) {
var planResult;
if (this._plan) {
planResult = this._plan(this.context);
}
if (this._dirty || planResult === 'reset') {
this._dirty = false;
reset(this);
}
......
......@@ -4,8 +4,10 @@ import * as componentUtil from '../util/component';
import * as clazzUtil from '../util/clazz';
import * as modelUtil from '../util/model';
import {createTask} from '../stream/task';
import createRenderPlanner from '../chart/helper/createRenderPlanner';
var inner = modelUtil.makeInner();
var renderPlanner = createRenderPlanner();
function Chart() {
......@@ -22,6 +24,7 @@ function Chart() {
this.uid = componentUtil.getUID('viewChart');
this.renderTask = createTask({
plan: renderTaskPlan,
reset: renderTaskReset
}, {view: this});
}
......@@ -149,7 +152,6 @@ function elSetState(el, state) {
* @param {module:echarts/data/List} data
* @param {Object} payload
* @param {string} state 'normal'|'emphasis'
* @inner
*/
function toggleHighlight(data, payload, state) {
var dataIndex = modelUtil.queryDataIndex(data, payload);
......@@ -176,20 +178,19 @@ Chart.markUpdateMethod = function (payload, methodName) {
inner(payload).updateMethod = methodName;
};
function renderTaskPlan(context) {
return renderPlanner(context.model);
}
function renderTaskReset(context) {
var seriesModel = context.model;
var ecModel = context.ecModel;
var api = context.api;
var payload = context.payload;
// ???! remove updateView updateVisual
var incremental = context.incremental;
var incremental = seriesModel.pipelineContext.incrementalRender;
var view = context.view;
// if (inner(view).incremental ^ incremental) {
// view.remove(ecModel, api);
// }
// inner(view).incremental = incremental;
var updateMethod = payload && inner(payload).updateMethod;
var methodName = incremental
? ((updateMethod && view.incrementalPrepareLayout)
......
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="lib/esl.js"></script>
<script src="lib/config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/facePrint.js"></script>
</head>
<body>
<style>
html, body, #main {
width: 100%;
height: 100%;
margin: 0;
}
</style>
<div id="main"></div>
<script>
var lngRange = [-10.781327, 131.48];
var latRange = [18.252847, 52.33];
var chunkMax = 5;
var chunkCount = 0;
function genData(count) {
lngRange[1] += 5;
lngRange[0] -= 10;
latRange[1] += 4;
var lngExtent = lngRange[1] - lngRange[0];
var latExtent = latRange[1] - latRange[0];
var data = [];
for (var i = 0; i < count; i++) {
data.push([
Math.random() * lngExtent + lngRange[0],
Math.random() * latExtent + latRange[0],
Math.random() * 1000
]);
}
return data;
}
var initData = genData(2001);
require([
'echarts'
// 'echarts/chart/map',
// 'echarts/chart/scatter',
// 'echarts/component/title',
// 'echarts/component/legend',
// 'echarts/component/geo',
// 'echarts/component/visualMap',
// 'echarts/component/markPoint',
// 'echarts/component/tooltip'
], function (echarts) {
require(['map/js/china'], function () {
var chart = echarts.init(document.getElementById('main'));
chart.setOption({
tooltip: {},
legend: {
orient: 'vertical',
left: 'left',
data:['categoryA','categoryB','categoryC']
},
// ???
// visualMap: {
// min: 0,
// max: 1500,
// left: 'left',
// top: 'bottom',
// text: ['High','Low'],
// seriesIndex: [1, 2, 3],
// inRange: {
// color: ['#006edd', '#e0ffff']
// },
// calculable : true
// },
xAxis: [{
}],
yAxis: [{
}],
series : [{
name: 'pm2.5',
type: 'scatter',
data: initData,
xAxisIndex: 0,
yAxisIndex: 0,
symbolSize: 2,
// symbol: 'rect',
itemStyle: {
normal: {
color: '#128de3'
}
},
progressive: 3000
}, {
name: 'pm2.5',
type: 'scatter',
data: initData,
xAxisIndex: 0,
yAxisIndex: 0,
symbolSize: 2,
// symbol: 'rect',
itemStyle: {
normal: {
borderWidth: 0.5,
borderColor: '#e01',
color: '#128de3'
}
},
progressive: 3000
}]
});
chart.on('click', function (param) {
alert('asdf');
});
next();
function next() {
if (chunkCount++ < chunkMax) {
var newData = genData(20000);
chart.addData({seriesIndex: 0, data: newData});
setTimeout(next, 3000);
}
}
});
});
</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.
先完成此消息的编辑!
想要评论请 注册