From 364720ba254540679f15d4b16d3f92bb03507579 Mon Sep 17 00:00:00 2001 From: sushuang Date: Wed, 18 Apr 2018 04:03:48 +0800 Subject: [PATCH] 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(-) create mode 100644 test/bar-large1.html diff --git a/src/chart/bar.js b/src/chart/bar.js index 787957231..21e7eee28 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 6f5d2f8dc..2c46956a1 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 7fd05b860..01ad89974 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 269deeb7e..46d18f57b 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 e4ebed56a..60530acae 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 4200c1cf4..511dcca48 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 d7c14e08a..a424ca6bf 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 eec6060db..784216d76 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 ba07b6dfb..f23c3fb00 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 = {}; @@ -197,22 +213,29 @@ function doCalBarWidthAndOffset(seriesInfoList, api) { 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 {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 000000000..a2114b839 --- /dev/null +++ b/test/bar-large1.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/test/candlestick-large2.html b/test/candlestick-large2.html index 9c4019b2d..e91528f0a 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 + '
', - // 'Open: ' + param.data[0] + '
', - // 'Close: ' + param.data[1] + '
', - // 'Lowest: ' + param.data[2] + '
', - // 'Highest: ' + param.data[3] + '
' - // ].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 + } + } ] }; -- GitLab