提交 424ad22d 编写于 作者: S sushuang

add lins stream examples

上级 279b90ef
......@@ -4,20 +4,20 @@
import * as graphic from '../../util/graphic';
import LineGroup from './Line';
import Polyline from './Polyline';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
function isPointNaN(pt) {
return isNaN(pt[0]) || isNaN(pt[1]);
}
function lineNeedsDraw(pts) {
return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
}
/**
* @alias module:echarts/component/marker/LineDraw
* @constructor
*/
function LineDraw(ctor) {
this._ctor = ctor || LineGroup;
// ??? The third mode: largeLineDraw?
this._incremental;
this.group = new graphic.Group();
}
......@@ -27,66 +27,143 @@ var lineDrawProto = LineDraw.prototype;
* @param {module:echarts/data/List} lineData
*/
lineDrawProto.updateData = function (lineData) {
var lineDraw = this;
var group = lineDraw.group;
var oldLineData = lineDraw._lineData;
lineDraw._lineData = lineData;
var seriesScope = makeSeriesScope(lineData);
// Check and change mode.
var streamRendering = seriesScope.streamRendering;
if (this._incremental ^ streamRendering) {
this.remove();
streamRendering && group.add(lineDraw._incremental = new IncrementalDisplayable());
}
// ??? Process that switch from stream to non-stream.
if (streamRendering) {
this._incremental.clearDisplaybles();
}
else {
lineData.diff(oldLineData)
.add(function (idx) {
doAdd(lineDraw, lineData, idx, seriesScope);
})
.update(function (newIdx, oldIdx) {
doUpdate(lineDraw, oldLineData, lineData, oldIdx, newIdx, seriesScope);
})
.remove(function (idx) {
group.remove(oldLineData.getItemGraphicEl(idx));
})
.execute();
}
// ??? set task start index.
createRenderTask(lineDraw, lineData, seriesScope);
};
// ??? remove?
// lineDrawProto.updateLayout = function () {
// var lineData = this._lineData;
// lineData.eachItemGraphicEl(function (el, idx) {
// el.updateLayout(lineData, idx);
// }, this);
// };
var oldLineData = this._lineData;
var group = this.group;
var LineCtor = this._ctor;
lineDrawProto.updateView = function () {
var lineData = this._lineData;
var lineDraw = this;
var seriesScope = makeSeriesScope(lineData);
if (seriesScope.streamRendering) {
this._incremental.clearDisplaybles();
}
else {
lineData.each(function (item, idx) {
doUpdate(lineDraw, lineData, lineData, idx, idx, seriesScope);
});
}
// ??? set task start index.
createRenderTask(lineDraw, lineData, seriesScope);
};
function doAdd(lineDraw, lineData, idx, seriesScope) {
if (!lineNeedsDraw(lineData.getItemLayout(idx))) {
return;
}
var itemEl = createItemEl(lineDraw, lineData, idx, seriesScope);
lineData.setItemGraphicEl(idx, itemEl);
seriesScope.streamRendering
? lineDraw._incremental.addDisplayable(itemEl, true)
: lineDraw.group.add(itemEl);
}
function doUpdate(lineDraw, oldLineData, newLineData, oldIdx, newIdx, seriesScope) {
var itemEl = oldLineData.getItemGraphicEl(oldIdx);
if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) {
lineDraw.group.remove(itemEl);
return;
}
if (!itemEl) {
itemEl = createItemEl(lineDraw, newLineData, newIdx, seriesScope);
}
else {
itemEl.updateData(newLineData, newIdx, seriesScope);
}
newLineData.setItemGraphicEl(newIdx, itemEl);
lineDraw.group.add(itemEl);
}
function createRenderTask(lineDraw, lineData, seriesScope) {
var hostModel = lineData.hostModel;
hostModel.pipeTask && hostModel.pipeTask(lineData.createEachTask(function (idx) {
doAdd(lineDraw, lineData, idx, seriesScope);
}), 'render');
}
var seriesScope = {
// ??? Modify Polyline, Line.js to support IncrementalDisplable?
function createItemEl(lineDraw, newLineData, newIdx, seriesScope) {
if (seriesScope.streamRendering) {
var el = new Polyline(newLineData, newIdx, seriesScope);
return el.childAt(0);
}
else {
return new lineDraw._ctor(newLineData, newIdx, seriesScope);
}
}
function makeSeriesScope(lineData) {
var hostModel = lineData.hostModel;
var streamSetting = hostModel.getStreamSetting();
return {
lineStyle: hostModel.getModel('lineStyle.normal').getLineStyle(),
hoverLineStyle: hostModel.getModel('lineStyle.emphasis').getLineStyle(),
labelModel: hostModel.getModel('label.normal'),
hoverLabelModel: hostModel.getModel('label.emphasis')
hoverLabelModel: hostModel.getModel('label.emphasis'),
streamRendering: streamSetting && streamSetting.threshold < lineData.count()
};
lineData.diff(oldLineData)
.add(function (idx) {
if (!lineNeedsDraw(lineData.getItemLayout(idx))) {
return;
}
var lineGroup = new LineCtor(lineData, idx, seriesScope);
lineData.setItemGraphicEl(idx, lineGroup);
group.add(lineGroup);
})
.update(function (newIdx, oldIdx) {
var lineGroup = oldLineData.getItemGraphicEl(oldIdx);
if (!lineNeedsDraw(lineData.getItemLayout(newIdx))) {
group.remove(lineGroup);
return;
}
if (!lineGroup) {
lineGroup = new LineCtor(lineData, newIdx, seriesScope);
}
else {
lineGroup.updateData(lineData, newIdx, seriesScope);
}
lineData.setItemGraphicEl(newIdx, lineGroup);
group.add(lineGroup);
})
.remove(function (idx) {
group.remove(oldLineData.getItemGraphicEl(idx));
})
.execute();
this._lineData = lineData;
};
lineDrawProto.updateLayout = function () {
var lineData = this._lineData;
lineData.eachItemGraphicEl(function (el, idx) {
el.updateLayout(lineData, idx);
}, this);
};
}
lineDrawProto.remove = function () {
this._incremental && this._incremental.clearDisplaybles();
this._incremental = null;
this.group.removeAll();
};
export default LineDraw;
\ No newline at end of file
function isPointNaN(pt) {
return isNaN(pt[0]) || isNaN(pt[1]);
}
function lineNeedsDraw(pts) {
return !isPointNaN(pts[0]) && !isPointNaN(pts[1]);
}
export default LineDraw;
......@@ -8,7 +8,9 @@ import * as graphic from '../../util/graphic';
* @constructor
*/
function SymbolDraw(symbolCtor) {
this.root = new IncrementalDisplayble();
var group = this.group = new graphic.Group();
group.add(this._root = new IncrementalDisplayble());
this._symbolCtor = symbolCtor || SymbolClz;
}
......@@ -33,7 +35,7 @@ symbolDrawProto.updateData = function (data, isIgnore) {
};
function doRender(self, seriesModel, isIgnore) {
var root = self.root;
var root = self._root;
var data = seriesModel.getData();
var seriesModel = data.hostModel;
var SymbolCtor = self._symbolCtor;
......@@ -78,34 +80,21 @@ function doRender(self, seriesModel, isIgnore) {
}
});
seriesModel.pipeTask(dataEachTask, 'render', ['updateViewBase']);
// ??? updateViewBase should not be here?
seriesModel.pipeTask(dataEachTask, 'render');
}
// ???
symbolDrawProto.updateView = function () {
var seriesModel = this._seriesModel;
if (!seriesModel) {
return;
if (this._seriesModel) {
doRender(this, this._seriesModel, this._isIgnore);
}
doRender(this, this._seriesModel, this._isIgnore);
};
symbolDrawProto.remove = function (enableAnimation) {
var root = this.root;
var data = this._data;
if (data) {
if (enableAnimation) {
data.eachItemGraphicEl(function (el) {
el.fadeOut(function () {
root.remove(el);
});
});
}
else {
root.clearDisplaybles();
}
}
var root = this._root;
root && root.clearDisplaybles();
this.group.removeAll();
};
export default SymbolDraw;
\ No newline at end of file
......@@ -40,6 +40,8 @@ var LinesSeries = SeriesModel.extend({
visualColorAccessPath: 'lineStyle.normal.color',
streamEnabled: true,
init: function (option) {
// Not using preprocessor because mergeOption may not have series.type
preprocessOption(option);
......
......@@ -86,7 +86,17 @@ export default echarts.extendChartView({
},
updateLayout: function (seriesModel, ecModel, api) {
// ??? do not support updateLayout in stream
this._lineDraw.updateLayout(seriesModel);
this._clearLayer(api);
},
updateView: function (seriesModel, ecModel, api) {
this._lineDraw.updateView(seriesModel);
this._clearLayer(api);
},
_clearLayer: function (api) {
// Not use motion when dragging or zooming
var zr = api.getZr();
var isSvg = zr.painter.getType() === 'svg';
......@@ -106,4 +116,5 @@ export default echarts.extendChartView({
},
dispose: function () {}
});
\ No newline at end of file
});
......@@ -6,7 +6,7 @@ export default function (ecModel) {
var lineData = seriesModel.getData();
// FIXME Use data dimensions ?
lineData.each(function (idx) {
var task = lineData.createEachTask(function (idx) {
var itemModel = lineData.getItemModel(idx);
var coords = (itemModel.option instanceof Array) ?
......@@ -38,5 +38,7 @@ export default function (ecModel) {
}
lineData.setItemLayout(idx, pts);
});
seriesModel.pipeTask(task, 'visual');
});
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ export default function (ecModel) {
data.setVisual('toSymbolSize', symbolSize && symbolSize[1]);
data.setVisual('opacity', seriesModel.get(opacityQuery));
data.each(function (idx) {
var task = data.createEachTask(function (idx) {
var itemModel = data.getItemModel(idx);
var symbolType = normalize(itemModel.getShallow('symbol', true));
var symbolSize = normalize(itemModel.getShallow('symbolSize', true));
......@@ -33,5 +33,7 @@ export default function (ecModel) {
data.setItemVisual(idx, 'opacity', opacity);
});
seriesModel.pipeTask(task, 'visual');
});
}
\ No newline at end of file
......@@ -17,7 +17,7 @@ echarts.extendChartView({
var data = seriesModel.getData();
var group = this.group;
var symbolDraw = seriesModel.useStream()
var symbolDraw = seriesModel.getStreamSetting()
? this._streamSymbolDraw
: seriesModel.get('large') && data.count() > seriesModel.get('largeThreshold')
? this._largeSymbolDraw
......@@ -25,7 +25,7 @@ echarts.extendChartView({
this._symbolDraw = symbolDraw;
symbolDraw.updateData(data);
group.add(symbolDraw.group || symbolDraw.root);
group.add(symbolDraw.group);
this._lasySymbolDrawGroup && group.remove(this._lasySymbolDrawGroup);
......@@ -33,6 +33,7 @@ echarts.extendChartView({
},
updateLayout: function (seriesModel) {
// ??? do not support updateLayout in stream
this._symbolDraw.updateLayout(seriesModel);
},
......
......@@ -1190,7 +1190,7 @@ echartsProto.addData = function (params) {
this._scheduler.unfinished = true;
// ??? Should handle this.
// if (!seriesModel.useStream()) {
// if (!seriesModel.getStreamSetting()) {
// refresh('prepareAndUpdate');
// }
};
......@@ -1225,7 +1225,7 @@ function invokeUpdateMethod(methodName, ecModel, payload) {
var chart = this._chartsMap[seriesModel.__viewId];
chart[methodName](seriesModel, ecModel, api, payload);
// ??? updateZ(seriesModel, chart);
updateZ(seriesModel, chart);
// ??? updateProgressiveAndBlend(seriesModel, chart);
}, this);
......@@ -1392,9 +1392,9 @@ function startRender(ecIns, ecModel, api, payload) {
chartView.render(seriesModel, ecModel, api, payload);
// ??? chartView.group.silent = !!seriesModel.get('silent');
chartView.group.silent = !!seriesModel.get('silent');
// ??? updateZ(seriesModel, chartView);
updateZ(seriesModel, chartView);
// ??? updateProgressiveAndBlend(seriesModel, chartView);
......@@ -1416,15 +1416,15 @@ function progressRender(ecIns, ecModel) {
ecIns._scheduler.progressStage(STAGE_RENDER);
// ???
// ecModel.eachSeries(function (seriesModel, idx) {
// ??? var chartView = ecIns._chartsMap[seriesModel.__viewId];
ecModel.eachSeries(function (seriesModel, idx) {
var chartView = ecIns._chartsMap[seriesModel.__viewId];
// ??? chartView.group.silent = !!seriesModel.get('silent');
chartView.group.silent = !!seriesModel.get('silent');
// ??? updateZ(seriesModel, chartView);
updateZ(seriesModel, chartView);
// ??? updateProgressiveAndBlend(seriesModel, chartView);
// });
});
}
var MOUSE_EVENT_NAMES = [
......@@ -1497,6 +1497,8 @@ echartsProto.dispose = function () {
}
this._disposed = true;
modelUtil.setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, '');
var api = this._api;
var ecModel = this._model;
......@@ -1760,12 +1762,7 @@ export function init(dom, theme, opts) {
chart.id = 'ec_' + idBase++;
instances[chart.id] = chart;
if (dom.setAttribute) {
dom.setAttribute(DOM_ATTRIBUTE_KEY, chart.id);
}
else {
dom[DOM_ATTRIBUTE_KEY] = chart.id;
}
modelUtil.setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id);
enableConnect(chart);
......@@ -1830,14 +1827,7 @@ export function dispose(chart) {
* @return {echarts~ECharts}
*/
export function getInstanceByDom(dom) {
var key;
if (dom.getAttribute) {
key = dom.getAttribute(DOM_ATTRIBUTE_KEY);
}
else {
key = dom[DOM_ATTRIBUTE_KEY];
}
return instances[key];
return instances[modelUtil.getAttribute(dom, DOM_ATTRIBUTE_KEY)];
}
/**
......
......@@ -21,6 +21,7 @@ function createTask(seriesType, seriesModel) {
}
var task;
// ??? no task support ?
if (dims.length === 1) {
task = data.createEachTask(dims[0], function (x, idx) {
// Also {Array.<number>}, not undefined to avoid if...else... statement
......
......@@ -10,6 +10,7 @@ import {
import {set, get} from '../util/clazz';
import * as modelUtil from '../util/model';
import ComponentModel from './Component';
import {isNumeric} from '../util/number';
import colorPaletteMixin from './mixin/colorPalette';
import {
getLayoutParams,
......@@ -369,9 +370,11 @@ var SeriesModel = ComponentModel.extend({
/**
* @public
*/
useStream: function () {
// ???
return this.streamEnabled && this.get('stream');
getStreamSetting: function () {
var stream = this.get('stream');
return this.streamEnabled && (stream != null || stream !== false) && {
threshold: isNumeric(stream) ? +stream : 0
};
}
});
......
......@@ -18,12 +18,6 @@ var STAGE = {
visual: 4,
render: 5
};
var TAG = {
updateBase: 1,
updateLayoutBase: 1,
updateVisualBase: 1,
updateViewBase: 1
};
var TEST_PROGRESS_STEP = 700;
......@@ -126,7 +120,9 @@ proto.flushTemps = function (tag, hosts) {
function flushPipelineTemps(pipeline) {
clearPipelineDownstreams(stageMap, pipeline, tag);
each(pipeline.temps, function (tmp) {
var temps = pipeline.temps;
setTags(temps);
each(temps, function (tmp) {
self.unfinished = true;
pipeTask(stageMap, pipeline.tasks, tmp.task, tmp.stage, tmp.tags);
}, this);
......@@ -134,6 +130,28 @@ proto.flushTemps = function (tag, hosts) {
}
};
// TODO when needed: customize tag
function setTags(temps) {
var hasUpdateViewBase;
for (var i = temps.length - 1; i >= 0; i--) {
var item = temps[i];
var stage = item.stage;
var innerTask = inner(item.task);
if (stage === 'render') {
innerTask.updateLayoutBase = innerTask.updateVisualBase = true;
}
else if (stage === 'dataClone') {
innerTask.updateBase = true;
}
// Find the last dataClone or processor task.
if (!hasUpdateViewBase && (stage === 'dataClone' || stage === 'processor')) {
innerTask.updateViewBase = true;
hasUpdateViewBase = true;
}
}
}
/**
* Only clear streams start from the tagged tasks.
* This is for cases like `updateView`, `updateVisual` and `updateLayout`,
......@@ -159,7 +177,7 @@ function clearPipelineDownstreams(stageMap, pipeline, tag) {
clearPipeline(stageMap, pipeline, baseIndex);
}
function pipeTask(stageMap, pipelineTasks, task, stage, tags) {
function pipeTask(stageMap, pipelineTasks, task, stage) {
if (__DEV__) {
// In case typo.
stage && assert(STAGE[stage] != null);
......@@ -168,13 +186,6 @@ function pipeTask(stageMap, pipelineTasks, task, stage, tags) {
});
}
each(normalizeToArray(tags), function (tag) {
if (__DEV__) {
assert(TAG[tag]);
}
inner(task)[tag] = true;
});
pipelineTasks.length && pipelineTasks[pipelineTasks.length - 1].pipe(task);
pipelineTasks.push(task);
......
......@@ -677,3 +677,16 @@ export function otherDimToDataDim(data, otherDim) {
function has(obj, prop) {
return obj && obj.hasOwnProperty(prop);
}
export function setAttribute(dom, key, value) {
dom.setAttribute
? dom.setAttribute(key, value)
: (dom[key] = value);
}
export function getAttribute(dom, key) {
return dom.getAttribute
? dom.getAttribute(key)
: dom[key];
}
......@@ -95,8 +95,7 @@
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
z: 0
}
},
series : [{
name: 'pm2.5',
......
<html>
<head>
<meta charset='utf-8'>
<script src='lib/esl.js'></script>
<script src='lib/config.js'></script>
<script src='lib/jquery.min.js'></script>
<script src="lib/dat.gui.min.js"></script>
<script src='http://api.map.baidu.com/api?v=2.0&ak=ZUONbpqGBsYGXNIYHicvbAbM'></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>
var xs = [440000, 450000];
var ys = [4368000, 4537000];
// var testGeoJson1 = {
// 'type': 'FeatureCollection',
// 'features': [
// {
// 'geometry': {
// 'type': 'Polygon',
// 'coordinates': [
// [
// [
// xs[0],
// ys[0]
// ],
// [
// xs[1],
// ys[0]
// ],
// [
// xs[1],
// ys[1]
// ],
// [
// xs[0],
// ys[1]
// ]
// ]
// ]
// },
// 'properties': {
// 'name': 'Bejing?',
// 'childNum': 1
// }
// }
// ]
// };
require([
'echarts',
// 'echarts/chart/lines',
// 'echarts/component/legend',
// 'extension/bmap'
], function (echarts) {
$.get('../map/json/world.json', function (worldJson) {
echarts.registerMap('world', worldJson);
// echarts.registerMap('test', testGeoJson1);
// $.get('data/Links_Beijing_0.json', function (data) {
$.get('data/Links_NewYork_1.json', function (data) {
var config = {
dataLoading: 'whole',
streamThreshold: 0,
streamRender: true
};
var chart;
var gui = new dat.GUI();
gui.add(config, 'dataLoading', ['whole', 'chunked'])
.onChange(init);
gui.add(config, 'streamRender')
.onChange(init);
gui.add(config, 'streamThreshold', 0, 200000)
.onChange(init);
init();
function init() {
if (chart) {
chart.dispose();
}
chart = echarts.init(document.getElementById('main'));
var lines = data.geometries.map(function (entry) {
return {
coords: entry.coordinates
};
});
chart.setOption({
animation: false,
geo: {
center: [-74.04327099998152, 40.86737600240287],
zoom: 360,
map: 'world',
roam: true,
label: {
normal: {
show: true,
textStyle: {
color: 'rgba(0,0,0,0.4)'
}
}
},
itemStyle: {
normal:{
borderColor: 'rgba(0, 0, 0, 0.2)'
},
emphasis:{
color: null,
areaColor: null,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
},
series: [{
type: 'lines',
coordinateSystem: 'geo',
data: lines,
polyline: true,
lineStyle: {
normal: {
color: 'purple',
opacity: 0.4,
width: 1
}
},
stream: config.streamRender ? config.streamThreshold : false
}]
});
}
});
});
});
</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.
先完成此消息的编辑!
想要评论请 注册