提交 ca83c55b 编写于 作者: 1 100pah

Merge branch 'master' into fix/geo-svg

...@@ -36,13 +36,13 @@ jobs: ...@@ -36,13 +36,13 @@ jobs:
run: | run: |
npm run release npm run release
test: # test:
runs-on: ubuntu-latest # runs-on: ubuntu-latest
needs: build # needs: build
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/release' # # if: ${{ github.base_ref == 'refs/heads/master' || github.base_ref == 'refs/heads/release' }}
steps: # steps:
- name: unit test # - name: unit test
run: | # run: |
npm run test # npm run test
...@@ -71,6 +71,7 @@ export interface EffectScatterSeriesOption extends SeriesOption<EffectScatterSta ...@@ -71,6 +71,7 @@ export interface EffectScatterSeriesOption extends SeriesOption<EffectScatterSta
* When to show the effect * When to show the effect
*/ */
showEffectOn?: 'render' | 'emphasis' showEffectOn?: 'render' | 'emphasis'
clip?: boolean
/** /**
* Ripple effect config * Ripple effect config
...@@ -107,6 +108,7 @@ class EffectScatterSeriesModel extends SeriesModel<EffectScatterSeriesOption> { ...@@ -107,6 +108,7 @@ class EffectScatterSeriesModel extends SeriesModel<EffectScatterSeriesOption> {
// When to show the effect, option: 'render'|'emphasis' // When to show the effect, option: 'render'|'emphasis'
showEffectOn: 'render', showEffectOn: 'render',
clip: true,
// Ripple effect config // Ripple effect config
rippleEffect: { rippleEffect: {
......
...@@ -41,10 +41,16 @@ class EffectScatterView extends ChartView { ...@@ -41,10 +41,16 @@ class EffectScatterView extends ChartView {
render(seriesModel: EffectScatterSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { render(seriesModel: EffectScatterSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
const data = seriesModel.getData(); const data = seriesModel.getData();
const effectSymbolDraw = this._symbolDraw; const effectSymbolDraw = this._symbolDraw;
effectSymbolDraw.updateData(data); effectSymbolDraw.updateData(data, {clipShape: this._getClipShape(seriesModel)});
this.group.add(effectSymbolDraw.group); this.group.add(effectSymbolDraw.group);
} }
_getClipShape(seriesModel: EffectScatterSeriesModel) {
const coordSys = seriesModel.coordinateSystem;
const clipArea = coordSys && coordSys.getArea && coordSys.getArea();
return seriesModel.get('clip', true) ? clipArea : null;
}
updateTransform(seriesModel: EffectScatterSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { updateTransform(seriesModel: EffectScatterSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
const data = seriesModel.getData(); const data = seriesModel.getData();
......
...@@ -30,6 +30,10 @@ import { ColorString, ECElement } from '../../util/types'; ...@@ -30,6 +30,10 @@ import { ColorString, ECElement } from '../../util/types';
import List from '../../data/List'; import List from '../../data/List';
import Sausage from '../../util/shape/sausage'; import Sausage from '../../util/shape/sausage';
import {createSymbol} from '../../util/symbol'; import {createSymbol} from '../../util/symbol';
import ZRImage from 'zrender/src/graphic/Image';
import {extend} from 'zrender/src/core/util';
type ECSymbol = ReturnType<typeof createSymbol>;
interface PosInfo { interface PosInfo {
cx: number cx: number
...@@ -476,9 +480,25 @@ class GaugeView extends ChartView { ...@@ -476,9 +480,25 @@ class GaugeView extends ChartView {
const itemModel = data.getItemModel<GaugeDataItemOption>(idx); const itemModel = data.getItemModel<GaugeDataItemOption>(idx);
const emphasisModel = itemModel.getModel('emphasis'); const emphasisModel = itemModel.getModel('emphasis');
if (showPointer) { if (showPointer) {
const pointer = data.getItemGraphicEl(idx) as PointerPath; const pointer = data.getItemGraphicEl(idx) as ECSymbol;
pointer.useStyle(data.getItemVisual(idx, 'style')); const symbolStyle = data.getItemVisual(idx, 'style');
const visualColor = symbolStyle.fill;
if (pointer instanceof ZRImage) {
const pathStyle = pointer.style;
pointer.useStyle(extend({
image: pathStyle.image,
x: pathStyle.x, y: pathStyle.y,
width: pathStyle.width, height: pathStyle.height
}, symbolStyle));
}
else {
pointer.useStyle(symbolStyle);
pointer.type !== 'pointer' && pointer.setColor(visualColor);
}
pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle()); pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle());
if (pointer.style.fill === 'auto') { if (pointer.style.fill === 'auto') {
pointer.setStyle('fill', getColor( pointer.setStyle('fill', getColor(
linearMap(data.get(valueDim, idx) as number, valueExtent, [0, 1], true) linearMap(data.get(valueDim, idx) as number, valueExtent, [0, 1], true)
......
...@@ -110,7 +110,8 @@ class EffectSymbol extends Group { ...@@ -110,7 +110,8 @@ class EffectSymbol extends Group {
// TODO Configurable effectCfg.period // TODO Configurable effectCfg.period
ripplePath.animate('', true) ripplePath.animate('', true)
.when(effectCfg.period, { .when(effectCfg.period, {
scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2] scaleX: effectCfg.rippleScale / 2,
scaleY: effectCfg.rippleScale / 2
}) })
.delay(delay) .delay(delay)
.start(); .start();
...@@ -184,11 +185,15 @@ class EffectSymbol extends Group { ...@@ -184,11 +185,15 @@ class EffectSymbol extends Group {
ripplePath.setStyle('fill', color); ripplePath.setStyle('fill', color);
}); });
const symbolOffset = itemModel.getShallow('symbolOffset'); let symbolOffset = data.getItemVisual(idx, 'symbolOffset');
if (symbolOffset) { if (symbolOffset) {
if (!zrUtil.isArray(symbolOffset)) {
symbolOffset = [symbolOffset, symbolOffset];
}
rippleGroup.x = parsePercent(symbolOffset[0], symbolSize[0]); rippleGroup.x = parsePercent(symbolOffset[0], symbolSize[0]);
rippleGroup.y = parsePercent(symbolOffset[1], symbolSize[1]); rippleGroup.y = parsePercent(zrUtil.retrieve2(symbolOffset[1], symbolOffset[0]) || 0, symbolSize[1]);
} }
const symbolRotate = data.getItemVisual(idx, 'symbolRotate'); const symbolRotate = data.getItemVisual(idx, 'symbolRotate');
rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0;
...@@ -247,4 +252,4 @@ class EffectSymbol extends Group { ...@@ -247,4 +252,4 @@ class EffectSymbol extends Group {
} }
zrUtil.inherits(EffectSymbol, Group); zrUtil.inherits(EffectSymbol, Group);
export default EffectSymbol; export default EffectSymbol;
\ No newline at end of file
...@@ -17,14 +17,14 @@ ...@@ -17,14 +17,14 @@
* under the License. * under the License.
*/ */
import * as zrUtil from 'zrender/src/core/util'; import { isArray, each, retrieve2 } from 'zrender/src/core/util';
import * as vector from 'zrender/src/core/vector'; import * as vector from 'zrender/src/core/vector';
import * as symbolUtil from '../../util/symbol'; import * as symbolUtil from '../../util/symbol';
import ECLinePath from './LinePath'; import ECLinePath from './LinePath';
import * as graphic from '../../util/graphic'; import * as graphic from '../../util/graphic';
import { enableHoverEmphasis, enterEmphasis, leaveEmphasis, SPECIAL_STATES } from '../../util/states'; import { enableHoverEmphasis, enterEmphasis, leaveEmphasis, SPECIAL_STATES } from '../../util/states';
import {getLabelStatesModels, setLabelStyle} from '../../label/labelStyle'; import {getLabelStatesModels, setLabelStyle} from '../../label/labelStyle';
import {round} from '../../util/number'; import {round, parsePercent} from '../../util/number';
import List from '../../data/List'; import List from '../../data/List';
import { ZRTextAlign, ZRTextVerticalAlign, LineLabelOption, ColorString } from '../../util/types'; import { ZRTextAlign, ZRTextVerticalAlign, LineLabelOption, ColorString } from '../../util/types';
import SeriesModel from '../../model/Series'; import SeriesModel from '../../model/Series';
...@@ -70,12 +70,27 @@ function createSymbol(name: 'fromSymbol' | 'toSymbol', lineData: LineList, idx: ...@@ -70,12 +70,27 @@ function createSymbol(name: 'fromSymbol' | 'toSymbol', lineData: LineList, idx:
const symbolSize = lineData.getItemVisual(idx, name + 'Size' as 'fromSymbolSize' | 'toSymbolSize'); const symbolSize = lineData.getItemVisual(idx, name + 'Size' as 'fromSymbolSize' | 'toSymbolSize');
const symbolRotate = lineData.getItemVisual(idx, name + 'Rotate' as 'fromSymbolRotate' | 'toSymbolRotate'); const symbolRotate = lineData.getItemVisual(idx, name + 'Rotate' as 'fromSymbolRotate' | 'toSymbolRotate');
const symbolOffset = lineData.getItemVisual(idx, name + 'Offset' as 'fromSymbolOffset' | 'toSymbolOffset') || 0;
const symbolKeepAspect = lineData.getItemVisual(idx,
name + 'KeepAspect' as 'fromSymbolKeepAspect' | 'toSymbolKeepAspect');
const symbolSizeArr = zrUtil.isArray(symbolSize) const symbolSizeArr = isArray(symbolSize)
? symbolSize : [symbolSize, symbolSize]; ? symbolSize : [symbolSize, symbolSize];
const symbolOffsetArr = isArray(symbolOffset)
? symbolOffset : [symbolOffset, symbolOffset];
symbolOffsetArr[0] = parsePercent(symbolOffsetArr[0], symbolSizeArr[0]);
symbolOffsetArr[1] = parsePercent(retrieve2(symbolOffsetArr[1], symbolOffsetArr[0]),symbolSizeArr[1]);
const symbolPath = symbolUtil.createSymbol( const symbolPath = symbolUtil.createSymbol(
symbolType, -symbolSizeArr[0] / 2, -symbolSizeArr[1] / 2, symbolType,
symbolSizeArr[0], symbolSizeArr[1] -symbolSizeArr[0] / 2 + (symbolOffsetArr as number[])[0],
-symbolSizeArr[1] / 2 + (symbolOffsetArr as number[])[1],
symbolSizeArr[0],
symbolSizeArr[1],
null,
symbolKeepAspect
); );
(symbolPath as LineECSymbol).__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) (symbolPath as LineECSymbol).__specifiedRotation = symbolRotate == null || isNaN(symbolRotate)
...@@ -142,7 +157,7 @@ class Line extends graphic.Group { ...@@ -142,7 +157,7 @@ class Line extends graphic.Group {
this.add(line); this.add(line);
zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { each(SYMBOL_CATEGORIES, function (symbolCategory) {
const symbol = createSymbol(symbolCategory, lineData, idx); const symbol = createSymbol(symbolCategory, lineData, idx);
// symbols must added after line to make sure // symbols must added after line to make sure
// it will be updated after line#update. // it will be updated after line#update.
...@@ -167,7 +182,7 @@ class Line extends graphic.Group { ...@@ -167,7 +182,7 @@ class Line extends graphic.Group {
setLinePoints(target.shape, linePoints); setLinePoints(target.shape, linePoints);
graphic.updateProps(line, target, seriesModel, idx); graphic.updateProps(line, target, seriesModel, idx);
zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { each(SYMBOL_CATEGORIES, function (symbolCategory) {
const symbolType = (lineData as LineList).getItemVisual(idx, symbolCategory); const symbolType = (lineData as LineList).getItemVisual(idx, symbolCategory);
const key = makeSymbolTypeKey(symbolCategory); const key = makeSymbolTypeKey(symbolCategory);
// Symbol changed // Symbol changed
...@@ -220,7 +235,7 @@ class Line extends graphic.Group { ...@@ -220,7 +235,7 @@ class Line extends graphic.Group {
line.ensureState('select').style = selectLineStyle; line.ensureState('select').style = selectLineStyle;
// Update symbol // Update symbol
zrUtil.each(SYMBOL_CATEGORIES, function (symbolCategory) { each(SYMBOL_CATEGORIES, function (symbolCategory) {
const symbol = this.childOfName(symbolCategory) as ECSymbol; const symbol = this.childOfName(symbolCategory) as ECSymbol;
if (symbol) { if (symbol) {
// Share opacity and color with line. // Share opacity and color with line.
...@@ -275,7 +290,7 @@ class Line extends graphic.Group { ...@@ -275,7 +290,7 @@ class Line extends graphic.Group {
label.__position = labelNormalModel.get('position') || 'middle'; label.__position = labelNormalModel.get('position') || 'middle';
let distance = labelNormalModel.get('distance'); let distance = labelNormalModel.get('distance');
if (!zrUtil.isArray(distance)) { if (!isArray(distance)) {
distance = [distance, distance]; distance = [distance, distance];
} }
label.__labelDistance = distance; label.__labelDistance = distance;
......
...@@ -28,7 +28,7 @@ import { ColorString, BlurScope, AnimationOption } from '../../util/types'; ...@@ -28,7 +28,7 @@ import { ColorString, BlurScope, AnimationOption } from '../../util/types';
import SeriesModel from '../../model/Series'; import SeriesModel from '../../model/Series';
import { PathProps } from 'zrender/src/graphic/Path'; import { PathProps } from 'zrender/src/graphic/Path';
import { SymbolDrawSeriesScope, SymbolDrawItemModelOption } from './SymbolDraw'; import { SymbolDrawSeriesScope, SymbolDrawItemModelOption } from './SymbolDraw';
import { extend } from 'zrender/src/core/util'; import { extend, isArray, retrieve2 } from 'zrender/src/core/util';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle'; import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
import ZRImage from 'zrender/src/graphic/Image'; import ZRImage from 'zrender/src/graphic/Image';
...@@ -216,8 +216,6 @@ class Symbol extends graphic.Group { ...@@ -216,8 +216,6 @@ class Symbol extends graphic.Group {
let focus; let focus;
let blurScope: BlurScope; let blurScope: BlurScope;
let symbolOffset;
let labelStatesModels; let labelStatesModels;
let hoverScale; let hoverScale;
...@@ -230,8 +228,6 @@ class Symbol extends graphic.Group { ...@@ -230,8 +228,6 @@ class Symbol extends graphic.Group {
focus = seriesScope.focus; focus = seriesScope.focus;
blurScope = seriesScope.blurScope; blurScope = seriesScope.blurScope;
symbolOffset = seriesScope.symbolOffset;
labelStatesModels = seriesScope.labelStatesModels; labelStatesModels = seriesScope.labelStatesModels;
hoverScale = seriesScope.hoverScale; hoverScale = seriesScope.hoverScale;
...@@ -250,8 +246,6 @@ class Symbol extends graphic.Group { ...@@ -250,8 +246,6 @@ class Symbol extends graphic.Group {
focus = emphasisModel.get('focus'); focus = emphasisModel.get('focus');
blurScope = emphasisModel.get('blurScope'); blurScope = emphasisModel.get('blurScope');
symbolOffset = itemModel.getShallow('symbolOffset');
labelStatesModels = getLabelStatesModels(itemModel); labelStatesModels = getLabelStatesModels(itemModel);
hoverScale = emphasisModel.getShallow('scale'); hoverScale = emphasisModel.getShallow('scale');
...@@ -259,12 +253,15 @@ class Symbol extends graphic.Group { ...@@ -259,12 +253,15 @@ class Symbol extends graphic.Group {
} }
const symbolRotate = data.getItemVisual(idx, 'symbolRotate'); const symbolRotate = data.getItemVisual(idx, 'symbolRotate');
symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0);
let symbolOffset = data.getItemVisual(idx, 'symbolOffset') || 0;
if (symbolOffset) { if (symbolOffset) {
if (!isArray(symbolOffset)) {
symbolOffset = [symbolOffset, symbolOffset];
}
symbolPath.x = parsePercent(symbolOffset[0], symbolSize[0]); symbolPath.x = parsePercent(symbolOffset[0], symbolSize[0]);
symbolPath.y = parsePercent(symbolOffset[1], symbolSize[1]); symbolPath.y = parsePercent(retrieve2(symbolOffset[1], symbolOffset[0]) || 0, symbolSize[1]);
} }
cursorStyle && symbolPath.attr('cursor', cursorStyle); cursorStyle && symbolPath.attr('cursor', cursorStyle);
...@@ -398,7 +395,7 @@ class Symbol extends graphic.Group { ...@@ -398,7 +395,7 @@ class Symbol extends graphic.Group {
static getSymbolSize(data: List, idx: number) { static getSymbolSize(data: List, idx: number) {
const symbolSize = data.getItemVisual(idx, 'symbolSize'); const symbolSize = data.getItemVisual(idx, 'symbolSize');
return symbolSize instanceof Array return isArray(symbolSize)
? symbolSize.slice() ? symbolSize.slice()
: [+symbolSize, +symbolSize]; : [+symbolSize, +symbolSize];
} }
......
...@@ -115,9 +115,6 @@ export interface SymbolDrawSeriesScope { ...@@ -115,9 +115,6 @@ export interface SymbolDrawSeriesScope {
focus?: DefaultEmphasisFocus focus?: DefaultEmphasisFocus
blurScope?: BlurScope blurScope?: BlurScope
symbolRotate?: ScatterSeriesOption['symbolRotate']
symbolOffset?: (number | string)[]
labelStatesModels: Record<DisplayState, Model<LabelOption>> labelStatesModels: Record<DisplayState, Model<LabelOption>>
itemModel?: Model<SymbolDrawItemModelOption> itemModel?: Model<SymbolDrawItemModelOption>
...@@ -139,8 +136,6 @@ function makeSeriesScope(data: List): SymbolDrawSeriesScope { ...@@ -139,8 +136,6 @@ function makeSeriesScope(data: List): SymbolDrawSeriesScope {
focus: emphasisModel.get('focus'), focus: emphasisModel.get('focus'),
blurScope: emphasisModel.get('blurScope'), blurScope: emphasisModel.get('blurScope'),
symbolRotate: seriesModel.get('symbolRotate'),
symbolOffset: seriesModel.get('symbolOffset'),
hoverScale: emphasisModel.get('scale'), hoverScale: emphasisModel.get('scale'),
labelStatesModels: getLabelStatesModels(seriesModel), labelStatesModels: getLabelStatesModels(seriesModel),
......
...@@ -738,7 +738,7 @@ class LineView extends ChartView { ...@@ -738,7 +738,7 @@ class LineView extends ChartView {
if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') { if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') {
const emphasisLineStyle = polyline.getState('emphasis').style; const emphasisLineStyle = polyline.getState('emphasis').style;
emphasisLineStyle.lineWidth = polyline.style.lineWidth + 1; emphasisLineStyle.lineWidth = +polyline.style.lineWidth + 1;
} }
// Needs seriesIndex for focus // Needs seriesIndex for focus
......
...@@ -132,30 +132,7 @@ export default function lineAnimationDiff( ...@@ -132,30 +132,7 @@ export default function lineAnimationDiff(
rawIndices.push(newData.getRawIndex(newIdx)); rawIndices.push(newData.getRawIndex(newIdx));
break; break;
case '-': case '-':
const oldIdx = diffItem.idx; pointAdded = false;
const rawIndex = oldData.getRawIndex(oldIdx);
const oldDataDimsForPoint = oldDataNewCoordInfo.dataDimsForPoint;
oldIdx2 = oldIdx * 2;
// Data is replaced. In the case of dynamic data queue
// FIXME FIXME FIXME
if (rawIndex !== oldIdx) {
const newPt = newCoordSys.dataToPoint([
oldData.get(oldDataDimsForPoint[0], oldIdx),
oldData.get(oldDataDimsForPoint[1], oldIdx)
]);
const newStackedOnPt = getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, oldIdx);
currPoints.push(oldPoints[oldIdx2], oldPoints[oldIdx2 + 1]);
nextPoints.push(newPt[0], newPt[1]);
currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]);
nextStackedPoints.push(newStackedOnPt[0], newStackedOnPt[1]);
rawIndices.push(rawIndex);
}
else {
pointAdded = false;
}
} }
// Original indices // Original indices
...@@ -205,4 +182,4 @@ export default function lineAnimationDiff( ...@@ -205,4 +182,4 @@ export default function lineAnimationDiff(
status: sortedStatus status: sortedStatus
}; };
} }
\ No newline at end of file
...@@ -518,7 +518,7 @@ class CalendarView extends ComponentView { ...@@ -518,7 +518,7 @@ class CalendarView extends ComponentView {
).time; ).time;
const cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()]; const cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]); margin = numberUtil.parsePercent(margin, Math.min(cellSize[1], cellSize[0]));
if (pos === 'start') { if (pos === 'start') {
start = coordSys.getNextNDay( start = coordSys.getNextNDay(
......
...@@ -60,6 +60,8 @@ export interface MarkLine1DDataItemOption extends MarkLineDataItemOptionBase { ...@@ -60,6 +60,8 @@ export interface MarkLine1DDataItemOption extends MarkLineDataItemOptionBase {
*/ */
symbol?: string[] | string symbol?: string[] | string
symbolSize?: number[] | number symbolSize?: number[] | number
symbolRotate?: number[] | number
symbolOffset: number | string | (number | string)[]
} }
// 2D markLine on any direction // 2D markLine on any direction
...@@ -82,6 +84,8 @@ export interface MarkLineOption extends MarkerOption, ...@@ -82,6 +84,8 @@ export interface MarkLineOption extends MarkerOption,
symbol?: string[] | string symbol?: string[] | string
symbolSize?: number[] | number symbolSize?: number[] | number
symbolRotate?: number[] | number
symbolOffset?: number | string | (number | string)[]
/** /**
* Precision used on statistic method * Precision used on statistic method
...@@ -112,6 +116,7 @@ class MarkLineModel extends MarkerModel<MarkLineOption> { ...@@ -112,6 +116,7 @@ class MarkLineModel extends MarkerModel<MarkLineOption> {
symbolSize: [8, 16], symbolSize: [8, 16],
//symbolRotate: 0, //symbolRotate: 0,
symbolOffset: 0,
precision: 2, precision: 2,
tooltip: { tooltip: {
...@@ -137,4 +142,4 @@ class MarkLineModel extends MarkerModel<MarkLineOption> { ...@@ -137,4 +142,4 @@ class MarkLineModel extends MarkerModel<MarkLineOption> {
}; };
} }
export default MarkLineModel; export default MarkLineModel;
\ No newline at end of file
...@@ -35,6 +35,7 @@ import MarkerModel from './MarkerModel'; ...@@ -35,6 +35,7 @@ import MarkerModel from './MarkerModel';
import { import {
isArray, isArray,
retrieve, retrieve,
retrieve2,
clone, clone,
extend, extend,
logError, logError,
...@@ -319,12 +320,20 @@ class MarkLineView extends MarkerView { ...@@ -319,12 +320,20 @@ class MarkLineView extends MarkerView {
let symbolType = mlModel.get('symbol'); let symbolType = mlModel.get('symbol');
let symbolSize = mlModel.get('symbolSize'); let symbolSize = mlModel.get('symbolSize');
let symbolRotate = mlModel.get('symbolRotate');
let symbolOffset = mlModel.get('symbolOffset');
if (!isArray(symbolType)) { if (!isArray(symbolType)) {
symbolType = [symbolType, symbolType]; symbolType = [symbolType, symbolType];
} }
if (!isArray(symbolSize)) { if (!isArray(symbolSize)) {
symbolSize = [symbolSize, symbolSize]; symbolSize = [symbolSize, symbolSize];
} }
if (!isArray(symbolRotate)) {
symbolRotate = [symbolRotate, symbolRotate];
}
if (!isArray(symbolOffset)) {
symbolOffset = [symbolOffset, symbolOffset];
}
// Update visual and layout of from symbol and to symbol // Update visual and layout of from symbol and to symbol
mlData.from.each(function (idx) { mlData.from.each(function (idx) {
...@@ -349,9 +358,13 @@ class MarkLineView extends MarkerView { ...@@ -349,9 +358,13 @@ class MarkLineView extends MarkerView {
} }
lineData.setItemVisual(idx, { lineData.setItemVisual(idx, {
fromSymbolKeepAspect: fromData.getItemVisual(idx, 'symbolKeepAspect'),
fromSymbolOffset: fromData.getItemVisual(idx, 'symbolOffset'),
fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'), fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'),
fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize') as number, fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize') as number,
fromSymbol: fromData.getItemVisual(idx, 'symbol'), fromSymbol: fromData.getItemVisual(idx, 'symbol'),
toSymbolKeepAspect: toData.getItemVisual(idx, 'symbolKeepAspect'),
toSymbolOffset: toData.getItemVisual(idx, 'symbolOffset'),
toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'), toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'),
toSymbolSize: toData.getItemVisual(idx, 'symbolSize') as number, toSymbolSize: toData.getItemVisual(idx, 'symbolSize') as number,
toSymbol: toData.getItemVisual(idx, 'symbol'), toSymbol: toData.getItemVisual(idx, 'symbol'),
...@@ -386,9 +399,12 @@ class MarkLineView extends MarkerView { ...@@ -386,9 +399,12 @@ class MarkLineView extends MarkerView {
} }
data.setItemVisual(idx, { data.setItemVisual(idx, {
symbolRotate: itemModel.get('symbolRotate'), symbolKeepAspect: itemModel.get('symbolKeepAspect'),
symbolSize: itemModel.get('symbolSize') || (symbolSize as number[])[isFrom ? 0 : 1], // `0` should be considered as a valid value, so use `retrieve2` instead of `||`
symbol: itemModel.get('symbol', true) || (symbolType as string[])[isFrom ? 0 : 1], symbolOffset: retrieve2(itemModel.get('symbolOffset'), (symbolOffset as (string | number)[])[isFrom ? 0 : 1]),
symbolRotate: retrieve2(itemModel.get('symbolRotate', true), (symbolRotate as number[])[isFrom ? 0 : 1]),
symbolSize: retrieve2(itemModel.get('symbolSize'), (symbolSize as number[])[isFrom ? 0 : 1]),
symbol: retrieve2(itemModel.get('symbol', true), (symbolType as string[])[isFrom ? 0 : 1]),
style style
}); });
} }
...@@ -462,4 +478,4 @@ function createList(coordSys: CoordinateSystem, seriesModel: SeriesModel, mlMode ...@@ -462,4 +478,4 @@ function createList(coordSys: CoordinateSystem, seriesModel: SeriesModel, mlMode
}; };
} }
export default MarkLineView; export default MarkLineView;
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { isArray } from 'zrender/src/core/util';
import { SeriesOption } from '../../util/types';
type MarkerTypes = 'markPoint' | 'markLine' | 'markArea';
type SeriesWithMarkerOption = SeriesOption & Partial<Record<MarkerTypes, unknown>>;
export default function checkMarkerInSeries(
seriesOpts: SeriesOption | SeriesOption[], markerType: MarkerTypes
): boolean {
if (!seriesOpts) {
return false;
}
const seriesOptArr = isArray(seriesOpts) ? seriesOpts : [seriesOpts];
for (let idx = 0; idx < seriesOptArr.length; idx++) {
if (seriesOptArr[idx] && (seriesOptArr[idx] as SeriesWithMarkerOption)[markerType]) {
return true;
}
}
return false;
}
\ No newline at end of file
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
import { EChartsExtensionInstallRegisters } from '../../extension'; import { EChartsExtensionInstallRegisters } from '../../extension';
import checkMarkerInSeries from './checkMarkerInSeries';
import MarkAreaModel from './MarkAreaModel'; import MarkAreaModel from './MarkAreaModel';
import MarkAreaView from './MarkAreaView'; import MarkAreaView from './MarkAreaView';
...@@ -26,7 +27,9 @@ export function install(registers: EChartsExtensionInstallRegisters) { ...@@ -26,7 +27,9 @@ export function install(registers: EChartsExtensionInstallRegisters) {
registers.registerComponentView(MarkAreaView); registers.registerComponentView(MarkAreaView);
registers.registerPreprocessor(function (opt) { registers.registerPreprocessor(function (opt) {
// Make sure markArea component is enabled if (checkMarkerInSeries(opt.series, 'markArea')) {
opt.markArea = opt.markArea || {}; // Make sure markArea component is enabled
opt.markArea = opt.markArea || {};
}
}); });
} }
\ No newline at end of file
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* under the License. * under the License.
*/ */
import { EChartsExtensionInstallRegisters } from '../../extension'; import { EChartsExtensionInstallRegisters } from '../../extension';
import checkMarkerInSeries from './checkMarkerInSeries';
import MarkLineModel from './MarkLineModel'; import MarkLineModel from './MarkLineModel';
import MarkLineView from './MarkLineView'; import MarkLineView from './MarkLineView';
...@@ -25,7 +26,9 @@ export function install(registers: EChartsExtensionInstallRegisters) { ...@@ -25,7 +26,9 @@ export function install(registers: EChartsExtensionInstallRegisters) {
registers.registerComponentView(MarkLineView); registers.registerComponentView(MarkLineView);
registers.registerPreprocessor(function (opt) { registers.registerPreprocessor(function (opt) {
// Make sure markLine component is enabled if (checkMarkerInSeries(opt.series, 'markLine')) {
opt.markLine = opt.markLine || {}; // Make sure markLine component is enabled
opt.markLine = opt.markLine || {};
}
}); });
} }
\ No newline at end of file
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* under the License. * under the License.
*/ */
import { EChartsExtensionInstallRegisters } from '../../extension'; import { EChartsExtensionInstallRegisters } from '../../extension';
import checkMarkerInSeries from './checkMarkerInSeries';
import MarkPointModel from './MarkPointModel'; import MarkPointModel from './MarkPointModel';
import MarkPointView from './MarkPointView'; import MarkPointView from './MarkPointView';
...@@ -25,7 +26,9 @@ export function install(registers: EChartsExtensionInstallRegisters) { ...@@ -25,7 +26,9 @@ export function install(registers: EChartsExtensionInstallRegisters) {
registers.registerComponentView(MarkPointView); registers.registerComponentView(MarkPointView);
registers.registerPreprocessor(function (opt) { registers.registerPreprocessor(function (opt) {
// Make sure markPoint component is enabled if (checkMarkerInSeries(opt.series, 'markPoint')) {
opt.markPoint = opt.markPoint || {}; // Make sure markPoint component is enabled
opt.markPoint = opt.markPoint || {};
}
}); });
} }
\ No newline at end of file
...@@ -550,15 +550,16 @@ class SliderTimelineView extends TimelineView { ...@@ -550,15 +550,16 @@ class SliderTimelineView extends TimelineView {
controlSize controlSize
); );
const rect = [0, -iconSize / 2, iconSize, iconSize]; const rect = [0, -iconSize / 2, iconSize, iconSize];
const opt = { const btn = makeControlIcon(timelineModel, iconName + 'Icon' as ControlIconName, rect, {
position: position, x: position[0],
origin: [controlSize / 2, 0], y: position[1],
originX: controlSize / 2,
originY: 0,
rotation: willRotate ? -rotation : 0, rotation: willRotate ? -rotation : 0,
rectHover: true, rectHover: true,
style: itemStyle, style: itemStyle,
onclick: onclick onclick: onclick
}; });
const btn = makeControlIcon(timelineModel, iconName + 'Icon' as ControlIconName, rect, opt);
btn.ensureState('emphasis').style = hoverStyle; btn.ensureState('emphasis').style = hoverStyle;
group.add(btn); group.add(btn);
enableHoverEmphasis(btn); enableHoverEmphasis(btn);
......
...@@ -89,7 +89,8 @@ import { ...@@ -89,7 +89,8 @@ import {
DimensionLoose, DimensionLoose,
ScaleDataValue, ScaleDataValue,
ZRElementEventName, ZRElementEventName,
ECElementEvent ECElementEvent,
AnimationOption
} from '../util/types'; } from '../util/types';
import Displayable from 'zrender/src/graphic/Displayable'; import Displayable from 'zrender/src/graphic/Displayable';
import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable'; import IncrementalDisplayable from 'zrender/src/graphic/IncrementalDisplayable';
...@@ -212,7 +213,15 @@ export interface SetOptionTransitionOptItem { ...@@ -212,7 +213,15 @@ export interface SetOptionTransitionOptItem {
from?: SetOptionTransitionOptFinder; from?: SetOptionTransitionOptFinder;
to: SetOptionTransitionOptFinder; to: SetOptionTransitionOptFinder;
dividingMethod: MorphDividingMethod; dividingMethod: MorphDividingMethod;
} };
export interface ResizeOpts {
width?: number | 'auto', // Can be 'auto' (the same as null/undefined)
height?: number | 'auto', // Can be 'auto' (the same as null/undefined)
animation?: AnimationOption
silent?: boolean // by default false.
};
interface SetOptionTransitionOptFinder extends modelUtil.ModelFinderObject { interface SetOptionTransitionOptFinder extends modelUtil.ModelFinderObject {
dimension: DimensionLoose; dimension: DimensionLoose;
} }
...@@ -1131,11 +1140,7 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1131,11 +1140,7 @@ class ECharts extends Eventful<ECEventDefinition> {
/** /**
* Resize the chart * Resize the chart
*/ */
resize(opts?: { resize(opts?: ResizeOpts): void {
width?: number | 'auto', // Can be 'auto' (the same as null/undefined)
height?: number | 'auto', // Can be 'auto' (the same as null/undefined)
silent?: boolean // by default false.
}): void {
if (__DEV__) { if (__DEV__) {
assert(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.'); assert(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.');
} }
...@@ -1164,10 +1169,10 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1164,10 +1169,10 @@ class ECharts extends Eventful<ECEventDefinition> {
optionChanged && prepare(this); optionChanged && prepare(this);
updateMethods.update.call(this, { updateMethods.update.call(this, {
type: 'resize', type: 'resize',
animation: { animation: zrUtil.extend({
// Disable animation // Disable animation
duration: 0 duration: 0
} }, opts && opts.animation)
}); });
this[IN_MAIN_PROCESS_KEY] = false; this[IN_MAIN_PROCESS_KEY] = false;
...@@ -1531,12 +1536,12 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1531,12 +1536,12 @@ class ECharts extends Eventful<ECEventDefinition> {
updateMethods = { updateMethods = {
prepareAndUpdate: function (this: ECharts, payload: Payload): void { prepareAndUpdate(this: ECharts, payload: Payload): void {
prepare(this); prepare(this);
updateMethods.update.call(this, payload); updateMethods.update.call(this, payload);
}, },
update: function (this: ECharts, payload: Payload): void { update(this: ECharts, payload: Payload): void {
// console.profile && console.profile('update'); // console.profile && console.profile('update');
const ecModel = this._model; const ecModel = this._model;
...@@ -1608,7 +1613,7 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1608,7 +1613,7 @@ class ECharts extends Eventful<ECEventDefinition> {
// console.profile && console.profileEnd('update'); // console.profile && console.profileEnd('update');
}, },
updateTransform: function (this: ECharts, payload: Payload): void { updateTransform(this: ECharts, payload: Payload): void {
const ecModel = this._model; const ecModel = this._model;
const api = this._api; const api = this._api;
...@@ -1665,7 +1670,7 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1665,7 +1670,7 @@ class ECharts extends Eventful<ECEventDefinition> {
performPostUpdateFuncs(ecModel, this._api); performPostUpdateFuncs(ecModel, this._api);
}, },
updateView: function (this: ECharts, payload: Payload): void { updateView(this: ECharts, payload: Payload): void {
const ecModel = this._model; const ecModel = this._model;
// update before setOption // update before setOption
...@@ -1687,7 +1692,7 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1687,7 +1692,7 @@ class ECharts extends Eventful<ECEventDefinition> {
performPostUpdateFuncs(ecModel, this._api); performPostUpdateFuncs(ecModel, this._api);
}, },
updateVisual: function (this: ECharts, payload: Payload): void { updateVisual(this: ECharts, payload: Payload): void {
// updateMethods.update.call(this, payload); // updateMethods.update.call(this, payload);
const ecModel = this._model; const ecModel = this._model;
...@@ -1728,7 +1733,7 @@ class ECharts extends Eventful<ECEventDefinition> { ...@@ -1728,7 +1733,7 @@ class ECharts extends Eventful<ECEventDefinition> {
performPostUpdateFuncs(ecModel, this._api); performPostUpdateFuncs(ecModel, this._api);
}, },
updateLayout: function (this: ECharts, payload: Payload): void { updateLayout(this: ECharts, payload: Payload): void {
updateMethods.update.call(this, payload); updateMethods.update.call(this, payload);
} }
}; };
......
...@@ -135,6 +135,7 @@ export interface DefaultDataVisual { ...@@ -135,6 +135,7 @@ export interface DefaultDataVisual {
symbolSize?: number | number[] symbolSize?: number | number[]
symbolRotate?: number symbolRotate?: number
symbolKeepAspect?: boolean symbolKeepAspect?: boolean
symbolOffset?: string | number | (string | number)[]
liftZ?: number liftZ?: number
// For legend. // For legend.
......
...@@ -38,4 +38,4 @@ export default { ...@@ -38,4 +38,4 @@ export default {
// @ts-ignore // @ts-ignore
return init.apply(null, arguments); return init.apply(null, arguments);
} }
} };
\ No newline at end of file \ No newline at end of file
...@@ -61,6 +61,7 @@ import Scheduler from '../core/Scheduler'; ...@@ -61,6 +61,7 @@ import Scheduler from '../core/Scheduler';
import { concatInternalOptions } from './internalComponentCreator'; import { concatInternalOptions } from './internalComponentCreator';
import { LocaleOption } from '../core/locale'; import { LocaleOption } from '../core/locale';
import {PaletteMixin} from './mixin/palette'; import {PaletteMixin} from './mixin/palette';
import { error } from '../util/log';
export interface GlobalModelSetOptionOpts { export interface GlobalModelSetOptionOpts {
replaceMerge: ComponentMainType | ComponentMainType[]; replaceMerge: ComponentMainType | ComponentMainType[];
...@@ -79,6 +80,63 @@ let initBase: (ecModel: GlobalModel, baseOption: ECUnitOption) => void; ...@@ -79,6 +80,63 @@ let initBase: (ecModel: GlobalModel, baseOption: ECUnitOption) => void;
const OPTION_INNER_KEY = '\0_ec_inner'; const OPTION_INNER_KEY = '\0_ec_inner';
const OPTION_INNER_VALUE = 1; const OPTION_INNER_VALUE = 1;
const BUITIN_COMPONENTS_MAP = {
grid: 'GridComponent',
polar: 'PolarComponent',
geo: 'GeoComponent',
singleAxis: 'SingleAxisComponent',
parallel: 'ParallelComponent',
calendar: 'CalendarComponent',
graphic: 'GraphicComponent',
toolbox: 'ToolboxComponent',
tooltip: 'TooltipComponent',
axisPointer: 'AxisPointerComponent',
brush: 'BrushComponent',
title: 'TitleComponent',
timeline: 'TimelineComponent',
markPoint: 'MarkPointComponent',
markLine: 'MarkLineComponent',
markArea: 'MarkAreaComponent',
legend: 'LegendComponent',
dataZoom: 'DataZoomComponent',
visualMap: 'VisualMapComponent',
// aria: 'AriaComponent',
// dataset: 'DatasetComponent',
// Dependencies
xAxis: 'GridComponent',
yAxis: 'GridComponent',
angleAxis: 'PolarComponent',
radiusAxis: 'PolarComponent'
} as const;
const BUILTIN_CHARTS_MAP = {
line: 'LineChart',
bar: 'BarChart',
pie: 'PieChart',
scatter: 'ScatterChart',
radar: 'RadarChart',
map: 'MapChart',
tree: 'TreeChart',
treemap: 'TreemapChart',
graph: 'GraphChart',
gauge: 'GaugeChart',
funnel: 'FunnelChart',
parallel: 'ParallelChart',
sankey: 'SankeyChart',
boxplot: 'BoxplotChart',
candlestick: 'CandlestickChart',
effectScatter: 'EffectScatterChart',
lines: 'LinesChart',
heatmap: 'HeatmapChart',
pictorialBar: 'PictorialBarChart',
themeRiver: 'ThemeRiverChart',
sunburst: 'SunburstChart',
custom: 'CustomChart'
} as const;
const componetsMissingLogPrinted: Record<string, boolean> = {};
class GlobalModel extends Model<ECUnitOption> { class GlobalModel extends Model<ECUnitOption> {
// @readonly // @readonly
option: ECUnitOption; option: ECUnitOption;
...@@ -250,6 +308,16 @@ class GlobalModel extends Model<ECUnitOption> { ...@@ -250,6 +308,16 @@ class GlobalModel extends Model<ECUnitOption> {
} }
if (!ComponentModel.hasClass(mainType)) { if (!ComponentModel.hasClass(mainType)) {
if (__DEV__) {
const componentImportName = BUITIN_COMPONENTS_MAP[mainType as keyof typeof BUITIN_COMPONENTS_MAP];
if (componentImportName && !componetsMissingLogPrinted[componentImportName]) {
error(`Component ${mainType} is used but not imported.
import { ${componentImportName} } from 'echarts/components';
echarts.use([${componentImportName}]);`);
componetsMissingLogPrinted[componentImportName] = true;
}
}
// globalSettingTask.dirty(); // globalSettingTask.dirty();
option[mainType] = option[mainType] == null option[mainType] = option[mainType] == null
? clone(componentOption) ? clone(componentOption)
...@@ -328,10 +396,31 @@ class GlobalModel extends Model<ECUnitOption> { ...@@ -328,10 +396,31 @@ class GlobalModel extends Model<ECUnitOption> {
// or it has been removed in previous `replaceMerge` and left a "hole" in this component index. // or it has been removed in previous `replaceMerge` and left a "hole" in this component index.
} }
else { else {
const isSeriesType = mainType === 'series';
const ComponentModelClass = (ComponentModel as ComponentModelConstructor).getClass( const ComponentModelClass = (ComponentModel as ComponentModelConstructor).getClass(
mainType, resultItem.keyInfo.subType, true mainType, resultItem.keyInfo.subType,
!isSeriesType // Give a more detailed warn later if series don't exists
); );
if (!ComponentModelClass) {
if (__DEV__) {
const subType = resultItem.keyInfo.subType;
const seriesImportName = BUILTIN_CHARTS_MAP[subType as keyof typeof BUILTIN_CHARTS_MAP];
if (!componetsMissingLogPrinted[subType]) {
componetsMissingLogPrinted[subType] = true;
if (seriesImportName) {
error(`Series ${subType} is used but not imported.
import { ${seriesImportName} } from 'echarts/charts';
echarts.use([${seriesImportName}]);`);
}
else {
error(`Unkown series ${subType}`);
}
}
}
return;
}
if (componentModel && componentModel.constructor === ComponentModelClass) { if (componentModel && componentModel.constructor === ComponentModelClass) {
componentModel.name = resultItem.keyInfo.name; componentModel.name = resultItem.keyInfo.name;
// componentModel.settingTask && componentModel.settingTask.dirty(); // componentModel.settingTask && componentModel.settingTask.dirty();
......
...@@ -292,7 +292,7 @@ export function enableClassManagement( ...@@ -292,7 +292,7 @@ export function enableClassManagement(
throw new Error( throw new Error(
!subType !subType
? mainType + '.' + 'type should be specified.' ? mainType + '.' + 'type should be specified.'
: 'Component ' + mainType + '.' + (subType || '') + ' not exists. Load it first.' : 'Component ' + mainType + '.' + (subType || '') + ' is used but not imported.'
); );
} }
......
...@@ -102,7 +102,7 @@ type DepGraph = {[cmptMainType: string]: DepGraphItem}; ...@@ -102,7 +102,7 @@ type DepGraph = {[cmptMainType: string]: DepGraphItem};
* Topological travel on Activity Network (Activity On Vertices). * Topological travel on Activity Network (Activity On Vertices).
* Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis']. * Dependencies is defined in Model.prototype.dependencies, like ['xAxis', 'yAxis'].
* If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology. * If 'xAxis' or 'yAxis' is absent in componentTypeList, just ignore it in topology.
* If there is circle dependencey, Error will be thrown. * If there is circular dependencey, Error will be thrown.
*/ */
export function enableTopologicalTravel<T>( export function enableTopologicalTravel<T>(
entity: TopologicalTravelable<T>, entity: TopologicalTravelable<T>,
...@@ -152,7 +152,7 @@ export function enableTopologicalTravel<T>( ...@@ -152,7 +152,7 @@ export function enableTopologicalTravel<T>(
zrUtil.each(targetNameSet, function () { zrUtil.each(targetNameSet, function () {
let errMsg = ''; let errMsg = '';
if (__DEV__) { if (__DEV__) {
errMsg = makePrintable('Circle dependency may exists: ', targetNameSet, targetNameList, fullNameList); errMsg = makePrintable('Circular dependency may exists: ', targetNameSet, targetNameList, fullNameList);
} }
throw new Error(errMsg); throw new Error(errMsg);
}); });
......
...@@ -922,7 +922,7 @@ export interface RoamOptionMixin { ...@@ -922,7 +922,7 @@ export interface RoamOptionMixin {
export type SymbolSizeCallback<T> = (rawValue: any, params: T) => number | number[]; export type SymbolSizeCallback<T> = (rawValue: any, params: T) => number | number[];
export type SymbolCallback<T> = (rawValue: any, params: T) => string; export type SymbolCallback<T> = (rawValue: any, params: T) => string;
export type SymbolRotateCallback<T> = (rawValue: any, params: T) => number; export type SymbolRotateCallback<T> = (rawValue: any, params: T) => number;
// export type SymbolOffsetCallback<T> = (rawValue: any, params: T) => (string | number)[]; export type SymbolOffsetCallback<T> = (rawValue: any, params: T) => (string | number)[];
/** /**
* Mixin of option set to control the element symbol. * Mixin of option set to control the element symbol.
* Include type of symbol, and size of symbol. * Include type of symbol, and size of symbol.
...@@ -941,7 +941,7 @@ export interface SymbolOptionMixin<T = unknown> { ...@@ -941,7 +941,7 @@ export interface SymbolOptionMixin<T = unknown> {
symbolKeepAspect?: boolean symbolKeepAspect?: boolean
symbolOffset?: (string | number)[] symbolOffset?: (string | number)[] | (unknown extends T ? never : SymbolOffsetCallback<T>)
} }
/** /**
......
...@@ -22,9 +22,13 @@ import { DefaultDataVisual } from '../data/List'; ...@@ -22,9 +22,13 @@ import { DefaultDataVisual } from '../data/List';
export interface LineDataVisual extends DefaultDataVisual { export interface LineDataVisual extends DefaultDataVisual {
fromSymbol: string fromSymbol: string
toSymbol: string toSymbol: string
fromSymbolSize: number fromSymbolSize: number | number[]
toSymbolSize: number toSymbolSize: number | number[]
fromSymbolRotate: number fromSymbolRotate: number
toSymbolRotate: number toSymbolRotate: number
fromSymbolOffset: string | number | (string | number)[]
toSymbolOffset: string | number | (string | number)[]
fromSymbolKeepAspect: boolean
toSymbolKeepAspect: boolean
} }
...@@ -25,7 +25,8 @@ import { ...@@ -25,7 +25,8 @@ import {
SymbolSizeCallback, SymbolSizeCallback,
SymbolCallback, SymbolCallback,
CallbackDataParams, CallbackDataParams,
SymbolRotateCallback SymbolRotateCallback,
SymbolOffsetCallback
} from '../util/types'; } from '../util/types';
import List from '../data/List'; import List from '../data/List';
import SeriesModel from '../model/Series'; import SeriesModel from '../model/Series';
...@@ -57,14 +58,20 @@ const seriesSymbolTask: StageHandler = { ...@@ -57,14 +58,20 @@ const seriesSymbolTask: StageHandler = {
const symbolSize = seriesModel.get('symbolSize'); const symbolSize = seriesModel.get('symbolSize');
const keepAspect = seriesModel.get('symbolKeepAspect'); const keepAspect = seriesModel.get('symbolKeepAspect');
const symbolRotate = seriesModel.get('symbolRotate'); const symbolRotate = seriesModel.get('symbolRotate');
const symbolOffset = seriesModel.get('symbolOffset');
const hasSymbolTypeCallback = isFunction(symbolType); const hasSymbolTypeCallback = isFunction(symbolType);
const hasSymbolSizeCallback = isFunction(symbolSize); const hasSymbolSizeCallback = isFunction(symbolSize);
const hasSymbolRotateCallback = isFunction(symbolRotate); const hasSymbolRotateCallback = isFunction(symbolRotate);
const hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback; const hasSymbolOffsetCallback = isFunction(symbolOffset);
const hasCallback = hasSymbolTypeCallback
|| hasSymbolSizeCallback
|| hasSymbolRotateCallback
|| hasSymbolOffsetCallback;
const seriesSymbol = (!hasSymbolTypeCallback && symbolType) ? symbolType : seriesModel.defaultSymbol; const seriesSymbol = (!hasSymbolTypeCallback && symbolType) ? symbolType : seriesModel.defaultSymbol;
const seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null; const seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;
const seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null; const seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null;
const seriesSymbolOffset = !hasSymbolOffsetCallback ? symbolOffset : null;
data.setVisual({ data.setVisual({
legendSymbol: seriesModel.legendSymbol || seriesSymbol as string, legendSymbol: seriesModel.legendSymbol || seriesSymbol as string,
...@@ -75,7 +82,8 @@ const seriesSymbolTask: StageHandler = { ...@@ -75,7 +82,8 @@ const seriesSymbolTask: StageHandler = {
symbol: seriesSymbol as string, symbol: seriesSymbol as string,
symbolSize: seriesSymbolSize as number | number[], symbolSize: seriesSymbolSize as number | number[],
symbolKeepAspect: keepAspect, symbolKeepAspect: keepAspect,
symbolRotate: seriesSymbolRotate as number symbolRotate: seriesSymbolRotate as number,
symbolOffset: seriesSymbolOffset as (string | number)[]
}); });
// Only visible series has each data be visual encoded // Only visible series has each data be visual encoded
...@@ -95,6 +103,9 @@ const seriesSymbolTask: StageHandler = { ...@@ -95,6 +103,9 @@ const seriesSymbolTask: StageHandler = {
hasSymbolRotateCallback && data.setItemVisual( hasSymbolRotateCallback && data.setItemVisual(
idx, 'symbolRotate', (symbolRotate as SymbolRotateCallback<CallbackDataParams>)(rawValue, params) idx, 'symbolRotate', (symbolRotate as SymbolRotateCallback<CallbackDataParams>)(rawValue, params)
); );
hasSymbolOffsetCallback && data.setItemVisual(
idx, 'symbolOffset', (symbolOffset as SymbolOffsetCallback<CallbackDataParams>)(rawValue, params)
);
} }
return { dataEach: hasCallback ? dataEach : null }; return { dataEach: hasCallback ? dataEach : null };
...@@ -127,6 +138,7 @@ const dataSymbolTask: StageHandler = { ...@@ -127,6 +138,7 @@ const dataSymbolTask: StageHandler = {
const itemSymbolType = itemModel.getShallow('symbol', true); const itemSymbolType = itemModel.getShallow('symbol', true);
const itemSymbolSize = itemModel.getShallow('symbolSize', true); const itemSymbolSize = itemModel.getShallow('symbolSize', true);
const itemSymbolRotate = itemModel.getShallow('symbolRotate', true); const itemSymbolRotate = itemModel.getShallow('symbolRotate', true);
const itemSymbolOffset = itemModel.getShallow('symbolOffset', true);
const itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); const itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true);
// If has item symbol // If has item symbol
...@@ -140,6 +152,9 @@ const dataSymbolTask: StageHandler = { ...@@ -140,6 +152,9 @@ const dataSymbolTask: StageHandler = {
if (itemSymbolRotate != null) { if (itemSymbolRotate != null) {
data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate); data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate);
} }
if (itemSymbolOffset != null) {
data.setItemVisual(idx, 'symbolOffset', itemSymbolOffset);
}
if (itemSymbolKeepAspect != null) { if (itemSymbolKeepAspect != null) {
data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect); data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
} }
...@@ -149,4 +164,4 @@ const dataSymbolTask: StageHandler = { ...@@ -149,4 +164,4 @@ const dataSymbolTask: StageHandler = {
} }
}; };
export {seriesSymbolTask, dataSymbolTask}; export {seriesSymbolTask, dataSymbolTask};
\ No newline at end of file
...@@ -45,6 +45,8 @@ under the License. ...@@ -45,6 +45,8 @@ under the License.
<div id="main5"></div> <div id="main5"></div>
<div id="main6"></div> <div id="main6"></div>
<div id="main7"></div> <div id="main7"></div>
<div id="main8"></div>
<div id="main9"></div>
...@@ -547,6 +549,86 @@ under the License. ...@@ -547,6 +549,86 @@ under the License.
date = null; date = null;
}, 1000); }, 1000);
var option8 = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
feature: {
restore: {},
saveAsImage: {}
}
},
series: [
{
name: '业务指标',
type: 'gauge',
anchor: {
show: true,
icon: "image://https://www.apache.org/img/support-apache.jpg",
size: 50,
showAbove: true
},
pointer: {
icon: "image://https://www.apache.org/img/support-apache.jpg",
length: "70%"
},
detail: {formatter: '{value}%'},
data: [{value: 58.46, name: '完成率'}]
}
]
};
var chart8 = testHelper.create(echarts, 'main8', {
title: [
'pointer.icon: "image://url"',
'anchor.icon: "image://url"'
],
option: option8
// height: 1200,
// buttons: [{text: 'btn-txt', onclick: function () {}}],
// recordCanvas: true,
});
var option9 = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
feature: {
restore: {},
saveAsImage: {}
}
},
series: [
{
name: '业务指标',
type: 'gauge',
pointer: {
icon: 'emptyCircle',
itemStyle: {
borderWidth: 10,
borderColor: '#f00'
},
},
anchor: {
// show: true
},
detail: {formatter: '{value}%'},
data: [{value: 58.46, name: '完成率'}]
}
]
};
var chart9 = testHelper.create(echarts, 'main9', {
title: [
'pointer.icon: emptyCircle',
'anchor.show: false'
],
option: option9
});
}); });
</script> </script>
......
此差异已折叠。
...@@ -117,6 +117,7 @@ under the License. ...@@ -117,6 +117,7 @@ under the License.
markLine: { markLine: {
silent: true, silent: true,
// symbol: 'triangle', // symbol: 'triangle',
symbolRotate: [20, 45],
data: [ data: [
[ [
{name: 'rotation not specified', coord: ['2014-06-20', 300], symbol: 'arrow'}, {name: 'rotation not specified', coord: ['2014-06-20', 300], symbol: 'arrow'},
...@@ -156,10 +157,13 @@ under the License. ...@@ -156,10 +157,13 @@ under the License.
[{ [{
symbol: 'rect', symbol: 'rect',
x: '90%', x: '90%',
yAxis: 'average' yAxis: 'average',
symbolRotate: 0,
symbolOffset: [50, 0]
}, { }, {
symbol: 'triangle', symbol: 'triangle',
symbolRotate: 180, symbolRotate: 130,
// symbolOffset: [-50, 0],
label: { label: {
position: 'start', position: 'start',
formatter: 'Average', formatter: 'Average',
......
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta charset="utf-8">
<script src="lib/esl.js"></script>
<script src="lib/config.js"></script>
<script src="lib/testHelper.js"></script>
<link rel="stylesheet" href="lib/reset.css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<style>
body {
position: absolute;
left: 0;
top: 0;
}
</style>
<div id="main0"></div>
<script>
require([
'echarts'
// 'echarts/chart/pie',
// 'echarts/component/title',
// 'echarts/component/legend',
// 'echarts/component/tooltip'
], function (echarts) {
require([
'echarts'
], function (echarts) {
const option = {
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient: 'vertical',
left: 'left',
data: ['直接访问','邮件营销','联盟广告','视频广告(value is null)','搜索引擎']
},
series : [
{
name: '访问来源',
type: 'pie',
radius : '55%',
center: ['50%', '60%'],
selectedMode: 'single',
data:[
{value:335, name:'直接访问'},
{value:310, name:'邮件营销'},
{value:234, name:'联盟广告'},
{value:null, name:'视频广告(value is null)'},
{value:1548, name:'搜索引擎'}
]
}
]
};
var myChart = testHelper.create(echarts, 'main0', {
width: 600,
height: 400,
title: [
'Resize animation should be configured properly'
],
option: option,
buttons: [{
text: 'Resize without animation by default',
onClick: () => {
myChart.resize({
width: 400,
height: 266
})
}
}, {
text: 'Resize with animaiton',
onClick: () => {
myChart.resize({
width: 300,
height: 200,
animation: {
// Use a long duration so it can be recorded
duration: 2000,
easing: 'cubicInOut'
}
})
}
}]
});
});
});
</script>
</body>
</html>
\ No newline at end of file
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
"line-boldWhenHover": 1, "line-boldWhenHover": 1,
"line-crash": 1, "line-crash": 1,
"line-endLabel": 1, "line-endLabel": 1,
"line-extraneous": 2,
"map": 3, "map": 3,
"map-contour": 2, "map-contour": 2,
"map-default": 1, "map-default": 1,
...@@ -130,6 +131,7 @@ ...@@ -130,6 +131,7 @@
"radar2": 1, "radar2": 1,
"radar3": 1, "radar3": 1,
"radar4": 1, "radar4": 1,
"resize-animation": 1,
"sankey-depth": 1, "sankey-depth": 1,
"sankey-jump": 1, "sankey-jump": 1,
"sankey-level": 1, "sankey-level": 1,
......
[{"name":"Action 1","ops":[{"type":"mousedown","time":596,"x":28,"y":93},{"type":"mouseup","time":698,"x":28,"y":93},{"time":699,"delay":2000,"type":"screenshot-auto"}],"scrollY":0,"scrollX":0,"timestamp":1568042380534},{"name":"Action 2","ops":[{"type":"mousedown","time":736,"x":218,"y":184},{"type":"mouseup","time":827,"x":218,"y":184},{"time":828,"delay":400,"type":"screenshot-auto"}],"scrollY":416,"scrollX":0,"timestamp":1617082817083}]
\ No newline at end of file
[{"name":"Action 1","ops":[{"type":"mousemove","time":294,"x":206,"y":78},{"type":"mousedown","time":382,"x":206,"y":78},{"type":"mouseup","time":481,"x":206,"y":78},{"time":482,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":910,"x":207,"y":78},{"type":"mousemove","time":1111,"x":248,"y":78},{"type":"mousedown","time":1201,"x":248,"y":78},{"type":"mouseup","time":1305,"x":248,"y":78},{"time":1306,"delay":400,"type":"screenshot-auto"},{"type":"mousemove","time":1320,"x":248,"y":78}],"scrollY":0,"scrollX":0,"timestamp":1617085338625}]
\ No newline at end of file
...@@ -34,6 +34,7 @@ under the License. ...@@ -34,6 +34,7 @@ under the License.
</head> </head>
<body> <body>
<div id="main0"></div> <div id="main0"></div>
<div id="main1"></div>
<script> <script>
require([ require([
...@@ -94,12 +95,55 @@ under the License. ...@@ -94,12 +95,55 @@ under the License.
}] }]
}; };
var series = {
name: 'Original',
type: 'scatter',
symbol: 'circle',
data: (function() {
function random(max) {
return +(Math.random() * max).toFixed(3);
}
var seriesData = [];
for (var i = 0; i < 20; i++) {
seriesData.push([random(10), random(10), random(20)]);
}
return seriesData;
})()
};
var option2 = {
legend: {},
xAxis: {},
yAxis: {},
tooltip: {
formatter: function(params) {
return params.marker + params.seriesName
+ (params.seriesName === 'Offset' ? '<br/>offset: ' + params.value[2] : '');
}
},
series: [
series,
Object.assign({}, series, {
name: 'Offset',
symbol: 'circle',
// symbolOffset: 20,
symbolOffset: function(data) {
return data[2]
}
})
]
};
var chart = testHelper.create(echarts, 'main0', { var chart = testHelper.create(echarts, 'main0', {
title: 'Rotates the symbol as we need', title: 'Rotates the symbol as we need',
option: option option: option
}); });
var chart2 = testHelper.create(echarts, 'main1', {
title: 'Symbol should have various offset',
option: option2
});
}); });
</script> </script>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
* under the License. * under the License.
*/ */
import { isValueFinite } from './utHelper'; function isValueFinite(val: unknown): boolean {
return val != null && val !== '' && isFinite(val as number);
}
// Setup expectes // Setup expectes
......
...@@ -46,6 +46,16 @@ export function createChart(params?: { ...@@ -46,6 +46,16 @@ export function createChart(params?: {
'bottom:0', 'bottom:0',
'right:0' 'right:0'
].join(';'); ].join(';');
Object.defineProperty(el, 'clientWidth', {
get() {
return params.width || 500;
}
});
Object.defineProperty(el, 'clientHeight', {
get() {
return params.height || 400;
}
});
const chart = init(el, params.theme, params.opts); const chart = init(el, params.theme, params.opts);
return chart; return chart;
}; };
...@@ -80,10 +90,6 @@ export const curry = zrUtilCurry; ...@@ -80,10 +90,6 @@ export const curry = zrUtilCurry;
export const bind = zrUtilBind; export const bind = zrUtilBind;
export function isValueFinite(val: unknown): boolean {
return val != null && val !== '' && isFinite(val as number);
}
// /** // /**
// * @public // * @public
// * @param {Array.<string>} deps // * @param {Array.<string>} deps
......
export {};
declare global {
namespace jest {
interface Matchers<R> {
toBeFinite(): R
// Greater than or equal
toBeGeaterThanOrEqualTo(bound: number): R
// Greater than
toBeGreaterThan(bound: number): R
toBeEmptyArray(): R
}
}
}
\ No newline at end of file
...@@ -21,10 +21,10 @@ import { createChart, getGraphicElements, getECModel } from '../../../core/utHel ...@@ -21,10 +21,10 @@ import { createChart, getGraphicElements, getECModel } from '../../../core/utHel
// import { imageURI } from './setOptionImageURI'; // import { imageURI } from './setOptionImageURI';
import { EChartsType } from '../../../../../src/echarts'; import { EChartsType } from '../../../../../src/echarts';
import Element from 'zrender/src/Element'; import Element from 'zrender/src/Element';
import { EChartsFullOption } from '../../../../../src/option'; import { EChartsOption } from '../../../../../src/export/option';
import { import {
GraphicComponentOption, GraphicComponentImageOption GraphicComponentOption, GraphicComponentImageOption
} from '../../../../../src/component/graphic'; } from '../../../../../src/component/graphic/install';
import Group from 'zrender/src/graphic/Group'; import Group from 'zrender/src/graphic/Group';
import { Dictionary } from 'zrender/src/core/types'; import { Dictionary } from 'zrender/src/core/types';
...@@ -1049,7 +1049,7 @@ describe('graphic_setOption', function () { ...@@ -1049,7 +1049,7 @@ describe('graphic_setOption', function () {
describe('boundingAndRotation', function () { describe('boundingAndRotation', function () {
function getOption(): EChartsFullOption { function getOption(): EChartsOption {
return { return {
legend: { legend: {
data: ['高度(km)与气温(°C)变化关系'] data: ['高度(km)与气温(°C)变化关系']
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
import { createChart, getECModel } from '../../../core/utHelper'; import { createChart, getECModel } from '../../../core/utHelper';
import { EChartsType } from '../../../../../src/echarts'; import { EChartsType } from '../../../../../src/echarts';
import { EChartsFullOption } from '../../../../../src/option'; import { EChartsOption } from '../../../../../src/export/option';
import { ContinousVisualMapOption } from '../../../../../src/component/visualMap/ContinuousModel'; import { ContinousVisualMapOption } from '../../../../../src/component/visualMap/ContinuousModel';
import { PiecewiseVisualMapOption } from '../../../../../src/component/visualMap/PiecewiseModel'; import { PiecewiseVisualMapOption } from '../../../../../src/component/visualMap/PiecewiseModel';
import VisualMapModel from '../../../../../src/component/visualMap/VisualMapModel'; import VisualMapModel from '../../../../../src/component/visualMap/VisualMapModel';
...@@ -94,15 +94,15 @@ describe('vsiaulMap_setOption', function () { ...@@ -94,15 +94,15 @@ describe('vsiaulMap_setOption', function () {
visualMap: {} visualMap: {}
}); });
expectTheSame(chart.getOption()); expectTheSame(chart.getOption() as EChartsOption);
chart.setOption({ chart.setOption({
series: [{data: [[44, 55]]}] // visualMap depends series series: [{data: [[44, 55]]}] // visualMap depends series
}); });
expectTheSame(chart.getOption()); expectTheSame(chart.getOption() as EChartsOption);
function expectTheSame(option: EChartsFullOption) { function expectTheSame(option: EChartsOption) {
const visualMapOptionGotten = option.visualMap as (ContinousVisualMapOption | PiecewiseVisualMapOption)[]; const visualMapOptionGotten = option.visualMap as (ContinousVisualMapOption | PiecewiseVisualMapOption)[];
expect(visualMapOptionGotten.length).toEqual(1); expect(visualMapOptionGotten.length).toEqual(1);
expect(visualMapOptionGotten[0].inRange.color).toEqual(['red', 'blue', 'yellow']); expect(visualMapOptionGotten[0].inRange.color).toEqual(['red', 'blue', 'yellow']);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
import { EChartsType } from '../../../../src/echarts'; import { EChartsType } from '../../../../src/echarts';
import { createChart, removeChart, getECModel } from '../../core/utHelper'; import { createChart, removeChart, getECModel } from '../../core/utHelper';
import { EChartsFullOption } from '../../../../src/option'; import { EChartsOption } from '../../../../src/export/option';
import { retrieveRawValue } from '../../../../src/data/helper/dataProvider'; import { retrieveRawValue } from '../../../../src/data/helper/dataProvider';
...@@ -59,7 +59,7 @@ describe('dataTransform', function () { ...@@ -59,7 +59,7 @@ describe('dataTransform', function () {
} }
it('forbid_seriesLayoutBy_row', function () { it('forbid_seriesLayoutBy_row', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
dataset: [{ dataset: [{
source: makeDatasetSourceDetection(), source: makeDatasetSourceDetection(),
// This config should cause error thrown. // This config should cause error thrown.
...@@ -78,7 +78,7 @@ describe('dataTransform', function () { ...@@ -78,7 +78,7 @@ describe('dataTransform', function () {
}); });
it('seriesLayoutBy_changed_no_transform', function () { it('seriesLayoutBy_changed_no_transform', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
dataset: { dataset: {
source: makeDatasetSourceDetection() source: makeDatasetSourceDetection()
}, },
...@@ -104,7 +104,7 @@ describe('dataTransform', function () { ...@@ -104,7 +104,7 @@ describe('dataTransform', function () {
] ]
}].forEach((dataset1, itIdx) => { }].forEach((dataset1, itIdx) => {
it(`seriesLayoutBy_changed_transform_detection_${itIdx}`, function () { it(`seriesLayoutBy_changed_transform_detection_${itIdx}`, function () {
const option: EChartsFullOption = { const option: EChartsOption = {
dataset: [{ dataset: [{
source: makeDatasetSourceDetection() source: makeDatasetSourceDetection()
}, dataset1], }, dataset1],
...@@ -136,7 +136,7 @@ describe('dataTransform', function () { ...@@ -136,7 +136,7 @@ describe('dataTransform', function () {
}].forEach((dataset1, itIdx) => { }].forEach((dataset1, itIdx) => {
it(`seriesLayoutBy_changed_transform_non_detection_${itIdx}`, function () { it(`seriesLayoutBy_changed_transform_non_detection_${itIdx}`, function () {
const sourceWrap = makeDatasetSourceNonDetectionByRow(); const sourceWrap = makeDatasetSourceNonDetectionByRow();
const option: EChartsFullOption = { const option: EChartsOption = {
dataset: [{ dataset: [{
dimensions: sourceWrap.dimensions, dimensions: sourceWrap.dimensions,
source: sourceWrap.source source: sourceWrap.source
...@@ -163,7 +163,7 @@ describe('dataTransform', function () { ...@@ -163,7 +163,7 @@ describe('dataTransform', function () {
] ]
}].forEach((dataset1, itIdx) => { }].forEach((dataset1, itIdx) => {
it(`inherit_detected_dimensions_${itIdx}`, function () { it(`inherit_detected_dimensions_${itIdx}`, function () {
const option: EChartsFullOption = { const option: EChartsOption = {
dataset: [{ dataset: [{
source: makeDatasetSourceDetection() source: makeDatasetSourceDetection()
}, dataset1], }, dataset1],
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import ComponentModel, { ComponentModelConstructor } from '../../../../src/model/Component';
import { ComponentMainType } from '../../../../src/util/types';
const componentModelConstructor = ComponentModel as ComponentModelConstructor;
describe('Component', function () {
let idx = 0;
function makeTypes(count: number): string[] {
const arr = [];
for (let i = 0; i < count; i++) {
arr.push('type_' + idx++);
}
return arr;
}
type TopoResultItem = [ComponentMainType, ComponentMainType[]];
describe('topologicalTravel', function () {
it('topologicalTravel_base', function () {
const [m1, a1, a2] = makeTypes(3);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a1});
componentModelConstructor.extend({type: a2});
const result: TopoResultItem[] = [];
const allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_a1IsAbsent', function () {
const [m1, a1, a2] = makeTypes(3);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a2});
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_empty', function () {
const [m1, a1, a2] = makeTypes(3);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a1});
componentModelConstructor.extend({type: a2});
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([]);
});
it('topologicalTravel_isolate', function () {
const [m1, a1, a2] = makeTypes(3);
componentModelConstructor.extend({type: a2});
componentModelConstructor.extend({type: a1});
componentModelConstructor.extend({type: m1, dependencies: [a2]});
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[a1, a2, m1],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a1, ['dataset']], [a2, ['dataset']], [m1, ['dataset', a2]]]);
});
it('topologicalTravel_diamond', function () {
const [m1, a1, a2, a3] = makeTypes(4);
componentModelConstructor.extend({type: a1, dependencies: []});
componentModelConstructor.extend({type: a2, dependencies: [a1]});
componentModelConstructor.extend({type: a3, dependencies: [a1]});
componentModelConstructor.extend({type: m1, dependencies: [a2, a3]});
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a1, a2, a3],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a1, ['dataset']],
[a3, ['dataset', a1]],
[a2, ['dataset', a1]],
[m1, ['dataset', a2, a3]]
]);
});
it('topologicalTravel_loop', function () {
const [m1, m2, a1, a2, a3] = makeTypes(5);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: m2, dependencies: [m1, a2]});
componentModelConstructor.extend({type: a1, dependencies: [m2, a2, a3]});
componentModelConstructor.extend({type: a2});
componentModelConstructor.extend({type: a3});
const allList = componentModelConstructor.getAllClassMainTypes();
expect(function () {
componentModelConstructor.topologicalTravel(
[m1, m2, a1],
allList,
() => {}
);
}).toThrowError(/Circl/);
});
it('topologicalTravel_multipleEchartsInstance', function () {
const [m1, m2, a1, a2] = makeTypes(4);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a1});
componentModelConstructor.extend({type: a2});
let allList = componentModelConstructor.getAllClassMainTypes();
let result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]);
result = [];
componentModelConstructor.extend({type: m2, dependencies: [a1, m1]});
allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m2, m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]], [m2, ['dataset', a1, m1]]]
);
});
it('topologicalTravel_missingSomeNodeButHasDependencies', function () {
const [m1, a1, a2, a3, a4] = makeTypes(5);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a2, dependencies: [a3]});
componentModelConstructor.extend({type: a3});
componentModelConstructor.extend({type: a4});
let result: TopoResultItem[] = [];
let allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[a3, m1],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]);
result = [];
allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a3],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_subType', function () {
const [m1, a1, a2, a3, a4] = makeTypes(5);
componentModelConstructor.extend({type: m1, dependencies: [a1, a2]});
componentModelConstructor.extend({type: a1 + '.aaa', dependencies: [a2]});
componentModelConstructor.extend({type: a1 + '.bbb', dependencies: [a3, a4]});
componentModelConstructor.extend({type: a2});
componentModelConstructor.extend({type: a3});
componentModelConstructor.extend({type: a4});
const result: TopoResultItem[] = [];
const allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a1, a2, a4],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a4, ['dataset']],
[a2, ['dataset']],
[a1, ['dataset', a2, a3, a4]],
[m1, ['dataset', a1, a2]]
]);
});
});
});
\ No newline at end of file
...@@ -24,7 +24,7 @@ import { ComponentMainType, ParsedValue } from '../../../../src/util/types'; ...@@ -24,7 +24,7 @@ import { ComponentMainType, ParsedValue } from '../../../../src/util/types';
import SeriesModel from '../../../../src/model/Series'; import SeriesModel from '../../../../src/model/Series';
import ComponentModel from '../../../../src/model/Component'; import ComponentModel from '../../../../src/model/Component';
import ChartView from '../../../../src/view/Chart'; import ChartView from '../../../../src/view/Chart';
import { EChartsFullOption } from '../../../../src/option'; import { EChartsOption } from '../../../../src/export/option';
type OriginModelView = { type OriginModelView = {
model: SeriesModel; model: SeriesModel;
...@@ -119,7 +119,7 @@ describe('modelAndOptionMapping', function () { ...@@ -119,7 +119,7 @@ describe('modelAndOptionMapping', function () {
describe('idNoNameNo', function () { describe('idNoNameNo', function () {
it('sameTypeNotMerge', function () { it('sameTypeNotMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -239,7 +239,7 @@ describe('modelAndOptionMapping', function () { ...@@ -239,7 +239,7 @@ describe('modelAndOptionMapping', function () {
describe('idSpecified', function () { describe('idSpecified', function () {
it('sameTypeNotMerge', function () { it('sameTypeNotMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -270,7 +270,7 @@ describe('modelAndOptionMapping', function () { ...@@ -270,7 +270,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('sameTypeMerge', function () { it('sameTypeMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -293,7 +293,7 @@ describe('modelAndOptionMapping', function () { ...@@ -293,7 +293,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeNotMerge', function () { it('differentTypeNotMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -307,7 +307,7 @@ describe('modelAndOptionMapping', function () { ...@@ -307,7 +307,7 @@ describe('modelAndOptionMapping', function () {
chart.setOption(option); chart.setOption(option);
const origins = saveOrigins(chart); const origins = saveOrigins(chart);
const option2: EChartsFullOption = { const option2: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -328,7 +328,7 @@ describe('modelAndOptionMapping', function () { ...@@ -328,7 +328,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeMergeFull', function () { it('differentTypeMergeFull', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -342,7 +342,7 @@ describe('modelAndOptionMapping', function () { ...@@ -342,7 +342,7 @@ describe('modelAndOptionMapping', function () {
chart.setOption(option); chart.setOption(option);
const origins = saveOrigins(chart); const origins = saveOrigins(chart);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'line', data: [11]}, {type: 'line', data: [11]},
{type: 'bar', data: [22], id: 20, name: 'a'}, {type: 'bar', data: [22], id: 20, name: 'a'},
...@@ -362,7 +362,7 @@ describe('modelAndOptionMapping', function () { ...@@ -362,7 +362,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeMergePartial1', function () { it('differentTypeMergePartial1', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -376,7 +376,7 @@ describe('modelAndOptionMapping', function () { ...@@ -376,7 +376,7 @@ describe('modelAndOptionMapping', function () {
chart.setOption(option); chart.setOption(option);
const origins = saveOrigins(chart); const origins = saveOrigins(chart);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], id: 40}, {type: 'bar', data: [444], id: 40},
{type: 'line', data: [333]}, {type: 'line', data: [333]},
...@@ -399,7 +399,7 @@ describe('modelAndOptionMapping', function () { ...@@ -399,7 +399,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeMergePartial2', function () { it('differentTypeMergePartial2', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -409,7 +409,7 @@ describe('modelAndOptionMapping', function () { ...@@ -409,7 +409,7 @@ describe('modelAndOptionMapping', function () {
}; };
chart.setOption(option); chart.setOption(option);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], id: 40}, {type: 'bar', data: [444], id: 40},
{type: 'line', data: [333]}, {type: 'line', data: [333]},
...@@ -429,7 +429,7 @@ describe('modelAndOptionMapping', function () { ...@@ -429,7 +429,7 @@ describe('modelAndOptionMapping', function () {
it('mergePartialDoNotMapToOtherId', function () { it('mergePartialDoNotMapToOtherId', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -439,7 +439,7 @@ describe('modelAndOptionMapping', function () { ...@@ -439,7 +439,7 @@ describe('modelAndOptionMapping', function () {
}; };
chart.setOption(option); chart.setOption(option);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], id: 40} {type: 'bar', data: [444], id: 40}
] ]
...@@ -455,7 +455,7 @@ describe('modelAndOptionMapping', function () { ...@@ -455,7 +455,7 @@ describe('modelAndOptionMapping', function () {
it('idDuplicate', function () { it('idDuplicate', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -524,7 +524,7 @@ describe('modelAndOptionMapping', function () { ...@@ -524,7 +524,7 @@ describe('modelAndOptionMapping', function () {
describe('noIdButNameExists', function () { describe('noIdButNameExists', function () {
it('sameTypeNotMerge', function () { it('sameTypeNotMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -558,7 +558,7 @@ describe('modelAndOptionMapping', function () { ...@@ -558,7 +558,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('sameTypeMerge', function () { it('sameTypeMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -581,7 +581,7 @@ describe('modelAndOptionMapping', function () { ...@@ -581,7 +581,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeNotMerge', function () { it('differentTypeNotMerge', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -595,7 +595,7 @@ describe('modelAndOptionMapping', function () { ...@@ -595,7 +595,7 @@ describe('modelAndOptionMapping', function () {
chart.setOption(option); chart.setOption(option);
const origins = saveOrigins(chart); const origins = saveOrigins(chart);
const option2: EChartsFullOption = { const option2: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -616,7 +616,7 @@ describe('modelAndOptionMapping', function () { ...@@ -616,7 +616,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeMergePartialOneMapTwo', function () { it('differentTypeMergePartialOneMapTwo', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -630,7 +630,7 @@ describe('modelAndOptionMapping', function () { ...@@ -630,7 +630,7 @@ describe('modelAndOptionMapping', function () {
chart.setOption(option); chart.setOption(option);
const origins = saveOrigins(chart); const origins = saveOrigins(chart);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], id: 40}, {type: 'bar', data: [444], id: 40},
{type: 'line', data: [333]}, {type: 'line', data: [333]},
...@@ -654,7 +654,7 @@ describe('modelAndOptionMapping', function () { ...@@ -654,7 +654,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('differentTypeMergePartialTwoMapOne', function () { it('differentTypeMergePartialTwoMapOne', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -664,7 +664,7 @@ describe('modelAndOptionMapping', function () { ...@@ -664,7 +664,7 @@ describe('modelAndOptionMapping', function () {
}; };
chart.setOption(option); chart.setOption(option);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], name: 'a'}, {type: 'bar', data: [444], name: 'a'},
{type: 'line', data: [333]}, {type: 'line', data: [333]},
...@@ -684,7 +684,7 @@ describe('modelAndOptionMapping', function () { ...@@ -684,7 +684,7 @@ describe('modelAndOptionMapping', function () {
it('mergePartialCanMapToOtherName', function () { it('mergePartialCanMapToOtherName', function () {
// Consider case: axis.name = 'some label', which can be overwritten. // Consider case: axis.name = 'some label', which can be overwritten.
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
series: [ series: [
...@@ -694,7 +694,7 @@ describe('modelAndOptionMapping', function () { ...@@ -694,7 +694,7 @@ describe('modelAndOptionMapping', function () {
}; };
chart.setOption(option); chart.setOption(option);
const option2: EChartsFullOption = { const option2: EChartsOption = {
series: [ series: [
{type: 'bar', data: [444], name: 40}, {type: 'bar', data: [444], name: 40},
{type: 'bar', data: [999], name: 40}, {type: 'bar', data: [999], name: 40},
...@@ -720,7 +720,7 @@ describe('modelAndOptionMapping', function () { ...@@ -720,7 +720,7 @@ describe('modelAndOptionMapping', function () {
describe('ohters', function () { describe('ohters', function () {
it('aBugCase', function () { it('aBugCase', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
series: [ series: [
{ {
type: 'pie', type: 'pie',
...@@ -790,7 +790,7 @@ describe('modelAndOptionMapping', function () { ...@@ -790,7 +790,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('color', function () { it('color', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
backgroundColor: 'rgba(1,1,1,1)', backgroundColor: 'rgba(1,1,1,1)',
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
...@@ -812,7 +812,7 @@ describe('modelAndOptionMapping', function () { ...@@ -812,7 +812,7 @@ describe('modelAndOptionMapping', function () {
}); });
it('innerId', function () { it('innerId', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: {data: ['a']}, xAxis: {data: ['a']},
yAxis: {}, yAxis: {},
toolbox: { toolbox: {
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import ComponentModel, { ComponentModelConstructor } from '../../../../src/model/Component';
import { ComponentMainType } from '../../../../src/util/types';
const componentModelConstructor = ComponentModel as ComponentModelConstructor;
function extendModel(type: string, dependencies?: string[]) {
class SubModel extends ComponentModel {
static type: string = type;
type: string = type;
static dependencies = dependencies || [];
};
ComponentModel.registerClass(SubModel);
return SubModel;
}
describe('componentDependency', function () {
let idx = 0;
function makeTypes(count: number): string[] {
const arr = [];
for (let i = 0; i < count; i++) {
arr.push('type_' + idx++);
}
return arr;
}
type TopoResultItem = [ComponentMainType, ComponentMainType[]];
it('topologicalTravel_base', function () {
const [m1, a1, a2] = makeTypes(3);
extendModel(m1, [a1, a2]);
extendModel(a1);
extendModel(a2);
const result: TopoResultItem[] = [];
const allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_a1IsAbsent', function () {
const [m1, a1, a2] = makeTypes(3);
extendModel(m1, [a1, a2]);
extendModel(a2);
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_empty', function () {
const [m1, a1, a2] = makeTypes(3);
extendModel(m1, [a1, a2]);
extendModel(a1);
extendModel(a2);
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([]);
});
it('topologicalTravel_isolate', function () {
const [m1, a1, a2] = makeTypes(3);
extendModel(a2);
extendModel(a1);
extendModel(m1, [a2]);
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[a1, a2, m1],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a1, ['dataset']], [a2, ['dataset']], [m1, ['dataset', a2]]]);
});
it('topologicalTravel_diamond', function () {
const [m1, a1, a2, a3] = makeTypes(4);
extendModel(a1, []);
extendModel(a2, [a1]);
extendModel(a3, [a1]);
extendModel(m1, [a2, a3]);
const allList = componentModelConstructor.getAllClassMainTypes();
const result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a1, a2, a3],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a1, ['dataset']],
[a3, ['dataset', a1]],
[a2, ['dataset', a1]],
[m1, ['dataset', a2, a3]]
]);
});
it('topologicalTravel_loop', function () {
const [m1, m2, a1, a2, a3] = makeTypes(5);
extendModel(m1, [a1, a2]);
extendModel(m2, [m1, a2]);
extendModel(a1, [m2, a2, a3]);
extendModel(a2);
extendModel(a3);
const allList = componentModelConstructor.getAllClassMainTypes();
expect(function () {
componentModelConstructor.topologicalTravel(
[m1, m2, a1],
allList,
() => {}
);
}).toThrowError(/Circular/);
});
it('topologicalTravel_multipleEchartsInstance', function () {
const [m1, m2, a1, a2] = makeTypes(4);
extendModel(m1, [a1, a2]);
extendModel(a1);
extendModel(a2);
let allList = componentModelConstructor.getAllClassMainTypes();
let result: TopoResultItem[] = [];
componentModelConstructor.topologicalTravel(
[m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]]]);
result = [];
extendModel(m2, [a1, m1]);
allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m2, m1, a1, a2],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a2, ['dataset']], [a1, ['dataset']], [m1, ['dataset', a1, a2]], [m2, ['dataset', a1, m1]]]
);
});
it('topologicalTravel_missingSomeNodeButHasDependencies', function () {
const [m1, a1, a2, a3, a4] = makeTypes(5);
extendModel(m1, [a1, a2]);
extendModel(a2, [a3]);
extendModel(a3);
extendModel(a4);
let result: TopoResultItem[] = [];
let allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[a3, m1],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]);
result = [];
allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a3],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual([[a3, ['dataset']], [a2, ['dataset', a3]], [m1, ['dataset', a1, a2]]]);
});
it('topologicalTravel_subType', function () {
const [m1, a1, a2, a3, a4] = makeTypes(5);
extendModel(m1, [a1, a2]);
extendModel(a1 + '.aaa', [a2]);
extendModel(a1 + '.bbb', [a3, a4]);
extendModel(a2);
extendModel(a3);
extendModel(a4);
const result: TopoResultItem[] = [];
const allList = componentModelConstructor.getAllClassMainTypes();
componentModelConstructor.topologicalTravel(
[m1, a1, a2, a4],
allList,
function (componentType, dependencies) {
result.push([componentType, dependencies]);
}
);
expect(result).toEqual(
[[a4, ['dataset']],
[a2, ['dataset']],
[a1, ['dataset', a2, a3, a4]],
[m1, ['dataset', a1, a2]]
]);
});
});
\ No newline at end of file
import { init, use, EChartsType } from '../../../../src/export/core';
import {
PieChart
} from '../../../../src/export/charts';
import {
TitleComponent
} from '../../../../src/export/components';
import {
CanvasRenderer
} from '../../../../src/export/renderers';
use([PieChart, TitleComponent, CanvasRenderer]);
import { EChartsOption } from '../../../../src/export/option';
function createChart(): EChartsType {
const el = document.createElement('div');
Object.defineProperty(el, 'clientWidth', {
get() {
return 500;
}
});
Object.defineProperty(el, 'clientHeight', {
get() {
return 400;
}
});
const chart = init(el);
return chart;
};
function makeComponentError(componentName: string, componentImportName: string) {
return `[ECharts] Component ${componentName} is used but not imported.
import { ${componentImportName} } from 'echarts/components';
echarts.use([${componentImportName}]);`;
}
function makeSerieError(seriesName: string, seriesImportName: string) {
return `[ECharts] Series ${seriesName} is used but not imported.
import { ${seriesImportName} } from 'echarts/charts';
echarts.use([${seriesImportName}]);`;
}
describe('model_componentMissing', function () {
it('Should report grid component missing error', function () {
const chart = createChart();
const oldConsoleErr = console.error;
console.error = jest.fn();
chart.setOption<EChartsOption>({
xAxis: {},
yAxis: {},
series: []
});
expect(console.error).toHaveBeenCalledWith(
makeComponentError('xAxis', 'GridComponent')
);
console.error = oldConsoleErr;
});
it('Should report dataZoom component missing error', function () {
const chart = createChart();
const oldConsoleErr = console.error;
console.error = jest.fn();
chart.setOption<EChartsOption>({
dataZoom: {}
});
expect(console.error).toHaveBeenCalledWith(
makeComponentError('dataZoom', 'DataZoomComponent')
);
console.error = oldConsoleErr;
});
it('Should not report title component missing error', function () {
const chart = createChart();
const oldConsoleErr = console.error;
console.error = jest.fn();
chart.setOption<EChartsOption>({
title: {},
series: []
});
expect(console.error).not.toBeCalled();
console.error = oldConsoleErr;
});
it('Should report funnel series missing error', function () {
const chart = createChart();
const oldConsoleErr = console.error;
console.error = jest.fn();
chart.setOption<EChartsOption>({
series: [{
type: 'funnel'
}]
});
expect(console.error).toHaveBeenCalledWith(
makeSerieError('funnel', 'FunnelChart')
);
console.error = oldConsoleErr;
});
it('Should not report pie series missing error', function () {
const chart = createChart();
const oldConsoleErr = console.error;
console.error = jest.fn();
chart.setOption<EChartsOption>({
series: [{
type: 'pie'
}]
});
expect(console.error).not.toBeCalled();
console.error = oldConsoleErr;
});
});
\ No newline at end of file
...@@ -24,7 +24,7 @@ import { ParsedValue } from '../../../../src/util/types'; ...@@ -24,7 +24,7 @@ import { ParsedValue } from '../../../../src/util/types';
import { LegendOption } from '../../../../src/component/legend/LegendModel'; import { LegendOption } from '../../../../src/component/legend/LegendModel';
import TimelineModel from '../../../../src/component/timeline/TimelineModel'; import TimelineModel from '../../../../src/component/timeline/TimelineModel';
import { createChart, getECModel } from '../../core/utHelper'; import { createChart, getECModel } from '../../core/utHelper';
import { EChartsFullOption } from '../../../../src/option'; import { EChartsOption } from '../../../../src/export/option';
describe('timelineMediaOptions', function () { describe('timelineMediaOptions', function () {
...@@ -36,7 +36,7 @@ describe('timelineMediaOptions', function () { ...@@ -36,7 +36,7 @@ describe('timelineMediaOptions', function () {
return getECModel(chart).getComponent('series', seriesIndex) as SeriesModel; return getECModel(chart).getComponent('series', seriesIndex) as SeriesModel;
} }
function getLegendOption(chart: EChartsType): LegendOption { function getLegendOption(chart: EChartsType): LegendOption {
return getECModel(chart).getComponent('legend', 0).option; return getECModel(chart).getComponent('legend', 0).option as LegendOption;
} }
function getTimelineComponent(chart: EChartsType): TimelineModel { function getTimelineComponent(chart: EChartsType): TimelineModel {
return getECModel(chart).getComponent('timeline', 0) as TimelineModel; return getECModel(chart).getComponent('timeline', 0) as TimelineModel;
...@@ -60,7 +60,7 @@ describe('timelineMediaOptions', function () { ...@@ -60,7 +60,7 @@ describe('timelineMediaOptions', function () {
describe('parse_timeline_media_option', function () { describe('parse_timeline_media_option', function () {
it('parse_media_has_baseOption_has_default', function () { it('parse_media_has_baseOption_has_default', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
baseOption: { baseOption: {
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
yAxis: {}, yAxis: {},
...@@ -88,7 +88,7 @@ describe('timelineMediaOptions', function () { ...@@ -88,7 +88,7 @@ describe('timelineMediaOptions', function () {
}); });
it('parse_media_no_baseOption_has_default', function () { it('parse_media_no_baseOption_has_default', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
yAxis: {}, yAxis: {},
legend: { left: 10 }, legend: { left: 10 },
...@@ -112,7 +112,7 @@ describe('timelineMediaOptions', function () { ...@@ -112,7 +112,7 @@ describe('timelineMediaOptions', function () {
}); });
it('parse_media_no_baseOption_no_default', function () { it('parse_media_no_baseOption_no_default', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
yAxis: {}, yAxis: {},
legend: { left: 10 }, legend: { left: 10 },
...@@ -132,7 +132,7 @@ describe('timelineMediaOptions', function () { ...@@ -132,7 +132,7 @@ describe('timelineMediaOptions', function () {
}); });
it('parse_timeline_media_has_baseOption', function () { it('parse_timeline_media_has_baseOption', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
baseOption: { baseOption: {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
...@@ -166,13 +166,13 @@ describe('timelineMediaOptions', function () { ...@@ -166,13 +166,13 @@ describe('timelineMediaOptions', function () {
expect(getData0(chart, 0)).toEqual(88); expect(getData0(chart, 0)).toEqual(88);
expect(getLegendOption(chart).left).toEqual(50); expect(getLegendOption(chart).left).toEqual(50);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
expect(getLegendOption(chart).left).toEqual(50); expect(getLegendOption(chart).left).toEqual(50);
}); });
it('parse_timeline_media_no_baseOption', function () { it('parse_timeline_media_no_baseOption', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
yAxis: {}, yAxis: {},
...@@ -202,13 +202,13 @@ describe('timelineMediaOptions', function () { ...@@ -202,13 +202,13 @@ describe('timelineMediaOptions', function () {
expect(getData0(chart, 0)).toEqual(88); expect(getData0(chart, 0)).toEqual(88);
expect(getLegendOption(chart).left).toEqual(50); expect(getLegendOption(chart).left).toEqual(50);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
expect(getLegendOption(chart).left).toEqual(50); expect(getLegendOption(chart).left).toEqual(50);
}); });
it('parse_timeline_has_baseOption', function () { it('parse_timeline_has_baseOption', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
baseOption: { baseOption: {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
...@@ -227,12 +227,12 @@ describe('timelineMediaOptions', function () { ...@@ -227,12 +227,12 @@ describe('timelineMediaOptions', function () {
expect(getLegendOption(chart).right).not.toEqual(123); expect(getLegendOption(chart).right).not.toEqual(123);
expect(getTimelineComponent(chart) != null).toEqual(true); expect(getTimelineComponent(chart) != null).toEqual(true);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
}); });
it('parse_timeline_has_baseOption_compat', function () { it('parse_timeline_has_baseOption_compat', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
baseOption: { baseOption: {
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
...@@ -251,12 +251,12 @@ describe('timelineMediaOptions', function () { ...@@ -251,12 +251,12 @@ describe('timelineMediaOptions', function () {
expect(getLegendOption(chart).right).not.toEqual(123); expect(getLegendOption(chart).right).not.toEqual(123);
expect(getTimelineComponent(chart) != null).toEqual(true); expect(getTimelineComponent(chart) != null).toEqual(true);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
}); });
it('parse_timeline_has_baseOption_compat', function () { it('parse_timeline_has_baseOption_compat', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
baseOption: { baseOption: {
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
...@@ -275,12 +275,12 @@ describe('timelineMediaOptions', function () { ...@@ -275,12 +275,12 @@ describe('timelineMediaOptions', function () {
expect(getLegendOption(chart).right).not.toEqual(123); expect(getLegendOption(chart).right).not.toEqual(123);
expect(getTimelineComponent(chart) != null).toEqual(true); expect(getTimelineComponent(chart) != null).toEqual(true);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
}); });
it('parse_timeline_no_baseOption', function () { it('parse_timeline_no_baseOption', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
timeline: { axisType: 'category' }, timeline: { axisType: 'category' },
xAxis: { data: ['a'] }, xAxis: { data: ['a'] },
yAxis: {}, yAxis: {},
...@@ -296,7 +296,7 @@ describe('timelineMediaOptions', function () { ...@@ -296,7 +296,7 @@ describe('timelineMediaOptions', function () {
expect(getLegendOption(chart).right).not.toEqual(123); expect(getLegendOption(chart).right).not.toEqual(123);
expect(getTimelineComponent(chart) != null).toEqual(true); expect(getTimelineComponent(chart) != null).toEqual(true);
chart.setOption({ timeline: { currentIndex: 1 } }); chart.setOption<EChartsOption>({ timeline: { currentIndex: 1 } });
expect(getData0(chart, 0)).toEqual(99); expect(getData0(chart, 0)).toEqual(99);
}); });
...@@ -310,7 +310,7 @@ describe('timelineMediaOptions', function () { ...@@ -310,7 +310,7 @@ describe('timelineMediaOptions', function () {
describe('timeline_onceMore', function () { describe('timeline_onceMore', function () {
it('timeline_setOptionOnceMore_baseOption', function () { it('timeline_setOptionOnceMore_baseOption', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
baseOption: { baseOption: {
timeline: { timeline: {
axisType: 'category', axisType: 'category',
...@@ -344,7 +344,7 @@ describe('timelineMediaOptions', function () { ...@@ -344,7 +344,7 @@ describe('timelineMediaOptions', function () {
expect(getData0(chart, 0)).toEqual(11); expect(getData0(chart, 0)).toEqual(11);
expect(getData0(chart, 1)).toEqual(22); expect(getData0(chart, 1)).toEqual(22);
chart.setOption({ chart.setOption<EChartsOption>({
xAxis: {data: ['c']}, xAxis: {data: ['c']},
timeline: { timeline: {
currentIndex: 1 currentIndex: 1
...@@ -358,7 +358,7 @@ describe('timelineMediaOptions', function () { ...@@ -358,7 +358,7 @@ describe('timelineMediaOptions', function () {
it('timeline_setOptionOnceMore_substitudeTimelineOptions', function () { it('timeline_setOptionOnceMore_substitudeTimelineOptions', function () {
const option: EChartsFullOption = { const option: EChartsOption = {
baseOption: { baseOption: {
timeline: { timeline: {
axisType: 'category', axisType: 'category',
...@@ -416,7 +416,7 @@ describe('timelineMediaOptions', function () { ...@@ -416,7 +416,7 @@ describe('timelineMediaOptions', function () {
expect(getData0(chart, 0)).toEqual(1111); expect(getData0(chart, 0)).toEqual(1111);
expect(getData0(chart, 1)).toEqual(2222); expect(getData0(chart, 1)).toEqual(2222);
chart.setOption({ chart.setOption<EChartsOption>({
timeline: { timeline: {
currentIndex: 0 currentIndex: 0
} }
...@@ -425,7 +425,7 @@ describe('timelineMediaOptions', function () { ...@@ -425,7 +425,7 @@ describe('timelineMediaOptions', function () {
expect(getData0(chart, 0)).toEqual(55); expect(getData0(chart, 0)).toEqual(55);
expect(getData0(chart, 1)).toEqual(66); expect(getData0(chart, 1)).toEqual(66);
chart.setOption({ chart.setOption<EChartsOption>({
timeline: { timeline: {
currentIndex: 2 currentIndex: 2
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* under the License. * under the License.
*/ */
import { createChart, isValueFinite, getECModel } from '../../core/utHelper'; import { createChart, getECModel } from '../../core/utHelper';
import { EChartsType } from '../../../../src/echarts'; import { EChartsType } from '../../../../src/echarts';
import CartesianAxisModel from '../../../../src/coord/cartesian/AxisModel'; import CartesianAxisModel from '../../../../src/coord/cartesian/AxisModel';
import IntervalScale from '../../../../src/scale/Interval'; import IntervalScale from '../../../../src/scale/Interval';
...@@ -124,10 +124,10 @@ describe('scale_interval', function () { ...@@ -124,10 +124,10 @@ describe('scale_interval', function () {
const resultInterval = result.interval; const resultInterval = result.interval;
const niceTickExtent = result.niceTickExtent; const niceTickExtent = result.niceTickExtent;
expect(isValueFinite(resultInterval)).toEqual(true); expect(resultInterval).toBeFinite();
expect(isValueFinite(intervalPrecision)).toEqual(true); expect(intervalPrecision).toBeFinite();
expect(isValueFinite(niceTickExtent[0])).toEqual(true); expect(niceTickExtent[0]).toBeFinite();
expect(isValueFinite(niceTickExtent[1])).toEqual(true); expect(niceTickExtent[1]).toBeFinite();
expect(niceTickExtent[0]).toBeGreaterThanOrEqual(extent[0]); expect(niceTickExtent[0]).toBeGreaterThanOrEqual(extent[0]);
expect(niceTickExtent[1]).not.toBeGreaterThan(extent[1]); expect(niceTickExtent[1]).not.toBeGreaterThan(extent[1]);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
import { EChartsType } from '../../../../src/echarts'; import { EChartsType } from '../../../../src/echarts';
import { createChart } from '../../core/utHelper'; import { createChart } from '../../core/utHelper';
import { ZRColor } from '../../../../src/util/types'; import { ZRColor } from '../../../../src/util/types';
import { CustomSeriesRenderItemAPI, CustomSeriesRenderItemParams } from '../../../../src/chart/custom'; import { CustomSeriesRenderItemAPI, CustomSeriesRenderItemParams } from '../../../../src/chart/custom/install';
describe('custom_series', function () { describe('custom_series', function () {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册