You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2018/04/17 20:04:37 UTC
[incubator-echarts] 03/03: Support large bar for some cases (to the
data amount of 2e5).
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit 364720ba254540679f15d4b16d3f92bb03507579
Author: sushuang <su...@gmail.com>
AuthorDate: Wed Apr 18 04:03:48 2018 +0800
Support large bar for some cases (to the data amount of 2e5).
---
src/chart/bar.js | 16 ++--
src/chart/bar/BarSeries.js | 26 +++++-
src/chart/bar/BarView.js | 99 ++++++++++++++++++++--
src/chart/bar/BaseBarSeries.js | 5 ++
src/chart/bar/helper.js | 2 +-
src/chart/candlestick/CandlestickView.js | 15 ++--
src/coord/axisHelper.js | 30 +++----
src/echarts.js | 11 ++-
src/layout/barGrid.js | 140 +++++++++++++++++++++++++------
test/bar-large1.html | 132 +++++++++++++++++++++++++++++
test/candlestick-large2.html | 123 ++++++++++++++-------------
11 files changed, 471 insertions(+), 128 deletions(-)
diff --git a/src/chart/bar.js b/src/chart/bar.js
index 7879572..21e7eee 100644
--- a/src/chart/bar.js
+++ b/src/chart/bar.js
@@ -1,6 +1,6 @@
import * as echarts from '../echarts';
import * as zrUtil from 'zrender/src/core/util';
-import { layout } from '../layout/barGrid';
+import {layout, largeLayout} from '../layout/barGrid';
import '../coord/cartesian/Grid';
import './bar/BarSeries';
@@ -10,11 +10,13 @@ import '../component/gridSimple';
echarts.registerLayout(zrUtil.curry(layout, 'bar'));
+// Should after normal bar layout, otherwise it is blocked by normal bar layout.
+echarts.registerLayout(largeLayout);
-// Visual coding for legend
-echarts.registerVisual(function (ecModel) {
- ecModel.eachSeriesByType('bar', function (seriesModel) {
- var data = seriesModel.getData();
- data.setVisual('legendSymbol', 'roundRect');
- });
+echarts.registerVisual({
+ seriesType: 'bar',
+ reset: function (seriesModel) {
+ // Visual coding for legend
+ seriesModel.getData().setVisual('legendSymbol', 'roundRect');
+ }
});
diff --git a/src/chart/bar/BarSeries.js b/src/chart/bar/BarSeries.js
index 6f5d2f8..2c46956 100644
--- a/src/chart/bar/BarSeries.js
+++ b/src/chart/bar/BarSeries.js
@@ -6,5 +6,29 @@ export default BaseBarSeries.extend({
dependencies: ['grid', 'polar'],
- brushSelector: 'rect'
+ brushSelector: 'rect',
+
+ /**
+ * @override
+ */
+ getProgressive: function () {
+ // Do not support progressive in normal mode.
+ return this.get('large')
+ ? this.get('progressive')
+ : false;
+ },
+
+ /**
+ * @override
+ */
+ getProgressiveThreshold: function () {
+ // Do not support progressive in normal mode.
+ var progressiveThreshold = this.get('progressiveThreshold');
+ var largeThreshold = this.get('largeThreshold');
+ if (largeThreshold > progressiveThreshold) {
+ progressiveThreshold = largeThreshold;
+ }
+ return progressiveThreshold;
+ }
+
});
diff --git a/src/chart/bar/BarView.js b/src/chart/bar/BarView.js
index 7fd05b8..01ad899 100644
--- a/src/chart/bar/BarView.js
+++ b/src/chart/bar/BarView.js
@@ -5,7 +5,7 @@ import * as graphic from '../../util/graphic';
import {setLabel} from './helper';
import Model from '../../model/Model';
import barItemStyle from './barItemStyle';
-
+import Path from 'zrender/src/graphic/Path';
var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];
@@ -18,12 +18,16 @@ export default echarts.extendChartView({
type: 'bar',
render: function (seriesModel, ecModel, api) {
+ this._updateDrawMode(seriesModel);
+
var coordinateSystemType = seriesModel.get('coordinateSystem');
if (coordinateSystemType === 'cartesian2d'
|| coordinateSystemType === 'polar'
) {
- this._render(seriesModel, ecModel, api);
+ this._isLargeDraw
+ ? this._renderLarge(seriesModel, ecModel, api)
+ : this._renderNormal(seriesModel, ecModel, api);
}
else if (__DEV__) {
console.warn('Only cartesian2d and polar supported for bar.');
@@ -32,9 +36,25 @@ export default echarts.extendChartView({
return this.group;
},
- dispose: zrUtil.noop,
+ incrementalPrepareRender: function (seriesModel, ecModel, api) {
+ this._clear();
+ this._updateDrawMode(seriesModel);
+ },
+
+ incrementalRender: function (params, seriesModel, ecModel, api) {
+ // Do not support progressive in normal mode.
+ this._incrementalRenderLarge(params, seriesModel);
+ },
+
+ _updateDrawMode: function (seriesModel) {
+ var isLargeDraw = seriesModel.pipelineContext.large;
+ if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) {
+ this._isLargeDraw = isLargeDraw;
+ this._clear();
+ }
+ },
- _render: function (seriesModel, ecModel, api) {
+ _renderNormal: function (seriesModel, ecModel, api) {
var group = this.group;
var data = seriesModel.getData();
var oldData = this._data;
@@ -114,10 +134,25 @@ export default echarts.extendChartView({
this._data = data;
},
- remove: function (ecModel, api) {
+ _renderLarge: function (seriesModel, ecModel, api) {
+ this._clear();
+ createLarge(seriesModel, this.group);
+ },
+
+ _incrementalRenderLarge: function (params, seriesModel) {
+ createLarge(seriesModel, this.group, true);
+ },
+
+ dispose: zrUtil.noop,
+
+ remove: function (ecModel) {
+ this._clear(ecModel);
+ },
+
+ _clear: function (ecModel) {
var group = this.group;
var data = this._data;
- if (ecModel.get('animation')) {
+ if (ecModel && ecModel.get('animation')) {
if (data) {
data.eachItemGraphicEl(function (el) {
if (el.type === 'sector') {
@@ -132,7 +167,9 @@ export default echarts.extendChartView({
else {
group.removeAll();
}
+ this._data = null;
}
+
});
var elementCreator = {
@@ -282,3 +319,53 @@ function getLineWidth(itemModel, rawLayout) {
var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
}
+
+
+var LargePath = Path.extend({
+
+ type: 'largeBar',
+
+ shape: {points: []},
+
+ buildPath: function (ctx, shape) {
+ // Drawing lines is more efficient than drawing
+ // a whole line or drawing rects.
+ var points = shape.points;
+ var startPoint = this.__startPoint;
+ var valueIdx = this.__valueIdx;
+
+ for (var i = 0; i < points.length; i += 2) {
+ startPoint[this.__valueIdx] = points[i + valueIdx];
+ ctx.moveTo(startPoint[0], startPoint[1]);
+ ctx.lineTo(points[i], points[i + 1]);
+ }
+ }
+});
+
+function createLarge(seriesModel, group, incremental) {
+ // TODO support polar
+ var data = seriesModel.getData();
+ var startPoint = [];
+ var valueIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
+ startPoint[1 - valueIdx] = data.getLayout('valueAxisStart');
+
+ var el = new LargePath({
+ shape: {points: data.getLayout('largePoints')},
+ incremental: !!incremental,
+ __startPoint: startPoint,
+ __valueIdx: valueIdx
+ });
+ group.add(el);
+ setLargeStyle(el, seriesModel, data);
+}
+
+function setLargeStyle(el, seriesModel, data) {
+ var borderColor = data.getVisual('borderColor') || data.getVisual('color');
+ var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(['color', 'borderColor']);
+
+ el.useStyle(itemStyle);
+ el.style.fill = null;
+ el.style.stroke = borderColor;
+ el.style.lineWidth = data.getLayout('barWidth');
+}
+
diff --git a/src/chart/bar/BaseBarSeries.js b/src/chart/bar/BaseBarSeries.js
index 269deeb..46d18f5 100644
--- a/src/chart/bar/BaseBarSeries.js
+++ b/src/chart/bar/BaseBarSeries.js
@@ -41,6 +41,11 @@ export default SeriesModel.extend({
barMinAngle: 0,
// cursor: null,
+ large: false,
+ largeThreshold: 400,
+ progressive: 5e3,
+ progressiveChunkMode: 'mod',
+
// barMaxWidth: null,
// 默认自适应
// barWidth: null,
diff --git a/src/chart/bar/helper.js b/src/chart/bar/helper.js
index e4ebed5..60530ac 100644
--- a/src/chart/bar/helper.js
+++ b/src/chart/bar/helper.js
@@ -26,4 +26,4 @@ function fixPosition(style, labelPositionOutside) {
if (style.textPosition === 'outside') {
style.textPosition = labelPositionOutside;
}
-}
\ No newline at end of file
+}
diff --git a/src/chart/candlestick/CandlestickView.js b/src/chart/candlestick/CandlestickView.js
index 4200c1c..511dcca 100644
--- a/src/chart/candlestick/CandlestickView.js
+++ b/src/chart/candlestick/CandlestickView.js
@@ -103,11 +103,8 @@ var CandlestickView = ChartView.extend({
},
_renderLarge: function (seriesModel) {
- var group = this.group;
-
- group.removeAll();
-
- createLarge(seriesModel, group);
+ this._clear();
+ createLarge(seriesModel, this.group);
},
_incrementalRenderNormal: function (params, seriesModel) {
@@ -264,15 +261,13 @@ function createLarge(seriesModel, group, incremental) {
}
function setLargeStyle(sign, el, seriesModel, data) {
- var normalItemStyleModel = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH);
var suffix = sign > 0 ? 'P' : 'N';
-
- var color = data.getVisual('color' + suffix);
- var borderColor = data.getVisual('borderColor' + suffix) || color;
+ var borderColor = data.getVisual('borderColor' + suffix)
+ || data.getVisual('color' + suffix);
// Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke
- var itemStyle = normalItemStyleModel.getItemStyle(SKIP_PROPS);
+ var itemStyle = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH).getItemStyle(SKIP_PROPS);
el.useStyle(itemStyle);
el.style.fill = null;
diff --git a/src/coord/axisHelper.js b/src/coord/axisHelper.js
index d7c14e0..a424ca6 100644
--- a/src/coord/axisHelper.js
+++ b/src/coord/axisHelper.js
@@ -4,7 +4,11 @@ import OrdinalScale from '../scale/Ordinal';
import IntervalScale from '../scale/Interval';
import Scale from '../scale/Scale';
import * as numberUtil from '../util/number';
-import {calBarWidthAndOffset} from '../layout/barGrid';
+import {
+ prepareLayoutBarSeries,
+ makeColumnLayout,
+ retrieveColumnLayout
+} from '../layout/barGrid';
import BoundingRect from 'zrender/src/core/BoundingRect';
import '../scale/Time';
@@ -120,26 +124,26 @@ export function getScaleExtent(scale, model) {
// is base axis
// FIXME
// (1) Consider support value axis, where below zero and axis `onZero` should be handled properly.
- // (2) Refactor the logic with `barGrid`. Is it not need to `calBarWidthAndOffset` twice with different extent?
+ // (2) Refactor the logic with `barGrid`. Is it not need to `makeBarWidthAndOffsetInfo` twice with different extent?
// Should not depend on series type `bar`?
// (3) Fix that might overlap when using dataZoom.
// (4) Consider other chart types using `barGrid`?
// See #6728, #4862, `test/bar-overflow-time-plot.html`
var ecModel = model.ecModel;
if (ecModel && (scaleType === 'time' /*|| scaleType === 'interval' */)) {
- var barSeriesModels = [];
+ var barSeriesModels = prepareLayoutBarSeries('bar', ecModel);
var isBaseAxisAndHasBarSeries;
- ecModel.eachSeriesByType('bar', function (seriesModel) {
- if (seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d') {
- barSeriesModels.push(seriesModel);
- isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis;
- }
+ zrUtil.each(barSeriesModels, function (seriesModel) {
+ isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis;
});
if (isBaseAxisAndHasBarSeries) {
+ // Calculate placement of bars on axis
+ var barWidthAndOffset = makeColumnLayout(barSeriesModels);
+
// Adjust axis min and max to account for overflow
- var adjustedScale = adjustScaleForOverflow(min, max, model, barSeriesModels);
+ var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset);
min = adjustedScale.min;
max = adjustedScale.max;
}
@@ -148,18 +152,14 @@ export function getScaleExtent(scale, model) {
return [min, max];
}
-function adjustScaleForOverflow(min, max, model, barSeriesModels) {
+function adjustScaleForOverflow(min, max, model, barWidthAndOffset) {
// Get Axis Length
var axisExtent = model.axis.getExtent();
var axisLength = axisExtent[1] - axisExtent[0];
- // Calculate placement of bars on axis
- var barWidthAndOffset = calBarWidthAndOffset(barSeriesModels);
-
// Get bars on current base axis and calculate min and max overflow
- var baseAxisKey = model.axis.dim + model.axis.index;
- var barsOnCurrentAxis = barWidthAndOffset[baseAxisKey];
+ var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis);
if (barsOnCurrentAxis === undefined) {
return {min: min, max: max};
}
diff --git a/src/echarts.js b/src/echarts.js
index eec6060..784216d 100644
--- a/src/echarts.js
+++ b/src/echarts.js
@@ -791,14 +791,17 @@ var updateMethods = {
scheduler.performDataProcessorTasks(ecModel, payload);
- coordSysMgr.update(ecModel, api);
-
// Current stream render is not supported in data process. So we can update
// stream modes after data processing, where the filtered data is used to
- // deteming whether use progressive rendering. And we update stream modes
- // after coordinate system updated, then full coord info can be fetched.
+ // deteming whether use progressive rendering.
updateStreamModes(this, ecModel);
+ // We update stream modes before coordinate system updated, then the modes info
+ // can be fetched when coord sys updating (consider the barGrid extent fix). But
+ // the drawback is the full coord info can not be fetched. Fortunately this full
+ // coord is not requied in stream mode updater currently.
+ coordSysMgr.update(ecModel, api);
+
clearColorPalette(ecModel);
scheduler.performVisualTasks(ecModel, payload);
diff --git a/src/layout/barGrid.js b/src/layout/barGrid.js
index ba07b6d..f23c3fb 100644
--- a/src/layout/barGrid.js
+++ b/src/layout/barGrid.js
@@ -1,8 +1,12 @@
import * as zrUtil from 'zrender/src/core/util';
import {parsePercent} from '../util/number';
import {isDimensionStacked} from '../data/helper/dataStackHelper';
+import createRenderPlanner from '../chart/helper/createRenderPlanner';
var STACK_PREFIX = '__ec_stack_';
+var LARGE_BAR_MIN_WIDTH = 0.5;
+
+var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array;
function getSeriesStackId(seriesModel) {
return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
@@ -22,7 +26,7 @@ function getAxisKey(axis) {
* @param {number} [opt.barCategoryGap]
* @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined.
*/
-export function getLayoutOnAxis(opt, api) {
+export function getLayoutOnAxis(opt) {
var params = [];
var baseAxis = opt.axis;
var axisKey = 'axis0';
@@ -39,7 +43,7 @@ export function getLayoutOnAxis(opt, api) {
stackId: STACK_PREFIX + i
}, opt));
}
- var widthAndOffsets = doCalBarWidthAndOffset(params, api);
+ var widthAndOffsets = doCalBarWidthAndOffset(params);
var result = [];
for (var i = 0; i < opt.count; i++) {
@@ -51,8 +55,20 @@ export function getLayoutOnAxis(opt, api) {
return result;
}
-export function calBarWidthAndOffset(barSeries, api) {
- var seriesInfoList = zrUtil.map(barSeries, function (seriesModel) {
+export function prepareLayoutBarSeries(seriesType, ecModel) {
+ var seriesModels = [];
+ ecModel.eachSeriesByType(seriesType, function (seriesModel) {
+ // Check series coordinate, do layout for cartesian2d only
+ if (isOnCartesian(seriesModel) && !isInLargeMode(seriesModel)) {
+ seriesModels.push(seriesModel);
+ }
+ });
+ return seriesModels;
+}
+
+export function makeColumnLayout(barSeries) {
+ var seriesInfoList = [];
+ zrUtil.each(barSeries, function (seriesModel) {
var data = seriesModel.getData();
var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis();
@@ -70,7 +86,7 @@ export function calBarWidthAndOffset(barSeries, api) {
var barGap = seriesModel.get('barGap');
var barCategoryGap = seriesModel.get('barCategoryGap');
- return {
+ seriesInfoList.push({
bandWidth: bandWidth,
barWidth: barWidth,
barMaxWidth: barMaxWidth,
@@ -78,13 +94,13 @@ export function calBarWidthAndOffset(barSeries, api) {
barCategoryGap: barCategoryGap,
axisKey: getAxisKey(baseAxis),
stackId: getSeriesStackId(seriesModel)
- };
+ });
});
- return doCalBarWidthAndOffset(seriesInfoList, api);
+ return doCalBarWidthAndOffset(seriesInfoList);
}
-function doCalBarWidthAndOffset(seriesInfoList, api) {
+function doCalBarWidthAndOffset(seriesInfoList) {
// Columns info on each category axis. Key is cartesian name
var columnsMap = {};
@@ -198,21 +214,28 @@ function doCalBarWidthAndOffset(seriesInfoList, api) {
}
/**
+ * @param {Object} barWidthAndOffset The result of makeColumnLayout
+ * @param {module:echarts/coord/Axis} axis
+ * @param {module:echarts/model/Series} [seriesModel] If not provided, return all.
+ * @return {Object} {stackId: {offset, width}} or {offset, width} if seriesModel provided.
+ */
+export function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) {
+ if (barWidthAndOffset && axis) {
+ var result = barWidthAndOffset[getAxisKey(axis)];
+ if (result != null && seriesModel != null) {
+ return result[getSeriesStackId(seriesModel)];
+ }
+ }
+}
+
+/**
* @param {string} seriesType
* @param {module:echarts/model/Global} ecModel
- * @param {module:echarts/ExtensionAPI} api
*/
-export function layout(seriesType, ecModel, api) {
+export function layout(seriesType, ecModel) {
- var seriesModels = [];
- ecModel.eachSeriesByType(seriesType, function (seriesModel) {
- // Check series coordinate, do layout for cartesian2d only
- if (seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d') {
- seriesModels.push(seriesModel);
- }
- });
-
- var barWidthAndOffset = calBarWidthAndOffset(seriesModels);
+ var seriesModels = prepareLayoutBarSeries(seriesType, ecModel);
+ var barWidthAndOffset = makeColumnLayout(seriesModels);
var lastStackCoords = {};
var lastStackCoordsOrigin = {};
@@ -244,12 +267,7 @@ export function layout(seriesType, ecModel, api) {
var stacked = isDimensionStacked(data, valueDim, baseDim);
var isValueAxisH = valueAxis.isHorizontal();
- var valueAxisStart = (
- zrUtil.indexOf(baseAxis.getAxesOnZeroOf(), valueAxis) >= 0
- || stacked
- )
- ? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0))
- : valueAxis.getGlobalExtent()[0];
+ var valueAxisStart = getValueAxisStart(baseAxis, valueAxis, stacked);
for (var idx = 0, len = data.count(); idx < len; idx++) {
var value = data.get(valueDim, idx);
@@ -318,4 +336,76 @@ export function layout(seriesType, ecModel, api) {
}, this);
}
+// TODO: Do not support stack in large mode yet.
+export var largeLayout = {
+
+ seriesType: 'bar',
+
+ plan: createRenderPlanner(),
+ reset: function (seriesModel) {
+ if (!isOnCartesian(seriesModel) || !isInLargeMode(seriesModel)) {
+ return;
+ }
+
+ var data = seriesModel.getData();
+ var cartesian = seriesModel.coordinateSystem;
+ var baseAxis = cartesian.getBaseAxis();
+ var valueAxis = cartesian.getOtherAxis(baseAxis);
+ var valueDim = data.mapDimension(valueAxis.dim);
+ var baseDim = data.mapDimension(baseAxis.dim);
+ var valueAxisHorizontal = valueAxis.isHorizontal();
+ var valueDimIdx = valueAxisHorizontal ? 0 : 1;
+
+ var barWidth = retrieveColumnLayout(
+ makeColumnLayout([seriesModel]), baseAxis, seriesModel
+ ).width;
+ if (!(barWidth > LARGE_BAR_MIN_WIDTH)) { // jshint ignore:line
+ barWidth = LARGE_BAR_MIN_WIDTH;
+ }
+
+ return {progress: progress};
+
+ function progress(params, data) {
+
+ var largePoints = new LargeArr(params.count * 2);
+ var dataIndex;
+ var coord = [];
+ var valuePair = [];
+ var offset = 0;
+
+ while ((dataIndex = params.next()) != null) {
+ valuePair[valueDimIdx] = data.get(valueDim, dataIndex);
+ valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex);
+
+ coord = cartesian.dataToPoint(valuePair, null, coord);
+ largePoints[offset++] = coord[0];
+ largePoints[offset++] = coord[1];
+ }
+
+ data.setLayout({
+ largePoints: largePoints,
+ barWidth: barWidth,
+ valueAxisStart: getValueAxisStart(baseAxis, valueAxis, false),
+ valueAxisHorizontal: valueAxisHorizontal
+ });
+ }
+ }
+};
+
+function isOnCartesian(seriesModel) {
+ return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d';
+}
+
+function isInLargeMode(seriesModel) {
+ return seriesModel.pipelineContext && seriesModel.pipelineContext.large;
+}
+
+function getValueAxisStart(baseAxis, valueAxis, stacked) {
+ return (
+ zrUtil.indexOf(baseAxis.getAxesOnZeroOf(), valueAxis) >= 0
+ || stacked
+ )
+ ? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0))
+ : valueAxis.getGlobalExtent()[0];
+}
diff --git a/test/bar-large1.html b/test/bar-large1.html
new file mode 100644
index 0000000..a2114b8
--- /dev/null
+++ b/test/bar-large1.html
@@ -0,0 +1,132 @@
+<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>
+ <script src="lib/testHelper.js"></script>
+ <link rel="stylesheet" href="lib/reset.css" />
+ </head>
+ <body>
+ <style>
+ .test-title {
+ background: #146402;
+ color: #fff;
+ }
+ </style>
+
+ <div id="main0"></div>
+
+ <script>
+
+ function ValueGenerator(baseValue) {
+ this._baseValue = baseValue;
+ }
+ ValueGenerator.prototype.next = function () {
+ var value = this._baseValue += Math.random() * 20 - 10;
+ return Math.max(0, Math.round(value) + 3000);
+ }
+
+ require([
+ 'echarts'
+ ], function (echarts) {
+
+ var count = 5e5;
+ // var count = 1e6;
+
+ var xAxisData = [];
+ var data1 = [];
+ var data2 = [];
+ var generator1 = new ValueGenerator(Math.random() * 1000);
+ // var generator2 = new ValueGenerator(Math.random() * 5000);
+
+ for (var i = 0; i < count; i++) {
+ xAxisData.push('category' + i);
+ data1.push(generator1.next().toFixed(2));
+ // data2.push(generator2.next().toFixed(2));
+ }
+
+ var option = {
+ title: {
+ text: echarts.format.addCommas(count) + ' Bars',
+ left: 10
+ },
+ legend: {
+ data: ['bar', 'bar2', 'bar3', 'bar4'],
+ align: 'left'
+ },
+ toolbox: {
+ // y: 'bottom',
+ feature: {
+ magicType: {
+ type: ['line', 'bar', 'stack', 'tiled']
+ },
+ dataZoom: {
+ yAxisIndex: false
+ },
+ dataView: {},
+ saveAsImage: {
+ pixelRatio: 2
+ }
+ }
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ }
+ },
+ dataZoom: [{
+ // startValue: 48,
+ // endValue: 99,
+ type: 'inside'
+ }, {
+ // startValue: 48,
+ // endValue: 99,
+ type: 'slider'
+ }],
+ xAxis: {
+ data: xAxisData,
+ silent: false,
+ splitLine: {
+ show: false
+ },
+ splitArea: {
+ show: false
+ }
+ },
+ yAxis: {
+ splitArea: {
+ show: false
+ }
+ },
+ series: [{
+ name: 'bar',
+ type: 'bar',
+ // stack: 'one',
+ data: data1,
+ itemStyle: {
+ color: 'green'
+ // borderColor: 'yellow'
+ },
+ large: true
+ // progressiveChunkMode: 'sequential'
+ // }, {
+ // show: false,
+ // name: 'bar2',
+ // type: 'bar',
+ // stack: 'one',
+ // data: data[1]
+ }]
+ };
+
+ testHelper.create(echarts, 'main0', {
+ option: option
+ });
+
+ });
+ </script>
+ </body>
+</html>
\ No newline at end of file
diff --git a/test/candlestick-large2.html b/test/candlestick-large2.html
index 9c4019b..e91528f 100644
--- a/test/candlestick-large2.html
+++ b/test/candlestick-large2.html
@@ -34,6 +34,7 @@
// The data count is from a real requirement.
var rawDataCount = 2e5;
+ // var rawDataCount = 2e2;
function run() {
var data = generateOHLC(rawDataCount);
@@ -47,16 +48,16 @@
var xValue = +new Date(2011, 0, 1);
var minute = 60 * 1000;
var baseValue = Math.random() * 12000;
- var tmpVals = new Array(4);
+ var boxVals = new Array(4);
var dayRange = 12;
for (var i = 0; i < count; i++) {
baseValue = baseValue + Math.random() * 20 - 10;
for (var j = 0; j < 4; j++) {
- tmpVals[j] = (Math.random() - 0.5) * dayRange + baseValue;
+ boxVals[j] = (Math.random() - 0.5) * dayRange + baseValue;
}
- tmpVals.sort();
+ boxVals.sort();
var idxRandom = Math.random();
var openIdx = Math.round(Math.random() * 3);
@@ -64,15 +65,17 @@
if (closeIdx === openIdx) {
closeIdx++;
}
+ var volumn = boxVals[3] * (1000 + Math.random() * 500);
- // ['open', 'close', 'lowest', 'highest']
+ // ['open', 'close', 'lowest', 'highest', 'volumn']
// [1, 4, 3, 2]
data.push([
echarts.format.formatTime('yyyy-MM-dd hh:mm:ss', xValue += minute),
- +tmpVals[openIdx].toFixed(2), // open
- +tmpVals[3].toFixed(2), // highest
- +tmpVals[0].toFixed(2), // lowest
- +tmpVals[closeIdx].toFixed(2) // close
+ +boxVals[openIdx].toFixed(2), // open
+ +boxVals[3].toFixed(2), // highest
+ +boxVals[0].toFixed(2), // lowest
+ +boxVals[closeIdx].toFixed(2), // close
+ volumn.toFixed(0)
]);
}
@@ -99,6 +102,11 @@
frameInsight.init(echarts, 'duration');
+ var upColor = '#ec0000';
+ var upBorderColor = '#8A0000';
+ var downColor = '#00da3c';
+ var downBorderColor = '#008F28';
+
var option = {
dataset: {
source: rawData
@@ -137,12 +145,12 @@
right: '10%',
height: 300
},
- // {
- // left: '10%',
- // right: '10%',
- // height: 70,
- // bottom: 80
- // }
+ {
+ left: '10%',
+ right: '10%',
+ height: 70,
+ bottom: 80
+ }
],
xAxis: [
{
@@ -156,20 +164,19 @@
min: 'dataMin',
max: 'dataMax'
},
- // {
- // type: 'category',
- // gridIndex: 1,
- // data: data.categoryData,
- // scale: true,
- // boundaryGap : false,
- // axisLine: {onZero: false},
- // axisTick: {show: false},
- // splitLine: {show: false},
- // axisLabel: {show: false},
- // splitNumber: 20,
- // min: 'dataMin',
- // max: 'dataMax'
- // }
+ {
+ type: 'category',
+ gridIndex: 1,
+ scale: true,
+ boundaryGap : false,
+ axisLine: {onZero: false},
+ axisTick: {show: false},
+ splitLine: {show: false},
+ axisLabel: {show: false},
+ splitNumber: 20,
+ min: 'dataMin',
+ max: 'dataMax'
+ }
],
yAxis: [
{
@@ -178,26 +185,26 @@
show: true
}
},
- // {
- // scale: true,
- // gridIndex: 1,
- // splitNumber: 2,
- // axisLabel: {show: false},
- // axisLine: {show: false},
- // axisTick: {show: false},
- // splitLine: {show: false}
- // }
+ {
+ scale: true,
+ gridIndex: 1,
+ splitNumber: 2,
+ axisLabel: {show: false},
+ axisLine: {show: false},
+ axisTick: {show: false},
+ splitLine: {show: false}
+ }
],
dataZoom: [
{
type: 'inside',
- // xAxisIndex: [0, 1],
+ xAxisIndex: [0, 1],
start: 10,
end: 100
},
{
show: true,
- // xAxisIndex: [0, 1],
+ xAxisIndex: [0, 1],
type: 'slider',
bottom: 10,
start: 10,
@@ -210,25 +217,19 @@
type: 'candlestick',
// progressiveMode: 'linear',
// data: data,
+ itemStyle: {
+ color: upColor,
+ color0: downColor,
+ borderColor: upBorderColor,
+ borderColor0: downBorderColor
+ },
encode: {
x: 0,
y: [1, 4, 3, 2]
},
// progressive: false
// progressive: progressive
- // tooltip: {
- // formatter: function (param) {
- // var param = param[0];
- // return [
- // 'Date: ' + param.name + '<hr size=1 style="margin: 3px 0">',
- // 'Open: ' + param.data[0] + '<br/>',
- // 'Close: ' + param.data[1] + '<br/>',
- // 'Lowest: ' + param.data[2] + '<br/>',
- // 'Highest: ' + param.data[3] + '<br/>'
- // ].join('')
- // }
- // }
- } //,
+ },
// {
// name: 'MA5',
// type: 'line',
@@ -265,13 +266,17 @@
// normal: {opacity: 0.5}
// }
// },
- // {
- // name: 'Volumn',
- // type: 'bar',
- // xAxisIndex: 1,
- // yAxisIndex: 1,
- // data: data.volumns
- // }
+ {
+ name: 'Volumn',
+ type: 'bar',
+ xAxisIndex: 1,
+ yAxisIndex: 1,
+ large: true,
+ encode: {
+ x: 0,
+ y: 5
+ }
+ }
]
};
--
To stop receiving notification emails like this one, please contact
sushuang@apache.org.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org