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/05 20:35:38 UTC
[incubator-echarts] 08/09: optimize candlestick.
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 096a88e5aba1cf452787711edd22cbc51c7e6ad9
Author: sushuang <su...@gmail.com>
AuthorDate: Thu Apr 5 03:21:16 2018 +0800
optimize candlestick.
---
src/chart/boxplot/BoxplotView.js | 4 +-
src/chart/candlestick/CandlestickSeries.js | 11 +-
src/chart/candlestick/CandlestickView.js | 280 +++++++++++----------
src/chart/candlestick/candlestickLayout.js | 50 +++-
src/chart/candlestick/candlestickVisual.js | 12 +-
src/chart/candlestick/helper.js | 28 ---
test/candlestick-large.html | 12 +-
...dlestick-large.html => candlestick-large2.html} | 177 +++++++------
...dlestick-large.html => candlestick-large3.html} | 155 ++++++------
test/lib/frameInsight.js | 4 +-
10 files changed, 395 insertions(+), 338 deletions(-)
diff --git a/src/chart/boxplot/BoxplotView.js b/src/chart/boxplot/BoxplotView.js
index 4e356a1..5032356 100644
--- a/src/chart/boxplot/BoxplotView.js
+++ b/src/chart/boxplot/BoxplotView.js
@@ -70,7 +70,9 @@ var BoxplotView = ChartView.extend({
data && data.eachItemGraphicEl(function (el) {
el && group.remove(el);
});
- }
+ },
+
+ dispose: zrUtil.noop
});
diff --git a/src/chart/candlestick/CandlestickSeries.js b/src/chart/candlestick/CandlestickSeries.js
index e9ec988..682cb7e 100644
--- a/src/chart/candlestick/CandlestickSeries.js
+++ b/src/chart/candlestick/CandlestickSeries.js
@@ -1,7 +1,6 @@
import * as zrUtil from 'zrender/src/core/util';
import SeriesModel from '../../model/Series';
import {seriesModelMixin} from '../helper/whiskerBoxCommon';
-// import {calculateCandleWidth} from './helper';
var CandlestickSeries = SeriesModel.extend({
@@ -57,7 +56,10 @@ var CandlestickSeries = SeriesModel.extend({
barWidth: null,
large: true,
- largeThreshold: 500,
+ largeThreshold: 600,
+
+ progressive: 5e3,
+ progressiveThreshold: 1e4,
animationUpdate: false,
animationEasing: 'linear',
@@ -77,11 +79,6 @@ var CandlestickSeries = SeriesModel.extend({
return itemLayout && selectors.rect(itemLayout.brushRect);
}
- // isLargeMode: function (data) {
- // // Experience number
- // return calculateCandleWidth(this, data) <= 1;
- // }
-
});
zrUtil.mixin(CandlestickSeries, seriesModelMixin, true);
diff --git a/src/chart/candlestick/CandlestickView.js b/src/chart/candlestick/CandlestickView.js
index 6f8d960..527f62a 100644
--- a/src/chart/candlestick/CandlestickView.js
+++ b/src/chart/candlestick/CandlestickView.js
@@ -5,18 +5,51 @@ import Path from 'zrender/src/graphic/Path';
var NORMAL_ITEM_STYLE_PATH = ['itemStyle'];
var EMPHASIS_ITEM_STYLE_PATH = ['emphasis', 'itemStyle'];
+var SKIP_PROPS = ['color', 'color0', 'borderColor', 'borderColor0'];
+
var CandlestickView = ChartView.extend({
type: 'candlestick',
render: function (seriesModel, ecModel, api) {
- var group = this.group;
+ this._updateDrawMode(seriesModel);
+
+ this._isLargeDraw
+ ? this._renderLarge(seriesModel)
+ : this._renderNormal(seriesModel);
+ },
+
+ incrementalPrepareRender: function (seriesModel, ecModel, api) {
+ this._clear();
+ this._updateDrawMode(seriesModel);
+ },
+
+ incrementalRender: function (params, seriesModel, ecModel, api) {
+ this._isLargeDraw
+ ? this._incrementalRenderLarge(params, seriesModel)
+ : this._incrementalRenderNormal(params, seriesModel);
+ },
+
+ _updateDrawMode: function (seriesModel) {
+ var isLargeDraw = seriesModel.pipelineContext.large;
+ if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) {
+ this._isLargeDraw = isLargeDraw;
+ this._clear();
+ }
+ },
+
+ _clear: function () {
+ this.group.removeAll();
+ this._data = null;
+ },
+
+ _renderNormal: function (seriesModel) {
+ // var largePoints = data.getLayout('largePoints');
var data = seriesModel.getData();
var oldData = this._data;
- var pipelineContext = seriesModel.pipelineContext;
- var isLargeRender = pipelineContext.large;
- var largePoints = isLargeRender && data.getLayout('largePoints');
+ var group = this.group;
+ var isSimpleBox = data.getLayout('isSimpleBox');
// There is no old data only when first rendering or switching from
// stream mode to normal mode, where previous elements should be removed.
@@ -27,42 +60,39 @@ var CandlestickView = ChartView.extend({
data.diff(oldData)
.add(function (newIdx) {
if (data.hasValue(newIdx)) {
- var symbolEl = isLargeRender
- ? createLargeBox(data, largePoints, newIdx)
- : createNormalBox(data, newIdx, true);
- data.setItemGraphicEl(newIdx, symbolEl);
- group.add(symbolEl);
+ var el;
+
+ var itemLayout = data.getItemLayout(newIdx);
+ el = createNormalBox(itemLayout, newIdx, true);
+ graphic.initProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);
+
+ setBoxCommon(el, data, newIdx, isSimpleBox);
+
+ group.add(el);
+ data.setItemGraphicEl(newIdx, el);
}
})
.update(function (newIdx, oldIdx) {
- var symbolEl = oldData.getItemGraphicEl(oldIdx);
+ var el = oldData.getItemGraphicEl(oldIdx);
// Empty data
if (!data.hasValue(newIdx)) {
- group.remove(symbolEl);
+ group.remove(el);
return;
}
- if (symbolEl && symbolEl.__largeWhiskerBox ^ isLargeRender) {
- group.remove(symbolEl);
- symbolEl = null;
- }
-
- if (!symbolEl) {
- symbolEl = isLargeRender
- ? createLargeBox(data, largePoints, newIdx)
- : createNormalBox(data, newIdx);
+ var itemLayout = data.getItemLayout(newIdx);
+ if (!el) {
+ el = createNormalBox(itemLayout, newIdx);
}
else {
- isLargeRender
- ? updateLargeBoxData(symbolEl, data, newIdx)
- : updateNormalBoxData(symbolEl, data, newIdx);
+ graphic.updateProps(el, {shape: {points: itemLayout.ends}}, seriesModel, newIdx);
}
- // Add back
- group.add(symbolEl);
+ setBoxCommon(el, data, newIdx, isSimpleBox);
- data.setItemGraphicEl(newIdx, symbolEl);
+ group.add(el);
+ data.setItemGraphicEl(newIdx, el);
})
.remove(function (oldIdx) {
var el = oldData.getItemGraphicEl(oldIdx);
@@ -73,26 +103,34 @@ var CandlestickView = ChartView.extend({
this._data = data;
},
- incrementalPrepareRender: function (seriesModel, ecModel, api) {
- this.group.removeAll();
- this._data = null;
+ _renderLarge: function (seriesModel) {
+ var group = this.group;
+
+ group.removeAll();
+
+ createLarge(seriesModel, group);
},
- incrementalRender: function (params, seriesModel, ecModel, api) {
+ _incrementalRenderNormal: function (params, seriesModel) {
var data = seriesModel.getData();
- var pipelineContext = seriesModel.pipelineContext;
- var isLargeRender = pipelineContext.large;
- var largePoints = isLargeRender && data.getLayout('largePoints');
-
- for (var idx = params.start; idx < params.end; idx++) {
- var symbolEl = isLargeRender
- ? createLargeBox(data, largePoints, idx, params.start)
- : createNormalBox(data, idx, this.styleUpdater, true);
- symbolEl.incremental = true;
- this.group.add(symbolEl);
+ var isSimpleBox = data.getLayout('isSimpleBox');
+
+ for (var dataIndex = params.start; dataIndex < params.end; dataIndex++) {
+ var el;
+
+ var itemLayout = data.getItemLayout(dataIndex);
+ el = createNormalBox(itemLayout, dataIndex);
+ setBoxCommon(el, data, dataIndex, isSimpleBox);
+
+ el.incremental = true;
+ this.group.add(el);
}
},
+ _incrementalRenderLarge: function (params, seriesModel) {
+ createLarge(seriesModel, this.group, true);
+ },
+
remove: function (ecModel) {
var group = this.group;
var data = this._data;
@@ -100,45 +138,44 @@ var CandlestickView = ChartView.extend({
data && data.eachItemGraphicEl(function (el) {
el && group.remove(el);
});
- }
-
-});
-
-
+ },
+ dispose: zrUtil.noop
+});
-// ---------------------
-// -- Normal Renderer --
-// ---------------------
var NormalBoxPath = Path.extend({
- type: 'candlestickBox',
+ type: 'normalCandlestickBox',
shape: {},
buildPath: function (ctx, shape) {
var ends = shape.points;
- ctx.moveTo(ends[0][0], ends[0][1]);
- ctx.lineTo(ends[1][0], ends[1][1]);
- ctx.lineTo(ends[2][0], ends[2][1]);
- ctx.lineTo(ends[3][0], ends[3][1]);
- ctx.closePath();
-
- ctx.moveTo(ends[4][0], ends[4][1]);
- ctx.lineTo(ends[5][0], ends[5][1]);
- ctx.moveTo(ends[6][0], ends[6][1]);
- ctx.lineTo(ends[7][0], ends[7][1]);
+ if (this.__simpleBox) {
+ ctx.moveTo(ends[4][0], ends[4][1]);
+ ctx.lineTo(ends[6][0], ends[6][1]);
+ }
+ else {
+ ctx.moveTo(ends[0][0], ends[0][1]);
+ ctx.lineTo(ends[1][0], ends[1][1]);
+ ctx.lineTo(ends[2][0], ends[2][1]);
+ ctx.lineTo(ends[3][0], ends[3][1]);
+ ctx.closePath();
+
+ ctx.moveTo(ends[4][0], ends[4][1]);
+ ctx.lineTo(ends[5][0], ends[5][1]);
+ ctx.moveTo(ends[6][0], ends[6][1]);
+ ctx.lineTo(ends[7][0], ends[7][1]);
+ }
}
});
-function createNormalBox(data, dataIndex, isInit) {
- var itemLayout = data.getItemLayout(dataIndex);
+function createNormalBox(itemLayout, dataIndex, isInit) {
var ends = itemLayout.ends;
-
- var el = new NormalBoxPath({
+ return new NormalBoxPath({
shape: {
points: isInit
? transInit(ends, itemLayout)
@@ -146,24 +183,9 @@ function createNormalBox(data, dataIndex, isInit) {
},
z2: 100
});
-
- updateNormalBoxData(el, data, dataIndex, isInit);
-
- return el;
}
-function updateNormalBoxData(el, data, dataIndex, isInit) {
- var seriesModel = data.hostModel;
- var itemLayout = data.getItemLayout(dataIndex);
- var updateMethod = graphic[isInit ? 'initProps' : 'updateProps'];
-
- updateMethod(
- el,
- {shape: {points: itemLayout.ends}},
- seriesModel,
- dataIndex
- );
-
+function setBoxCommon(el, data, dataIndex, isSimpleBox) {
var itemModel = data.getItemModel(dataIndex);
var normalItemStyleModel = itemModel.getModel(NORMAL_ITEM_STYLE_PATH);
var color = data.getItemVisual(dataIndex, 'color');
@@ -171,15 +193,15 @@ function updateNormalBoxData(el, data, dataIndex, isInit) {
// Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke
- var itemStyle = normalItemStyleModel.getItemStyle(
- ['color', 'color0', 'borderColor', 'borderColor0']
- );
+ var itemStyle = normalItemStyleModel.getItemStyle(SKIP_PROPS);
el.useStyle(itemStyle);
el.style.strokeNoScale = true;
el.style.fill = color;
el.style.stroke = borderColor;
+ el.__simpleBox = isSimpleBox;
+
var hoverStyle = itemModel.getModel(EMPHASIS_ITEM_STYLE_PATH).getItemStyle();
graphic.setHoverStyle(el, hoverStyle);
}
@@ -194,70 +216,72 @@ function transInit(points, itemLayout) {
+var LargeBoxPath = Path.extend({
+ type: 'largeCandlestickBox',
+ shape: {},
-// --------------------
-// -- Large Renderer --
-// --------------------
+ buildPath: function (ctx, shape) {
+ // Drawing lines is more efficient than drawing
+ // a whole line or drawing rects.
+ var points = shape.points;
+ for (var i = 0; i < points.length;) {
+ if (this.__sign === points[i++]) {
+ var x = points[i++];
+ ctx.moveTo(x, points[i++]);
+ ctx.lineTo(x, points[i++]);
+ }
+ else {
+ i += 3;
+ }
+ }
+ }
+});
-var NORMAL_STYLE_ACCESS_PATH = ['itemStyle'];
-var EMPHASIS_STYLE_ACCESS_PATH = ['emphasis', 'itemStyle'];
+function createLarge(seriesModel, group, incremental) {
+ var data = seriesModel.getData();
+ var largePoints = data.getLayout('largePoints');
-function createLargeBox(data, largePoints, dataIndex, segmentStart) {
- var boxEl = new graphic.Line({
- shape: largeBoxMakeShape(largePoints, dataIndex, segmentStart)
+ var elP = new LargeBoxPath({
+ shape: {points: largePoints},
+ __sign: 1
});
+ group.add(elP);
+ var elN = new LargeBoxPath({
+ shape: {points: largePoints},
+ __sign: -1
+ });
+ group.add(elN);
- boxEl.__largeWhiskerBox = true;
-
- largeBoxSetStyle(boxEl, data, dataIndex);
-
- return boxEl;
-}
+ setLargeStyle(1, elP, seriesModel, data);
+ setLargeStyle(-1, elN, seriesModel, data);
-function largeBoxMakeShape(largePoints, dataIndex, segmentStart) {
- var baseIdx = (dataIndex - (segmentStart || 0)) * 5;
- return {
- x1: largePoints[baseIdx + 1],
- y1: largePoints[baseIdx + 2],
- x2: largePoints[baseIdx + 3],
- y2: largePoints[baseIdx + 4]
- };
+ if (incremental) {
+ elP.incremental = true;
+ elN.incremental = true;
+ }
}
-function updateLargeBoxData(boxEl, data, dataIndex) {
- graphic.updateProps(
- boxEl,
- {shape: largeBoxMakeShape(data.getLayout('largePoints'), dataIndex, 0)},
- data.hostModel,
- dataIndex
- );
+function setLargeStyle(sign, el, seriesModel, data) {
+ var normalItemStyleModel = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH);
+ var suffix = sign > 0 ? 'P' : 'N';
- largeBoxSetStyle(boxEl, data, dataIndex);
-}
-
-function largeBoxSetStyle(boxEl, data, dataIndex) {
- var itemModel = data.getItemModel(dataIndex);
- var normalItemStyleModel = itemModel.getModel(NORMAL_STYLE_ACCESS_PATH);
- var color = data.getItemVisual(dataIndex, 'color');
- var borderColor = data.getItemVisual(dataIndex, 'borderColor') || color;
+ var color = data.getVisual('color' + suffix);
+ var borderColor = data.getVisual('borderColor' + suffix) || color;
// Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke
- var itemStyle = normalItemStyleModel.getItemStyle(
- ['color', 'color0', 'borderColor', 'borderColor0']
- );
+ var itemStyle = normalItemStyleModel.getItemStyle(SKIP_PROPS);
- boxEl.useStyle(itemStyle);
- boxEl.style.stroke = borderColor;
-
- var hoverStyle = itemModel.getModel(EMPHASIS_STYLE_ACCESS_PATH).getItemStyle();
- graphic.setHoverStyle(boxEl, hoverStyle);
+ el.useStyle(itemStyle);
+ el.style.fill = null;
+ el.style.stroke = borderColor;
+ // No different
+ // el.style.lineWidth = .5;
}
-
export default CandlestickView;
diff --git a/src/chart/candlestick/candlestickLayout.js b/src/chart/candlestick/candlestickLayout.js
index 6fa8fda..3aa8d5c 100644
--- a/src/chart/candlestick/candlestickLayout.js
+++ b/src/chart/candlestick/candlestickLayout.js
@@ -1,6 +1,7 @@
import {subPixelOptimize} from '../../util/graphic';
import createRenderPlanner from '../helper/createRenderPlanner';
-import {calculateCandleWidth} from './helper';
+import {parsePercent} from '../../util/number';
+import {retrieve2} from 'zrender/src/core/util';
var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array;
@@ -12,9 +13,6 @@ export default {
reset: function (seriesModel) {
- var pipelineContext = seriesModel.pipelineContext;
- var isLargeRender = pipelineContext.large;
-
var coordSys = seriesModel.coordinateSystem;
var data = seriesModel.getData();
var candleWidth = calculateCandleWidth(seriesModel, data);
@@ -28,12 +26,20 @@ export default {
var lowestDim = vDims[2];
var highestDim = vDims[3];
+ data.setLayout({
+ candleWidth: candleWidth,
+ // The value is experimented visually.
+ isSimpleBox: candleWidth <= 1.3
+ });
+
if (cDim == null || vDims.length < 4) {
return;
}
- return {progress: isLargeRender ? largeProgress : normalProgress};
-
+ return {
+ progress: seriesModel.pipelineContext.large
+ ? largeProgress : normalProgress
+ };
function normalProgress(params, data) {
@@ -121,7 +127,7 @@ export default {
function largeProgress(params, data) {
var segCount = params.end - params.start;
- // Structure: [sign, x1, y1, x2, y2, sign, x1, y1, x2, y2, ...]
+ // Structure: [sign, x, yhigh, ylow, sign, x, yhigh, ylow, ...]
var points = new LargeArr(segCount * 5);
for (
@@ -149,15 +155,12 @@ export default {
point = coordSys.dataToPoint(tmpIn, null, tmpOut);
points[offset++] = point ? point[0] : NaN;
points[offset++] = point ? point[1] : NaN;
-
tmpIn[vDimIdx] = highestVal;
point = coordSys.dataToPoint(tmpIn, null, tmpOut);
- points[offset++] = point ? point[0] : NaN;
points[offset++] = point ? point[1] : NaN;
}
data.setLayout('largePoints', points);
- data.setLayout('candleWidth', candleWidth);
}
}
};
@@ -180,3 +183,30 @@ function getSign(data, dataIndex, openVal, closeVal, closeDim) {
return sign;
}
+
+function calculateCandleWidth(seriesModel, data) {
+ var baseAxis = seriesModel.getBaseAxis();
+ var extent;
+
+ var bandWidth = baseAxis.type === 'category'
+ ? baseAxis.getBandWidth()
+ : (
+ extent = baseAxis.getExtent(),
+ Math.abs(extent[1] - extent[0]) / data.count()
+ );
+
+ var barMaxWidth = parsePercent(
+ retrieve2(seriesModel.get('barMaxWidth'), bandWidth),
+ bandWidth
+ );
+ var barMinWidth = parsePercent(
+ retrieve2(seriesModel.get('barMinWidth'), 1),
+ bandWidth
+ );
+ var barWidth = seriesModel.get('barWidth');
+
+ return barWidth != null
+ ? parsePercent(barWidth, bandWidth)
+ // Put max outer to ensure bar visible in spite of overlap.
+ : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
+}
diff --git a/src/chart/candlestick/candlestickVisual.js b/src/chart/candlestick/candlestickVisual.js
index ad94894..9273480 100644
--- a/src/chart/candlestick/candlestickVisual.js
+++ b/src/chart/candlestick/candlestickVisual.js
@@ -17,9 +17,7 @@ export default {
reset: function (seriesModel, ecModel) {
var data = seriesModel.getData();
- var pipelineContext = seriesModel.pipelineContext;
- var isLargeRender = pipelineContext.large;
- var largePoints = isLargeRender && data.getLayout('largePoints');
+ var isLargeRender = seriesModel.pipelineContext.large;
data.setVisual({
legendSymbol: 'roundRect',
@@ -34,12 +32,13 @@ export default {
return;
}
+ return !isLargeRender && {progress: progress};
+
+
function progress(params, data) {
for (var dataIndex = params.start; dataIndex < params.end; dataIndex++) {
var itemModel = data.getItemModel(dataIndex);
- var sign = isLargeRender
- ? largePoints[(dataIndex - params.start) * 5]
- : data.getItemLayout(dataIndex).sign;
+ var sign = data.getItemLayout(dataIndex).sign;
data.setItemVisual(
dataIndex,
@@ -63,7 +62,6 @@ export default {
);
}
- return {progress: progress};
}
};
\ No newline at end of file
diff --git a/src/chart/candlestick/helper.js b/src/chart/candlestick/helper.js
deleted file mode 100644
index a0b778e..0000000
--- a/src/chart/candlestick/helper.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import {parsePercent} from '../../util/number';
-import {retrieve2} from 'zrender/src/core/util';
-
-export function calculateCandleWidth(seriesModel, data) {
- var baseAxis = seriesModel.getBaseAxis();
- var extent;
-
- var bandWidth = baseAxis.type === 'category'
- ? baseAxis.getBandWidth()
- : (
- extent = baseAxis.getExtent(),
- Math.abs(extent[1] - extent[0]) / data.count()
- );
-
- var barMaxWidth = parsePercent(
- retrieve2(seriesModel.get('barMaxWidth'), bandWidth),
- bandWidth
- );
- var barMinWidth = parsePercent(
- retrieve2(seriesModel.get('barMinWidth'), 1),
- bandWidth
- );
- var barWidth = seriesModel.get('barWidth');
- return barWidth != null
- ? parsePercent(barWidth, bandWidth)
- // Put max outer to ensure bar visible in spite of overlap.
- : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
-}
diff --git a/test/candlestick-large.html b/test/candlestick-large.html
index e5b797c..e6665f3 100644
--- a/test/candlestick-large.html
+++ b/test/candlestick-large.html
@@ -183,22 +183,28 @@
{
type: 'inside',
// xAxisIndex: [0, 1],
- // start: 10,
+ // start: 99,
// end: 100
+ // startValue: '2010-08-17',
+ // endValue: '2012-08-06'
},
{
show: true,
// xAxisIndex: [0, 1],
type: 'slider',
bottom: 10,
- // start: 10,
+ // start: 99,
// end: 100
+ // startValue: '2010-08-17',
+ // endValue: '2012-08-06'
}
],
+ animation: false,
series: [
{
name: 'Dow-Jones index',
type: 'candlestick',
+ // large: false,
encode: {
x: 0,
y: [1, 2, 3, 4]
@@ -271,7 +277,7 @@
var panel = document.getElementById('panel0');
var chart = testHelper.create(echarts, 'main0', {
- title: 'Use dataset',
+ title: 'Use dataset. Check item tooltip in large mode.',
option: option,
height: 550
});
diff --git a/test/candlestick-large.html b/test/candlestick-large2.html
similarity index 68%
copy from test/candlestick-large.html
copy to test/candlestick-large2.html
index e5b797c..ec99971 100644
--- a/test/candlestick-large.html
+++ b/test/candlestick-large2.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
- <script src="lib/esl.js"></script>
+ <script src="../dist/echarts.js"></script>
<script src="lib/config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/facePrint.js"></script>
@@ -28,81 +28,106 @@
<script>
- /**
- * @see <https://en.wikipedia.org/wiki/Michelson%E2%80%93Morley_experiment>
- * @see <http://bl.ocks.org/mbostock/4061502>
- */
- require([
- 'echarts',
- 'data/stock-DJI.json'
- ], update)
-
- function splitData(rawData) {
- var categoryData = [];
- var values = [];
- var volumns = [];
- for (var i = 0; i < rawData.length; i++) {
- categoryData.push(rawData[i].splice(0, 1)[0]);
- values.push(rawData[i])
- volumns.push(rawData[i][4]);
+ // The data count is from a real requirement.
+ var rawDataCount = 2e5;
+ var progressive = 4e3;
+
+ function run() {
+ var data = generateOHLC(rawDataCount);
+ var result = reorder(data);
+ init(result.data, result.categoryData);
+ }
+
+ function generateOHLC(count) {
+ var data = [];
+
+ var xValue = +new Date(2011, 0, 1);
+ var minute = 60 * 1000;
+ var baseValue = Math.random() * 12000;
+ var tmpVals = 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;
+ }
+ tmpVals.sort();
+
+ var idxRandom = Math.random();
+ var openIdx = Math.round(Math.random() * 3);
+ var closeIdx = Math.round(Math.random() * 2);
+ if (closeIdx === openIdx) {
+ closeIdx++;
+ }
+
+ // ['open', 'close', 'lowest', 'highest']
+ // [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
+ ]);
}
- return {
- categoryData: categoryData,
- values: values,
- volumns: volumns
- };
+
+ return data;
}
- function calculateMA(dayCount, rawData) {
+ function reorder(data) {
+ var categoryData = new Array(data.length);
+ var categoryMap = {};
+ for (var i = 0; i < data.length; i++) {
+ categoryData[i] = data[i][0];
+ categoryMap[categoryData[i]] = i;
+ }
+
+ var newData = new Array(data.length);
+ var step = Math.round(data.length / progressive);
+ var newOffset = 0;
+ for (var offset = 0; offset < step; offset++) {
+ for (var i = offset; i < data.length; i += step) {
+ var item = data[i].slice();
+ newData[newOffset++] = item;
+ item[0] = categoryMap[item[0]];
+ }
+ }
+ return {data: newData, categoryData: categoryData};
+ }
+
+ function calculateMA(dayCount, data) {
var result = [];
- for (var i = 0, len = rawData.length; i < len; i++) {
+ for (var i = 0, len = data.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
- sum += rawData[i - j][2];
+ sum += data[i - j][2];
}
result.push(+(sum / dayCount).toFixed(3));
}
return result;
}
- function update(echarts, rawData) {
-
- // var data = splitData(rawData);
+ function init(rawData, categoryData) {
var option = {
dataset: {
source: rawData
},
backgroundColor: '#eee',
+ // animation: false,
legend: {
- left: 0,
+ left: 0
},
tooltip: {
trigger: 'axis',
axisPointer: {
- type: 'cross'
- },
- backgroundColor: 'rgba(245, 245, 245, 0.8)',
- borderWidth: 1,
- borderColor: '#ccc',
- padding: 10,
- textStyle: {
- color: '#000'
- },
- position: function (pos, params, el, elRect, size) {
- var obj = {top: 10};
- obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 30;
- return obj;
- }
- },
- axisPointer: {
- link: {xAxisIndex: 'all'},
- label: {
- backgroundColor: '#777'
+ type: 'line'
}
},
toolbox: {
@@ -115,13 +140,13 @@
}
}
},
- brush: {
- xAxisIndex: 'all',
- brushLink: 'all',
- outOfBrush: {
- colorAlpha: 0.1
- }
- },
+ // brush: {
+ // xAxisIndex: 'all',
+ // brushLink: 'all',
+ // outOfBrush: {
+ // colorAlpha: 0.1
+ // }
+ // },
grid: [
{
left: '10%',
@@ -138,14 +163,14 @@
xAxis: [
{
type: 'category',
- // data: data.categoryData,
scale: true,
boundaryGap : false,
axisLine: {onZero: false},
splitLine: {show: false},
splitNumber: 20,
min: 'dataMin',
- max: 'dataMax'
+ max: 'dataMax',
+ data: categoryData
},
// {
// type: 'category',
@@ -183,32 +208,28 @@
{
type: 'inside',
// xAxisIndex: [0, 1],
- // start: 10,
- // end: 100
+ start: 10,
+ end: 100
},
{
show: true,
// xAxisIndex: [0, 1],
type: 'slider',
bottom: 10,
- // start: 10,
- // end: 100
+ start: 10,
+ end: 100
}
],
series: [
{
- name: 'Dow-Jones index',
+ name: 'Fake index',
type: 'candlestick',
+ // data: data,
encode: {
x: 0,
- y: [1, 2, 3, 4]
- },
- itemStyle: {
- normal: {
- borderColor: null,
- borderColor0: null
- }
+ y: [1, 4, 3, 2]
},
+ progressive: progressive
// tooltip: {
// formatter: function (param) {
// var param = param[0];
@@ -221,12 +242,11 @@
// ].join('')
// }
// }
- },
+ } //,
// {
// name: 'MA5',
// type: 'line',
- // sampling: 'max',
- // data: calculateMA(5, rawData),
+ // data: calculateMA(5, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -235,7 +255,7 @@
// {
// name: 'MA10',
// type: 'line',
- // data: calculateMA(10, rawData),
+ // data: calculateMA(10, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -244,7 +264,7 @@
// {
// name: 'MA20',
// type: 'line',
- // data: calculateMA(20, rawData),
+ // data: calculateMA(20, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -253,7 +273,7 @@
// {
// name: 'MA30',
// type: 'line',
- // data: calculateMA(30, rawData),
+ // data: calculateMA(30, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -271,7 +291,7 @@
var panel = document.getElementById('panel0');
var chart = testHelper.create(echarts, 'main0', {
- title: 'Use dataset',
+ title: 'Fake OHLC data',
option: option,
height: 550
});
@@ -312,8 +332,11 @@
// }
// ]
// });
+
}
+ run();
+
</script>
diff --git a/test/candlestick-large.html b/test/candlestick-large3.html
similarity index 73%
copy from test/candlestick-large.html
copy to test/candlestick-large3.html
index e5b797c..9d3f579 100644
--- a/test/candlestick-large.html
+++ b/test/candlestick-large3.html
@@ -3,11 +3,12 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
- <script src="lib/esl.js"></script>
+ <script src="../dist/echarts.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>
+ <script src="lib/frameInsight.js"></script>
<link rel="stylesheet" href="lib/reset.css" />
</head>
<body>
@@ -21,6 +22,7 @@
<div id="main0"></div>
<div id="panel0"></div>
+ <div id="duration"></div>
@@ -28,81 +30,86 @@
<script>
- /**
- * @see <https://en.wikipedia.org/wiki/Michelson%E2%80%93Morley_experiment>
- * @see <http://bl.ocks.org/mbostock/4061502>
- */
- require([
- 'echarts',
- 'data/stock-DJI.json'
- ], update)
-
- function splitData(rawData) {
- var categoryData = [];
- var values = [];
- var volumns = [];
- for (var i = 0; i < rawData.length; i++) {
- categoryData.push(rawData[i].splice(0, 1)[0]);
- values.push(rawData[i])
- volumns.push(rawData[i][4]);
+ // The data count is from a real requirement.
+ var rawDataCount = 2e5;
+
+ function run() {
+ var data = generateOHLC(rawDataCount);
+ // var result = reorder(data);
+ init(data);
+ }
+
+ function generateOHLC(count) {
+ var data = [];
+
+ var xValue = +new Date(2011, 0, 1);
+ var minute = 60 * 1000;
+ var baseValue = Math.random() * 12000;
+ var tmpVals = 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;
+ }
+ tmpVals.sort();
+
+ var idxRandom = Math.random();
+ var openIdx = Math.round(Math.random() * 3);
+ var closeIdx = Math.round(Math.random() * 2);
+ if (closeIdx === openIdx) {
+ closeIdx++;
+ }
+
+ // ['open', 'close', 'lowest', 'highest']
+ // [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
+ ]);
}
- return {
- categoryData: categoryData,
- values: values,
- volumns: volumns
- };
+
+ return data;
}
- function calculateMA(dayCount, rawData) {
+ function calculateMA(dayCount, data) {
var result = [];
- for (var i = 0, len = rawData.length; i < len; i++) {
+ for (var i = 0, len = data.length; i < len; i++) {
if (i < dayCount) {
result.push('-');
continue;
}
var sum = 0;
for (var j = 0; j < dayCount; j++) {
- sum += rawData[i - j][2];
+ sum += data[i - j][2];
}
result.push(+(sum / dayCount).toFixed(3));
}
return result;
}
- function update(echarts, rawData) {
+ function init(rawData) {
- // var data = splitData(rawData);
+ frameInsight.init(echarts, 'duration');
var option = {
dataset: {
source: rawData
},
backgroundColor: '#eee',
+ // animation: false,
legend: {
- left: 0,
+ left: 0
},
tooltip: {
trigger: 'axis',
axisPointer: {
- type: 'cross'
- },
- backgroundColor: 'rgba(245, 245, 245, 0.8)',
- borderWidth: 1,
- borderColor: '#ccc',
- padding: 10,
- textStyle: {
- color: '#000'
- },
- position: function (pos, params, el, elRect, size) {
- var obj = {top: 10};
- obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 30;
- return obj;
- }
- },
- axisPointer: {
- link: {xAxisIndex: 'all'},
- label: {
- backgroundColor: '#777'
+ type: 'line'
}
},
toolbox: {
@@ -115,13 +122,13 @@
}
}
},
- brush: {
- xAxisIndex: 'all',
- brushLink: 'all',
- outOfBrush: {
- colorAlpha: 0.1
- }
- },
+ // brush: {
+ // xAxisIndex: 'all',
+ // brushLink: 'all',
+ // outOfBrush: {
+ // colorAlpha: 0.1
+ // }
+ // },
grid: [
{
left: '10%',
@@ -138,7 +145,6 @@
xAxis: [
{
type: 'category',
- // data: data.categoryData,
scale: true,
boundaryGap : false,
axisLine: {onZero: false},
@@ -183,32 +189,29 @@
{
type: 'inside',
// xAxisIndex: [0, 1],
- // start: 10,
- // end: 100
+ start: 10,
+ end: 100
},
{
show: true,
// xAxisIndex: [0, 1],
type: 'slider',
bottom: 10,
- // start: 10,
- // end: 100
+ start: 10,
+ end: 100
}
],
series: [
{
- name: 'Dow-Jones index',
+ name: 'Fake index',
type: 'candlestick',
+ // data: data,
encode: {
x: 0,
- y: [1, 2, 3, 4]
- },
- itemStyle: {
- normal: {
- borderColor: null,
- borderColor0: null
- }
+ y: [1, 4, 3, 2]
},
+ // progressive: false
+ // progressive: progressive
// tooltip: {
// formatter: function (param) {
// var param = param[0];
@@ -221,12 +224,11 @@
// ].join('')
// }
// }
- },
+ } //,
// {
// name: 'MA5',
// type: 'line',
- // sampling: 'max',
- // data: calculateMA(5, rawData),
+ // data: calculateMA(5, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -235,7 +237,7 @@
// {
// name: 'MA10',
// type: 'line',
- // data: calculateMA(10, rawData),
+ // data: calculateMA(10, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -244,7 +246,7 @@
// {
// name: 'MA20',
// type: 'line',
- // data: calculateMA(20, rawData),
+ // data: calculateMA(20, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -253,7 +255,7 @@
// {
// name: 'MA30',
// type: 'line',
- // data: calculateMA(30, rawData),
+ // data: calculateMA(30, data),
// smooth: true,
// lineStyle: {
// normal: {opacity: 0.5}
@@ -271,7 +273,7 @@
var panel = document.getElementById('panel0');
var chart = testHelper.create(echarts, 'main0', {
- title: 'Use dataset',
+ title: 'Fake OHLC data',
option: option,
height: 550
});
@@ -312,8 +314,11 @@
// }
// ]
// });
+
}
+ run();
+
</script>
diff --git a/test/lib/frameInsight.js b/test/lib/frameInsight.js
index b19c6f3..1a397e9 100644
--- a/test/lib/frameInsight.js
+++ b/test/lib/frameInsight.js
@@ -139,9 +139,9 @@
var domStyle = dom.style;
// domStyle.border = '2px solid #333';
domStyle.boxShadow = '0 0 3px #000';
- domStyle.backgroundColor = '#fff';
+ domStyle.backgroundColor = '#eee';
domStyle.padding = '0';
- domStyle.height = '80px';
+ domStyle.height = '60px';
domStyle.margin = '10px 20px';
var domWidth = getSize(dom, 0);
--
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