提交 364720ba 编写于 作者: S sushuang

Support large bar for some cases (to the data amount of 2e5).

上级 df46e28e
import * as echarts from '../echarts'; import * as echarts from '../echarts';
import * as zrUtil from 'zrender/src/core/util'; import * as zrUtil from 'zrender/src/core/util';
import { layout } from '../layout/barGrid'; import {layout, largeLayout} from '../layout/barGrid';
import '../coord/cartesian/Grid'; import '../coord/cartesian/Grid';
import './bar/BarSeries'; import './bar/BarSeries';
...@@ -10,11 +10,13 @@ import '../component/gridSimple'; ...@@ -10,11 +10,13 @@ import '../component/gridSimple';
echarts.registerLayout(zrUtil.curry(layout, 'bar')); 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({
echarts.registerVisual(function (ecModel) { seriesType: 'bar',
ecModel.eachSeriesByType('bar', function (seriesModel) { reset: function (seriesModel) {
var data = seriesModel.getData(); // Visual coding for legend
data.setVisual('legendSymbol', 'roundRect'); seriesModel.getData().setVisual('legendSymbol', 'roundRect');
}); }
}); });
...@@ -6,5 +6,29 @@ export default BaseBarSeries.extend({ ...@@ -6,5 +6,29 @@ export default BaseBarSeries.extend({
dependencies: ['grid', 'polar'], 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;
}
}); });
...@@ -5,7 +5,7 @@ import * as graphic from '../../util/graphic'; ...@@ -5,7 +5,7 @@ import * as graphic from '../../util/graphic';
import {setLabel} from './helper'; import {setLabel} from './helper';
import Model from '../../model/Model'; import Model from '../../model/Model';
import barItemStyle from './barItemStyle'; import barItemStyle from './barItemStyle';
import Path from 'zrender/src/graphic/Path';
var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth']; var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];
...@@ -18,12 +18,16 @@ export default echarts.extendChartView({ ...@@ -18,12 +18,16 @@ export default echarts.extendChartView({
type: 'bar', type: 'bar',
render: function (seriesModel, ecModel, api) { render: function (seriesModel, ecModel, api) {
this._updateDrawMode(seriesModel);
var coordinateSystemType = seriesModel.get('coordinateSystem'); var coordinateSystemType = seriesModel.get('coordinateSystem');
if (coordinateSystemType === 'cartesian2d' if (coordinateSystemType === 'cartesian2d'
|| coordinateSystemType === 'polar' || coordinateSystemType === 'polar'
) { ) {
this._render(seriesModel, ecModel, api); this._isLargeDraw
? this._renderLarge(seriesModel, ecModel, api)
: this._renderNormal(seriesModel, ecModel, api);
} }
else if (__DEV__) { else if (__DEV__) {
console.warn('Only cartesian2d and polar supported for bar.'); console.warn('Only cartesian2d and polar supported for bar.');
...@@ -32,9 +36,25 @@ export default echarts.extendChartView({ ...@@ -32,9 +36,25 @@ export default echarts.extendChartView({
return this.group; 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 group = this.group;
var data = seriesModel.getData(); var data = seriesModel.getData();
var oldData = this._data; var oldData = this._data;
...@@ -114,10 +134,25 @@ export default echarts.extendChartView({ ...@@ -114,10 +134,25 @@ export default echarts.extendChartView({
this._data = data; 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 group = this.group;
var data = this._data; var data = this._data;
if (ecModel.get('animation')) { if (ecModel && ecModel.get('animation')) {
if (data) { if (data) {
data.eachItemGraphicEl(function (el) { data.eachItemGraphicEl(function (el) {
if (el.type === 'sector') { if (el.type === 'sector') {
...@@ -132,7 +167,9 @@ export default echarts.extendChartView({ ...@@ -132,7 +167,9 @@ export default echarts.extendChartView({
else { else {
group.removeAll(); group.removeAll();
} }
this._data = null;
} }
}); });
var elementCreator = { var elementCreator = {
...@@ -282,3 +319,53 @@ function getLineWidth(itemModel, rawLayout) { ...@@ -282,3 +319,53 @@ function getLineWidth(itemModel, rawLayout) {
var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height)); 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');
}
...@@ -41,6 +41,11 @@ export default SeriesModel.extend({ ...@@ -41,6 +41,11 @@ export default SeriesModel.extend({
barMinAngle: 0, barMinAngle: 0,
// cursor: null, // cursor: null,
large: false,
largeThreshold: 400,
progressive: 5e3,
progressiveChunkMode: 'mod',
// barMaxWidth: null, // barMaxWidth: null,
// 默认自适应 // 默认自适应
// barWidth: null, // barWidth: null,
......
...@@ -103,11 +103,8 @@ var CandlestickView = ChartView.extend({ ...@@ -103,11 +103,8 @@ var CandlestickView = ChartView.extend({
}, },
_renderLarge: function (seriesModel) { _renderLarge: function (seriesModel) {
var group = this.group; this._clear();
createLarge(seriesModel, this.group);
group.removeAll();
createLarge(seriesModel, group);
}, },
_incrementalRenderNormal: function (params, seriesModel) { _incrementalRenderNormal: function (params, seriesModel) {
...@@ -264,15 +261,13 @@ function createLarge(seriesModel, group, incremental) { ...@@ -264,15 +261,13 @@ function createLarge(seriesModel, group, incremental) {
} }
function setLargeStyle(sign, el, seriesModel, data) { function setLargeStyle(sign, el, seriesModel, data) {
var normalItemStyleModel = seriesModel.getModel(NORMAL_ITEM_STYLE_PATH);
var suffix = sign > 0 ? 'P' : 'N'; var suffix = sign > 0 ? 'P' : 'N';
var borderColor = data.getVisual('borderColor' + suffix)
var color = data.getVisual('color' + suffix); || data.getVisual('color' + suffix);
var borderColor = data.getVisual('borderColor' + suffix) || color;
// Color must be excluded. // Color must be excluded.
// Because symbol provide setColor individually to set fill and stroke // 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.useStyle(itemStyle);
el.style.fill = null; el.style.fill = null;
......
...@@ -4,7 +4,11 @@ import OrdinalScale from '../scale/Ordinal'; ...@@ -4,7 +4,11 @@ import OrdinalScale from '../scale/Ordinal';
import IntervalScale from '../scale/Interval'; import IntervalScale from '../scale/Interval';
import Scale from '../scale/Scale'; import Scale from '../scale/Scale';
import * as numberUtil from '../util/number'; 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 BoundingRect from 'zrender/src/core/BoundingRect';
import '../scale/Time'; import '../scale/Time';
...@@ -120,26 +124,26 @@ export function getScaleExtent(scale, model) { ...@@ -120,26 +124,26 @@ export function getScaleExtent(scale, model) {
// is base axis // is base axis
// FIXME // FIXME
// (1) Consider support value axis, where below zero and axis `onZero` should be handled properly. // (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`? // Should not depend on series type `bar`?
// (3) Fix that might overlap when using dataZoom. // (3) Fix that might overlap when using dataZoom.
// (4) Consider other chart types using `barGrid`? // (4) Consider other chart types using `barGrid`?
// See #6728, #4862, `test/bar-overflow-time-plot.html` // See #6728, #4862, `test/bar-overflow-time-plot.html`
var ecModel = model.ecModel; var ecModel = model.ecModel;
if (ecModel && (scaleType === 'time' /*|| scaleType === 'interval' */)) { if (ecModel && (scaleType === 'time' /*|| scaleType === 'interval' */)) {
var barSeriesModels = []; var barSeriesModels = prepareLayoutBarSeries('bar', ecModel);
var isBaseAxisAndHasBarSeries; var isBaseAxisAndHasBarSeries;
ecModel.eachSeriesByType('bar', function (seriesModel) { zrUtil.each(barSeriesModels, function (seriesModel) {
if (seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d') {
barSeriesModels.push(seriesModel);
isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis; isBaseAxisAndHasBarSeries |= seriesModel.getBaseAxis() === model.axis;
}
}); });
if (isBaseAxisAndHasBarSeries) { if (isBaseAxisAndHasBarSeries) {
// Calculate placement of bars on axis
var barWidthAndOffset = makeColumnLayout(barSeriesModels);
// Adjust axis min and max to account for overflow // 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; min = adjustedScale.min;
max = adjustedScale.max; max = adjustedScale.max;
} }
...@@ -148,18 +152,14 @@ export function getScaleExtent(scale, model) { ...@@ -148,18 +152,14 @@ export function getScaleExtent(scale, model) {
return [min, max]; return [min, max];
} }
function adjustScaleForOverflow(min, max, model, barSeriesModels) { function adjustScaleForOverflow(min, max, model, barWidthAndOffset) {
// Get Axis Length // Get Axis Length
var axisExtent = model.axis.getExtent(); var axisExtent = model.axis.getExtent();
var axisLength = axisExtent[1] - axisExtent[0]; 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 // Get bars on current base axis and calculate min and max overflow
var baseAxisKey = model.axis.dim + model.axis.index; var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis);
var barsOnCurrentAxis = barWidthAndOffset[baseAxisKey];
if (barsOnCurrentAxis === undefined) { if (barsOnCurrentAxis === undefined) {
return {min: min, max: max}; return {min: min, max: max};
} }
......
...@@ -791,14 +791,17 @@ var updateMethods = { ...@@ -791,14 +791,17 @@ var updateMethods = {
scheduler.performDataProcessorTasks(ecModel, payload); scheduler.performDataProcessorTasks(ecModel, payload);
coordSysMgr.update(ecModel, api);
// Current stream render is not supported in data process. So we can update // 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 // stream modes after data processing, where the filtered data is used to
// deteming whether use progressive rendering. And we update stream modes // deteming whether use progressive rendering.
// after coordinate system updated, then full coord info can be fetched.
updateStreamModes(this, ecModel); 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); clearColorPalette(ecModel);
scheduler.performVisualTasks(ecModel, payload); scheduler.performVisualTasks(ecModel, payload);
......
import * as zrUtil from 'zrender/src/core/util'; import * as zrUtil from 'zrender/src/core/util';
import {parsePercent} from '../util/number'; import {parsePercent} from '../util/number';
import {isDimensionStacked} from '../data/helper/dataStackHelper'; import {isDimensionStacked} from '../data/helper/dataStackHelper';
import createRenderPlanner from '../chart/helper/createRenderPlanner';
var STACK_PREFIX = '__ec_stack_'; var STACK_PREFIX = '__ec_stack_';
var LARGE_BAR_MIN_WIDTH = 0.5;
var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array;
function getSeriesStackId(seriesModel) { function getSeriesStackId(seriesModel) {
return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex;
...@@ -22,7 +26,7 @@ function getAxisKey(axis) { ...@@ -22,7 +26,7 @@ function getAxisKey(axis) {
* @param {number} [opt.barCategoryGap] * @param {number} [opt.barCategoryGap]
* @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined. * @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 params = [];
var baseAxis = opt.axis; var baseAxis = opt.axis;
var axisKey = 'axis0'; var axisKey = 'axis0';
...@@ -39,7 +43,7 @@ export function getLayoutOnAxis(opt, api) { ...@@ -39,7 +43,7 @@ export function getLayoutOnAxis(opt, api) {
stackId: STACK_PREFIX + i stackId: STACK_PREFIX + i
}, opt)); }, opt));
} }
var widthAndOffsets = doCalBarWidthAndOffset(params, api); var widthAndOffsets = doCalBarWidthAndOffset(params);
var result = []; var result = [];
for (var i = 0; i < opt.count; i++) { for (var i = 0; i < opt.count; i++) {
...@@ -51,8 +55,20 @@ export function getLayoutOnAxis(opt, api) { ...@@ -51,8 +55,20 @@ export function getLayoutOnAxis(opt, api) {
return result; return result;
} }
export function calBarWidthAndOffset(barSeries, api) { export function prepareLayoutBarSeries(seriesType, ecModel) {
var seriesInfoList = zrUtil.map(barSeries, function (seriesModel) { 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 data = seriesModel.getData();
var cartesian = seriesModel.coordinateSystem; var cartesian = seriesModel.coordinateSystem;
var baseAxis = cartesian.getBaseAxis(); var baseAxis = cartesian.getBaseAxis();
...@@ -70,7 +86,7 @@ export function calBarWidthAndOffset(barSeries, api) { ...@@ -70,7 +86,7 @@ export function calBarWidthAndOffset(barSeries, api) {
var barGap = seriesModel.get('barGap'); var barGap = seriesModel.get('barGap');
var barCategoryGap = seriesModel.get('barCategoryGap'); var barCategoryGap = seriesModel.get('barCategoryGap');
return { seriesInfoList.push({
bandWidth: bandWidth, bandWidth: bandWidth,
barWidth: barWidth, barWidth: barWidth,
barMaxWidth: barMaxWidth, barMaxWidth: barMaxWidth,
...@@ -78,13 +94,13 @@ export function calBarWidthAndOffset(barSeries, api) { ...@@ -78,13 +94,13 @@ export function calBarWidthAndOffset(barSeries, api) {
barCategoryGap: barCategoryGap, barCategoryGap: barCategoryGap,
axisKey: getAxisKey(baseAxis), axisKey: getAxisKey(baseAxis),
stackId: getSeriesStackId(seriesModel) 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 // Columns info on each category axis. Key is cartesian name
var columnsMap = {}; var columnsMap = {};
...@@ -197,22 +213,29 @@ function doCalBarWidthAndOffset(seriesInfoList, api) { ...@@ -197,22 +213,29 @@ function doCalBarWidthAndOffset(seriesInfoList, api) {
return result; return result;
} }
/**
* @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 {string} seriesType
* @param {module:echarts/model/Global} ecModel * @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 lastStackCoords = {};
var lastStackCoordsOrigin = {}; var lastStackCoordsOrigin = {};
...@@ -244,12 +267,7 @@ export function layout(seriesType, ecModel, api) { ...@@ -244,12 +267,7 @@ export function layout(seriesType, ecModel, api) {
var stacked = isDimensionStacked(data, valueDim, baseDim); var stacked = isDimensionStacked(data, valueDim, baseDim);
var isValueAxisH = valueAxis.isHorizontal(); var isValueAxisH = valueAxis.isHorizontal();
var valueAxisStart = ( var valueAxisStart = getValueAxisStart(baseAxis, valueAxis, stacked);
zrUtil.indexOf(baseAxis.getAxesOnZeroOf(), valueAxis) >= 0
|| stacked
)
? valueAxis.toGlobalCoord(valueAxis.dataToCoord(0))
: valueAxis.getGlobalExtent()[0];
for (var idx = 0, len = data.count(); idx < len; idx++) { for (var idx = 0, len = data.count(); idx < len; idx++) {
var value = data.get(valueDim, idx); var value = data.get(valueDim, idx);
...@@ -318,4 +336,76 @@ export function layout(seriesType, ecModel, api) { ...@@ -318,4 +336,76 @@ export function layout(seriesType, ecModel, api) {
}, this); }, 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];
}
<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
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
// The data count is from a real requirement. // The data count is from a real requirement.
var rawDataCount = 2e5; var rawDataCount = 2e5;
// var rawDataCount = 2e2;
function run() { function run() {
var data = generateOHLC(rawDataCount); var data = generateOHLC(rawDataCount);
...@@ -47,16 +48,16 @@ ...@@ -47,16 +48,16 @@
var xValue = +new Date(2011, 0, 1); var xValue = +new Date(2011, 0, 1);
var minute = 60 * 1000; var minute = 60 * 1000;
var baseValue = Math.random() * 12000; var baseValue = Math.random() * 12000;
var tmpVals = new Array(4); var boxVals = new Array(4);
var dayRange = 12; var dayRange = 12;
for (var i = 0; i < count; i++) { for (var i = 0; i < count; i++) {
baseValue = baseValue + Math.random() * 20 - 10; baseValue = baseValue + Math.random() * 20 - 10;
for (var j = 0; j < 4; j++) { 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 idxRandom = Math.random();
var openIdx = Math.round(Math.random() * 3); var openIdx = Math.round(Math.random() * 3);
...@@ -64,15 +65,17 @@ ...@@ -64,15 +65,17 @@
if (closeIdx === openIdx) { if (closeIdx === openIdx) {
closeIdx++; closeIdx++;
} }
var volumn = boxVals[3] * (1000 + Math.random() * 500);
// ['open', 'close', 'lowest', 'highest'] // ['open', 'close', 'lowest', 'highest', 'volumn']
// [1, 4, 3, 2] // [1, 4, 3, 2]
data.push([ data.push([
echarts.format.formatTime('yyyy-MM-dd hh:mm:ss', xValue += minute), echarts.format.formatTime('yyyy-MM-dd hh:mm:ss', xValue += minute),
+tmpVals[openIdx].toFixed(2), // open +boxVals[openIdx].toFixed(2), // open
+tmpVals[3].toFixed(2), // highest +boxVals[3].toFixed(2), // highest
+tmpVals[0].toFixed(2), // lowest +boxVals[0].toFixed(2), // lowest
+tmpVals[closeIdx].toFixed(2) // close +boxVals[closeIdx].toFixed(2), // close
volumn.toFixed(0)
]); ]);
} }
...@@ -99,6 +102,11 @@ ...@@ -99,6 +102,11 @@
frameInsight.init(echarts, 'duration'); frameInsight.init(echarts, 'duration');
var upColor = '#ec0000';
var upBorderColor = '#8A0000';
var downColor = '#00da3c';
var downBorderColor = '#008F28';
var option = { var option = {
dataset: { dataset: {
source: rawData source: rawData
...@@ -137,12 +145,12 @@ ...@@ -137,12 +145,12 @@
right: '10%', right: '10%',
height: 300 height: 300
}, },
// { {
// left: '10%', left: '10%',
// right: '10%', right: '10%',
// height: 70, height: 70,
// bottom: 80 bottom: 80
// } }
], ],
xAxis: [ xAxis: [
{ {
...@@ -156,20 +164,19 @@ ...@@ -156,20 +164,19 @@
min: 'dataMin', min: 'dataMin',
max: 'dataMax' max: 'dataMax'
}, },
// { {
// type: 'category', type: 'category',
// gridIndex: 1, gridIndex: 1,
// data: data.categoryData, scale: true,
// scale: true, boundaryGap : false,
// boundaryGap : false, axisLine: {onZero: false},
// axisLine: {onZero: false}, axisTick: {show: false},
// axisTick: {show: false}, splitLine: {show: false},
// splitLine: {show: false}, axisLabel: {show: false},
// axisLabel: {show: false}, splitNumber: 20,
// splitNumber: 20, min: 'dataMin',
// min: 'dataMin', max: 'dataMax'
// max: 'dataMax' }
// }
], ],
yAxis: [ yAxis: [
{ {
...@@ -178,26 +185,26 @@ ...@@ -178,26 +185,26 @@
show: true show: true
} }
}, },
// { {
// scale: true, scale: true,
// gridIndex: 1, gridIndex: 1,
// splitNumber: 2, splitNumber: 2,
// axisLabel: {show: false}, axisLabel: {show: false},
// axisLine: {show: false}, axisLine: {show: false},
// axisTick: {show: false}, axisTick: {show: false},
// splitLine: {show: false} splitLine: {show: false}
// } }
], ],
dataZoom: [ dataZoom: [
{ {
type: 'inside', type: 'inside',
// xAxisIndex: [0, 1], xAxisIndex: [0, 1],
start: 10, start: 10,
end: 100 end: 100
}, },
{ {
show: true, show: true,
// xAxisIndex: [0, 1], xAxisIndex: [0, 1],
type: 'slider', type: 'slider',
bottom: 10, bottom: 10,
start: 10, start: 10,
...@@ -210,25 +217,19 @@ ...@@ -210,25 +217,19 @@
type: 'candlestick', type: 'candlestick',
// progressiveMode: 'linear', // progressiveMode: 'linear',
// data: data, // data: data,
itemStyle: {
color: upColor,
color0: downColor,
borderColor: upBorderColor,
borderColor0: downBorderColor
},
encode: { encode: {
x: 0, x: 0,
y: [1, 4, 3, 2] y: [1, 4, 3, 2]
}, },
// progressive: false // progressive: false
// progressive: progressive // 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', // name: 'MA5',
// type: 'line', // type: 'line',
...@@ -265,13 +266,17 @@ ...@@ -265,13 +266,17 @@
// normal: {opacity: 0.5} // normal: {opacity: 0.5}
// } // }
// }, // },
// { {
// name: 'Volumn', name: 'Volumn',
// type: 'bar', type: 'bar',
// xAxisIndex: 1, xAxisIndex: 1,
// yAxisIndex: 1, yAxisIndex: 1,
// data: data.volumns large: true,
// } encode: {
x: 0,
y: 5
}
}
] ]
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册