;
-
- var markupFragment;
-
- if (isObject(result)) {
- if (result.type) {
- markupFragment = result;
- } else {
- if ("development" !== 'production') {
- console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result));
- }
- } // else {
- // markupText = (result as TooltipFormatResultLegacyObject).html;
- // markers = (result as TooltipFormatResultLegacyObject).markers;
- // if (markersExisting) {
- // markers = zrUtil.merge(markersExisting, markers);
- // }
- // }
-
- } else {
- markupText = result;
- }
-
- return {
- markupText: markupText,
- // markers: markers || markersExisting,
- markupFragment: markupFragment
- };
- }
-
- /**
- * @param {Object} define
- * @return See the return of `createTask`.
- */
-
- function createTask(define) {
- return new Task(define);
- }
-
- var Task =
- /** @class */
- function () {
- function Task(define) {
- define = define || {};
- this._reset = define.reset;
- this._plan = define.plan;
- this._count = define.count;
- this._onDirty = define.onDirty;
- this._dirty = true;
- }
- /**
- * @param step Specified step.
- * @param skip Skip customer perform call.
- * @param modBy Sampling window size.
- * @param modDataCount Sampling count.
- * @return whether unfinished.
- */
-
-
- Task.prototype.perform = function (performArgs) {
- var upTask = this._upstream;
- var skip = performArgs && performArgs.skip; // TODO some refactor.
- // Pull data. Must pull data each time, because context.data
- // may be updated by Series.setData.
-
- if (this._dirty && upTask) {
- var context = this.context;
- context.data = context.outputData = upTask.context.outputData;
- }
-
- if (this.__pipeline) {
- this.__pipeline.currentTask = this;
- }
-
- var planResult;
-
- if (this._plan && !skip) {
- planResult = this._plan(this.context);
- } // Support sharding by mod, which changes the render sequence and makes the rendered graphic
- // elements uniformed distributed when progress, especially when moving or zooming.
-
-
- var lastModBy = normalizeModBy(this._modBy);
- var lastModDataCount = this._modDataCount || 0;
- var modBy = normalizeModBy(performArgs && performArgs.modBy);
- var modDataCount = performArgs && performArgs.modDataCount || 0;
-
- if (lastModBy !== modBy || lastModDataCount !== modDataCount) {
- planResult = 'reset';
- }
-
- function normalizeModBy(val) {
- !(val >= 1) && (val = 1); // jshint ignore:line
-
- return val;
- }
-
- var forceFirstProgress;
-
- if (this._dirty || planResult === 'reset') {
- this._dirty = false;
- forceFirstProgress = this._doReset(skip);
- }
-
- this._modBy = modBy;
- this._modDataCount = modDataCount;
- var step = performArgs && performArgs.step;
-
- if (upTask) {
- if ("development" !== 'production') {
- assert(upTask._outputDueEnd != null);
- }
-
- this._dueEnd = upTask._outputDueEnd;
- } // DataTask or overallTask
- else {
- if ("development" !== 'production') {
- assert(!this._progress || this._count);
- }
-
- this._dueEnd = this._count ? this._count(this.context) : Infinity;
- } // Note: Stubs, that its host overall task let it has progress, has progress.
- // If no progress, pass index from upstream to downstream each time plan called.
-
-
- if (this._progress) {
- var start = this._dueIndex;
- var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd);
-
- if (!skip && (forceFirstProgress || start < end)) {
- var progress = this._progress;
-
- if (isArray(progress)) {
- for (var i = 0; i < progress.length; i++) {
- this._doProgress(progress[i], start, end, modBy, modDataCount);
- }
- } else {
- this._doProgress(progress, start, end, modBy, modDataCount);
- }
- }
-
- this._dueIndex = end; // If no `outputDueEnd`, assume that output data and
- // input data is the same, so use `dueIndex` as `outputDueEnd`.
-
- var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end;
-
- if ("development" !== 'production') {
- // ??? Can not rollback.
- assert(outputDueEnd >= this._outputDueEnd);
- }
-
- this._outputDueEnd = outputDueEnd;
- } else {
- // (1) Some overall task has no progress.
- // (2) Stubs, that its host overall task do not let it has progress, has no progress.
- // This should always be performed so it can be passed to downstream.
- this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd;
- }
-
- return this.unfinished();
- };
-
- Task.prototype.dirty = function () {
- this._dirty = true;
- this._onDirty && this._onDirty(this.context);
- };
-
- Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) {
- iterator.reset(start, end, modBy, modDataCount);
- this._callingProgress = progress;
-
- this._callingProgress({
- start: start,
- end: end,
- count: end - start,
- next: iterator.next
- }, this.context);
- };
-
- Task.prototype._doReset = function (skip) {
- this._dueIndex = this._outputDueEnd = this._dueEnd = 0;
- this._settedOutputEnd = null;
- var progress;
- var forceFirstProgress;
-
- if (!skip && this._reset) {
- progress = this._reset(this.context);
-
- if (progress && progress.progress) {
- forceFirstProgress = progress.forceFirstProgress;
- progress = progress.progress;
- } // To simplify no progress checking, array must has item.
-
-
- if (isArray(progress) && !progress.length) {
- progress = null;
- }
- }
-
- this._progress = progress;
- this._modBy = this._modDataCount = null;
- var downstream = this._downstream;
- downstream && downstream.dirty();
- return forceFirstProgress;
- };
-
- Task.prototype.unfinished = function () {
- return this._progress && this._dueIndex < this._dueEnd;
- };
- /**
- * @param downTask The downstream task.
- * @return The downstream task.
- */
-
-
- Task.prototype.pipe = function (downTask) {
- if ("development" !== 'production') {
- assert(downTask && !downTask._disposed && downTask !== this);
- } // If already downstream, do not dirty downTask.
-
-
- if (this._downstream !== downTask || this._dirty) {
- this._downstream = downTask;
- downTask._upstream = this;
- downTask.dirty();
- }
- };
-
- Task.prototype.dispose = function () {
- if (this._disposed) {
- return;
- }
-
- this._upstream && (this._upstream._downstream = null);
- this._downstream && (this._downstream._upstream = null);
- this._dirty = false;
- this._disposed = true;
- };
-
- Task.prototype.getUpstream = function () {
- return this._upstream;
- };
-
- Task.prototype.getDownstream = function () {
- return this._downstream;
- };
-
- Task.prototype.setOutputEnd = function (end) {
- // This only happend in dataTask, dataZoom, map, currently.
- // where dataZoom do not set end each time, but only set
- // when reset. So we should record the setted end, in case
- // that the stub of dataZoom perform again and earse the
- // setted end by upstream.
- this._outputDueEnd = this._settedOutputEnd = end;
- };
-
- return Task;
- }();
-
- var iterator = function () {
- var end;
- var current;
- var modBy;
- var modDataCount;
- var winCount;
- var it = {
- reset: function (s, e, sStep, sCount) {
- current = s;
- end = e;
- modBy = sStep;
- modDataCount = sCount;
- winCount = Math.ceil(modDataCount / modBy);
- it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext;
- }
- };
- return it;
-
- function sequentialNext() {
- return current < end ? current++ : null;
- }
-
- function modNext() {
- var dataIndex = current % winCount * modBy + Math.ceil(current / winCount);
- var result = current >= end ? null : dataIndex < modDataCount ? dataIndex // If modDataCount is smaller than data.count() (consider `appendData` case),
- // Use normal linear rendering mode.
- : current;
- current++;
- return result;
- }
- }(); ///////////////////////////////////////////////////////////
- // For stream debug (Should be commented out after used!)
- // @usage: printTask(this, 'begin');
- // @usage: printTask(this, null, {someExtraProp});
- // @usage: Use `__idxInPipeline` as conditional breakpiont.
- //
- // window.printTask = function (task: any, prefix: string, extra: { [key: string]: unknown }): void {
- // window.ecTaskUID == null && (window.ecTaskUID = 0);
- // task.uidDebug == null && (task.uidDebug = `task_${window.ecTaskUID++}`);
- // task.agent && task.agent.uidDebug == null && (task.agent.uidDebug = `task_${window.ecTaskUID++}`);
- // let props = [];
- // if (task.__pipeline) {
- // let val = `${task.__idxInPipeline}/${task.__pipeline.tail.__idxInPipeline} ${task.agent ? '(stub)' : ''}`;
- // props.push({text: '__idxInPipeline/total', value: val});
- // } else {
- // let stubCount = 0;
- // task.agentStubMap.each(() => stubCount++);
- // props.push({text: 'idx', value: `overall (stubs: ${stubCount})`});
- // }
- // props.push({text: 'uid', value: task.uidDebug});
- // if (task.__pipeline) {
- // props.push({text: 'pipelineId', value: task.__pipeline.id});
- // task.agent && props.push(
- // {text: 'stubFor', value: task.agent.uidDebug}
- // );
- // }
- // props.push(
- // {text: 'dirty', value: task._dirty},
- // {text: 'dueIndex', value: task._dueIndex},
- // {text: 'dueEnd', value: task._dueEnd},
- // {text: 'outputDueEnd', value: task._outputDueEnd}
- // );
- // if (extra) {
- // Object.keys(extra).forEach(key => {
- // props.push({text: key, value: extra[key]});
- // });
- // }
- // let args = ['color: blue'];
- // let msg = `%c[${prefix || 'T'}] %c` + props.map(item => (
- // args.push('color: green', 'color: red'),
- // `${item.text}: %c${item.value}`
- // )).join('%c, ');
- // console.log.apply(console, [msg].concat(args));
- // // console.log(this);
- // };
- // window.printPipeline = function (task: any, prefix: string) {
- // const pipeline = task.__pipeline;
- // let currTask = pipeline.head;
- // while (currTask) {
- // window.printTask(currTask, prefix);
- // currTask = currTask._downstream;
- // }
- // };
- // window.showChain = function (chainHeadTask) {
- // var chain = [];
- // var task = chainHeadTask;
- // while (task) {
- // chain.push({
- // task: task,
- // up: task._upstream,
- // down: task._downstream,
- // idxInPipeline: task.__idxInPipeline
- // });
- // task = task._downstream;
- // }
- // return chain;
- // };
- // window.findTaskInChain = function (task, chainHeadTask) {
- // let chain = window.showChain(chainHeadTask);
- // let result = [];
- // for (let i = 0; i < chain.length; i++) {
- // let chainItem = chain[i];
- // if (chainItem.task === task) {
- // result.push(i);
- // }
- // }
- // return result;
- // };
- // window.printChainAEachInChainB = function (chainHeadTaskA, chainHeadTaskB) {
- // let chainA = window.showChain(chainHeadTaskA);
- // for (let i = 0; i < chainA.length; i++) {
- // console.log('chainAIdx:', i, 'inChainB:', window.findTaskInChain(chainA[i].task, chainHeadTaskB));
- // }
- // };
-
- /**
- * Convert raw the value in to inner value in List.
- *
- * [Performance sensitive]
- *
- * [Caution]: this is the key logic of user value parser.
- * For backward compatibiliy, do not modify it until have to!
- */
-
- function parseDataValue(value, // For high performance, do not omit the second param.
- opt) {
- // Performance sensitive.
- var dimType = opt && opt.type;
-
- if (dimType === 'ordinal') {
- // If given value is a category string
- return value;
- }
-
- if (dimType === 'time' // spead up when using timestamp
- && typeof value !== 'number' && value != null && value !== '-') {
- value = +parseDate(value);
- } // dimType defaults 'number'.
- // If dimType is not ordinal and value is null or undefined or NaN or '-',
- // parse to NaN.
- // number-like string (like ' 123 ') can be converted to a number.
- // where null/undefined or other string will be converted to NaN.
-
-
- return value == null || value === '' ? NaN // If string (like '-'), using '+' parse to NaN
- // If object, also parse to NaN
- : +value;
- }
- var valueParserMap = createHashMap({
- 'number': function (val) {
- // Do not use `numericToNumber` here. We have by defualt `numericToNumber`.
- // Here the number parser can have loose rule:
- // enable to cut suffix: "120px" => 120, "14%" => 14.
- return parseFloat(val);
- },
- 'time': function (val) {
- // return timestamp.
- return +parseDate(val);
- },
- 'trim': function (val) {
- return typeof val === 'string' ? trim(val) : val;
- }
- });
- function getRawValueParser(type) {
- return valueParserMap.get(type);
- }
- var ORDER_COMPARISON_OP_MAP = {
- lt: function (lval, rval) {
- return lval < rval;
- },
- lte: function (lval, rval) {
- return lval <= rval;
- },
- gt: function (lval, rval) {
- return lval > rval;
- },
- gte: function (lval, rval) {
- return lval >= rval;
- }
- };
-
- var FilterOrderComparator =
- /** @class */
- function () {
- function FilterOrderComparator(op, rval) {
- if (typeof rval !== 'number') {
- var errMsg = '';
-
- if ("development" !== 'production') {
- errMsg = 'rvalue of "<", ">", "<=", ">=" can only be number in filter.';
- }
-
- throwError(errMsg);
- }
-
- this._opFn = ORDER_COMPARISON_OP_MAP[op];
- this._rvalFloat = numericToNumber(rval);
- } // Performance sensitive.
-
-
- FilterOrderComparator.prototype.evaluate = function (lval) {
- // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat.
- return typeof lval === 'number' ? this._opFn(lval, this._rvalFloat) : this._opFn(numericToNumber(lval), this._rvalFloat);
- };
-
- return FilterOrderComparator;
- }();
-
- var SortOrderComparator =
- /** @class */
- function () {
- /**
- * @param order by defualt: 'asc'
- * @param incomparable by defualt: Always on the tail.
- * That is, if 'asc' => 'max', if 'desc' => 'min'
- * See the definition of "incomparable" in [SORT_COMPARISON_RULE]
- */
- function SortOrderComparator(order, incomparable) {
- var isDesc = order === 'desc';
- this._resultLT = isDesc ? 1 : -1;
-
- if (incomparable == null) {
- incomparable = isDesc ? 'min' : 'max';
- }
-
- this._incomparable = incomparable === 'min' ? -Infinity : Infinity;
- } // See [SORT_COMPARISON_RULE].
- // Performance sensitive.
-
-
- SortOrderComparator.prototype.evaluate = function (lval, rval) {
- // Most cases is 'number', and typeof maybe 10 times faseter than parseFloat.
- var lvalTypeof = typeof lval;
- var rvalTypeof = typeof rval;
- var lvalFloat = lvalTypeof === 'number' ? lval : numericToNumber(lval);
- var rvalFloat = rvalTypeof === 'number' ? rval : numericToNumber(rval);
- var lvalNotNumeric = isNaN(lvalFloat);
- var rvalNotNumeric = isNaN(rvalFloat);
-
- if (lvalNotNumeric) {
- lvalFloat = this._incomparable;
- }
-
- if (rvalNotNumeric) {
- rvalFloat = this._incomparable;
- }
-
- if (lvalNotNumeric && rvalNotNumeric) {
- var lvalIsStr = lvalTypeof === 'string';
- var rvalIsStr = rvalTypeof === 'string';
-
- if (lvalIsStr) {
- lvalFloat = rvalIsStr ? lval : 0;
- }
-
- if (rvalIsStr) {
- rvalFloat = lvalIsStr ? rval : 0;
- }
- }
-
- return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0;
- };
-
- return SortOrderComparator;
- }();
-
- var FilterEqualityComparator =
- /** @class */
- function () {
- function FilterEqualityComparator(isEq, rval) {
- this._rval = rval;
- this._isEQ = isEq;
- this._rvalTypeof = typeof rval;
- this._rvalFloat = numericToNumber(rval);
- } // Performance sensitive.
-
-
- FilterEqualityComparator.prototype.evaluate = function (lval) {
- var eqResult = lval === this._rval;
-
- if (!eqResult) {
- var lvalTypeof = typeof lval;
-
- if (lvalTypeof !== this._rvalTypeof && (lvalTypeof === 'number' || this._rvalTypeof === 'number')) {
- eqResult = numericToNumber(lval) === this._rvalFloat;
- }
- }
-
- return this._isEQ ? eqResult : !eqResult;
- };
-
- return FilterEqualityComparator;
- }();
- /**
- * [FILTER_COMPARISON_RULE]
- * `lt`|`lte`|`gt`|`gte`:
- * + rval must be a number. And lval will be converted to number (`numericToNumber`) to compare.
- * `eq`:
- * + If same type, compare with `===`.
- * + If there is one number, convert to number (`numericToNumber`) to compare.
- * + Else return `false`.
- * `ne`:
- * + Not `eq`.
- *
- *
- * [SORT_COMPARISON_RULE]
- * All the values are grouped into three categories:
- * + "numeric" (number and numeric string)
- * + "non-numeric-string" (string that excluding numeric string)
- * + "others"
- * "numeric" vs "numeric": values are ordered by number order.
- * "non-numeric-string" vs "non-numeric-string": values are ordered by ES spec (#sec-abstract-relational-comparison).
- * "others" vs "others": do not change order (always return 0).
- * "numeric" vs "non-numeric-string": "non-numeric-string" is treated as "incomparable".
- * "number" vs "others": "others" is treated as "incomparable".
- * "non-numeric-string" vs "others": "others" is treated as "incomparable".
- * "incomparable" will be seen as -Infinity or Infinity (depends on the settings).
- * MEMO:
- * non-numeric string sort make sence when need to put the items with the same tag together.
- * But if we support string sort, we still need to avoid the misleading like `'2' > '12'`,
- * So we treat "numeric-string" sorted by number order rather than string comparison.
- *
- *
- * [CHECK_LIST_OF_THE_RULE_DESIGN]
- * + Do not support string comparison until required. And also need to
- * void the misleading of "2" > "12".
- * + Should avoid the misleading case:
- * `" 22 " gte "22"` is `true` but `" 22 " eq "22"` is `false`.
- * + JS bad case should be avoided: null <= 0, [] <= 0, ' ' <= 0, ...
- * + Only "numeric" can be converted to comparable number, otherwise converted to NaN.
- * See `util/number.ts#numericToNumber`.
- *
- * @return If `op` is not `RelationalOperator`, return null;
- */
-
-
- function createFilterComparator(op, rval) {
- return op === 'eq' || op === 'ne' ? new FilterEqualityComparator(op === 'eq', rval) : hasOwn(ORDER_COMPARISON_OP_MAP, op) ? new FilterOrderComparator(op, rval) : null;
- }
-
- /**
- * TODO: disable writable.
- * This structure will be exposed to users.
- */
-
- var ExternalSource =
- /** @class */
- function () {
- function ExternalSource() {}
-
- ExternalSource.prototype.getRawData = function () {
- // Only built-in transform available.
- throw new Error('not supported');
- };
-
- ExternalSource.prototype.getRawDataItem = function (dataIndex) {
- // Only built-in transform available.
- throw new Error('not supported');
- };
-
- ExternalSource.prototype.cloneRawData = function () {
- return;
- };
- /**
- * @return If dimension not found, return null/undefined.
- */
-
-
- ExternalSource.prototype.getDimensionInfo = function (dim) {
- return;
- };
- /**
- * dimensions defined if and only if either:
- * (a) dataset.dimensions are declared.
- * (b) dataset data include dimensions definitions in data (detected or via specified `sourceHeader`).
- * If dimensions are defined, `dimensionInfoAll` is corresponding to
- * the defined dimensions.
- * Otherwise, `dimensionInfoAll` is determined by data columns.
- * @return Always return an array (even empty array).
- */
-
-
- ExternalSource.prototype.cloneAllDimensionInfo = function () {
- return;
- };
-
- ExternalSource.prototype.count = function () {
- return;
- };
- /**
- * Only support by dimension index.
- * No need to support by dimension name in transform function,
- * becuase transform function is not case-specific, no need to use name literally.
- */
-
-
- ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) {
- return;
- };
-
- ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) {
- return;
- };
-
- ExternalSource.prototype.convertValue = function (rawVal, dimInfo) {
- return parseDataValue(rawVal, dimInfo);
- };
-
- return ExternalSource;
- }();
-
- function createExternalSource(internalSource, externalTransform) {
- var extSource = new ExternalSource();
- var data = internalSource.data;
- var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat;
- var sourceHeaderCount = internalSource.startIndex;
- var errMsg = '';
-
- if (internalSource.seriesLayoutBy !== SERIES_LAYOUT_BY_COLUMN) {
- // For the logic simplicity in transformer, only 'culumn' is
- // supported in data transform. Otherwise, the `dimensionsDefine`
- // might be detected by 'row', which probably confuses users.
- if ("development" !== 'production') {
- errMsg = '`seriesLayoutBy` of upstream dataset can only be "column" in data transform.';
- }
-
- throwError(errMsg);
- } // [MEMO]
- // Create a new dimensions structure for exposing.
- // Do not expose all dimension info to users directly.
- // Becuase the dimension is probably auto detected from data and not might reliable.
- // Should not lead the transformers to think that is relialbe and return it.
- // See [DIMENSION_INHERIT_RULE] in `sourceManager.ts`.
-
-
- var dimensions = [];
- var dimsByName = {};
- var dimsDef = internalSource.dimensionsDefine;
-
- if (dimsDef) {
- each(dimsDef, function (dimDef, idx) {
- var name = dimDef.name;
- var dimDefExt = {
- index: idx,
- name: name,
- displayName: dimDef.displayName
- };
- dimensions.push(dimDefExt); // Users probably not sepcify dimension name. For simplicity, data transform
- // do not generate dimension name.
-
- if (name != null) {
- // Dimension name should not be duplicated.
- // For simplicity, data transform forbid name duplication, do not generate
- // new name like module `completeDimensions.ts` did, but just tell users.
- var errMsg_1 = '';
-
- if (hasOwn(dimsByName, name)) {
- if ("development" !== 'production') {
- errMsg_1 = 'dimension name "' + name + '" duplicated.';
- }
-
- throwError(errMsg_1);
- }
-
- dimsByName[name] = dimDefExt;
- }
- });
- } // If dimension definitions are not defined and can not be detected.
- // e.g., pure data `[[11, 22], ...]`.
- else {
- for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) {
- // Do not generete name or anything others. The consequence process in
- // `transform` or `series` probably have there own name generation strategry.
- dimensions.push({
- index: i
- });
- }
- } // Implement public methods:
-
-
- var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);
-
- if (externalTransform.__isBuiltIn) {
- extSource.getRawDataItem = function (dataIndex) {
- return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
- };
-
- extSource.getRawData = bind(getRawData, null, internalSource);
- }
-
- extSource.cloneRawData = bind(cloneRawData, null, internalSource);
- var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN);
- extSource.count = bind(rawCounter, null, data, sourceHeaderCount, dimensions);
- var rawValueGetter = getRawSourceValueGetter(sourceFormat);
-
- extSource.retrieveValue = function (dataIndex, dimIndex) {
- var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex);
- return retrieveValueFromItem(rawItem, dimIndex);
- };
-
- var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) {
- if (dataItem == null) {
- return;
- }
-
- var dimDef = dimensions[dimIndex]; // When `dimIndex` is `null`, `rawValueGetter` return the whole item.
-
- if (dimDef) {
- return rawValueGetter(dataItem, dimIndex, dimDef.name);
- }
- };
-
- extSource.getDimensionInfo = bind(getDimensionInfo, null, dimensions, dimsByName);
- extSource.cloneAllDimensionInfo = bind(cloneAllDimensionInfo, null, dimensions);
- return extSource;
- }
-
- function getRawData(upstream) {
- var sourceFormat = upstream.sourceFormat;
-
- if (!isSupportedSourceFormat(sourceFormat)) {
- var errMsg = '';
-
- if ("development" !== 'production') {
- errMsg = '`getRawData` is not supported in source format ' + sourceFormat;
- }
-
- throwError(errMsg);
- }
-
- return upstream.data;
- }
-
- function cloneRawData(upstream) {
- var sourceFormat = upstream.sourceFormat;
- var data = upstream.data;
-
- if (!isSupportedSourceFormat(sourceFormat)) {
- var errMsg = '';
-
- if ("development" !== 'production') {
- errMsg = '`cloneRawData` is not supported in source format ' + sourceFormat;
- }
-
- throwError(errMsg);
- }
-
- if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) {
- var result = [];
-
- for (var i = 0, len = data.length; i < len; i++) {
- // Not strictly clone for performance
- result.push(data[i].slice());
- }
-
- return result;
- } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) {
- var result = [];
-
- for (var i = 0, len = data.length; i < len; i++) {
- // Not strictly clone for performance
- result.push(extend({}, data[i]));
- }
-
- return result;
- }
- }
-
- function getDimensionInfo(dimensions, dimsByName, dim) {
- if (dim == null) {
- return;
- } // Keep the same logic as `List::getDimension` did.
-
-
- if (typeof dim === 'number' // If being a number-like string but not being defined a dimension name.
- || !isNaN(dim) && !hasOwn(dimsByName, dim)) {
- return dimensions[dim];
- } else if (hasOwn(dimsByName, dim)) {
- return dimsByName[dim];
- }
- }
-
- function cloneAllDimensionInfo(dimensions) {
- return clone(dimensions);
- }
-
- var externalTransformMap = createHashMap();
- function registerExternalTransform(externalTransform) {
- externalTransform = clone(externalTransform);
- var type = externalTransform.type;
- var errMsg = '';
-
- if (!type) {
- if ("development" !== 'production') {
- errMsg = 'Must have a `type` when `registerTransform`.';
- }
-
- throwError(errMsg);
- }
-
- var typeParsed = type.split(':');
-
- if (typeParsed.length !== 2) {
- if ("development" !== 'production') {
- errMsg = 'Name must include namespace like "ns:regression".';
- }
-
- throwError(errMsg);
- } // Namespace 'echarts:xxx' is official namespace, where the transforms should
- // be called directly via 'xxx' rather than 'echarts:xxx'.
-
-
- var isBuiltIn = false;
-
- if (typeParsed[0] === 'echarts') {
- type = typeParsed[1];
- isBuiltIn = true;
- }
-
- externalTransform.__isBuiltIn = isBuiltIn;
- externalTransformMap.set(type, externalTransform);
- }
- function applyDataTransform(rawTransOption, sourceList, infoForPrint) {
- var pipedTransOption = normalizeToArray(rawTransOption);
- var pipeLen = pipedTransOption.length;
- var errMsg = '';
-
- if (!pipeLen) {
- if ("development" !== 'production') {
- errMsg = 'If `transform` declared, it should at least contain one transform.';
- }
-
- throwError(errMsg);
- }
-
- for (var i = 0, len = pipeLen; i < len; i++) {
- var transOption = pipedTransOption[i];
- sourceList = applySingleDataTransform(transOption, sourceList, infoForPrint, pipeLen === 1 ? null : i); // piped transform only support single input, except the fist one.
- // piped transform only support single output, except the last one.
-
- if (i !== len - 1) {
- sourceList.length = Math.max(sourceList.length, 1);
- }
- }
-
- return sourceList;
- }
-
- function applySingleDataTransform(transOption, upSourceList, infoForPrint, // If `pipeIndex` is null/undefined, no piped transform.
- pipeIndex) {
- var errMsg = '';
-
- if (!upSourceList.length) {
- if ("development" !== 'production') {
- errMsg = 'Must have at least one upstream dataset.';
- }
-
- throwError(errMsg);
- }
-
- if (!isObject(transOption)) {
- if ("development" !== 'production') {
- errMsg = 'transform declaration must be an object rather than ' + typeof transOption + '.';
- }
-
- throwError(errMsg);
- }
-
- var transType = transOption.type;
- var externalTransform = externalTransformMap.get(transType);
-
- if (!externalTransform) {
- if ("development" !== 'production') {
- errMsg = 'Can not find transform on type "' + transType + '".';
- }
-
- throwError(errMsg);
- } // Prepare source
-
-
- var extUpSourceList = map(upSourceList, function (upSource) {
- return createExternalSource(upSource, externalTransform);
- });
- var resultList = normalizeToArray(externalTransform.transform({
- upstream: extUpSourceList[0],
- upstreamList: extUpSourceList,
- config: clone(transOption.config)
- }));
-
- if ("development" !== 'production') {
- if (transOption.print) {
- var printStrArr = map(resultList, function (extSource) {
- var pipeIndexStr = pipeIndex != null ? ' === pipe index: ' + pipeIndex : '';
- return ['=== dataset index: ' + infoForPrint.datasetIndex + pipeIndexStr + ' ===', '- transform result data:', makePrintable(extSource.data), '- transform result dimensions:', makePrintable(extSource.dimensions)].join('\n');
- }).join('\n');
- consoleLog(printStrArr);
- }
- }
-
- return map(resultList, function (result, resultIndex) {
- var errMsg = '';
-
- if (!isObject(result)) {
- if ("development" !== 'production') {
- errMsg = 'A transform should not return some empty results.';
- }
-
- throwError(errMsg);
- }
-
- if (!result.data) {
- if ("development" !== 'production') {
- errMsg = 'Transform result data should be not be null or undefined';
- }
-
- throwError(errMsg);
- }
-
- var sourceFormat = detectSourceFormat(result.data);
-
- if (!isSupportedSourceFormat(sourceFormat)) {
- if ("development" !== 'production') {
- errMsg = 'Transform result data should be array rows or object rows.';
- }
-
- throwError(errMsg);
- }
-
- var resultMetaRawOption;
- var firstUpSource = upSourceList[0];
- /**
- * Intuitively, the end users known the content of the original `dataset.source`,
- * calucating the transform result in mind.
- * Suppose the original `dataset.source` is:
- * ```js
- * [
- * ['product', '2012', '2013', '2014', '2015'],
- * ['AAA', 41.1, 30.4, 65.1, 53.3],
- * ['BBB', 86.5, 92.1, 85.7, 83.1],
- * ['CCC', 24.1, 67.2, 79.5, 86.4]
- * ]
- * ```
- * The dimension info have to be detected from the source data.
- * Some of the transformers (like filter, sort) will follow the dimension info
- * of upstream, while others use new dimensions (like aggregate).
- * Transformer can output a field `dimensions` to define the its own output dimensions.
- * We also allow transformers to ignore the output `dimensions` field, and
- * inherit the upstream dimensions definition. It can reduce the burden of handling
- * dimensions in transformers.
- *
- * See also [DIMENSION_INHERIT_RULE] in `sourceManager.ts`.
- */
-
- if (firstUpSource && resultIndex === 0 // If transformer returns `dimensions`, it means that the transformer has different
- // dimensions definitions. We do not inherit anything from upstream.
- && !result.dimensions) {
- var startIndex = firstUpSource.startIndex; // We copy the header of upstream to the result becuase:
- // (1) The returned data always does not contain header line and can not be used
- // as dimension-detection. In this case we can not use "detected dimensions" of
- // upstream directly, because it might be detected based on different `seriesLayoutBy`.
- // (2) We should support that the series read the upstream source in `seriesLayoutBy: 'row'`.
- // So the original detected header should be add to the result, otherwise they can not be read.
-
- if (startIndex) {
- result.data = firstUpSource.data.slice(0, startIndex).concat(result.data);
- }
-
- resultMetaRawOption = {
- seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,
- sourceHeader: startIndex,
- dimensions: firstUpSource.metaRawOption.dimensions
- };
- } else {
- resultMetaRawOption = {
- seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN,
- sourceHeader: 0,
- dimensions: result.dimensions
- };
- }
-
- return createSource(result.data, resultMetaRawOption, null);
- });
- }
-
- function isSupportedSourceFormat(sourceFormat) {
- return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS;
- }
-
- var UNDEFINED = 'undefined';
- /* global Float64Array, Int32Array, Uint32Array, Uint16Array */
- // Caution: MUST not use `new CtorUint32Array(arr, 0, len)`, because the Ctor of array is
- // different from the Ctor of typed array.
-
- var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array;
- var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array;
- var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array;
- var CtorFloat64Array = typeof Float64Array === UNDEFINED ? Array : Float64Array;
- /**
- * Multi dimensional data store
- */
-
- var dataCtors = {
- 'float': CtorFloat64Array,
- 'int': CtorInt32Array,
- // Ordinal data type can be string or int
- 'ordinal': Array,
- 'number': Array,
- 'time': CtorFloat64Array
- };
- var defaultDimValueGetters;
-
- function getIndicesCtor(rawCount) {
- // The possible max value in this._indicies is always this._rawCount despite of filtering.
- return rawCount > 65535 ? CtorUint32Array : CtorUint16Array;
- }
-
- function getInitialExtent() {
- return [Infinity, -Infinity];
- }
-
- function cloneChunk(originalChunk) {
- var Ctor = originalChunk.constructor; // Only shallow clone is enough when Array.
-
- return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk);
- }
-
- function prepareStore(store, dimIdx, dimType, end, append) {
- var DataCtor = dataCtors[dimType || 'float'];
-
- if (append) {
- var oldStore = store[dimIdx];
- var oldLen = oldStore && oldStore.length;
-
- if (!(oldLen === end)) {
- var newStore = new DataCtor(end); // The cost of the copy is probably inconsiderable
- // within the initial chunkSize.
-
- for (var j = 0; j < oldLen; j++) {
- newStore[j] = oldStore[j];
- }
-
- store[dimIdx] = newStore;
- }
- } else {
- store[dimIdx] = new DataCtor(end);
- }
- }
- /**
- * Basically, DataStore API keep immutable.
- */
-
- var DataStore =
- /** @class */
- function () {
- function DataStore() {
- this._chunks = []; // It will not be calculated util needed.
-
- this._rawExtent = [];
- this._extent = [];
- this._count = 0;
- this._rawCount = 0;
- this._calcDimNameToIdx = createHashMap();
- }
- /**
- * Initialize from data
- */
-
-
- DataStore.prototype.initData = function (provider, inputDimensions, dimValueGetter) {
- if ("development" !== 'production') {
- assert(isFunction(provider.getItem) && isFunction(provider.count), 'Inavlid data provider.');
- }
-
- this._provider = provider; // Clear
-
- this._chunks = [];
- this._indices = null;
- this.getRawIndex = this._getRawIdxIdentity;
- var source = provider.getSource();
- var defaultGetter = this.defaultDimValueGetter = defaultDimValueGetters[source.sourceFormat]; // Default dim value getter
-
- this._dimValueGetter = dimValueGetter || defaultGetter; // Reset raw extent.
-
- this._rawExtent = [];
- var willRetrieveDataByName = shouldRetrieveDataByName(source);
- this._dimensions = map(inputDimensions, function (dim) {
- if ("development" !== 'production') {
- if (willRetrieveDataByName) {
- assert(dim.property != null);
- }
- }
-
- return {
- // Only pick these two props. Not leak other properties like orderMeta.
- type: dim.type,
- property: dim.property
- };
- });
-
- this._initDataFromProvider(0, provider.count());
- };
-
- DataStore.prototype.getProvider = function () {
- return this._provider;
- };
- /**
- * Caution: even when a `source` instance owned by a series, the created data store
- * may still be shared by different sereis (the source hash does not use all `source`
- * props, see `sourceManager`). In this case, the `source` props that are not used in
- * hash (like `source.dimensionDefine`) probably only belongs to a certain series and
- * thus should not be fetch here.
- */
-
-
- DataStore.prototype.getSource = function () {
- return this._provider.getSource();
- };
- /**
- * @caution Only used in dataStack.
- */
-
-
- DataStore.prototype.ensureCalculationDimension = function (dimName, type) {
- var calcDimNameToIdx = this._calcDimNameToIdx;
- var dimensions = this._dimensions;
- var calcDimIdx = calcDimNameToIdx.get(dimName);
-
- if (calcDimIdx != null) {
- if (dimensions[calcDimIdx].type === type) {
- return calcDimIdx;
- }
- } else {
- calcDimIdx = dimensions.length;
- }
-
- dimensions[calcDimIdx] = {
- type: type
- };
- calcDimNameToIdx.set(dimName, calcDimIdx);
- this._chunks[calcDimIdx] = new dataCtors[type || 'float'](this._rawCount);
- this._rawExtent[calcDimIdx] = getInitialExtent();
- return calcDimIdx;
- };
-
- DataStore.prototype.collectOrdinalMeta = function (dimIdx, ordinalMeta) {
- var chunk = this._chunks[dimIdx];
- var dim = this._dimensions[dimIdx];
- var rawExtents = this._rawExtent;
- var offset = dim.ordinalOffset || 0;
- var len = chunk.length;
-
- if (offset === 0) {
- // We need to reset the rawExtent if collect is from start.
- // Because this dimension may be guessed as number and calcuating a wrong extent.
- rawExtents[dimIdx] = getInitialExtent();
- }
-
- var dimRawExtent = rawExtents[dimIdx]; // Parse from previous data offset. len may be changed after appendData
-
- for (var i = offset; i < len; i++) {
- var val = chunk[i] = ordinalMeta.parseAndCollect(chunk[i]);
- dimRawExtent[0] = Math.min(val, dimRawExtent[0]);
- dimRawExtent[1] = Math.max(val, dimRawExtent[1]);
- }
-
- dim.ordinalMeta = ordinalMeta;
- dim.ordinalOffset = len;
- dim.type = 'ordinal'; // Force to be ordinal
- };
-
- DataStore.prototype.getOrdinalMeta = function (dimIdx) {
- var dimInfo = this._dimensions[dimIdx];
- var ordinalMeta = dimInfo.ordinalMeta;
- return ordinalMeta;
- };
-
- DataStore.prototype.getDimensionProperty = function (dimIndex) {
- var item = this._dimensions[dimIndex];
- return item && item.property;
- };
- /**
- * Caution: Can be only called on raw data (before `this._indices` created).
- */
-
-
- DataStore.prototype.appendData = function (data) {
- if ("development" !== 'production') {
- assert(!this._indices, 'appendData can only be called on raw data.');
- }
-
- var provider = this._provider;
- var start = this.count();
- provider.appendData(data);
- var end = provider.count();
-
- if (!provider.persistent) {
- end += start;
- }
-
- if (start < end) {
- this._initDataFromProvider(start, end, true);
- }
-
- return [start, end];
- };
-
- DataStore.prototype.appendValues = function (values, minFillLen) {
- var chunks = this._chunks;
- var dimensions = this._dimensions;
- var dimLen = dimensions.length;
- var rawExtent = this._rawExtent;
- var start = this.count();
- var end = start + Math.max(values.length, minFillLen || 0);
-
- for (var i = 0; i < dimLen; i++) {
- var dim = dimensions[i];
- prepareStore(chunks, i, dim.type, end, true);
- }
-
- var emptyDataItem = [];
-
- for (var idx = start; idx < end; idx++) {
- var sourceIdx = idx - start; // Store the data by dimensions
-
- for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
- var dim = dimensions[dimIdx];
- var val = defaultDimValueGetters.arrayRows.call(this, values[sourceIdx] || emptyDataItem, dim.property, sourceIdx, dimIdx);
- chunks[dimIdx][idx] = val;
- var dimRawExtent = rawExtent[dimIdx];
- val < dimRawExtent[0] && (dimRawExtent[0] = val);
- val > dimRawExtent[1] && (dimRawExtent[1] = val);
- }
- }
-
- this._rawCount = this._count = end;
- return {
- start: start,
- end: end
- };
- };
-
- DataStore.prototype._initDataFromProvider = function (start, end, append) {
- var provider = this._provider;
- var chunks = this._chunks;
- var dimensions = this._dimensions;
- var dimLen = dimensions.length;
- var rawExtent = this._rawExtent;
- var dimNames = map(dimensions, function (dim) {
- return dim.property;
- });
-
- for (var i = 0; i < dimLen; i++) {
- var dim = dimensions[i];
-
- if (!rawExtent[i]) {
- rawExtent[i] = getInitialExtent();
- }
-
- prepareStore(chunks, i, dim.type, end, append);
- }
-
- if (provider.fillStorage) {
- provider.fillStorage(start, end, chunks, rawExtent);
- } else {
- var dataItem = [];
-
- for (var idx = start; idx < end; idx++) {
- // NOTICE: Try not to write things into dataItem
- dataItem = provider.getItem(idx, dataItem); // Each data item is value
- // [1, 2]
- // 2
- // Bar chart, line chart which uses category axis
- // only gives the 'y' value. 'x' value is the indices of category
- // Use a tempValue to normalize the value to be a (x, y) value
- // Store the data by dimensions
-
- for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) {
- var dimStorage = chunks[dimIdx]; // PENDING NULL is empty or zero
-
- var val = this._dimValueGetter(dataItem, dimNames[dimIdx], idx, dimIdx);
-
- dimStorage[idx] = val;
- var dimRawExtent = rawExtent[dimIdx];
- val < dimRawExtent[0] && (dimRawExtent[0] = val);
- val > dimRawExtent[1] && (dimRawExtent[1] = val);
- }
- }
- }
-
- if (!provider.persistent && provider.clean) {
- // Clean unused data if data source is typed array.
- provider.clean();
- }
-
- this._rawCount = this._count = end; // Reset data extent
-
- this._extent = [];
- };
-
- DataStore.prototype.count = function () {
- return this._count;
- };
- /**
- * Get value. Return NaN if idx is out of range.
- */
-
-
- DataStore.prototype.get = function (dim, idx) {
- if (!(idx >= 0 && idx < this._count)) {
- return NaN;
- }
-
- var dimStore = this._chunks[dim];
- return dimStore ? dimStore[this.getRawIndex(idx)] : NaN;
- };
-
- DataStore.prototype.getValues = function (dimensions, idx) {
- var values = [];
- var dimArr = [];
-
- if (idx == null) {
- idx = dimensions; // TODO get all from store?
-
- dimensions = []; // All dimensions
-
- for (var i = 0; i < this._dimensions.length; i++) {
- dimArr.push(i);
- }
- } else {
- dimArr = dimensions;
- }
-
- for (var i = 0, len = dimArr.length; i < len; i++) {
- values.push(this.get(dimArr[i], idx));
- }
-
- return values;
- };
- /**
- * @param dim concrete dim
- */
-
-
- DataStore.prototype.getByRawIndex = function (dim, rawIdx) {
- if (!(rawIdx >= 0 && rawIdx < this._rawCount)) {
- return NaN;
- }
-
- var dimStore = this._chunks[dim];
- return dimStore ? dimStore[rawIdx] : NaN;
- };
- /**
- * Get sum of data in one dimension
- */
-
-
- DataStore.prototype.getSum = function (dim) {
- var dimData = this._chunks[dim];
- var sum = 0;
-
- if (dimData) {
- for (var i = 0, len = this.count(); i < len; i++) {
- var value = this.get(dim, i);
-
- if (!isNaN(value)) {
- sum += value;
- }
- }
- }
-
- return sum;
- };
- /**
- * Get median of data in one dimension
- */
-
-
- DataStore.prototype.getMedian = function (dim) {
- var dimDataArray = []; // map all data of one dimension
-
- this.each([dim], function (val) {
- if (!isNaN(val)) {
- dimDataArray.push(val);
- }
- }); // TODO
- // Use quick select?
-
- var sortedDimDataArray = dimDataArray.sort(function (a, b) {
- return a - b;
- });
- var len = this.count(); // calculate median
-
- return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2;
- };
- /**
- * Retreive the index with given raw data index
- */
-
-
- DataStore.prototype.indexOfRawIndex = function (rawIndex) {
- if (rawIndex >= this._rawCount || rawIndex < 0) {
- return -1;
- }
-
- if (!this._indices) {
- return rawIndex;
- } // Indices are ascending
-
-
- var indices = this._indices; // If rawIndex === dataIndex
-
- var rawDataIndex = indices[rawIndex];
-
- if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) {
- return rawIndex;
- }
-
- var left = 0;
- var right = this._count - 1;
-
- while (left <= right) {
- var mid = (left + right) / 2 | 0;
-
- if (indices[mid] < rawIndex) {
- left = mid + 1;
- } else if (indices[mid] > rawIndex) {
- right = mid - 1;
- } else {
- return mid;
- }
- }
-
- return -1;
- };
- /**
- * Retreive the index of nearest value
- * @param dim
- * @param value
- * @param [maxDistance=Infinity]
- * @return If and only if multiple indices has
- * the same value, they are put to the result.
- */
-
-
- DataStore.prototype.indicesOfNearest = function (dim, value, maxDistance) {
- var chunks = this._chunks;
- var dimData = chunks[dim];
- var nearestIndices = [];
-
- if (!dimData) {
- return nearestIndices;
- }
-
- if (maxDistance == null) {
- maxDistance = Infinity;
- }
-
- var minDist = Infinity;
- var minDiff = -1;
- var nearestIndicesLen = 0; // Check the test case of `test/ut/spec/data/SeriesData.js`.
-
- for (var i = 0, len = this.count(); i < len; i++) {
- var dataIndex = this.getRawIndex(i);
- var diff = value - dimData[dataIndex];
- var dist = Math.abs(diff);
-
- if (dist <= maxDistance) {
- // When the `value` is at the middle of `this.get(dim, i)` and `this.get(dim, i+1)`,
- // we'd better not push both of them to `nearestIndices`, otherwise it is easy to
- // get more than one item in `nearestIndices` (more specifically, in `tooltip`).
- // So we chose the one that `diff >= 0` in this csae.
- // But if `this.get(dim, i)` and `this.get(dim, j)` get the same value, both of them
- // should be push to `nearestIndices`.
- if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) {
- minDist = dist;
- minDiff = diff;
- nearestIndicesLen = 0;
- }
-
- if (diff === minDiff) {
- nearestIndices[nearestIndicesLen++] = i;
- }
- }
- }
-
- nearestIndices.length = nearestIndicesLen;
- return nearestIndices;
- };
-
- DataStore.prototype.getIndices = function () {
- var newIndices;
- var indices = this._indices;
-
- if (indices) {
- var Ctor = indices.constructor;
- var thisCount = this._count; // `new Array(a, b, c)` is different from `new Uint32Array(a, b, c)`.
-
- if (Ctor === Array) {
- newIndices = new Ctor(thisCount);
-
- for (var i = 0; i < thisCount; i++) {
- newIndices[i] = indices[i];
- }
- } else {
- newIndices = new Ctor(indices.buffer, 0, thisCount);
- }
- } else {
- var Ctor = getIndicesCtor(this._rawCount);
- newIndices = new Ctor(this.count());
-
- for (var i = 0; i < newIndices.length; i++) {
- newIndices[i] = i;
- }
- }
-
- return newIndices;
- };
- /**
- * Data filter.
- */
-
-
- DataStore.prototype.filter = function (dims, cb) {
- if (!this._count) {
- return this;
- }
-
- var newStore = this.clone();
- var count = newStore.count();
- var Ctor = getIndicesCtor(newStore._rawCount);
- var newIndices = new Ctor(count);
- var value = [];
- var dimSize = dims.length;
- var offset = 0;
- var dim0 = dims[0];
- var chunks = newStore._chunks;
-
- for (var i = 0; i < count; i++) {
- var keep = void 0;
- var rawIdx = newStore.getRawIndex(i); // Simple optimization
-
- if (dimSize === 0) {
- keep = cb(i);
- } else if (dimSize === 1) {
- var val = chunks[dim0][rawIdx];
- keep = cb(val, i);
- } else {
- var k = 0;
-
- for (; k < dimSize; k++) {
- value[k] = chunks[dims[k]][rawIdx];
- }
-
- value[k] = i;
- keep = cb.apply(null, value);
- }
-
- if (keep) {
- newIndices[offset++] = rawIdx;
- }
- } // Set indices after filtered.
-
-
- if (offset < count) {
- newStore._indices = newIndices;
- }
-
- newStore._count = offset; // Reset data extent
-
- newStore._extent = [];
-
- newStore._updateGetRawIdx();
-
- return newStore;
- };
- /**
- * Select data in range. (For optimization of filter)
- * (Manually inline code, support 5 million data filtering in data zoom.)
- */
-
-
- DataStore.prototype.selectRange = function (range) {
- var newStore = this.clone();
- var len = newStore._count;
-
- if (!len) {
- return this;
- }
-
- var dims = keys(range);
- var dimSize = dims.length;
-
- if (!dimSize) {
- return this;
- }
-
- var originalCount = newStore.count();
- var Ctor = getIndicesCtor(newStore._rawCount);
- var newIndices = new Ctor(originalCount);
- var offset = 0;
- var dim0 = dims[0];
- var min = range[dim0][0];
- var max = range[dim0][1];
- var storeArr = newStore._chunks;
- var quickFinished = false;
-
- if (!newStore._indices) {
- // Extreme optimization for common case. About 2x faster in chrome.
- var idx = 0;
-
- if (dimSize === 1) {
- var dimStorage = storeArr[dims[0]];
-
- for (var i = 0; i < len; i++) {
- var val = dimStorage[i]; // NaN will not be filtered. Consider the case, in line chart, empty
- // value indicates the line should be broken. But for the case like
- // scatter plot, a data item with empty value will not be rendered,
- // but the axis extent may be effected if some other dim of the data
- // item has value. Fortunately it is not a significant negative effect.
-
- if (val >= min && val <= max || isNaN(val)) {
- newIndices[offset++] = idx;
- }
-
- idx++;
- }
-
- quickFinished = true;
- } else if (dimSize === 2) {
- var dimStorage = storeArr[dims[0]];
- var dimStorage2 = storeArr[dims[1]];
- var min2 = range[dims[1]][0];
- var max2 = range[dims[1]][1];
-
- for (var i = 0; i < len; i++) {
- var val = dimStorage[i];
- var val2 = dimStorage2[i]; // Do not filter NaN, see comment above.
-
- if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) {
- newIndices[offset++] = idx;
- }
-
- idx++;
- }
-
- quickFinished = true;
- }
- }
-
- if (!quickFinished) {
- if (dimSize === 1) {
- for (var i = 0; i < originalCount; i++) {
- var rawIndex = newStore.getRawIndex(i);
- var val = storeArr[dims[0]][rawIndex]; // Do not filter NaN, see comment above.
-
- if (val >= min && val <= max || isNaN(val)) {
- newIndices[offset++] = rawIndex;
- }
- }
- } else {
- for (var i = 0; i < originalCount; i++) {
- var keep = true;
- var rawIndex = newStore.getRawIndex(i);
-
- for (var k = 0; k < dimSize; k++) {
- var dimk = dims[k];
- var val = storeArr[dimk][rawIndex]; // Do not filter NaN, see comment above.
-
- if (val < range[dimk][0] || val > range[dimk][1]) {
- keep = false;
- }
- }
-
- if (keep) {
- newIndices[offset++] = newStore.getRawIndex(i);
- }
- }
- }
- } // Set indices after filtered.
-
-
- if (offset < originalCount) {
- newStore._indices = newIndices;
- }
-
- newStore._count = offset; // Reset data extent
-
- newStore._extent = [];
-
- newStore._updateGetRawIdx();
-
- return newStore;
- }; // /**
- // * Data mapping to a plain array
- // */
- // mapArray(dims: DimensionIndex[], cb: MapArrayCb): any[] {
- // const result: any[] = [];
- // this.each(dims, function () {
- // result.push(cb && (cb as MapArrayCb).apply(null, arguments));
- // });
- // return result;
- // }
-
- /**
- * Data mapping to a new List with given dimensions
- */
-
-
- DataStore.prototype.map = function (dims, cb) {
- // TODO only clone picked chunks.
- var target = this.clone(dims);
-
- this._updateDims(target, dims, cb);
-
- return target;
- };
- /**
- * @caution Danger!! Only used in dataStack.
- */
-
-
- DataStore.prototype.modify = function (dims, cb) {
- this._updateDims(this, dims, cb);
- };
-
- DataStore.prototype._updateDims = function (target, dims, cb) {
- var targetChunks = target._chunks;
- var tmpRetValue = [];
- var dimSize = dims.length;
- var dataCount = target.count();
- var values = [];
- var rawExtent = target._rawExtent;
-
- for (var i = 0; i < dims.length; i++) {
- rawExtent[dims[i]] = getInitialExtent();
- }
-
- for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) {
- var rawIndex = target.getRawIndex(dataIndex);
-
- for (var k = 0; k < dimSize; k++) {
- values[k] = targetChunks[dims[k]][rawIndex];
- }
-
- values[dimSize] = dataIndex;
- var retValue = cb && cb.apply(null, values);
-
- if (retValue != null) {
- // a number or string (in oridinal dimension)?
- if (typeof retValue !== 'object') {
- tmpRetValue[0] = retValue;
- retValue = tmpRetValue;
- }
-
- for (var i = 0; i < retValue.length; i++) {
- var dim = dims[i];
- var val = retValue[i];
- var rawExtentOnDim = rawExtent[dim];
- var dimStore = targetChunks[dim];
-
- if (dimStore) {
- dimStore[rawIndex] = val;
- }
-
- if (val < rawExtentOnDim[0]) {
- rawExtentOnDim[0] = val;
- }
-
- if (val > rawExtentOnDim[1]) {
- rawExtentOnDim[1] = val;
- }
- }
- }
- }
- };
- /**
- * Large data down sampling using largest-triangle-three-buckets
- * @param {string} valueDimension
- * @param {number} targetCount
- */
-
-
- DataStore.prototype.lttbDownSample = function (valueDimension, rate) {
- var target = this.clone([valueDimension], true);
- var targetStorage = target._chunks;
- var dimStore = targetStorage[valueDimension];
- var len = this.count();
- var sampledIndex = 0;
- var frameSize = Math.floor(1 / rate);
- var currentRawIndex = this.getRawIndex(0);
- var maxArea;
- var area;
- var nextRawIndex;
- var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize) + 2); // First frame use the first data.
-
- newIndices[sampledIndex++] = currentRawIndex;
-
- for (var i = 1; i < len - 1; i += frameSize) {
- var nextFrameStart = Math.min(i + frameSize, len - 1);
- var nextFrameEnd = Math.min(i + frameSize * 2, len);
- var avgX = (nextFrameEnd + nextFrameStart) / 2;
- var avgY = 0;
-
- for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) {
- var rawIndex = this.getRawIndex(idx);
- var y = dimStore[rawIndex];
-
- if (isNaN(y)) {
- continue;
- }
-
- avgY += y;
- }
-
- avgY /= nextFrameEnd - nextFrameStart;
- var frameStart = i;
- var frameEnd = Math.min(i + frameSize, len);
- var pointAX = i - 1;
- var pointAY = dimStore[currentRawIndex];
- maxArea = -1;
- nextRawIndex = frameStart; // Find a point from current frame that construct a triangel with largest area with previous selected point
- // And the average of next frame.
-
- for (var idx = frameStart; idx < frameEnd; idx++) {
- var rawIndex = this.getRawIndex(idx);
- var y = dimStore[rawIndex];
-
- if (isNaN(y)) {
- continue;
- } // Calculate triangle area over three buckets
-
-
- area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY));
-
- if (area > maxArea) {
- maxArea = area;
- nextRawIndex = rawIndex; // Next a is this b
- }
- }
-
- newIndices[sampledIndex++] = nextRawIndex;
- currentRawIndex = nextRawIndex; // This a is the next a (chosen b)
- } // First frame use the last data.
-
-
- newIndices[sampledIndex++] = this.getRawIndex(len - 1);
- target._count = sampledIndex;
- target._indices = newIndices;
- target.getRawIndex = this._getRawIdx;
- return target;
- };
- /**
- * Large data down sampling on given dimension
- * @param sampleIndex Sample index for name and id
- */
-
-
- DataStore.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) {
- var target = this.clone([dimension], true);
- var targetStorage = target._chunks;
- var frameValues = [];
- var frameSize = Math.floor(1 / rate);
- var dimStore = targetStorage[dimension];
- var len = this.count();
- var rawExtentOnDim = target._rawExtent[dimension] = getInitialExtent();
- var newIndices = new (getIndicesCtor(this._rawCount))(Math.ceil(len / frameSize));
- var offset = 0;
-
- for (var i = 0; i < len; i += frameSize) {
- // Last frame
- if (frameSize > len - i) {
- frameSize = len - i;
- frameValues.length = frameSize;
- }
-
- for (var k = 0; k < frameSize; k++) {
- var dataIdx = this.getRawIndex(i + k);
- frameValues[k] = dimStore[dataIdx];
- }
-
- var value = sampleValue(frameValues);
- var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); // Only write value on the filtered data
-
- dimStore[sampleFrameIdx] = value;
-
- if (value < rawExtentOnDim[0]) {
- rawExtentOnDim[0] = value;
- }
-
- if (value > rawExtentOnDim[1]) {
- rawExtentOnDim[1] = value;
- }
-
- newIndices[offset++] = sampleFrameIdx;
- }
-
- target._count = offset;
- target._indices = newIndices;
-
- target._updateGetRawIdx();
-
- return target;
- };
- /**
- * Data iteration
- * @param ctx default this
- * @example
- * list.each('x', function (x, idx) {});
- * list.each(['x', 'y'], function (x, y, idx) {});
- * list.each(function (idx) {})
- */
-
-
- DataStore.prototype.each = function (dims, cb) {
- if (!this._count) {
- return;
- }
-
- var dimSize = dims.length;
- var chunks = this._chunks;
-
- for (var i = 0, len = this.count(); i < len; i++) {
- var rawIdx = this.getRawIndex(i); // Simple optimization
-
- switch (dimSize) {
- case 0:
- cb(i);
- break;
-
- case 1:
- cb(chunks[dims[0]][rawIdx], i);
- break;
-
- case 2:
- cb(chunks[dims[0]][rawIdx], chunks[dims[1]][rawIdx], i);
- break;
-
- default:
- var k = 0;
- var value = [];
-
- for (; k < dimSize; k++) {
- value[k] = chunks[dims[k]][rawIdx];
- } // Index
-
-
- value[k] = i;
- cb.apply(null, value);
- }
- }
- };
- /**
- * Get extent of data in one dimension
- */
-
-
- DataStore.prototype.getDataExtent = function (dim) {
- // Make sure use concrete dim as cache name.
- var dimData = this._chunks[dim];
- var initialExtent = getInitialExtent();
-
- if (!dimData) {
- return initialExtent;
- } // Make more strict checkings to ensure hitting cache.
-
-
- var currEnd = this.count(); // Consider the most cases when using data zoom, `getDataExtent`
- // happened before filtering. We cache raw extent, which is not
- // necessary to be cleared and recalculated when restore data.
-
- var useRaw = !this._indices;
- var dimExtent;
-
- if (useRaw) {
- return this._rawExtent[dim].slice();
- }
-
- dimExtent = this._extent[dim];
-
- if (dimExtent) {
- return dimExtent.slice();
- }
-
- dimExtent = initialExtent;
- var min = dimExtent[0];
- var max = dimExtent[1];
-
- for (var i = 0; i < currEnd; i++) {
- var rawIdx = this.getRawIndex(i);
- var value = dimData[rawIdx];
- value < min && (min = value);
- value > max && (max = value);
- }
-
- dimExtent = [min, max];
- this._extent[dim] = dimExtent;
- return dimExtent;
- };
- /**
- * Get raw data item
- */
-
-
- DataStore.prototype.getRawDataItem = function (idx) {
- var rawIdx = this.getRawIndex(idx);
-
- if (!this._provider.persistent) {
- var val = [];
- var chunks = this._chunks;
-
- for (var i = 0; i < chunks.length; i++) {
- val.push(chunks[i][rawIdx]);
- }
-
- return val;
- } else {
- return this._provider.getItem(rawIdx);
- }
- };
- /**
- * Clone shallow.
- *
- * @param clonedDims Determine which dims to clone. Will share the data if not specified.
- */
-
-
- DataStore.prototype.clone = function (clonedDims, ignoreIndices) {
- var target = new DataStore();
- var chunks = this._chunks;
- var clonedDimsMap = clonedDims && reduce(clonedDims, function (obj, dimIdx) {
- obj[dimIdx] = true;
- return obj;
- }, {});
-
- if (clonedDimsMap) {
- for (var i = 0; i < chunks.length; i++) {
- // Not clone if dim is not picked.
- target._chunks[i] = !clonedDimsMap[i] ? chunks[i] : cloneChunk(chunks[i]);
- }
- } else {
- target._chunks = chunks;
- }
-
- this._copyCommonProps(target);
-
- if (!ignoreIndices) {
- target._indices = this._cloneIndices();
- }
-
- target._updateGetRawIdx();
-
- return target;
- };
-
- DataStore.prototype._copyCommonProps = function (target) {
- target._count = this._count;
- target._rawCount = this._rawCount;
- target._provider = this._provider;
- target._dimensions = this._dimensions;
- target._extent = clone(this._extent);
- target._rawExtent = clone(this._rawExtent);
- };
-
- DataStore.prototype._cloneIndices = function () {
- if (this._indices) {
- var Ctor = this._indices.constructor;
- var indices = void 0;
-
- if (Ctor === Array) {
- var thisCount = this._indices.length;
- indices = new Ctor(thisCount);
-
- for (var i = 0; i < thisCount; i++) {
- indices[i] = this._indices[i];
- }
- } else {
- indices = new Ctor(this._indices);
- }
-
- return indices;
- }
-
- return null;
- };
-
- DataStore.prototype._getRawIdxIdentity = function (idx) {
- return idx;
- };
-
- DataStore.prototype._getRawIdx = function (idx) {
- if (idx < this._count && idx >= 0) {
- return this._indices[idx];
- }
-
- return -1;
- };
-
- DataStore.prototype._updateGetRawIdx = function () {
- this.getRawIndex = this._indices ? this._getRawIdx : this._getRawIdxIdentity;
- };
-
- DataStore.internalField = function () {
- function getDimValueSimply(dataItem, property, dataIndex, dimIndex) {
- return parseDataValue(dataItem[dimIndex], this._dimensions[dimIndex]);
- }
-
- defaultDimValueGetters = {
- arrayRows: getDimValueSimply,
- objectRows: function (dataItem, property, dataIndex, dimIndex) {
- return parseDataValue(dataItem[property], this._dimensions[dimIndex]);
- },
- keyedColumns: getDimValueSimply,
- original: function (dataItem, property, dataIndex, dimIndex) {
- // Performance sensitive, do not use modelUtil.getDataItemValue.
- // If dataItem is an plain object with no value field, the let `value`
- // will be assigned with the object, but it will be tread correctly
- // in the `convertValue`.
- var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value);
- return parseDataValue(value instanceof Array ? value[dimIndex] // If value is a single number or something else not array.
- : value, this._dimensions[dimIndex]);
- },
- typedArray: function (dataItem, property, dataIndex, dimIndex) {
- return dataItem[dimIndex];
- }
- };
- }();
-
- return DataStore;
- }();
-
- /**
- * [REQUIREMENT_MEMO]:
- * (0) `metaRawOption` means `dimensions`/`sourceHeader`/`seriesLayoutBy` in raw option.
- * (1) Keep support the feature: `metaRawOption` can be specified both on `series` and
- * `root-dataset`. Them on `series` has higher priority.
- * (2) Do not support to set `metaRawOption` on a `non-root-dataset`, because it might
- * confuse users: whether those props indicate how to visit the upstream source or visit
- * the transform result source, and some transforms has nothing to do with these props,
- * and some transforms might have multiple upstream.
- * (3) Transforms should specify `metaRawOption` in each output, just like they can be
- * declared in `root-dataset`.
- * (4) At present only support visit source in `SERIES_LAYOUT_BY_COLUMN` in transforms.
- * That is for reducing complexity in transfroms.
- * PENDING: Whether to provide transposition transform?
- *
- * [IMPLEMENTAION_MEMO]:
- * "sourceVisitConfig" are calculated from `metaRawOption` and `data`.
- * They will not be calculated until `source` is about to be visited (to prevent from
- * duplicate calcuation). `source` is visited only in series and input to transforms.
- *
- * [DIMENSION_INHERIT_RULE]:
- * By default the dimensions are inherited from ancestors, unless a transform return
- * a new dimensions definition.
- * Consider the case:
- * ```js
- * dataset: [{
- * source: [ ['Product', 'Sales', 'Prise'], ['Cookies', 321, 44.21], ...]
- * }, {
- * transform: { type: 'filter', ... }
- * }]
- * dataset: [{
- * dimension: ['Product', 'Sales', 'Prise'],
- * source: [ ['Cookies', 321, 44.21], ...]
- * }, {
- * transform: { type: 'filter', ... }
- * }]
- * ```
- * The two types of option should have the same behavior after transform.
- *
- *
- * [SCENARIO]:
- * (1) Provide source data directly:
- * ```js
- * series: {
- * encode: {...},
- * dimensions: [...]
- * seriesLayoutBy: 'row',
- * data: [[...]]
- * }
- * ```
- * (2) Series refer to dataset.
- * ```js
- * series: [{
- * encode: {...}
- * // Ignore datasetIndex means `datasetIndex: 0`
- * // and the dimensions defination in dataset is used
- * }, {
- * encode: {...},
- * seriesLayoutBy: 'column',
- * datasetIndex: 1
- * }]
- * ```
- * (3) dataset transform
- * ```js
- * dataset: [{
- * source: [...]
- * }, {
- * source: [...]
- * }, {
- * // By default from 0.
- * transform: { type: 'filter', config: {...} }
- * }, {
- * // Piped.
- * transform: [
- * { type: 'filter', config: {...} },
- * { type: 'sort', config: {...} }
- * ]
- * }, {
- * id: 'regressionData',
- * fromDatasetIndex: 1,
- * // Third-party transform
- * transform: { type: 'ecStat:regression', config: {...} }
- * }, {
- * // retrieve the extra result.
- * id: 'regressionFormula',
- * fromDatasetId: 'regressionData',
- * fromTransformResult: 1
- * }]
- * ```
- */
-
- var SourceManager =
- /** @class */
- function () {
- function SourceManager(sourceHost) {
- // Cached source. Do not repeat calculating if not dirty.
- this._sourceList = [];
- this._storeList = []; // version sign of each upstream source manager.
-
- this._upstreamSignList = [];
- this._versionSignBase = 0;
- this._dirty = true;
- this._sourceHost = sourceHost;
- }
- /**
- * Mark dirty.
- */
-
-
- SourceManager.prototype.dirty = function () {
- this._setLocalSource([], []);
-
- this._storeList = [];
- this._dirty = true;
- };
-
- SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) {
- this._sourceList = sourceList;
- this._upstreamSignList = upstreamSignList;
- this._versionSignBase++;
-
- if (this._versionSignBase > 9e10) {
- this._versionSignBase = 0;
- }
- };
- /**
- * For detecting whether the upstream source is dirty, so that
- * the local cached source (in `_sourceList`) should be discarded.
- */
-
-
- SourceManager.prototype._getVersionSign = function () {
- return this._sourceHost.uid + '_' + this._versionSignBase;
- };
- /**
- * Always return a source instance. Otherwise throw error.
- */
-
-
- SourceManager.prototype.prepareSource = function () {
- // For the case that call `setOption` multiple time but no data changed,
- // cache the result source to prevent from repeating transform.
- if (this._isDirty()) {
- this._createSource();
-
- this._dirty = false;
- }
- };
-
- SourceManager.prototype._createSource = function () {
- this._setLocalSource([], []);
-
- var sourceHost = this._sourceHost;
-
- var upSourceMgrList = this._getUpstreamSourceManagers();
-
- var hasUpstream = !!upSourceMgrList.length;
- var resultSourceList;
- var upstreamSignList;
-
- if (isSeries(sourceHost)) {
- var seriesModel = sourceHost;
- var data = void 0;
- var sourceFormat = void 0;
- var upSource = void 0; // Has upstream dataset
-
- if (hasUpstream) {
- var upSourceMgr = upSourceMgrList[0];
- upSourceMgr.prepareSource();
- upSource = upSourceMgr.getSource();
- data = upSource.data;
- sourceFormat = upSource.sourceFormat;
- upstreamSignList = [upSourceMgr._getVersionSign()];
- } // Series data is from own.
- else {
- data = seriesModel.get('data', true);
- sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL;
- upstreamSignList = [];
- } // See [REQUIREMENT_MEMO], merge settings on series and parent dataset if it is root.
-
-
- var newMetaRawOption = this._getSourceMetaRawOption() || {};
- var upMetaRawOption = upSource && upSource.metaRawOption || {};
- var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption.seriesLayoutBy) || null;
- var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption.sourceHeader) || null; // Note here we should not use `upSource.dimensionsDefine`. Consider the case:
- // `upSource.dimensionsDefine` is detected by `seriesLayoutBy: 'column'`,
- // but series need `seriesLayoutBy: 'row'`.
-
- var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption.dimensions); // We share source with dataset as much as possible
- // to avoid extra memroy cost of high dimensional data.
-
- var needsCreateSource = seriesLayoutBy !== upMetaRawOption.seriesLayoutBy || !!sourceHeader !== !!upMetaRawOption.sourceHeader || dimensions;
- resultSourceList = needsCreateSource ? [createSource(data, {
- seriesLayoutBy: seriesLayoutBy,
- sourceHeader: sourceHeader,
- dimensions: dimensions
- }, sourceFormat)] : [];
- } else {
- var datasetModel = sourceHost; // Has upstream dataset.
-
- if (hasUpstream) {
- var result = this._applyTransform(upSourceMgrList);
-
- resultSourceList = result.sourceList;
- upstreamSignList = result.upstreamSignList;
- } // Is root dataset.
- else {
- var sourceData = datasetModel.get('source', true);
- resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null)];
- upstreamSignList = [];
- }
- }
-
- if ("development" !== 'production') {
- assert(resultSourceList && upstreamSignList);
- }
-
- this._setLocalSource(resultSourceList, upstreamSignList);
- };
-
- SourceManager.prototype._applyTransform = function (upMgrList) {
- var datasetModel = this._sourceHost;
- var transformOption = datasetModel.get('transform', true);
- var fromTransformResult = datasetModel.get('fromTransformResult', true);
-
- if ("development" !== 'production') {
- assert(fromTransformResult != null || transformOption != null);
- }
-
- if (fromTransformResult != null) {
- var errMsg = '';
-
- if (upMgrList.length !== 1) {
- if ("development" !== 'production') {
- errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset';
- }
-
- doThrow(errMsg);
- }
- }
-
- var sourceList;
- var upSourceList = [];
- var upstreamSignList = [];
- each(upMgrList, function (upMgr) {
- upMgr.prepareSource();
- var upSource = upMgr.getSource(fromTransformResult || 0);
- var errMsg = '';
-
- if (fromTransformResult != null && !upSource) {
- if ("development" !== 'production') {
- errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult;
- }
-
- doThrow(errMsg);
- }
-
- upSourceList.push(upSource);
- upstreamSignList.push(upMgr._getVersionSign());
- });
-
- if (transformOption) {
- sourceList = applyDataTransform(transformOption, upSourceList, {
- datasetIndex: datasetModel.componentIndex
- });
- } else if (fromTransformResult != null) {
- sourceList = [cloneSourceShallow(upSourceList[0])];
- }
-
- return {
- sourceList: sourceList,
- upstreamSignList: upstreamSignList
- };
- };
-
- SourceManager.prototype._isDirty = function () {
- if (this._dirty) {
- return true;
- } // All sourceList is from the some upsteam.
-
-
- var upSourceMgrList = this._getUpstreamSourceManagers();
-
- for (var i = 0; i < upSourceMgrList.length; i++) {
- var upSrcMgr = upSourceMgrList[i];
-
- if ( // Consider the case that there is ancestor diry, call it recursively.
- // The performance is probably not an issue because usually the chain is not long.
- upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) {
- return true;
- }
- }
- };
- /**
- * @param sourceIndex By defualt 0, means "main source".
- * Most cases there is only one source.
- */
-
-
- SourceManager.prototype.getSource = function (sourceIndex) {
- sourceIndex = sourceIndex || 0;
- var source = this._sourceList[sourceIndex];
-
- if (!source) {
- // Series may share source instance with dataset.
- var upSourceMgrList = this._getUpstreamSourceManagers();
-
- return upSourceMgrList[0] && upSourceMgrList[0].getSource(sourceIndex);
- }
-
- return source;
- };
- /**
- *
- * Get a data store which can be shared across series.
- * Only available for series.
- *
- * @param seriesDimRequest Dimensions that are generated in series.
- * Should have been sorted by `storeDimIndex` asc.
- */
-
-
- SourceManager.prototype.getSharedDataStore = function (seriesDimRequest) {
- if ("development" !== 'production') {
- assert(isSeries(this._sourceHost), 'Can only call getDataStore on series source manager.');
- }
-
- var schema = seriesDimRequest.makeStoreSchema();
- return this._innerGetDataStore(schema.dimensions, seriesDimRequest.source, schema.hash);
- };
-
- SourceManager.prototype._innerGetDataStore = function (storeDims, seriesSource, sourceReadKey) {
- // TODO Can use other sourceIndex?
- var sourceIndex = 0;
- var storeList = this._storeList;
- var cachedStoreMap = storeList[sourceIndex];
-
- if (!cachedStoreMap) {
- cachedStoreMap = storeList[sourceIndex] = {};
- }
-
- var cachedStore = cachedStoreMap[sourceReadKey];
-
- if (!cachedStore) {
- var upSourceMgr = this._getUpstreamSourceManagers()[0];
-
- if (isSeries(this._sourceHost) && upSourceMgr) {
- cachedStore = upSourceMgr._innerGetDataStore(storeDims, seriesSource, sourceReadKey);
- } else {
- cachedStore = new DataStore(); // Always create store from source of series.
-
- cachedStore.initData(new DefaultDataProvider(seriesSource, storeDims.length), storeDims);
- }
-
- cachedStoreMap[sourceReadKey] = cachedStore;
- }
-
- return cachedStore;
- };
- /**
- * PEDING: Is it fast enough?
- * If no upstream, return empty array.
- */
-
-
- SourceManager.prototype._getUpstreamSourceManagers = function () {
- // Always get the relationship from the raw option.
- // Do not cache the link of the dependency graph, so that
- // no need to update them when change happen.
- var sourceHost = this._sourceHost;
-
- if (isSeries(sourceHost)) {
- var datasetModel = querySeriesUpstreamDatasetModel(sourceHost);
- return !datasetModel ? [] : [datasetModel.getSourceManager()];
- } else {
- return map(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) {
- return datasetModel.getSourceManager();
- });
- }
- };
-
- SourceManager.prototype._getSourceMetaRawOption = function () {
- var sourceHost = this._sourceHost;
- var seriesLayoutBy;
- var sourceHeader;
- var dimensions;
-
- if (isSeries(sourceHost)) {
- seriesLayoutBy = sourceHost.get('seriesLayoutBy', true);
- sourceHeader = sourceHost.get('sourceHeader', true);
- dimensions = sourceHost.get('dimensions', true);
- } // See [REQUIREMENT_MEMO], `non-root-dataset` do not support them.
- else if (!this._getUpstreamSourceManagers().length) {
- var model = sourceHost;
- seriesLayoutBy = model.get('seriesLayoutBy', true);
- sourceHeader = model.get('sourceHeader', true);
- dimensions = model.get('dimensions', true);
- }
-
- return {
- seriesLayoutBy: seriesLayoutBy,
- sourceHeader: sourceHeader,
- dimensions: dimensions
- };
- };
-
- return SourceManager;
- }();
- // disable the transform merge, but do not disable transfrom clone from rawOption.
-
- function disableTransformOptionMerge(datasetModel) {
- var transformOption = datasetModel.option.transform;
- transformOption && setAsPrimitive(datasetModel.option.transform);
- }
-
- function isSeries(sourceHost) {
- // Avoid circular dependency with Series.ts
- return sourceHost.mainType === 'series';
- }
-
- function doThrow(errMsg) {
- throw new Error(errMsg);
- }
-
- var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1'; // TODO: more textStyle option
-
- function getTooltipTextStyle(textStyle, renderMode) {
- var nameFontColor = textStyle.color || '#6e7079';
- var nameFontSize = textStyle.fontSize || 12;
- var nameFontWeight = textStyle.fontWeight || '400';
- var valueFontColor = textStyle.color || '#464646';
- var valueFontSize = textStyle.fontSize || 14;
- var valueFontWeight = textStyle.fontWeight || '900';
-
- if (renderMode === 'html') {
- // `textStyle` is probably from user input, should be encoded to reduce security risk.
- return {
- // eslint-disable-next-line max-len
- nameStyle: "font-size:" + encodeHTML(nameFontSize + '') + "px;color:" + encodeHTML(nameFontColor) + ";font-weight:" + encodeHTML(nameFontWeight + ''),
- // eslint-disable-next-line max-len
- valueStyle: "font-size:" + encodeHTML(valueFontSize + '') + "px;color:" + encodeHTML(valueFontColor) + ";font-weight:" + encodeHTML(valueFontWeight + '')
- };
- } else {
- return {
- nameStyle: {
- fontSize: nameFontSize,
- fill: nameFontColor,
- fontWeight: nameFontWeight
- },
- valueStyle: {
- fontSize: valueFontSize,
- fill: valueFontColor,
- fontWeight: valueFontWeight
- }
- };
- }
- } // See `TooltipMarkupLayoutIntent['innerGapLevel']`.
- // (value from UI design)
-
-
- var HTML_GAPS = [0, 10, 20, 30];
- var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n']; // eslint-disable-next-line max-len
-
- function createTooltipMarkup(type, option) {
- option.type = type;
- return option;
- }
-
- function getBuilder(fragment) {
- return hasOwn(builderMap, fragment.type) && builderMap[fragment.type];
- }
-
- var builderMap = {
- /**
- * A `section` block is like:
- * ```
- * header
- * subBlock
- * subBlock
- * ...
- * ```
- */
- section: {
- planLayout: function (fragment) {
- var subBlockLen = fragment.blocks.length;
- var thisBlockHasInnerGap = subBlockLen > 1 || subBlockLen > 0 && !fragment.noHeader;
- var thisGapLevelBetweenSubBlocks = 0;
- each(fragment.blocks, function (subBlock) {
- getBuilder(subBlock).planLayout(subBlock);
- var subGapLevel = subBlock.__gapLevelBetweenSubBlocks; // If the some of the sub-blocks have some gaps (like 10px) inside, this block
- // should use a larger gap (like 20px) to distinguish those sub-blocks.
-
- if (subGapLevel >= thisGapLevelBetweenSubBlocks) {
- thisGapLevelBetweenSubBlocks = subGapLevel + (thisBlockHasInnerGap && ( // 0 always can not be readable gap level.
- !subGapLevel // If no header, always keep the sub gap level. Otherwise
- // look weird in case `multipleSeries`.
- || subBlock.type === 'section' && !subBlock.noHeader) ? 1 : 0);
- }
- });
- fragment.__gapLevelBetweenSubBlocks = thisGapLevelBetweenSubBlocks;
- },
- build: function (ctx, fragment, topMarginForOuterGap, toolTipTextStyle) {
- var noHeader = fragment.noHeader;
- var gaps = getGap(fragment);
- var subMarkupText = buildSubBlocks(ctx, fragment, noHeader ? topMarginForOuterGap : gaps.html, toolTipTextStyle);
-
- if (noHeader) {
- return subMarkupText;
- }
-
- var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC);
- var nameStyle = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode).nameStyle;
-
- if (ctx.renderMode === 'richText') {
- return wrapInlineNameRichText(ctx, displayableHeader, nameStyle) + gaps.richText + subMarkupText;
- } else {
- return wrapBlockHTML("" + encodeHTML(displayableHeader) + '
' + subMarkupText, topMarginForOuterGap);
- }
- }
- },
-
- /**
- * A `nameValue` block is like:
- * ```
- * marker name value
- * ```
- */
- nameValue: {
- planLayout: function (fragment) {
- fragment.__gapLevelBetweenSubBlocks = 0;
- },
- build: function (ctx, fragment, topMarginForOuterGap, toolTipTextStyle) {
- var renderMode = ctx.renderMode;
- var noName = fragment.noName;
- var noValue = fragment.noValue;
- var noMarker = !fragment.markerType;
- var name = fragment.name;
- var value = fragment.value;
- var useUTC = ctx.useUTC;
-
- if (noName && noValue) {
- return;
- }
-
- var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode);
- var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC);
- var valueTypeOption = fragment.valueType;
- var readableValueList = noValue ? [] : isArray(value) ? map(value, function (val, idx) {
- return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC);
- }) : [makeValueReadable(value, isArray(valueTypeOption) ? valueTypeOption[0] : valueTypeOption, useUTC)];
- var valueAlignRight = !noMarker || !noName; // It little weird if only value next to marker but far from marker.
-
- var valueCloseToMarker = !noMarker && noName;
-
- var _a = getTooltipTextStyle(toolTipTextStyle, renderMode),
- nameStyle = _a.nameStyle,
- valueStyle = _a.valueStyle;
-
- return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle)) // Value has commas inside, so use ' ' as delimiter for multiple values.
- + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)), topMarginForOuterGap);
- }
- }
- };
-
- function buildSubBlocks(ctx, fragment, topMarginForOuterGap, tooltipTextStyle) {
- var subMarkupTextList = [];
- var subBlocks = fragment.blocks || [];
- assert(!subBlocks || isArray(subBlocks));
- subBlocks = subBlocks || [];
- var orderMode = ctx.orderMode;
-
- if (fragment.sortBlocks && orderMode) {
- subBlocks = subBlocks.slice();
- var orderMap = {
- valueAsc: 'asc',
- valueDesc: 'desc'
- };
-
- if (hasOwn(orderMap, orderMode)) {
- var comparator_1 = new SortOrderComparator(orderMap[orderMode], null);
- subBlocks.sort(function (a, b) {
- return comparator_1.evaluate(a.sortParam, b.sortParam);
- });
- } // FIXME 'seriesDesc' necessary?
- else if (orderMode === 'seriesDesc') {
- subBlocks.reverse();
- }
- }
-
- var gaps = getGap(fragment);
- each(subBlocks, function (subBlock, idx) {
- var subMarkupText = getBuilder(subBlock).build(ctx, subBlock, idx > 0 ? gaps.html : 0, tooltipTextStyle);
- subMarkupText != null && subMarkupTextList.push(subMarkupText);
- });
-
- if (!subMarkupTextList.length) {
- return;
- }
-
- return ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), topMarginForOuterGap);
- }
- /**
- * @return markupText. null/undefined means no content.
- */
-
-
- function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC, toolTipTextStyle) {
- if (!fragment) {
- return;
- }
-
- var builder = getBuilder(fragment);
- builder.planLayout(fragment);
- var ctx = {
- useUTC: useUTC,
- renderMode: renderMode,
- orderMode: orderMode,
- markupStyleCreator: markupStyleCreator
- };
- return builder.build(ctx, fragment, 0, toolTipTextStyle);
- }
-
- function getGap(fragment) {
- var gapLevelBetweenSubBlocks = fragment.__gapLevelBetweenSubBlocks;
- return {
- html: HTML_GAPS[gapLevelBetweenSubBlocks],
- richText: RICH_TEXT_GAPS[gapLevelBetweenSubBlocks]
- };
- }
-
- function wrapBlockHTML(encodedContent, topGap) {
- var clearfix = '';
- var marginCSS = "margin: " + topGap + "px 0 0";
- return "" + encodedContent + clearfix + '
';
- }
-
- function wrapInlineNameHTML(name, leftHasMarker, style) {
- var marginCss = leftHasMarker ? 'margin-left:2px' : '';
- return "" + encodeHTML(name) + '';
- }
-
- function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker, style) {
- // Do not too close to marker, considering there are multiple values separated by spaces.
- var paddingStr = valueCloseToMarker ? '10px' : '20px';
- var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : '';
- return "" // Value has commas inside, so use ' ' as delimiter for multiple values.
- + map(valueList, function (value) {
- return encodeHTML(value);
- }).join(' ') + '';
- }
-
- function wrapInlineNameRichText(ctx, name, style) {
- return ctx.markupStyleCreator.wrapRichTextStyle(name, style);
- }
-
- function wrapInlineValueRichText(ctx, valueList, alignRight, valueCloseToMarker, style) {
- var styles = [style];
- var paddingLeft = valueCloseToMarker ? 10 : 20;
- alignRight && styles.push({
- padding: [0, 0, 0, paddingLeft],
- align: 'right'
- }); // Value has commas inside, so use ' ' as delimiter for multiple values.
-
- return ctx.markupStyleCreator.wrapRichTextStyle(valueList.join(' '), styles);
- }
-
- function retrieveVisualColorForTooltipMarker(series, dataIndex) {
- var style = series.getData().getItemVisual(dataIndex, 'style');
- var color = style[series.visualDrawType];
- return convertToColorString(color);
- }
- function getPaddingFromTooltipModel(model, renderMode) {
- var padding = model.get('padding');
- return padding != null ? padding // We give slightly different to look pretty.
- : renderMode === 'richText' ? [8, 10] : 10;
- }
- /**
- * The major feature is generate styles for `renderMode: 'richText'`.
- * But it also serves `renderMode: 'html'` to provide
- * "renderMode-independent" API.
- */
-
- var TooltipMarkupStyleCreator =
- /** @class */
- function () {
- function TooltipMarkupStyleCreator() {
- this.richTextStyles = {}; // Notice that "generate a style name" usuall happens repeatly when mouse moving and
- // displaying a tooltip. So we put the `_nextStyleNameId` as a member of each creator
- // rather than static shared by all creators (which will cause it increase to fast).
-
- this._nextStyleNameId = getRandomIdBase();
- }
-
- TooltipMarkupStyleCreator.prototype._generateStyleName = function () {
- return '__EC_aUTo_' + this._nextStyleNameId++;
- };
-
- TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) {
- var markerId = renderMode === 'richText' ? this._generateStyleName() : null;
- var marker = getTooltipMarker({
- color: colorStr,
- type: markerType,
- renderMode: renderMode,
- markerId: markerId
- });
-
- if (isString(marker)) {
- return marker;
- } else {
- if ("development" !== 'production') {
- assert(markerId);
- }
-
- this.richTextStyles[markerId] = marker.style;
- return marker.content;
- }
- };
- /**
- * @usage
- * ```ts
- * const styledText = markupStyleCreator.wrapRichTextStyle([
- * // The styles will be auto merged.
- * {
- * fontSize: 12,
- * color: 'blue'
- * },
- * {
- * padding: 20
- * }
- * ]);
- * ```
- */
-
-
- TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) {
- var finalStl = {};
-
- if (isArray(styles)) {
- each(styles, function (stl) {
- return extend(finalStl, stl);
- });
- } else {
- extend(finalStl, styles);
- }
-
- var styleName = this._generateStyleName();
-
- this.richTextStyles[styleName] = finalStl;
- return "{" + styleName + "|" + text + "}";
- };
-
- return TooltipMarkupStyleCreator;
- }();
-
- function defaultSeriesFormatTooltip(opt) {
- var series = opt.series;
- var dataIndex = opt.dataIndex;
- var multipleSeries = opt.multipleSeries;
- var data = series.getData();
- var tooltipDims = data.mapDimensionsAll('defaultedTooltip');
- var tooltipDimLen = tooltipDims.length;
- var value = series.getRawValue(dataIndex);
- var isValueArr = isArray(value);
- var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); // Complicated rule for pretty tooltip.
-
- var inlineValue;
- var inlineValueType;
- var subBlocks;
- var sortParam;
-
- if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) {
- var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor);
- inlineValue = formatArrResult.inlineValues;
- inlineValueType = formatArrResult.inlineValueTypes;
- subBlocks = formatArrResult.blocks; // Only support tooltip sort by the first inline value. It's enough in most cases.
-
- sortParam = formatArrResult.inlineValues[0];
- } else if (tooltipDimLen) {
- var dimInfo = data.getDimensionInfo(tooltipDims[0]);
- sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]);
- inlineValueType = dimInfo.type;
- } else {
- sortParam = inlineValue = isValueArr ? value[0] : value;
- } // Do not show generated series name. It might not be readable.
-
-
- var seriesNameSpecified = isNameSpecified(series);
- var seriesName = seriesNameSpecified && series.name || '';
- var itemName = data.getName(dataIndex);
- var inlineName = multipleSeries ? seriesName : itemName;
- return createTooltipMarkup('section', {
- header: seriesName,
- // When series name not specified, do not show a header line with only '-'.
- // This case alway happen in tooltip.trigger: 'item'.
- noHeader: multipleSeries || !seriesNameSpecified,
- sortParam: sortParam,
- blocks: [createTooltipMarkup('nameValue', {
- markerType: 'item',
- markerColor: markerColor,
- // Do not mix display seriesName and itemName in one tooltip,
- // which might confuses users.
- name: inlineName,
- // name dimension might be auto assigned, where the name might
- // be not readable. So we check trim here.
- noName: !trim(inlineName),
- value: inlineValue,
- valueType: inlineValueType
- })].concat(subBlocks || [])
- });
- }
-
- function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) {
- // check: category-no-encode-has-axis-data in dataset.html
- var data = series.getData();
- var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) {
- var dimItem = data.getDimensionInfo(idx);
- return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null;
- }, false);
- var inlineValues = [];
- var inlineValueTypes = [];
- var blocks = [];
- tooltipDims.length ? each(tooltipDims, function (dim) {
- setEachItem(retrieveRawValue(data, dataIndex, dim), dim);
- }) // By default, all dims is used on tooltip.
- : each(value, setEachItem);
-
- function setEachItem(val, dim) {
- var dimInfo = data.getDimensionInfo(dim); // If `dimInfo.tooltip` is not set, show tooltip.
-
- if (!dimInfo || dimInfo.otherDims.tooltip === false) {
- return;
- }
-
- if (isValueMultipleLine) {
- blocks.push(createTooltipMarkup('nameValue', {
- markerType: 'subItem',
- markerColor: colorStr,
- name: dimInfo.displayName,
- value: val,
- valueType: dimInfo.type
- }));
- } else {
- inlineValues.push(val);
- inlineValueTypes.push(dimInfo.type);
- }
- }
-
- return {
- inlineValues: inlineValues,
- inlineValueTypes: inlineValueTypes,
- blocks: blocks
- };
- }
-
- var inner$1 = makeInner();
-
- function getSelectionKey(data, dataIndex) {
- return data.getName(dataIndex) || data.getId(dataIndex);
- }
-
- var SERIES_UNIVERSAL_TRANSITION_PROP = '__universalTransitionEnabled';
-
- var SeriesModel =
- /** @class */
- function (_super) {
- __extends(SeriesModel, _super);
-
- function SeriesModel() {
- // [Caution]: Becuase this class or desecendants can be used as `XXX.extend(subProto)`,
- // the class members must not be initialized in constructor or declaration place.
- // Otherwise there is bad case:
- // class A {xxx = 1;}
- // enableClassExtend(A);
- // class B extends A {}
- // var C = B.extend({xxx: 5});
- // var c = new C();
- // console.log(c.xxx); // expect 5 but always 1.
- var _this = _super !== null && _super.apply(this, arguments) || this; // ---------------------------------------
- // Props about data selection
- // ---------------------------------------
-
-
- _this._selectedDataIndicesMap = {};
- return _this;
- }
-
- SeriesModel.prototype.init = function (option, parentModel, ecModel) {
- this.seriesIndex = this.componentIndex;
- this.dataTask = createTask({
- count: dataTaskCount,
- reset: dataTaskReset
- });
- this.dataTask.context = {
- model: this
- };
- this.mergeDefaultAndTheme(option, ecModel);
- var sourceManager = inner$1(this).sourceManager = new SourceManager(this);
- sourceManager.prepareSource();
- var data = this.getInitialData(option, ecModel);
- wrapData(data, this);
- this.dataTask.context.data = data;
-
- if ("development" !== 'production') {
- assert(data, 'getInitialData returned invalid data.');
- }
-
- inner$1(this).dataBeforeProcessed = data; // If we reverse the order (make data firstly, and then make
- // dataBeforeProcessed by cloneShallow), cloneShallow will
- // cause data.graph.data !== data when using
- // module:echarts/data/Graph or module:echarts/data/Tree.
- // See module:echarts/data/helper/linkSeriesData
- // Theoretically, it is unreasonable to call `seriesModel.getData()` in the model
- // init or merge stage, because the data can be restored. So we do not `restoreData`
- // and `setData` here, which forbids calling `seriesModel.getData()` in this stage.
- // Call `seriesModel.getRawData()` instead.
- // this.restoreData();
-
- autoSeriesName(this);
-
- this._initSelectedMapFromData(data);
- };
- /**
- * Util for merge default and theme to option
- */
-
-
- SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) {
- var layoutMode = fetchLayoutMode(this);
- var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; // Backward compat: using subType on theme.
- // But if name duplicate between series subType
- // (for example: parallel) add component mainType,
- // add suffix 'Series'.
-
- var themeSubType = this.subType;
-
- if (ComponentModel.hasClass(themeSubType)) {
- themeSubType += 'Series';
- }
-
- merge(option, ecModel.getTheme().get(this.subType));
- merge(option, this.getDefaultOption()); // Default label emphasis `show`
-
- defaultEmphasis(option, 'label', ['show']);
- this.fillDataTextStyle(option.data);
-
- if (layoutMode) {
- mergeLayoutParam(option, inputPositionParams, layoutMode);
- }
- };
-
- SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) {
- // this.settingTask.dirty();
- newSeriesOption = merge(this.option, newSeriesOption, true);
- this.fillDataTextStyle(newSeriesOption.data);
- var layoutMode = fetchLayoutMode(this);
-
- if (layoutMode) {
- mergeLayoutParam(this.option, newSeriesOption, layoutMode);
- }
-
- var sourceManager = inner$1(this).sourceManager;
- sourceManager.dirty();
- sourceManager.prepareSource();
- var data = this.getInitialData(newSeriesOption, ecModel);
- wrapData(data, this);
- this.dataTask.dirty();
- this.dataTask.context.data = data;
- inner$1(this).dataBeforeProcessed = data;
- autoSeriesName(this);
-
- this._initSelectedMapFromData(data);
- };
-
- SeriesModel.prototype.fillDataTextStyle = function (data) {
- // Default data label emphasis `show`
- // FIXME Tree structure data ?
- // FIXME Performance ?
- if (data && !isTypedArray(data)) {
- var props = ['show'];
-
- for (var i = 0; i < data.length; i++) {
- if (data[i] && data[i].label) {
- defaultEmphasis(data[i], 'label', props);
- }
- }
- }
- };
- /**
- * Init a data structure from data related option in series
- * Must be overriden.
- */
-
-
- SeriesModel.prototype.getInitialData = function (option, ecModel) {
- return;
- };
- /**
- * Append data to list
- */
-
-
- SeriesModel.prototype.appendData = function (params) {
- // FIXME ???
- // (1) If data from dataset, forbidden append.
- // (2) support append data of dataset.
- var data = this.getRawData();
- data.appendData(params.data);
- };
- /**
- * Consider some method like `filter`, `map` need make new data,
- * We should make sure that `seriesModel.getData()` get correct
- * data in the stream procedure. So we fetch data from upstream
- * each time `task.perform` called.
- */
-
-
- SeriesModel.prototype.getData = function (dataType) {
- var task = getCurrentTask(this);
-
- if (task) {
- var data = task.context.data;
- return dataType == null ? data : data.getLinkedData(dataType);
- } else {
- // When series is not alive (that may happen when click toolbox
- // restore or setOption with not merge mode), series data may
- // be still need to judge animation or something when graphic
- // elements want to know whether fade out.
- return inner$1(this).data;
- }
- };
-
- SeriesModel.prototype.getAllData = function () {
- var mainData = this.getData();
- return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{
- data: mainData
- }];
- };
-
- SeriesModel.prototype.setData = function (data) {
- var task = getCurrentTask(this);
-
- if (task) {
- var context = task.context; // Consider case: filter, data sample.
- // FIXME:TS never used, so comment it
- // if (context.data !== data && task.modifyOutputEnd) {
- // task.setOutputEnd(data.count());
- // }
-
- context.outputData = data; // Caution: setData should update context.data,
- // Because getData may be called multiply in a
- // single stage and expect to get the data just
- // set. (For example, AxisProxy, x y both call
- // getData and setDate sequentially).
- // So the context.data should be fetched from
- // upstream each time when a stage starts to be
- // performed.
-
- if (task !== this.dataTask) {
- context.data = data;
- }
- }
-
- inner$1(this).data = data;
- };
-
- SeriesModel.prototype.getEncode = function () {
- var encode = this.get('encode', true);
-
- if (encode) {
- return createHashMap(encode);
- }
- };
-
- SeriesModel.prototype.getSourceManager = function () {
- return inner$1(this).sourceManager;
- };
-
- SeriesModel.prototype.getSource = function () {
- return this.getSourceManager().getSource();
- };
- /**
- * Get data before processed
- */
-
-
- SeriesModel.prototype.getRawData = function () {
- return inner$1(this).dataBeforeProcessed;
- };
-
- SeriesModel.prototype.getColorBy = function () {
- var colorBy = this.get('colorBy');
- return colorBy || 'series';
- };
-
- SeriesModel.prototype.isColorBySeries = function () {
- return this.getColorBy() === 'series';
- };
- /**
- * Get base axis if has coordinate system and has axis.
- * By default use coordSys.getBaseAxis();
- * Can be overrided for some chart.
- * @return {type} description
- */
-
-
- SeriesModel.prototype.getBaseAxis = function () {
- var coordSys = this.coordinateSystem; // @ts-ignore
-
- return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
- };
- /**
- * Default tooltip formatter
- *
- * @param dataIndex
- * @param multipleSeries
- * @param dataType
- * @param renderMode valid values: 'html'(by default) and 'richText'.
- * 'html' is used for rendering tooltip in extra DOM form, and the result
- * string is used as DOM HTML content.
- * 'richText' is used for rendering tooltip in rich text form, for those where
- * DOM operation is not supported.
- * @return formatted tooltip with `html` and `markers`
- * Notice: The override method can also return string
- */
-
-
- SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) {
- return defaultSeriesFormatTooltip({
- series: this,
- dataIndex: dataIndex,
- multipleSeries: multipleSeries
- });
- };
-
- SeriesModel.prototype.isAnimationEnabled = function () {
- if (env.node) {
- return false;
- }
-
- var animationEnabled = this.getShallow('animation');
-
- if (animationEnabled) {
- if (this.getData().count() > this.getShallow('animationThreshold')) {
- animationEnabled = false;
- }
- }
-
- return !!animationEnabled;
- };
-
- SeriesModel.prototype.restoreData = function () {
- this.dataTask.dirty();
- };
-
- SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) {
- var ecModel = this.ecModel; // PENDING
-
- var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum);
-
- if (!color) {
- color = ecModel.getColorFromPalette(name, scope, requestColorNum);
- }
-
- return color;
- };
- /**
- * Use `data.mapDimensionsAll(coordDim)` instead.
- * @deprecated
- */
-
-
- SeriesModel.prototype.coordDimToDataDim = function (coordDim) {
- return this.getRawData().mapDimensionsAll(coordDim);
- };
- /**
- * Get progressive rendering count each step
- */
-
-
- SeriesModel.prototype.getProgressive = function () {
- return this.get('progressive');
- };
- /**
- * Get progressive rendering count each step
- */
-
-
- SeriesModel.prototype.getProgressiveThreshold = function () {
- return this.get('progressiveThreshold');
- }; // PENGING If selectedMode is null ?
-
-
- SeriesModel.prototype.select = function (innerDataIndices, dataType) {
- this._innerSelect(this.getData(dataType), innerDataIndices);
- };
-
- SeriesModel.prototype.unselect = function (innerDataIndices, dataType) {
- var selectedMap = this.option.selectedMap;
-
- if (!selectedMap) {
- return;
- }
-
- var data = this.getData(dataType);
-
- for (var i = 0; i < innerDataIndices.length; i++) {
- var dataIndex = innerDataIndices[i];
- var nameOrId = getSelectionKey(data, dataIndex);
- selectedMap[nameOrId] = false;
- this._selectedDataIndicesMap[nameOrId] = -1;
- }
- };
-
- SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) {
- var tmpArr = [];
-
- for (var i = 0; i < innerDataIndices.length; i++) {
- tmpArr[0] = innerDataIndices[i];
- this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType);
- }
- };
-
- SeriesModel.prototype.getSelectedDataIndices = function () {
- var selectedDataIndicesMap = this._selectedDataIndicesMap;
- var nameOrIds = keys(selectedDataIndicesMap);
- var dataIndices = [];
-
- for (var i = 0; i < nameOrIds.length; i++) {
- var dataIndex = selectedDataIndicesMap[nameOrIds[i]];
-
- if (dataIndex >= 0) {
- dataIndices.push(dataIndex);
- }
- }
-
- return dataIndices;
- };
-
- SeriesModel.prototype.isSelected = function (dataIndex, dataType) {
- var selectedMap = this.option.selectedMap;
-
- if (!selectedMap) {
- return false;
- }
-
- var data = this.getData(dataType);
- var nameOrId = getSelectionKey(data, dataIndex);
- return selectedMap[nameOrId] || false;
- };
-
- SeriesModel.prototype.isUniversalTransitionEnabled = function () {
- if (this[SERIES_UNIVERSAL_TRANSITION_PROP]) {
- return true;
- }
-
- var universalTransitionOpt = this.option.universalTransition; // Quick reject
-
- if (!universalTransitionOpt) {
- return false;
- }
-
- if (universalTransitionOpt === true) {
- return true;
- } // Can be simply 'universalTransition: true'
-
-
- return universalTransitionOpt && universalTransitionOpt.enabled;
- };
-
- SeriesModel.prototype._innerSelect = function (data, innerDataIndices) {
- var _a, _b;
-
- var selectedMode = this.option.selectedMode;
- var len = innerDataIndices.length;
-
- if (!selectedMode || !len) {
- return;
- }
-
- if (selectedMode === 'multiple') {
- var selectedMap = this.option.selectedMap || (this.option.selectedMap = {});
-
- for (var i = 0; i < len; i++) {
- var dataIndex = innerDataIndices[i]; // TODO diffrent types of data share same object.
-
- var nameOrId = getSelectionKey(data, dataIndex);
- selectedMap[nameOrId] = true;
- this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex);
- }
- } else if (selectedMode === 'single' || selectedMode === true) {
- var lastDataIndex = innerDataIndices[len - 1];
- var nameOrId = getSelectionKey(data, lastDataIndex);
- this.option.selectedMap = (_a = {}, _a[nameOrId] = true, _a);
- this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b);
- }
- };
-
- SeriesModel.prototype._initSelectedMapFromData = function (data) {
- // Ignore select info in data if selectedMap exists.
- // NOTE It's only for legacy usage. edge data is not supported.
- if (this.option.selectedMap) {
- return;
- }
-
- var dataIndices = [];
-
- if (data.hasItemOption) {
- data.each(function (idx) {
- var rawItem = data.getRawDataItem(idx);
-
- if (rawItem && rawItem.selected) {
- dataIndices.push(idx);
- }
- });
- }
-
- if (dataIndices.length > 0) {
- this._innerSelect(data, dataIndices);
- }
- }; // /**
- // * @see {module:echarts/stream/Scheduler}
- // */
- // abstract pipeTask: null
-
-
- SeriesModel.registerClass = function (clz) {
- return ComponentModel.registerClass(clz);
- };
-
- SeriesModel.protoInitialize = function () {
- var proto = SeriesModel.prototype;
- proto.type = 'series.__base__';
- proto.seriesIndex = 0;
- proto.ignoreStyleOnData = false;
- proto.hasSymbolVisual = false;
- proto.defaultSymbol = 'circle'; // Make sure the values can be accessed!
-
- proto.visualStyleAccessPath = 'itemStyle';
- proto.visualDrawType = 'fill';
- }();
-
- return SeriesModel;
- }(ComponentModel);
-
- mixin(SeriesModel, DataFormatMixin);
- mixin(SeriesModel, PaletteMixin);
- mountExtend(SeriesModel, ComponentModel);
- /**
- * MUST be called after `prepareSource` called
- * Here we need to make auto series, especially for auto legend. But we
- * do not modify series.name in option to avoid side effects.
- */
-
- function autoSeriesName(seriesModel) {
- // User specified name has higher priority, otherwise it may cause
- // series can not be queried unexpectedly.
- var name = seriesModel.name;
-
- if (!isNameSpecified(seriesModel)) {
- seriesModel.name = getSeriesAutoName(seriesModel) || name;
- }
- }
-
- function getSeriesAutoName(seriesModel) {
- var data = seriesModel.getRawData();
- var dataDims = data.mapDimensionsAll('seriesName');
- var nameArr = [];
- each(dataDims, function (dataDim) {
- var dimInfo = data.getDimensionInfo(dataDim);
- dimInfo.displayName && nameArr.push(dimInfo.displayName);
- });
- return nameArr.join(' ');
- }
-
- function dataTaskCount(context) {
- return context.model.getRawData().count();
- }
-
- function dataTaskReset(context) {
- var seriesModel = context.model;
- seriesModel.setData(seriesModel.getRawData().cloneShallow());
- return dataTaskProgress;
- }
-
- function dataTaskProgress(param, context) {
- // Avoid repead cloneShallow when data just created in reset.
- if (context.outputData && param.end > context.outputData.count()) {
- context.model.getRawData().cloneShallow(context.outputData);
- }
- } // TODO refactor
-
-
- function wrapData(data, seriesModel) {
- each(concatArray(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) {
- data.wrapMethod(methodName, curry(onDataChange, seriesModel));
- });
- }
-
- function onDataChange(seriesModel, newList) {
- var task = getCurrentTask(seriesModel);
-
- if (task) {
- // Consider case: filter, selectRange
- task.setOutputEnd((newList || this).count());
- }
-
- return newList;
- }
-
- function getCurrentTask(seriesModel) {
- var scheduler = (seriesModel.ecModel || {}).scheduler;
- var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid);
-
- if (pipeline) {
- // When pipline finished, the currrentTask keep the last
- // task (renderTask).
- var task = pipeline.currentTask;
-
- if (task) {
- var agentStubMap = task.agentStubMap;
-
- if (agentStubMap) {
- task = agentStubMap.get(seriesModel.uid);
- }
- }
-
- return task;
- }
- }
-
- var ComponentView =
- /** @class */
- function () {
- function ComponentView() {
- this.group = new Group();
- this.uid = getUID('viewComponent');
- }
-
- ComponentView.prototype.init = function (ecModel, api) {};
-
- ComponentView.prototype.render = function (model, ecModel, api, payload) {};
-
- ComponentView.prototype.dispose = function (ecModel, api) {};
-
- ComponentView.prototype.updateView = function (model, ecModel, api, payload) {// Do nothing;
- };
-
- ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {// Do nothing;
- };
-
- ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {// Do nothing;
- };
- /**
- * Hook for blur target series.
- * Can be used in marker for blur the markers
- */
-
-
- ComponentView.prototype.blurSeries = function (seriesModels, ecModel) {// Do nothing;
- };
-
- return ComponentView;
- }();
- enableClassExtend(ComponentView);
- enableClassManagement(ComponentView);
-
- /**
- * @return {string} If large mode changed, return string 'reset';
- */
-
- function createRenderPlanner() {
- var inner = makeInner();
- return function (seriesModel) {
- var fields = inner(seriesModel);
- var pipelineContext = seriesModel.pipelineContext;
- var originalLarge = !!fields.large;
- var originalProgressive = !!fields.progressiveRender; // FIXME: if the planner works on a filtered series, `pipelineContext` does not
- // exists. See #11611 . Probably we need to modify this structure, see the comment
- // on `performRawSeries` in `Schedular.js`.
-
- var large = fields.large = !!(pipelineContext && pipelineContext.large);
- var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender);
- return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset';
- };
- }
-
- var inner$2 = makeInner();
- var renderPlanner = createRenderPlanner();
-
- var ChartView =
- /** @class */
- function () {
- function ChartView() {
- this.group = new Group();
- this.uid = getUID('viewChart');
- this.renderTask = createTask({
- plan: renderTaskPlan,
- reset: renderTaskReset
- });
- this.renderTask.context = {
- view: this
- };
- }
-
- ChartView.prototype.init = function (ecModel, api) {};
-
- ChartView.prototype.render = function (seriesModel, ecModel, api, payload) {};
- /**
- * Highlight series or specified data item.
- */
-
-
- ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) {
- toggleHighlight(seriesModel.getData(), payload, 'emphasis');
- };
- /**
- * Downplay series or specified data item.
- */
-
-
- ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) {
- toggleHighlight(seriesModel.getData(), payload, 'normal');
- };
- /**
- * Remove self.
- */
-
-
- ChartView.prototype.remove = function (ecModel, api) {
- this.group.removeAll();
- };
- /**
- * Dispose self.
- */
-
-
- ChartView.prototype.dispose = function (ecModel, api) {};
-
- ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) {
- this.render(seriesModel, ecModel, api, payload);
- }; // FIXME never used?
-
-
- ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) {
- this.render(seriesModel, ecModel, api, payload);
- }; // FIXME never used?
-
-
- ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) {
- this.render(seriesModel, ecModel, api, payload);
- };
-
- ChartView.markUpdateMethod = function (payload, methodName) {
- inner$2(payload).updateMethod = methodName;
- };
-
- ChartView.protoInitialize = function () {
- var proto = ChartView.prototype;
- proto.type = 'chart';
- }();
-
- return ChartView;
- }();
- /**
- * Set state of single element
- */
-
- function elSetState(el, state, highlightDigit) {
- if (el) {
- (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit);
- }
- }
-
- function toggleHighlight(data, payload, state) {
- var dataIndex = queryDataIndex(data, payload);
- var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null;
-
- if (dataIndex != null) {
- each(normalizeToArray(dataIndex), function (dataIdx) {
- elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit);
- });
- } else {
- data.eachItemGraphicEl(function (el) {
- elSetState(el, state, highlightDigit);
- });
- }
- }
-
- enableClassExtend(ChartView, ['dispose']);
- enableClassManagement(ChartView);
-
- function renderTaskPlan(context) {
- return renderPlanner(context.model);
- }
-
- function renderTaskReset(context) {
- var seriesModel = context.model;
- var ecModel = context.ecModel;
- var api = context.api;
- var payload = context.payload; // FIXME: remove updateView updateVisual
-
- var progressiveRender = seriesModel.pipelineContext.progressiveRender;
- var view = context.view;
- var updateMethod = payload && inner$2(payload).updateMethod;
- var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod // `appendData` is also supported when data amount
- // is less than progressive threshold.
- : 'render';
-
- if (methodName !== 'render') {
- view[methodName](seriesModel, ecModel, api, payload);
- }
-
- return progressMethodMap[methodName];
- }
-
- var progressMethodMap = {
- incrementalPrepareRender: {
- progress: function (params, context) {
- context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload);
- }
- },
- render: {
- // Put view.render in `progress` to support appendData. But in this case
- // view.render should not be called in reset, otherwise it will be called
- // twise. Use `forceFirstProgress` to make sure that view.render is called
- // in any cases.
- forceFirstProgress: true,
- progress: function (params, context) {
- context.view.render(context.model, context.ecModel, context.api, context.payload);
- }
- }
- };
-
- /*
- * 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.
- */
-
-
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
-
- /*
- * 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.
- */
- var ORIGIN_METHOD = '\0__throttleOriginMethod';
- var RATE = '\0__throttleRate';
- var THROTTLE_TYPE = '\0__throttleType';
- /**
- * @public
- * @param {(Function)} fn
- * @param {number} [delay=0] Unit: ms.
- * @param {boolean} [debounce=false]
- * true: If call interval less than `delay`, only the last call works.
- * false: If call interval less than `delay, call works on fixed rate.
- * @return {(Function)} throttled fn.
- */
-
- function throttle(fn, delay, debounce) {
- var currCall;
- var lastCall = 0;
- var lastExec = 0;
- var timer = null;
- var diff;
- var scope;
- var args;
- var debounceNextCall;
- delay = delay || 0;
-
- function exec() {
- lastExec = new Date().getTime();
- timer = null;
- fn.apply(scope, args || []);
- }
-
- var cb = function () {
- var cbArgs = [];
-
- for (var _i = 0; _i < arguments.length; _i++) {
- cbArgs[_i] = arguments[_i];
- }
-
- currCall = new Date().getTime();
- scope = this;
- args = cbArgs;
- var thisDelay = debounceNextCall || delay;
- var thisDebounce = debounceNextCall || debounce;
- debounceNextCall = null;
- diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay;
- clearTimeout(timer); // Here we should make sure that: the `exec` SHOULD NOT be called later
- // than a new call of `cb`, that is, preserving the command order. Consider
- // calculating "scale rate" when roaming as an example. When a call of `cb`
- // happens, either the `exec` is called dierectly, or the call is delayed.
- // But the delayed call should never be later than next call of `cb`. Under
- // this assurance, we can simply update view state each time `dispatchAction`
- // triggered by user roaming, but not need to add extra code to avoid the
- // state being "rolled-back".
-
- if (thisDebounce) {
- timer = setTimeout(exec, thisDelay);
- } else {
- if (diff >= 0) {
- exec();
- } else {
- timer = setTimeout(exec, -diff);
- }
- }
-
- lastCall = currCall;
- };
- /**
- * Clear throttle.
- * @public
- */
-
-
- cb.clear = function () {
- if (timer) {
- clearTimeout(timer);
- timer = null;
- }
- };
- /**
- * Enable debounce once.
- */
-
-
- cb.debounceNextCall = function (debounceDelay) {
- debounceNextCall = debounceDelay;
- };
-
- return cb;
- }
- /**
- * Create throttle method or update throttle rate.
- *
- * @example
- * ComponentView.prototype.render = function () {
- * ...
- * throttle.createOrUpdate(
- * this,
- * '_dispatchAction',
- * this.model.get('throttle'),
- * 'fixRate'
- * );
- * };
- * ComponentView.prototype.remove = function () {
- * throttle.clear(this, '_dispatchAction');
- * };
- * ComponentView.prototype.dispose = function () {
- * throttle.clear(this, '_dispatchAction');
- * };
- *
- */
-
- function createOrUpdate(obj, fnAttr, rate, throttleType) {
- var fn = obj[fnAttr];
-
- if (!fn) {
- return;
- }
-
- var originFn = fn[ORIGIN_METHOD] || fn;
- var lastThrottleType = fn[THROTTLE_TYPE];
- var lastRate = fn[RATE];
-
- if (lastRate !== rate || lastThrottleType !== throttleType) {
- if (rate == null || !throttleType) {
- return obj[fnAttr] = originFn;
- }
-
- fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce');
- fn[ORIGIN_METHOD] = originFn;
- fn[THROTTLE_TYPE] = throttleType;
- fn[RATE] = rate;
- }
-
- return fn;
- }
- /**
- * Clear throttle. Example see throttle.createOrUpdate.
- */
-
- function clear(obj, fnAttr) {
- var fn = obj[fnAttr];
-
- if (fn && fn[ORIGIN_METHOD]) {
- obj[fnAttr] = fn[ORIGIN_METHOD];
- }
- }
-
- var inner$3 = makeInner();
- var defaultStyleMappers = {
- itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true),
- lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true)
- };
- var defaultColorKey = {
- lineStyle: 'stroke',
- itemStyle: 'fill'
- };
-
- function getStyleMapper(seriesModel, stylePath) {
- var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath];
-
- if (!styleMapper) {
- console.warn("Unkown style type '" + stylePath + "'.");
- return defaultStyleMappers.itemStyle;
- }
-
- return styleMapper;
- }
-
- function getDefaultColorKey(seriesModel, stylePath) {
- // return defaultColorKey[stylePath] ||
- var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath];
-
- if (!colorKey) {
- console.warn("Unkown style type '" + stylePath + "'.");
- return 'fill';
- }
-
- return colorKey;
- }
-
- var seriesStyleTask = {
- createOnAllSeries: true,
- performRawSeries: true,
- reset: function (seriesModel, ecModel) {
- var data = seriesModel.getData();
- var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle
-
- var styleModel = seriesModel.getModel(stylePath);
- var getStyle = getStyleMapper(seriesModel, stylePath);
- var globalStyle = getStyle(styleModel);
- var decalOption = styleModel.getShallow('decal');
-
- if (decalOption) {
- data.setVisual('decal', decalOption);
- decalOption.dirty = true;
- } // TODO
-
-
- var colorKey = getDefaultColorKey(seriesModel, stylePath);
- var color = globalStyle[colorKey]; // TODO style callback
-
- var colorCallback = isFunction(color) ? color : null;
- var hasAutoColor = globalStyle.fill === 'auto' || globalStyle.stroke === 'auto'; // Get from color palette by default.
-
- if (!globalStyle[colorKey] || colorCallback || hasAutoColor) {
- // Note: if some series has color specified (e.g., by itemStyle.color), we DO NOT
- // make it effect palette. Bacause some scenarios users need to make some series
- // transparent or as background, which should better not effect the palette.
- var colorPalette = seriesModel.getColorFromPalette( // TODO series count changed.
- seriesModel.name, null, ecModel.getSeriesCount());
-
- if (!globalStyle[colorKey]) {
- globalStyle[colorKey] = colorPalette;
- data.setVisual('colorFromPalette', true);
- }
-
- globalStyle.fill = globalStyle.fill === 'auto' || typeof globalStyle.fill === 'function' ? colorPalette : globalStyle.fill;
- globalStyle.stroke = globalStyle.stroke === 'auto' || typeof globalStyle.stroke === 'function' ? colorPalette : globalStyle.stroke;
- }
-
- data.setVisual('style', globalStyle);
- data.setVisual('drawType', colorKey); // Only visible series has each data be visual encoded
-
- if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) {
- data.setVisual('colorFromPalette', false);
- return {
- dataEach: function (data, idx) {
- var dataParams = seriesModel.getDataParams(idx);
- var itemStyle = extend({}, globalStyle);
- itemStyle[colorKey] = colorCallback(dataParams);
- data.setItemVisual(idx, 'style', itemStyle);
- }
- };
- }
- }
- };
- var sharedModel = new Model();
- var dataStyleTask = {
- createOnAllSeries: true,
- performRawSeries: true,
- reset: function (seriesModel, ecModel) {
- if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) {
- return;
- }
-
- var data = seriesModel.getData();
- var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; // Set in itemStyle
-
- var getStyle = getStyleMapper(seriesModel, stylePath);
- var colorKey = data.getVisual('drawType');
- return {
- dataEach: data.hasItemOption ? function (data, idx) {
- // Not use getItemModel for performance considuration
- var rawItem = data.getRawDataItem(idx);
-
- if (rawItem && rawItem[stylePath]) {
- sharedModel.option = rawItem[stylePath];
- var style = getStyle(sharedModel);
- var existsStyle = data.ensureUniqueItemVisual(idx, 'style');
- extend(existsStyle, style);
-
- if (sharedModel.option.decal) {
- data.setItemVisual(idx, 'decal', sharedModel.option.decal);
- sharedModel.option.decal.dirty = true;
- }
-
- if (colorKey in style) {
- data.setItemVisual(idx, 'colorFromPalette', false);
- }
- }
- } : null
- };
- }
- }; // Pick color from palette for the data which has not been set with color yet.
- // Note: do not support stream rendering. No such cases yet.
-
- var dataColorPaletteTask = {
- performRawSeries: true,
- overallReset: function (ecModel) {
- // Each type of series use one scope.
- // Pie and funnel are using diferrent scopes
- var paletteScopeGroupByType = createHashMap();
- ecModel.eachSeries(function (seriesModel) {
- var colorBy = seriesModel.getColorBy();
-
- if (seriesModel.isColorBySeries()) {
- return;
- }
-
- var key = seriesModel.type + '-' + colorBy;
- var colorScope = paletteScopeGroupByType.get(key);
-
- if (!colorScope) {
- colorScope = {};
- paletteScopeGroupByType.set(key, colorScope);
- }
-
- inner$3(seriesModel).scope = colorScope;
- });
- ecModel.eachSeries(function (seriesModel) {
- if (seriesModel.isColorBySeries() || ecModel.isSeriesFiltered(seriesModel)) {
- return;
- }
-
- var dataAll = seriesModel.getRawData();
- var idxMap = {};
- var data = seriesModel.getData();
- var colorScope = inner$3(seriesModel).scope;
- var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle';
- var colorKey = getDefaultColorKey(seriesModel, stylePath);
- data.each(function (idx) {
- var rawIdx = data.getRawIndex(idx);
- idxMap[rawIdx] = idx;
- }); // Iterate on data before filtered. To make sure color from palette can be
- // Consistent when toggling legend.
-
- dataAll.each(function (rawIdx) {
- var idx = idxMap[rawIdx];
- var fromPalette = data.getItemVisual(idx, 'colorFromPalette'); // Get color from palette for each data only when the color is inherited from series color, which is
- // also picked from color palette. So following situation is not in the case:
- // 1. series.itemStyle.color is set
- // 2. color is encoded by visualMap
-
- if (fromPalette) {
- var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
- var name_1 = dataAll.getName(rawIdx) || rawIdx + '';
- var dataCount = dataAll.count();
- itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount);
- }
- });
- });
- }
- };
-
- var PI$3 = Math.PI;
- /**
- * @param {module:echarts/ExtensionAPI} api
- * @param {Object} [opts]
- * @param {string} [opts.text]
- * @param {string} [opts.color]
- * @param {string} [opts.textColor]
- * @return {module:zrender/Element}
- */
-
- function defaultLoading(api, opts) {
- opts = opts || {};
- defaults(opts, {
- text: 'loading',
- textColor: '#000',
- fontSize: 12,
- fontWeight: 'normal',
- fontStyle: 'normal',
- fontFamily: 'sans-serif',
- maskColor: 'rgba(255, 255, 255, 0.8)',
- showSpinner: true,
- color: '#5470c6',
- spinnerRadius: 10,
- lineWidth: 5,
- zlevel: 0
- });
- var group = new Group();
- var mask = new Rect({
- style: {
- fill: opts.maskColor
- },
- zlevel: opts.zlevel,
- z: 10000
- });
- group.add(mask);
- var textContent = new ZRText({
- style: {
- text: opts.text,
- fill: opts.textColor,
- fontSize: opts.fontSize,
- fontWeight: opts.fontWeight,
- fontStyle: opts.fontStyle,
- fontFamily: opts.fontFamily
- },
- zlevel: opts.zlevel,
- z: 10001
- });
- var labelRect = new Rect({
- style: {
- fill: 'none'
- },
- textContent: textContent,
- textConfig: {
- position: 'right',
- distance: 10
- },
- zlevel: opts.zlevel,
- z: 10001
- });
- group.add(labelRect);
- var arc;
-
- if (opts.showSpinner) {
- arc = new Arc({
- shape: {
- startAngle: -PI$3 / 2,
- endAngle: -PI$3 / 2 + 0.1,
- r: opts.spinnerRadius
- },
- style: {
- stroke: opts.color,
- lineCap: 'round',
- lineWidth: opts.lineWidth
- },
- zlevel: opts.zlevel,
- z: 10001
- });
- arc.animateShape(true).when(1000, {
- endAngle: PI$3 * 3 / 2
- }).start('circularInOut');
- arc.animateShape(true).when(1000, {
- startAngle: PI$3 * 3 / 2
- }).delay(300).start('circularInOut');
- group.add(arc);
- } // Inject resize
-
-
- group.resize = function () {
- var textWidth = textContent.getBoundingRect().width;
- var r = opts.showSpinner ? opts.spinnerRadius : 0; // cx = (containerWidth - arcDiameter - textDistance - textWidth) / 2
- // textDistance needs to be calculated when both animation and text exist
-
- var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner && textWidth ? 0 : 5 + textWidth / 2) // only show the text
- + (opts.showSpinner ? 0 : textWidth / 2) // only show the spinner
- + (textWidth ? 0 : r);
- var cy = api.getHeight() / 2;
- opts.showSpinner && arc.setShape({
- cx: cx,
- cy: cy
- });
- labelRect.setShape({
- x: cx - r,
- y: cy - r,
- width: r * 2,
- height: r * 2
- });
- mask.setShape({
- x: 0,
- y: 0,
- width: api.getWidth(),
- height: api.getHeight()
- });
- };
-
- group.resize();
- return group;
- }
-
- var Scheduler =
- /** @class */
- function () {
- function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) {
- // key: handlerUID
- this._stageTaskMap = createHashMap();
- this.ecInstance = ecInstance;
- this.api = api; // Fix current processors in case that in some rear cases that
- // processors might be registered after echarts instance created.
- // Register processors incrementally for a echarts instance is
- // not supported by this stream architecture.
-
- dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice();
- visualHandlers = this._visualHandlers = visualHandlers.slice();
- this._allHandlers = dataProcessorHandlers.concat(visualHandlers);
- }
-
- Scheduler.prototype.restoreData = function (ecModel, payload) {
- // TODO: Only restore needed series and components, but not all components.
- // Currently `restoreData` of all of the series and component will be called.
- // But some independent components like `title`, `legend`, `graphic`, `toolbox`,
- // `tooltip`, `axisPointer`, etc, do not need series refresh when `setOption`,
- // and some components like coordinate system, axes, dataZoom, visualMap only
- // need their target series refresh.
- // (1) If we are implementing this feature some day, we should consider these cases:
- // if a data processor depends on a component (e.g., dataZoomProcessor depends
- // on the settings of `dataZoom`), it should be re-performed if the component
- // is modified by `setOption`.
- // (2) If a processor depends on sevral series, speicified by its `getTargetSeries`,
- // it should be re-performed when the result array of `getTargetSeries` changed.
- // We use `dependencies` to cover these issues.
- // (3) How to update target series when coordinate system related components modified.
- // TODO: simply the dirty mechanism? Check whether only the case here can set tasks dirty,
- // and this case all of the tasks will be set as dirty.
- ecModel.restoreData(payload); // Theoretically an overall task not only depends on each of its target series, but also
- // depends on all of the series.
- // The overall task is not in pipeline, and `ecModel.restoreData` only set pipeline tasks
- // dirty. If `getTargetSeries` of an overall task returns nothing, we should also ensure
- // that the overall task is set as dirty and to be performed, otherwise it probably cause
- // state chaos. So we have to set dirty of all of the overall tasks manually, otherwise it
- // probably cause state chaos (consider `dataZoomProcessor`).
-
- this._stageTaskMap.each(function (taskRecord) {
- var overallTask = taskRecord.overallTask;
- overallTask && overallTask.dirty();
- });
- }; // If seriesModel provided, incremental threshold is check by series data.
-
-
- Scheduler.prototype.getPerformArgs = function (task, isBlock) {
- // For overall task
- if (!task.__pipeline) {
- return;
- }
-
- var pipeline = this._pipelineMap.get(task.__pipeline.id);
-
- var pCtx = pipeline.context;
- var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex;
- var step = incremental ? pipeline.step : null;
- var modDataCount = pCtx && pCtx.modDataCount;
- var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null;
- return {
- step: step,
- modBy: modBy,
- modDataCount: modDataCount
- };
- };
-
- Scheduler.prototype.getPipeline = function (pipelineId) {
- return this._pipelineMap.get(pipelineId);
- };
- /**
- * Current, progressive rendering starts from visual and layout.
- * Always detect render mode in the same stage, avoiding that incorrect
- * detection caused by data filtering.
- * Caution:
- * `updateStreamModes` use `seriesModel.getData()`.
- */
-
-
- Scheduler.prototype.updateStreamModes = function (seriesModel, view) {
- var pipeline = this._pipelineMap.get(seriesModel.uid);
-
- var data = seriesModel.getData();
- var dataLen = data.count(); // `progressiveRender` means that can render progressively in each
- // animation frame. Note that some types of series do not provide
- // `view.incrementalPrepareRender` but support `chart.appendData`. We
- // use the term `incremental` but not `progressive` to describe the
- // case that `chart.appendData`.
-
- var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold;
- var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); // TODO: modDataCount should not updated if `appendData`, otherwise cause whole repaint.
- // see `test/candlestick-large3.html`
-
- var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null;
- seriesModel.pipelineContext = pipeline.context = {
- progressiveRender: progressiveRender,
- modDataCount: modDataCount,
- large: large
- };
- };
-
- Scheduler.prototype.restorePipelines = function (ecModel) {
- var scheduler = this;
- var pipelineMap = scheduler._pipelineMap = createHashMap();
- ecModel.eachSeries(function (seriesModel) {
- var progressive = seriesModel.getProgressive();
- var pipelineId = seriesModel.uid;
- pipelineMap.set(pipelineId, {
- id: pipelineId,
- head: null,
- tail: null,
- threshold: seriesModel.getProgressiveThreshold(),
- progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()),
- blockIndex: -1,
- step: Math.round(progressive || 700),
- count: 0
- });
-
- scheduler._pipe(seriesModel, seriesModel.dataTask);
- });
- };
-
- Scheduler.prototype.prepareStageTasks = function () {
- var stageTaskMap = this._stageTaskMap;
- var ecModel = this.api.getModel();
- var api = this.api;
- each(this._allHandlers, function (handler) {
- var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {});
- var errMsg = '';
-
- if ("development" !== 'production') {
- // Currently do not need to support to sepecify them both.
- errMsg = '"reset" and "overallReset" must not be both specified.';
- }
-
- assert(!(handler.reset && handler.overallReset), errMsg);
- handler.reset && this._createSeriesStageTask(handler, record, ecModel, api);
- handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api);
- }, this);
- };
-
- Scheduler.prototype.prepareView = function (view, model, ecModel, api) {
- var renderTask = view.renderTask;
- var context = renderTask.context;
- context.model = model;
- context.ecModel = ecModel;
- context.api = api;
- renderTask.__block = !view.incrementalPrepareRender;
-
- this._pipe(model, renderTask);
- };
-
- Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) {
- // If we do not use `block` here, it should be considered when to update modes.
- this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, {
- block: true
- });
- };
-
- Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) {
- this._performStageTasks(this._visualHandlers, ecModel, payload, opt);
- };
-
- Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) {
- opt = opt || {};
- var unfinished = false;
- var scheduler = this;
- each(stageHandlers, function (stageHandler, idx) {
- if (opt.visualType && opt.visualType !== stageHandler.visualType) {
- return;
- }
-
- var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid);
-
- var seriesTaskMap = stageHandlerRecord.seriesTaskMap;
- var overallTask = stageHandlerRecord.overallTask;
-
- if (overallTask) {
- var overallNeedDirty_1;
- var agentStubMap = overallTask.agentStubMap;
- agentStubMap.each(function (stub) {
- if (needSetDirty(opt, stub)) {
- stub.dirty();
- overallNeedDirty_1 = true;
- }
- });
- overallNeedDirty_1 && overallTask.dirty();
- scheduler.updatePayload(overallTask, payload);
- var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block); // Execute stubs firstly, which may set the overall task dirty,
- // then execute the overall task. And stub will call seriesModel.setData,
- // which ensures that in the overallTask seriesModel.getData() will not
- // return incorrect data.
-
- agentStubMap.each(function (stub) {
- stub.perform(performArgs_1);
- });
-
- if (overallTask.perform(performArgs_1)) {
- unfinished = true;
- }
- } else if (seriesTaskMap) {
- seriesTaskMap.each(function (task, pipelineId) {
- if (needSetDirty(opt, task)) {
- task.dirty();
- }
-
- var performArgs = scheduler.getPerformArgs(task, opt.block); // FIXME
- // if intending to decalare `performRawSeries` in handlers, only
- // stream-independent (specifically, data item independent) operations can be
- // performed. Because is a series is filtered, most of the tasks will not
- // be performed. A stream-dependent operation probably cause wrong biz logic.
- // Perhaps we should not provide a separate callback for this case instead
- // of providing the config `performRawSeries`. The stream-dependent operaions
- // and stream-independent operations should better not be mixed.
-
- performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model);
- scheduler.updatePayload(task, payload);
-
- if (task.perform(performArgs)) {
- unfinished = true;
- }
- });
- }
- });
-
- function needSetDirty(opt, task) {
- return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id));
- }
-
- this.unfinished = unfinished || this.unfinished;
- };
-
- Scheduler.prototype.performSeriesTasks = function (ecModel) {
- var unfinished;
- ecModel.eachSeries(function (seriesModel) {
- // Progress to the end for dataInit and dataRestore.
- unfinished = seriesModel.dataTask.perform() || unfinished;
- });
- this.unfinished = unfinished || this.unfinished;
- };
-
- Scheduler.prototype.plan = function () {
- // Travel pipelines, check block.
- this._pipelineMap.each(function (pipeline) {
- var task = pipeline.tail;
-
- do {
- if (task.__block) {
- pipeline.blockIndex = task.__idxInPipeline;
- break;
- }
-
- task = task.getUpstream();
- } while (task);
- });
- };
-
- Scheduler.prototype.updatePayload = function (task, payload) {
- payload !== 'remain' && (task.context.payload = payload);
- };
-
- Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
- var scheduler = this;
- var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap; // The count of stages are totally about only several dozen, so
- // do not need to reuse the map.
-
- var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap();
- var seriesType = stageHandler.seriesType;
- var getTargetSeries = stageHandler.getTargetSeries; // If a stageHandler should cover all series, `createOnAllSeries` should be declared mandatorily,
- // to avoid some typo or abuse. Otherwise if an extension do not specify a `seriesType`,
- // it works but it may cause other irrelevant charts blocked.
-
- if (stageHandler.createOnAllSeries) {
- ecModel.eachRawSeries(create);
- } else if (seriesType) {
- ecModel.eachRawSeriesByType(seriesType, create);
- } else if (getTargetSeries) {
- getTargetSeries(ecModel, api).each(create);
- }
-
- function create(seriesModel) {
- var pipelineId = seriesModel.uid; // Init tasks for each seriesModel only once.
- // Reuse original task instance.
-
- var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({
- plan: seriesTaskPlan,
- reset: seriesTaskReset,
- count: seriesTaskCount
- }));
- task.context = {
- model: seriesModel,
- ecModel: ecModel,
- api: api,
- // PENDING: `useClearVisual` not used?
- useClearVisual: stageHandler.isVisual && !stageHandler.isLayout,
- plan: stageHandler.plan,
- reset: stageHandler.reset,
- scheduler: scheduler
- };
-
- scheduler._pipe(seriesModel, task);
- }
- };
-
- Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) {
- var scheduler = this;
- var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask // For overall task, the function only be called on reset stage.
- || createTask({
- reset: overallTaskReset
- });
- overallTask.context = {
- ecModel: ecModel,
- api: api,
- overallReset: stageHandler.overallReset,
- scheduler: scheduler
- };
- var oldAgentStubMap = overallTask.agentStubMap; // The count of stages are totally about only several dozen, so
- // do not need to reuse the map.
-
- var newAgentStubMap = overallTask.agentStubMap = createHashMap();
- var seriesType = stageHandler.seriesType;
- var getTargetSeries = stageHandler.getTargetSeries;
- var overallProgress = true;
- var shouldOverallTaskDirty = false; // FIXME:TS never used, so comment it
- // let modifyOutputEnd = stageHandler.modifyOutputEnd;
- // An overall task with seriesType detected or has `getTargetSeries`, we add
- // stub in each pipelines, it will set the overall task dirty when the pipeline
- // progress. Moreover, to avoid call the overall task each frame (too frequent),
- // we set the pipeline block.
-
- var errMsg = '';
-
- if ("development" !== 'production') {
- errMsg = '"createOnAllSeries" do not supported for "overallReset", ' + 'becuase it will block all streams.';
- }
-
- assert(!stageHandler.createOnAllSeries, errMsg);
-
- if (seriesType) {
- ecModel.eachRawSeriesByType(seriesType, createStub);
- } else if (getTargetSeries) {
- getTargetSeries(ecModel, api).each(createStub);
- } // Otherwise, (usually it is legancy case), the overall task will only be
- // executed when upstream dirty. Otherwise the progressive rendering of all
- // pipelines will be disabled unexpectedly. But it still needs stubs to receive
- // dirty info from upsteam.
- else {
- overallProgress = false;
- each(ecModel.getSeries(), createStub);
- }
-
- function createStub(seriesModel) {
- var pipelineId = seriesModel.uid;
- var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || ( // When the result of `getTargetSeries` changed, the overallTask
- // should be set as dirty and re-performed.
- shouldOverallTaskDirty = true, createTask({
- reset: stubReset,
- onDirty: stubOnDirty
- })));
- stub.context = {
- model: seriesModel,
- overallProgress: overallProgress // FIXME:TS never used, so comment it
- // modifyOutputEnd: modifyOutputEnd
-
- };
- stub.agent = overallTask;
- stub.__block = overallProgress;
-
- scheduler._pipe(seriesModel, stub);
- }
-
- if (shouldOverallTaskDirty) {
- overallTask.dirty();
- }
- };
-
- Scheduler.prototype._pipe = function (seriesModel, task) {
- var pipelineId = seriesModel.uid;
-
- var pipeline = this._pipelineMap.get(pipelineId);
-
- !pipeline.head && (pipeline.head = task);
- pipeline.tail && pipeline.tail.pipe(task);
- pipeline.tail = task;
- task.__idxInPipeline = pipeline.count++;
- task.__pipeline = pipeline;
- };
-
- Scheduler.wrapStageHandler = function (stageHandler, visualType) {
- if (isFunction(stageHandler)) {
- stageHandler = {
- overallReset: stageHandler,
- seriesType: detectSeriseType(stageHandler)
- };
- }
-
- stageHandler.uid = getUID('stageHandler');
- visualType && (stageHandler.visualType = visualType);
- return stageHandler;
- };
- return Scheduler;
- }();
-
- function overallTaskReset(context) {
- context.overallReset(context.ecModel, context.api, context.payload);
- }
-
- function stubReset(context) {
- return context.overallProgress && stubProgress;
- }
-
- function stubProgress() {
- this.agent.dirty();
- this.getDownstream().dirty();
- }
-
- function stubOnDirty() {
- this.agent && this.agent.dirty();
- }
-
- function seriesTaskPlan(context) {
- return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null;
- }
-
- function seriesTaskReset(context) {
- if (context.useClearVisual) {
- context.data.clearAllVisual();
- }
-
- var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload));
- return resetDefines.length > 1 ? map(resetDefines, function (v, idx) {
- return makeSeriesTaskProgress(idx);
- }) : singleSeriesTaskProgress;
- }
-
- var singleSeriesTaskProgress = makeSeriesTaskProgress(0);
-
- function makeSeriesTaskProgress(resetDefineIdx) {
- return function (params, context) {
- var data = context.data;
- var resetDefine = context.resetDefines[resetDefineIdx];
-
- if (resetDefine && resetDefine.dataEach) {
- for (var i = params.start; i < params.end; i++) {
- resetDefine.dataEach(data, i);
- }
- } else if (resetDefine && resetDefine.progress) {
- resetDefine.progress(params, data);
- }
- };
- }
-
- function seriesTaskCount(context) {
- return context.data.count();
- }
- /**
- * Only some legacy stage handlers (usually in echarts extensions) are pure function.
- * To ensure that they can work normally, they should work in block mode, that is,
- * they should not be started util the previous tasks finished. So they cause the
- * progressive rendering disabled. We try to detect the series type, to narrow down
- * the block range to only the series type they concern, but not all series.
- */
-
-
- function detectSeriseType(legacyFunc) {
- seriesType = null;
-
- try {
- // Assume there is no async when calling `eachSeriesByType`.
- legacyFunc(ecModelMock, apiMock);
- } catch (e) {}
-
- return seriesType;
- }
-
- var ecModelMock = {};
- var apiMock = {};
- var seriesType;
- mockMethods(ecModelMock, GlobalModel);
- mockMethods(apiMock, ExtensionAPI);
-
- ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) {
- seriesType = type;
- };
-
- ecModelMock.eachComponent = function (cond) {
- if (cond.mainType === 'series' && cond.subType) {
- seriesType = cond.subType;
- }
- };
-
- function mockMethods(target, Clz) {
- /* eslint-disable */
- for (var name_1 in Clz.prototype) {
- // Do not use hasOwnProperty
- target[name_1] = noop;
- }
- /* eslint-enable */
-
- }
-
- /*
- * 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.
- */
-
-
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
-
- /*
- * 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.
- */
- var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'];
- var lightTheme = {
- color: colorAll,
- colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll]
- };
-
- /*
- * 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.
- */
-
-
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
-
- /*
- * 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.
- */
- var contrastColor = '#B9B8CE';
- var backgroundColor = '#100C2A';
-
- var axisCommon = function () {
- return {
- axisLine: {
- lineStyle: {
- color: contrastColor
- }
- },
- splitLine: {
- lineStyle: {
- color: '#484753'
- }
- },
- splitArea: {
- areaStyle: {
- color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)']
- }
- },
- minorSplitLine: {
- lineStyle: {
- color: '#20203B'
- }
- }
- };
- };
-
- var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff'];
- var theme = {
- darkMode: true,
- color: colorPalette,
- backgroundColor: backgroundColor,
- axisPointer: {
- lineStyle: {
- color: '#817f91'
- },
- crossStyle: {
- color: '#817f91'
- },
- label: {
- // TODO Contrast of label backgorundColor
- color: '#fff'
- }
- },
- legend: {
- textStyle: {
- color: contrastColor
- }
- },
- textStyle: {
- color: contrastColor
- },
- title: {
- textStyle: {
- color: '#EEF1FA'
- },
- subtextStyle: {
- color: '#B9B8CE'
- }
- },
- toolbox: {
- iconStyle: {
- borderColor: contrastColor
- }
- },
- dataZoom: {
- borderColor: '#71708A',
- textStyle: {
- color: contrastColor
- },
- brushStyle: {
- color: 'rgba(135,163,206,0.3)'
- },
- handleStyle: {
- color: '#353450',
- borderColor: '#C5CBE3'
- },
- moveHandleStyle: {
- color: '#B0B6C3',
- opacity: 0.3
- },
- fillerColor: 'rgba(135,163,206,0.2)',
- emphasis: {
- handleStyle: {
- borderColor: '#91B7F2',
- color: '#4D587D'
- },
- moveHandleStyle: {
- color: '#636D9A',
- opacity: 0.7
- }
- },
- dataBackground: {
- lineStyle: {
- color: '#71708A',
- width: 1
- },
- areaStyle: {
- color: '#71708A'
- }
- },
- selectedDataBackground: {
- lineStyle: {
- color: '#87A3CE'
- },
- areaStyle: {
- color: '#87A3CE'
- }
- }
- },
- visualMap: {
- textStyle: {
- color: contrastColor
- }
- },
- timeline: {
- lineStyle: {
- color: contrastColor
- },
- label: {
- color: contrastColor
- },
- controlStyle: {
- color: contrastColor,
- borderColor: contrastColor
- }
- },
- calendar: {
- itemStyle: {
- color: backgroundColor
- },
- dayLabel: {
- color: contrastColor
- },
- monthLabel: {
- color: contrastColor
- },
- yearLabel: {
- color: contrastColor
- }
- },
- timeAxis: axisCommon(),
- logAxis: axisCommon(),
- valueAxis: axisCommon(),
- categoryAxis: axisCommon(),
- line: {
- symbol: 'circle'
- },
- graph: {
- color: colorPalette
- },
- gauge: {
- title: {
- color: contrastColor
- },
- axisLine: {
- lineStyle: {
- color: [[1, 'rgba(207,212,219,0.2)']]
- }
- },
- axisLabel: {
- color: contrastColor
- },
- detail: {
- color: '#EEF1FA'
- }
- },
- candlestick: {
- itemStyle: {
- color: '#f64e56',
- color0: '#54ea92',
- borderColor: '#f64e56',
- borderColor0: '#54ea92' // borderColor: '#ca2824',
- // borderColor0: '#09a443'
-
- }
- }
- };
- theme.categoryAxis.splitLine.show = false;
-
- /**
- * Usage of query:
- * `chart.on('click', query, handler);`
- * The `query` can be:
- * + The component type query string, only `mainType` or `mainType.subType`,
- * like: 'xAxis', 'series', 'xAxis.category' or 'series.line'.
- * + The component query object, like:
- * `{seriesIndex: 2}`, `{seriesName: 'xx'}`, `{seriesId: 'some'}`,
- * `{xAxisIndex: 2}`, `{xAxisName: 'xx'}`, `{xAxisId: 'some'}`.
- * + The data query object, like:
- * `{dataIndex: 123}`, `{dataType: 'link'}`, `{name: 'some'}`.
- * + The other query object (cmponent customized query), like:
- * `{element: 'some'}` (only available in custom series).
- *
- * Caveat: If a prop in the `query` object is `null/undefined`, it is the
- * same as there is no such prop in the `query` object.
- */
-
- var ECEventProcessor =
- /** @class */
- function () {
- function ECEventProcessor() {}
-
- ECEventProcessor.prototype.normalizeQuery = function (query) {
- var cptQuery = {};
- var dataQuery = {};
- var otherQuery = {}; // `query` is `mainType` or `mainType.subType` of component.
-
- if (isString(query)) {
- var condCptType = parseClassType(query); // `.main` and `.sub` may be ''.
-
- cptQuery.mainType = condCptType.main || null;
- cptQuery.subType = condCptType.sub || null;
- } // `query` is an object, convert to {mainType, index, name, id}.
- else {
- // `xxxIndex`, `xxxName`, `xxxId`, `name`, `dataIndex`, `dataType` is reserved,
- // can not be used in `compomentModel.filterForExposedEvent`.
- var suffixes_1 = ['Index', 'Name', 'Id'];
- var dataKeys_1 = {
- name: 1,
- dataIndex: 1,
- dataType: 1
- };
- each(query, function (val, key) {
- var reserved = false;
-
- for (var i = 0; i < suffixes_1.length; i++) {
- var propSuffix = suffixes_1[i];
- var suffixPos = key.lastIndexOf(propSuffix);
-
- if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) {
- var mainType = key.slice(0, suffixPos); // Consider `dataIndex`.
-
- if (mainType !== 'data') {
- cptQuery.mainType = mainType;
- cptQuery[propSuffix.toLowerCase()] = val;
- reserved = true;
- }
- }
- }
-
- if (dataKeys_1.hasOwnProperty(key)) {
- dataQuery[key] = val;
- reserved = true;
- }
-
- if (!reserved) {
- otherQuery[key] = val;
- }
- });
- }
-
- return {
- cptQuery: cptQuery,
- dataQuery: dataQuery,
- otherQuery: otherQuery
- };
- };
-
- ECEventProcessor.prototype.filter = function (eventType, query) {
- // They should be assigned before each trigger call.
- var eventInfo = this.eventInfo;
-
- if (!eventInfo) {
- return true;
- }
-
- var targetEl = eventInfo.targetEl;
- var packedEvent = eventInfo.packedEvent;
- var model = eventInfo.model;
- var view = eventInfo.view; // For event like 'globalout'.
-
- if (!model || !view) {
- return true;
- }
-
- var cptQuery = query.cptQuery;
- var dataQuery = query.dataQuery;
- return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent));
-
- function check(query, host, prop, propOnHost) {
- return query[prop] == null || host[propOnHost || prop] === query[prop];
- }
- };
-
- ECEventProcessor.prototype.afterTrigger = function () {
- // Make sure the eventInfo wont be used in next trigger.
- this.eventInfo = null;
- };
-
- return ECEventProcessor;
- }();
-
- var seriesSymbolTask = {
- createOnAllSeries: true,
- // For legend.
- performRawSeries: true,
- reset: function (seriesModel, ecModel) {
- var data = seriesModel.getData();
-
- if (seriesModel.legendIcon) {
- data.setVisual('legendIcon', seriesModel.legendIcon);
- }
-
- if (!seriesModel.hasSymbolVisual) {
- return;
- }
-
- var symbolType = seriesModel.get('symbol');
- var symbolSize = seriesModel.get('symbolSize');
- var keepAspect = seriesModel.get('symbolKeepAspect');
- var symbolRotate = seriesModel.get('symbolRotate');
- var symbolOffset = seriesModel.get('symbolOffset');
- var hasSymbolTypeCallback = isFunction(symbolType);
- var hasSymbolSizeCallback = isFunction(symbolSize);
- var hasSymbolRotateCallback = isFunction(symbolRotate);
- var hasSymbolOffsetCallback = isFunction(symbolOffset);
- var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback || hasSymbolOffsetCallback;
- var seriesSymbol = !hasSymbolTypeCallback && symbolType ? symbolType : seriesModel.defaultSymbol;
- var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null;
- var seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null;
- var seriesSymbolOffset = !hasSymbolOffsetCallback ? symbolOffset : null;
- data.setVisual({
- legendIcon: seriesModel.legendIcon || seriesSymbol,
- // If seting callback functions on `symbol` or `symbolSize`, for simplicity and avoiding
- // to bring trouble, we do not pick a reuslt from one of its calling on data item here,
- // but just use the default value. Callback on `symbol` or `symbolSize` is convenient in
- // some cases but generally it is not recommanded.
- symbol: seriesSymbol,
- symbolSize: seriesSymbolSize,
- symbolKeepAspect: keepAspect,
- symbolRotate: seriesSymbolRotate,
- symbolOffset: seriesSymbolOffset
- }); // Only visible series has each data be visual encoded
-
- if (ecModel.isSeriesFiltered(seriesModel)) {
- return;
- }
-
- function dataEach(data, idx) {
- var rawValue = seriesModel.getRawValue(idx);
- var params = seriesModel.getDataParams(idx);
- hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params));
- hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params));
- hasSymbolRotateCallback && data.setItemVisual(idx, 'symbolRotate', symbolRotate(rawValue, params));
- hasSymbolOffsetCallback && data.setItemVisual(idx, 'symbolOffset', symbolOffset(rawValue, params));
- }
-
- return {
- dataEach: hasCallback ? dataEach : null
- };
- }
- };
- var dataSymbolTask = {
- createOnAllSeries: true,
- // For legend.
- performRawSeries: true,
- reset: function (seriesModel, ecModel) {
- if (!seriesModel.hasSymbolVisual) {
- return;
- } // Only visible series has each data be visual encoded
-
-
- if (ecModel.isSeriesFiltered(seriesModel)) {
- return;
- }
-
- var data = seriesModel.getData();
-
- function dataEach(data, idx) {
- var itemModel = data.getItemModel(idx);
- var itemSymbolType = itemModel.getShallow('symbol', true);
- var itemSymbolSize = itemModel.getShallow('symbolSize', true);
- var itemSymbolRotate = itemModel.getShallow('symbolRotate', true);
- var itemSymbolOffset = itemModel.getShallow('symbolOffset', true);
- var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); // If has item symbol
-
- if (itemSymbolType != null) {
- data.setItemVisual(idx, 'symbol', itemSymbolType);
- }
-
- if (itemSymbolSize != null) {
- // PENDING Transform symbolSize ?
- data.setItemVisual(idx, 'symbolSize', itemSymbolSize);
- }
-
- if (itemSymbolRotate != null) {
- data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate);
- }
-
- if (itemSymbolOffset != null) {
- data.setItemVisual(idx, 'symbolOffset', itemSymbolOffset);
- }
-
- if (itemSymbolKeepAspect != null) {
- data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect);
- }
- }
-
- return {
- dataEach: data.hasItemOption ? dataEach : null
- };
- }
- };
-
- /*
- * 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.
- */
-
-
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
-
- /*
- * 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.
- */
- function getItemVisualFromData(data, dataIndex, key) {
- switch (key) {
- case 'color':
- var style = data.getItemVisual(dataIndex, 'style');
- return style[data.getVisual('drawType')];
-
- case 'opacity':
- return data.getItemVisual(dataIndex, 'style').opacity;
-
- case 'symbol':
- case 'symbolSize':
- case 'liftZ':
- return data.getItemVisual(dataIndex, key);
-
- default:
- if ("development" !== 'production') {
- console.warn("Unknown visual type " + key);
- }
-
- }
- }
- function getVisualFromData(data, key) {
- switch (key) {
- case 'color':
- var style = data.getVisual('style');
- return style[data.getVisual('drawType')];
-
- case 'opacity':
- return data.getVisual('style').opacity;
-
- case 'symbol':
- case 'symbolSize':
- case 'liftZ':
- return data.getVisual(key);
-
- default:
- if ("development" !== 'production') {
- console.warn("Unknown visual type " + key);
- }
-
- }
- }
- function setItemVisualFromData(data, dataIndex, key, value) {
- switch (key) {
- case 'color':
- // Make sure not sharing style object.
- var style = data.ensureUniqueItemVisual(dataIndex, 'style');
- style[data.getVisual('drawType')] = value; // Mark the color has been changed, not from palette anymore
-
- data.setItemVisual(dataIndex, 'colorFromPalette', false);
- break;
-
- case 'opacity':
- data.ensureUniqueItemVisual(dataIndex, 'style').opacity = value;
- break;
-
- case 'symbol':
- case 'symbolSize':
- case 'liftZ':
- data.setItemVisual(dataIndex, key, value);
- break;
-
- default:
- if ("development" !== 'production') {
- console.warn("Unknown visual type " + key);
- }
-
- }
- }
-
- // Inlucdes: pieSelect, pieUnSelect, pieToggleSelect, mapSelect, mapUnSelect, mapToggleSelect
-
- function createLegacyDataSelectAction(seriesType, ecRegisterAction) {
- function getSeriesIndices(ecModel, payload) {
- var seriesIndices = [];
- ecModel.eachComponent({
- mainType: 'series',
- subType: seriesType,
- query: payload
- }, function (seriesModel) {
- seriesIndices.push(seriesModel.seriesIndex);
- });
- return seriesIndices;
- }
-
- each([[seriesType + 'ToggleSelect', 'toggleSelect'], [seriesType + 'Select', 'select'], [seriesType + 'UnSelect', 'unselect']], function (eventsMap) {
- ecRegisterAction(eventsMap[0], function (payload, ecModel, api) {
- payload = extend({}, payload);
-
- if ("development" !== 'production') {
- deprecateReplaceLog(payload.type, eventsMap[1]);
- }
-
- api.dispatchAction(extend(payload, {
- type: eventsMap[1],
- seriesIndex: getSeriesIndices(ecModel, payload)
- }));
- });
- });
- }
-
- function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) {
- var legacyEventName = type + eventPostfix;
-
- if (!ecIns.isSilent(legacyEventName)) {
- if ("development" !== 'production') {
- deprecateLog("event " + legacyEventName + " is deprecated.");
- }
-
- ecModel.eachComponent({
- mainType: 'series',
- subType: 'pie'
- }, function (seriesModel) {
- var seriesIndex = seriesModel.seriesIndex;
- var selected = payload.selected;
-
- for (var i = 0; i < selected.length; i++) {
- if (selected[i].seriesIndex === seriesIndex) {
- var data = seriesModel.getData();
- var dataIndex = queryDataIndex(data, payload.fromActionPayload);
- ecIns.trigger(legacyEventName, {
- type: legacyEventName,
- seriesId: seriesModel.id,
- name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex),
- selected: extend({}, seriesModel.option.selectedMap)
- });
- }
- }
- });
- }
- }
-
- function handleLegacySelectEvents(messageCenter, ecIns, api) {
- messageCenter.on('selectchanged', function (params) {
- var ecModel = api.getModel();
-
- if (params.isFromClick) {
- handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params);
- handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params);
- } else if (params.fromAction === 'select') {
- handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params);
- handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params);
- } else if (params.fromAction === 'unselect') {
- handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params);
- handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params);
- }
- });
- }
-
- /*
- * 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.
- */
-
-
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
-
- /*
- * 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.
- */
- function findEventDispatcher(target, det, returnFirstMatch) {
- var found;
-
- while (target) {
- if (det(target)) {
- found = target;
-
- if (returnFirstMatch) {
- break;
- }
- }
-
- target = target.__hostTarget || target.parent;
- }
-
- return found;
- }
-
- var wmUniqueIndex = Math.round(Math.random() * 9);
- var supportDefineProperty = typeof Object.defineProperty === 'function';
- var WeakMap = (function () {
- function WeakMap() {
- this._id = '__ec_inner_' + wmUniqueIndex++;
- }
- WeakMap.prototype.get = function (key) {
- return this._guard(key)[this._id];
- };
- WeakMap.prototype.set = function (key, value) {
- var target = this._guard(key);
- if (supportDefineProperty) {
- Object.defineProperty(target, this._id, {
- value: value,
- enumerable: false,
- configurable: true
- });
- }
- else {
- target[this._id] = value;
- }
- return this;
- };
- WeakMap.prototype["delete"] = function (key) {
- if (this.has(key)) {
- delete this._guard(key)[this._id];
- return true;
- }
- return false;
- };
- WeakMap.prototype.has = function (key) {
- return !!this._guard(key)[this._id];
- };
- WeakMap.prototype._guard = function (key) {
- if (key !== Object(key)) {
- throw TypeError('Value of WeakMap is not a non-null object.');
- }
- return key;
- };
- return WeakMap;
- }());
-
- /**
- * Triangle shape
- * @inner
- */
-
- var Triangle = Path.extend({
- type: 'triangle',
- shape: {
- cx: 0,
- cy: 0,
- width: 0,
- height: 0
- },
- buildPath: function (path, shape) {
- var cx = shape.cx;
- var cy = shape.cy;
- var width = shape.width / 2;
- var height = shape.height / 2;
- path.moveTo(cx, cy - height);
- path.lineTo(cx + width, cy + height);
- path.lineTo(cx - width, cy + height);
- path.closePath();
- }
- });
- /**
- * Diamond shape
- * @inner
- */
-
- var Diamond = Path.extend({
- type: 'diamond',
- shape: {
- cx: 0,
- cy: 0,
- width: 0,
- height: 0
- },
- buildPath: function (path, shape) {
- var cx = shape.cx;
- var cy = shape.cy;
- var width = shape.width / 2;
- var height = shape.height / 2;
- path.moveTo(cx, cy - height);
- path.lineTo(cx + width, cy);
- path.lineTo(cx, cy + height);
- path.lineTo(cx - width, cy);
- path.closePath();
- }
- });
- /**
- * Pin shape
- * @inner
- */
-
- var Pin = Path.extend({
- type: 'pin',
- shape: {
- // x, y on the cusp
- x: 0,
- y: 0,
- width: 0,
- height: 0
- },
- buildPath: function (path, shape) {
- var x = shape.x;
- var y = shape.y;
- var w = shape.width / 5 * 3; // Height must be larger than width
-
- var h = Math.max(w, shape.height);
- var r = w / 2; // Dist on y with tangent point and circle center
-
- var dy = r * r / (h - r);
- var cy = y - h + r + dy;
- var angle = Math.asin(dy / r); // Dist on x with tangent point and circle center
-
- var dx = Math.cos(angle) * r;
- var tanX = Math.sin(angle);
- var tanY = Math.cos(angle);
- var cpLen = r * 0.6;
- var cpLen2 = r * 0.7;
- path.moveTo(x - dx, cy + dy);
- path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle);
- path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y);
- path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy);
- path.closePath();
- }
- });
- /**
- * Arrow shape
- * @inner
- */
-
- var Arrow = Path.extend({
- type: 'arrow',
- shape: {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- },
- buildPath: function (ctx, shape) {
- var height = shape.height;
- var width = shape.width;
- var x = shape.x;
- var y = shape.y;
- var dx = width / 3 * 2;
- ctx.moveTo(x, y);
- ctx.lineTo(x + dx, y + height);
- ctx.lineTo(x, y + height / 4 * 3);
- ctx.lineTo(x - dx, y + height);
- ctx.lineTo(x, y);
- ctx.closePath();
- }
- });
- /**
- * Map of path contructors
- */
- // TODO Use function to build symbol path.
-
- var symbolCtors = {
- line: Line,
- rect: Rect,
- roundRect: Rect,
- square: Rect,
- circle: Circle,
- diamond: Diamond,
- pin: Pin,
- arrow: Arrow,
- triangle: Triangle
- };
- var symbolShapeMakers = {
- line: function (x, y, w, h, shape) {
- shape.x1 = x;
- shape.y1 = y + h / 2;
- shape.x2 = x + w;
- shape.y2 = y + h / 2;
- },
- rect: function (x, y, w, h, shape) {
- shape.x = x;
- shape.y = y;
- shape.width = w;
- shape.height = h;
- },
- roundRect: function (x, y, w, h, shape) {
- shape.x = x;
- shape.y = y;
- shape.width = w;
- shape.height = h;
- shape.r = Math.min(w, h) / 4;
- },
- square: function (x, y, w, h, shape) {
- var size = Math.min(w, h);
- shape.x = x;
- shape.y = y;
- shape.width = size;
- shape.height = size;
- },
- circle: function (x, y, w, h, shape) {
- // Put circle in the center of square
- shape.cx = x + w / 2;
- shape.cy = y + h / 2;
- shape.r = Math.min(w, h) / 2;
- },
- diamond: function (x, y, w, h, shape) {
- shape.cx = x + w / 2;
- shape.cy = y + h / 2;
- shape.width = w;
- shape.height = h;
- },
- pin: function (x, y, w, h, shape) {
- shape.x = x + w / 2;
- shape.y = y + h / 2;
- shape.width = w;
- shape.height = h;
- },
- arrow: function (x, y, w, h, shape) {
- shape.x = x + w / 2;
- shape.y = y + h / 2;
- shape.width = w;
- shape.height = h;
- },
- triangle: function (x, y, w, h, shape) {
- shape.cx = x + w / 2;
- shape.cy = y + h / 2;
- shape.width = w;
- shape.height = h;
- }
- };
- var symbolBuildProxies = {};
- each(symbolCtors, function (Ctor, name) {
- symbolBuildProxies[name] = new Ctor();
- });
- var SymbolClz = Path.extend({
- type: 'symbol',
- shape: {
- symbolType: '',
- x: 0,
- y: 0,
- width: 0,
- height: 0
- },
- calculateTextPosition: function (out, config, rect) {
- var res = calculateTextPosition(out, config, rect);
- var shape = this.shape;
-
- if (shape && shape.symbolType === 'pin' && config.position === 'inside') {
- res.y = rect.y + rect.height * 0.4;
- }
-
- return res;
- },
- buildPath: function (ctx, shape, inBundle) {
- var symbolType = shape.symbolType;
-
- if (symbolType !== 'none') {
- var proxySymbol = symbolBuildProxies[symbolType];
-
- if (!proxySymbol) {
- // Default rect
- symbolType = 'rect';
- proxySymbol = symbolBuildProxies[symbolType];
- }
-
- symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape);
- proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle);
- }
- }
- }); // Provide setColor helper method to avoid determine if set the fill or stroke outside
-
- function symbolPathSetColor(color, innerColor) {
- if (this.type !== 'image') {
- var symbolStyle = this.style;
-
- if (this.__isEmptyBrush) {
- symbolStyle.stroke = color;
- symbolStyle.fill = innerColor || '#fff'; // TODO Same width with lineStyle in LineView
-
- symbolStyle.lineWidth = 2;
- } else if (this.shape.symbolType === 'line') {
- symbolStyle.stroke = color;
- } else {
- symbolStyle.fill = color;
- }
-
- this.markRedraw();
- }
- }
- /**
- * Create a symbol element with given symbol configuration: shape, x, y, width, height, color
- */
-
-
- function createSymbol(symbolType, x, y, w, h, color, // whether to keep the ratio of w/h,
- keepAspect) {
- // TODO Support image object, DynamicImage.
- var isEmpty = symbolType.indexOf('empty') === 0;
-
- if (isEmpty) {
- symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6);
- }
-
- var symbolPath;
-
- if (symbolType.indexOf('image://') === 0) {
- symbolPath = makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
- } else if (symbolType.indexOf('path://') === 0) {
- symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover');
- } else {
- symbolPath = new SymbolClz({
- shape: {
- symbolType: symbolType,
- x: x,
- y: y,
- width: w,
- height: h
- }
- });
- }
-
- symbolPath.__isEmptyBrush = isEmpty; // TODO Should deprecate setColor
-
- symbolPath.setColor = symbolPathSetColor;
-
- if (color) {
- symbolPath.setColor(color);
- }
-
- return symbolPath;
- }
- function normalizeSymbolSize(symbolSize) {
- if (!isArray(symbolSize)) {
- symbolSize = [+symbolSize, +symbolSize];
- }
-
- return [symbolSize[0] || 0, symbolSize[1] || 0];
- }
- function normalizeSymbolOffset(symbolOffset, symbolSize) {
- if (symbolOffset == null) {
- return;
- }
-
- if (!isArray(symbolOffset)) {
- symbolOffset = [symbolOffset, symbolOffset];
- }
-
- return [parsePercent$1(symbolOffset[0], symbolSize[0]) || 0, parsePercent$1(retrieve2(symbolOffset[1], symbolOffset[0]), symbolSize[1]) || 0];
- }
-
- function createLinearGradient(ctx, obj, rect) {
- var x = obj.x == null ? 0 : obj.x;
- var x2 = obj.x2 == null ? 1 : obj.x2;
- var y = obj.y == null ? 0 : obj.y;
- var y2 = obj.y2 == null ? 0 : obj.y2;
- if (!obj.global) {
- x = x * rect.width + rect.x;
- x2 = x2 * rect.width + rect.x;
- y = y * rect.height + rect.y;
- y2 = y2 * rect.height + rect.y;
- }
- x = isNaN(x) ? 0 : x;
- x2 = isNaN(x2) ? 1 : x2;
- y = isNaN(y) ? 0 : y;
- y2 = isNaN(y2) ? 0 : y2;
- var canvasGradient = ctx.createLinearGradient(x, y, x2, y2);
- return canvasGradient;
- }
- function createRadialGradient(ctx, obj, rect) {
- var width = rect.width;
- var height = rect.height;
- var min = Math.min(width, height);
- var x = obj.x == null ? 0.5 : obj.x;
- var y = obj.y == null ? 0.5 : obj.y;
- var r = obj.r == null ? 0.5 : obj.r;
- if (!obj.global) {
- x = x * width + rect.x;
- y = y * height + rect.y;
- r = r * min;
- }
- var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r);
- return canvasGradient;
- }
- function getCanvasGradient(ctx, obj, rect) {
- var canvasGradient = obj.type === 'radial'
- ? createRadialGradient(ctx, obj, rect)
- : createLinearGradient(ctx, obj, rect);
- var colorStops = obj.colorStops;
- for (var i = 0; i < colorStops.length; i++) {
- canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color);
- }
- return canvasGradient;
- }
- function isClipPathChanged(clipPaths, prevClipPaths) {
- if (clipPaths === prevClipPaths || (!clipPaths && !prevClipPaths)) {
- return false;
- }
- if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) {
- return true;
- }
- for (var i = 0; i < clipPaths.length; i++) {
- if (clipPaths[i] !== prevClipPaths[i]) {
- return true;
- }
- }
- return false;
- }
-
- function normalizeLineDash(lineType, lineWidth) {
- if (!lineType || lineType === 'solid' || !(lineWidth > 0)) {
- return null;
- }
- lineWidth = lineWidth || 1;
- return lineType === 'dashed'
- ? [4 * lineWidth, 2 * lineWidth]
- : lineType === 'dotted'
- ? [lineWidth]
- : isNumber(lineType)
- ? [lineType] : isArray(lineType) ? lineType : null;
- }
-
- var pathProxyForDraw = new PathProxy(true);
- function styleHasStroke(style) {
- var stroke = style.stroke;
- return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0));
- }
- function isValidStrokeFillStyle(strokeOrFill) {
- return typeof strokeOrFill === 'string' && strokeOrFill !== 'none';
- }
- function styleHasFill(style) {
- var fill = style.fill;
- return fill != null && fill !== 'none';
- }
- function doFillPath(ctx, style) {
- if (style.fillOpacity != null && style.fillOpacity !== 1) {
- var originalGlobalAlpha = ctx.globalAlpha;
- ctx.globalAlpha = style.fillOpacity * style.opacity;
- ctx.fill();
- ctx.globalAlpha = originalGlobalAlpha;
- }
- else {
- ctx.fill();
- }
- }
- function doStrokePath(ctx, style) {
- if (style.strokeOpacity != null && style.strokeOpacity !== 1) {
- var originalGlobalAlpha = ctx.globalAlpha;
- ctx.globalAlpha = style.strokeOpacity * style.opacity;
- ctx.stroke();
- ctx.globalAlpha = originalGlobalAlpha;
- }
- else {
- ctx.stroke();
- }
- }
- function createCanvasPattern(ctx, pattern, el) {
- var image = createOrUpdateImage(pattern.image, pattern.__image, el);
- if (isImageReady(image)) {
- var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat');
- if (typeof DOMMatrix === 'function'
- && canvasPattern.setTransform) {
- var matrix = new DOMMatrix();
- matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180);
- matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1));
- matrix.translateSelf((pattern.x || 0), (pattern.y || 0));
- canvasPattern.setTransform(matrix);
- }
- return canvasPattern;
- }
- }
- function brushPath(ctx, el, style, inBatch) {
- var hasStroke = styleHasStroke(style);
- var hasFill = styleHasFill(style);
- var strokePercent = style.strokePercent;
- var strokePart = strokePercent < 1;
- var firstDraw = !el.path;
- if ((!el.silent || strokePart) && firstDraw) {
- el.createPathProxy();
- }
- var path = el.path || pathProxyForDraw;
- if (!inBatch) {
- var fill = style.fill;
- var stroke = style.stroke;
- var hasFillGradient = hasFill && !!fill.colorStops;
- var hasStrokeGradient = hasStroke && !!stroke.colorStops;
- var hasFillPattern = hasFill && !!fill.image;
- var hasStrokePattern = hasStroke && !!stroke.image;
- var fillGradient = void 0;
- var strokeGradient = void 0;
- var fillPattern = void 0;
- var strokePattern = void 0;
- var rect = void 0;
- if (hasFillGradient || hasStrokeGradient) {
- rect = el.getBoundingRect();
- }
- if (hasFillGradient) {
- fillGradient = el.__dirty
- ? getCanvasGradient(ctx, fill, rect)
- : el.__canvasFillGradient;
- el.__canvasFillGradient = fillGradient;
- }
- if (hasStrokeGradient) {
- strokeGradient = el.__dirty
- ? getCanvasGradient(ctx, stroke, rect)
- : el.__canvasStrokeGradient;
- el.__canvasStrokeGradient = strokeGradient;
- }
- if (hasFillPattern) {
- fillPattern = (el.__dirty || !el.__canvasFillPattern)
- ? createCanvasPattern(ctx, fill, el)
- : el.__canvasFillPattern;
- el.__canvasFillPattern = fillPattern;
- }
- if (hasStrokePattern) {
- strokePattern = (el.__dirty || !el.__canvasStrokePattern)
- ? createCanvasPattern(ctx, stroke, el)
- : el.__canvasStrokePattern;
- el.__canvasStrokePattern = fillPattern;
- }
- if (hasFillGradient) {
- ctx.fillStyle = fillGradient;
- }
- else if (hasFillPattern) {
- if (fillPattern) {
- ctx.fillStyle = fillPattern;
- }
- else {
- hasFill = false;
- }
- }
- if (hasStrokeGradient) {
- ctx.strokeStyle = strokeGradient;
- }
- else if (hasStrokePattern) {
- if (strokePattern) {
- ctx.strokeStyle = strokePattern;
- }
- else {
- hasStroke = false;
- }
- }
- }
- var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth);
- var lineDashOffset = style.lineDashOffset;
- var ctxLineDash = !!ctx.setLineDash;
- var scale = el.getGlobalScale();
- path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold);
- if (lineDash) {
- var lineScale_1 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1;
- if (lineScale_1 && lineScale_1 !== 1) {
- lineDash = map(lineDash, function (rawVal) {
- return rawVal / lineScale_1;
- });
- lineDashOffset /= lineScale_1;
- }
- }
- var needsRebuild = true;
- if (firstDraw || (el.__dirty & SHAPE_CHANGED_BIT)
- || (lineDash && !ctxLineDash && hasStroke)) {
- path.setDPR(ctx.dpr);
- if (strokePart) {
- path.setContext(null);
- }
- else {
- path.setContext(ctx);
- needsRebuild = false;
- }
- path.reset();
- if (lineDash && !ctxLineDash) {
- path.setLineDash(lineDash);
- path.setLineDashOffset(lineDashOffset);
- }
- el.buildPath(path, el.shape, inBatch);
- path.toStatic();
- el.pathUpdated();
- }
- if (needsRebuild) {
- path.rebuildPath(ctx, strokePart ? strokePercent : 1);
- }
- if (lineDash && ctxLineDash) {
- ctx.setLineDash(lineDash);
- ctx.lineDashOffset = lineDashOffset;
- }
- if (!inBatch) {
- if (style.strokeFirst) {
- if (hasStroke) {
- doStrokePath(ctx, style);
- }
- if (hasFill) {
- doFillPath(ctx, style);
- }
- }
- else {
- if (hasFill) {
- doFillPath(ctx, style);
- }
- if (hasStroke) {
- doStrokePath(ctx, style);
- }
- }
- }
- if (lineDash && ctxLineDash) {
- ctx.setLineDash([]);
- }
- }
- function brushImage(ctx, el, style) {
- var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload);
- if (!image || !isImageReady(image)) {
- return;
- }
- var x = style.x || 0;
- var y = style.y || 0;
- var width = el.getWidth();
- var height = el.getHeight();
- var aspect = image.width / image.height;
- if (width == null && height != null) {
- width = height * aspect;
- }
- else if (height == null && width != null) {
- height = width / aspect;
- }
- else if (width == null && height == null) {
- width = image.width;
- height = image.height;
- }
- if (style.sWidth && style.sHeight) {
- var sx = style.sx || 0;
- var sy = style.sy || 0;
- ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height);
- }
- else if (style.sx && style.sy) {
- var sx = style.sx;
- var sy = style.sy;
- var sWidth = width - sx;
- var sHeight = height - sy;
- ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height);
- }
- else {
- ctx.drawImage(image, x, y, width, height);
- }
- }
- function brushText(ctx, el, style) {
- var text = style.text;
- text != null && (text += '');
- if (text) {
- ctx.font = style.font || DEFAULT_FONT;
- ctx.textAlign = style.textAlign;
- ctx.textBaseline = style.textBaseline;
- var hasLineDash = void 0;
- if (ctx.setLineDash) {
- var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth);
- var lineDashOffset = style.lineDashOffset;
- if (lineDash) {
- var lineScale_2 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1;
- if (lineScale_2 && lineScale_2 !== 1) {
- lineDash = map(lineDash, function (rawVal) {
- return rawVal / lineScale_2;
- });
- lineDashOffset /= lineScale_2;
- }
- ctx.setLineDash(lineDash);
- ctx.lineDashOffset = lineDashOffset;
- hasLineDash = true;
- }
- }
- if (style.strokeFirst) {
- if (styleHasStroke(style)) {
- ctx.strokeText(text, style.x, style.y);
- }
- if (styleHasFill(style)) {
- ctx.fillText(text, style.x, style.y);
- }
- }
- else {
- if (styleHasFill(style)) {
- ctx.fillText(text, style.x, style.y);
- }
- if (styleHasStroke(style)) {
- ctx.strokeText(text, style.x, style.y);
- }
- }
- if (hasLineDash) {
- ctx.setLineDash([]);
- }
- }
- }
- var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];
- var STROKE_PROPS = [
- ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10]
- ];
- function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) {
- var styleChanged = false;
- if (!forceSetAll) {
- prevStyle = prevStyle || {};
- if (style === prevStyle) {
- return false;
- }
- }
- if (forceSetAll || style.opacity !== prevStyle.opacity) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- var opacity = Math.max(Math.min(style.opacity, 1), 0);
- ctx.globalAlpha = isNaN(opacity) ? DEFAULT_COMMON_STYLE.opacity : opacity;
- }
- if (forceSetAll || style.blend !== prevStyle.blend) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend;
- }
- for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) {
- var propName = SHADOW_NUMBER_PROPS[i];
- if (forceSetAll || style[propName] !== prevStyle[propName]) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx[propName] = ctx.dpr * (style[propName] || 0);
- }
- }
- if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor;
- }
- return styleChanged;
- }
- function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) {
- var style = getStyle(el, scope.inHover);
- var prevStyle = forceSetAll
- ? null
- : (prevEl && getStyle(prevEl, scope.inHover) || {});
- if (style === prevStyle) {
- return false;
- }
- var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope);
- if (forceSetAll || style.fill !== prevStyle.fill) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- isValidStrokeFillStyle(style.fill) && (ctx.fillStyle = style.fill);
- }
- if (forceSetAll || style.stroke !== prevStyle.stroke) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- isValidStrokeFillStyle(style.stroke) && (ctx.strokeStyle = style.stroke);
- }
- if (forceSetAll || style.opacity !== prevStyle.opacity) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx.globalAlpha = style.opacity == null ? 1 : style.opacity;
- }
- if (el.hasStroke()) {
- var lineWidth = style.lineWidth;
- var newLineWidth = lineWidth / ((style.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1);
- if (ctx.lineWidth !== newLineWidth) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx.lineWidth = newLineWidth;
- }
- }
- for (var i = 0; i < STROKE_PROPS.length; i++) {
- var prop = STROKE_PROPS[i];
- var propName = prop[0];
- if (forceSetAll || style[propName] !== prevStyle[propName]) {
- if (!styleChanged) {
- flushPathDrawn(ctx, scope);
- styleChanged = true;
- }
- ctx[propName] = style[propName] || prop[1];
- }
- }
- return styleChanged;
- }
- function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) {
- return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope);
- }
- function setContextTransform(ctx, el) {
- var m = el.transform;
- var dpr = ctx.dpr || 1;
- if (m) {
- ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]);
- }
- else {
- ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
- }
- }
- function updateClipStatus(clipPaths, ctx, scope) {
- var allClipped = false;
- for (var i = 0; i < clipPaths.length; i++) {
- var clipPath = clipPaths[i];
- allClipped = allClipped || clipPath.isZeroArea();
- setContextTransform(ctx, clipPath);
- ctx.beginPath();
- clipPath.buildPath(ctx, clipPath.shape);
- ctx.clip();
- }
- scope.allClipped = allClipped;
- }
- function isTransformChanged(m0, m1) {
- if (m0 && m1) {
- return m0[0] !== m1[0]
- || m0[1] !== m1[1]
- || m0[2] !== m1[2]
- || m0[3] !== m1[3]
- || m0[4] !== m1[4]
- || m0[5] !== m1[5];
- }
- else if (!m0 && !m1) {
- return false;
- }
- return true;
- }
- var DRAW_TYPE_PATH = 1;
- var DRAW_TYPE_IMAGE = 2;
- var DRAW_TYPE_TEXT = 3;
- var DRAW_TYPE_INCREMENTAL = 4;
- function canPathBatch(style) {
- var hasFill = styleHasFill(style);
- var hasStroke = styleHasStroke(style);
- return !(style.lineDash
- || !(+hasFill ^ +hasStroke)
- || (hasFill && typeof style.fill !== 'string')
- || (hasStroke && typeof style.stroke !== 'string')
- || style.strokePercent < 1
- || style.strokeOpacity < 1
- || style.fillOpacity < 1);
- }
- function flushPathDrawn(ctx, scope) {
- scope.batchFill && ctx.fill();
- scope.batchStroke && ctx.stroke();
- scope.batchFill = '';
- scope.batchStroke = '';
- }
- function getStyle(el, inHover) {
- return inHover ? (el.__hoverStyle || el.style) : el.style;
- }
- function brushSingle(ctx, el) {
- brush(ctx, el, { inHover: false, viewWidth: 0, viewHeight: 0 }, true);
- }
- function brush(ctx, el, scope, isLast) {
- var m = el.transform;
- if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) {
- el.__dirty &= ~REDARAW_BIT;
- el.__isRendered = false;
- return;
- }
- var clipPaths = el.__clipPaths;
- var prevElClipPaths = scope.prevElClipPaths;
- var forceSetTransform = false;
- var forceSetStyle = false;
- if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) {
- if (prevElClipPaths && prevElClipPaths.length) {
- flushPathDrawn(ctx, scope);
- ctx.restore();
- forceSetStyle = forceSetTransform = true;
- scope.prevElClipPaths = null;
- scope.allClipped = false;
- scope.prevEl = null;
- }
- if (clipPaths && clipPaths.length) {
- flushPathDrawn(ctx, scope);
- ctx.save();
- updateClipStatus(clipPaths, ctx, scope);
- forceSetTransform = true;
- }
- scope.prevElClipPaths = clipPaths;
- }
- if (scope.allClipped) {
- el.__isRendered = false;
- return;
- }
- el.beforeBrush && el.beforeBrush();
- el.innerBeforeBrush();
- var prevEl = scope.prevEl;
- if (!prevEl) {
- forceSetStyle = forceSetTransform = true;
- }
- var canBatchPath = el instanceof Path
- && el.autoBatch
- && canPathBatch(el.style);
- if (forceSetTransform || isTransformChanged(m, prevEl.transform)) {
- flushPathDrawn(ctx, scope);
- setContextTransform(ctx, el);
- }
- else if (!canBatchPath) {
- flushPathDrawn(ctx, scope);
- }
- var style = getStyle(el, scope.inHover);
- if (el instanceof Path) {
- if (scope.lastDrawType !== DRAW_TYPE_PATH) {
- forceSetStyle = true;
- scope.lastDrawType = DRAW_TYPE_PATH;
- }
- bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);
- if (!canBatchPath || (!scope.batchFill && !scope.batchStroke)) {
- ctx.beginPath();
- }
- brushPath(ctx, el, style, canBatchPath);
- if (canBatchPath) {
- scope.batchFill = style.fill || '';
- scope.batchStroke = style.stroke || '';
- }
- }
- else {
- if (el instanceof TSpan) {
- if (scope.lastDrawType !== DRAW_TYPE_TEXT) {
- forceSetStyle = true;
- scope.lastDrawType = DRAW_TYPE_TEXT;
- }
- bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope);
- brushText(ctx, el, style);
- }
- else if (el instanceof ZRImage) {
- if (scope.lastDrawType !== DRAW_TYPE_IMAGE) {
- forceSetStyle = true;
- scope.lastDrawType = DRAW_TYPE_IMAGE;
- }
- bindImageStyle(ctx, el, prevEl, forceSetStyle, scope);
- brushImage(ctx, el, style);
- }
- else if (el instanceof IncrementalDisplayable) {
- if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) {
- forceSetStyle = true;
- scope.lastDrawType = DRAW_TYPE_INCREMENTAL;
- }
- brushIncremental(ctx, el, scope);
- }
- }
- if (canBatchPath && isLast) {
- flushPathDrawn(ctx, scope);
- }
- el.innerAfterBrush();
- el.afterBrush && el.afterBrush();
- scope.prevEl = el;
- el.__dirty = 0;
- el.__isRendered = true;
- }
- function brushIncremental(ctx, el, scope) {
- var displayables = el.getDisplayables();
- var temporalDisplayables = el.getTemporalDisplayables();
- ctx.save();
- var innerScope = {
- prevElClipPaths: null,
- prevEl: null,
- allClipped: false,
- viewWidth: scope.viewWidth,
- viewHeight: scope.viewHeight,
- inHover: scope.inHover
- };
- var i;
- var len;
- for (i = el.getCursor(), len = displayables.length; i < len; i++) {
- var displayable = displayables[i];
- displayable.beforeBrush && displayable.beforeBrush();
- displayable.innerBeforeBrush();
- brush(ctx, displayable, innerScope, i === len - 1);
- displayable.innerAfterBrush();
- displayable.afterBrush && displayable.afterBrush();
- innerScope.prevEl = displayable;
- }
- for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) {
- var displayable = temporalDisplayables[i_1];
- displayable.beforeBrush && displayable.beforeBrush();
- displayable.innerBeforeBrush();
- brush(ctx, displayable, innerScope, i_1 === len_1 - 1);
- displayable.innerAfterBrush();
- displayable.afterBrush && displayable.afterBrush();
- innerScope.prevEl = displayable;
- }
- el.clearTemporalDisplayables();
- el.notClear = true;
- ctx.restore();
- }
-
- var decalMap = new WeakMap();
- var decalCache = new LRU(100);
- var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'maxTileWidth', 'maxTileHeight'];
- /**
- * Create or update pattern image from decal options
- *
- * @param {InnerDecalObject | 'none'} decalObject decal options, 'none' if no decal
- * @return {Pattern} pattern with generated image, null if no decal
- */
-
- function createOrUpdatePatternFromDecal(decalObject, api) {
- if (decalObject === 'none') {
- return null;
- }
-
- var dpr = api.getDevicePixelRatio();
- var zr = api.getZr();
- var isSVG = zr.painter.type === 'svg';
-
- if (decalObject.dirty) {
- decalMap["delete"](decalObject);
- }
-
- var oldPattern = decalMap.get(decalObject);
-
- if (oldPattern) {
- return oldPattern;
- }
-
- var decalOpt = defaults(decalObject, {
- symbol: 'rect',
- symbolSize: 1,
- symbolKeepAspect: true,
- color: 'rgba(0, 0, 0, 0.2)',
- backgroundColor: null,
- dashArrayX: 5,
- dashArrayY: 5,
- rotation: 0,
- maxTileWidth: 512,
- maxTileHeight: 512
- });
-
- if (decalOpt.backgroundColor === 'none') {
- decalOpt.backgroundColor = null;
- }
-
- var pattern = {
- repeat: 'repeat'
- };
- setPatternnSource(pattern);
- pattern.rotation = decalOpt.rotation;
- pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr;
- decalMap.set(decalObject, pattern);
- decalObject.dirty = false;
- return pattern;
-
- function setPatternnSource(pattern) {
- var keys = [dpr];
- var isValidKey = true;
-
- for (var i = 0; i < decalKeys.length; ++i) {
- var value = decalOpt[decalKeys[i]];
- var valueType = typeof value;
-
- if (value != null && !isArray(value) && valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') {
- isValidKey = false;
- break;
- }
-
- keys.push(value);
- }
-
- var cacheKey;
-
- if (isValidKey) {
- cacheKey = keys.join(',') + (isSVG ? '-svg' : '');
- var cache = decalCache.get(cacheKey);
-
- if (cache) {
- isSVG ? pattern.svgElement = cache : pattern.image = cache;
- }
- }
-
- var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX);
- var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY);
- var symbolArray = normalizeSymbolArray(decalOpt.symbol);
- var lineBlockLengthsX = getLineBlockLengthX(dashArrayX);
- var lineBlockLengthY = getLineBlockLengthY(dashArrayY);
- var canvas = !isSVG && createCanvas();
- var svgRoot = isSVG && zr.painter.createSVGElement('g');
- var pSize = getPatternSize();
- var ctx;
-
- if (canvas) {
- canvas.width = pSize.width * dpr;
- canvas.height = pSize.height * dpr;
- ctx = canvas.getContext('2d');
- }
-
- brushDecal();
-
- if (isValidKey) {
- decalCache.put(cacheKey, canvas || svgRoot);
- }
-
- pattern.image = canvas;
- pattern.svgElement = svgRoot;
- pattern.svgWidth = pSize.width;
- pattern.svgHeight = pSize.height;
- /**
- * Get minumum length that can make a repeatable pattern.
- *
- * @return {Object} pattern width and height
- */
-
- function getPatternSize() {
- /**
- * For example, if dash is [[3, 2], [2, 1]] for X, it looks like
- * |--- --- --- --- --- ...
- * |-- -- -- -- -- -- -- -- ...
- * |--- --- --- --- --- ...
- * |-- -- -- -- -- -- -- -- ...
- * So the minumum length of X is 15,
- * which is the least common multiple of `3 + 2` and `2 + 1`
- * |--- --- --- |--- --- ...
- * |-- -- -- -- -- |-- -- -- ...
- */
- var width = 1;
-
- for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) {
- width = getLeastCommonMultiple(width, lineBlockLengthsX[i]);
- }
-
- var symbolRepeats = 1;
-
- for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) {
- symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length);
- }
-
- width *= symbolRepeats;
- var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length;
-
- if ("development" !== 'production') {
- var warn = function (attrName) {
- /* eslint-disable-next-line */
- console.warn("Calculated decal size is greater than " + attrName + " due to decal option settings so " + attrName + " is used for the decal size. Please consider changing the decal option to make a smaller decal or set " + attrName + " to be larger to avoid incontinuity.");
- };
-
- if (width > decalOpt.maxTileWidth) {
- warn('maxTileWidth');
- }
-
- if (height > decalOpt.maxTileHeight) {
- warn('maxTileHeight');
- }
- }
-
- return {
- width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)),
- height: Math.max(1, Math.min(height, decalOpt.maxTileHeight))
- };
- }
-
- function brushDecal() {
- if (ctx) {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
-
- if (decalOpt.backgroundColor) {
- ctx.fillStyle = decalOpt.backgroundColor;
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
- }
-
- var ySum = 0;
-
- for (var i = 0; i < dashArrayY.length; ++i) {
- ySum += dashArrayY[i];
- }
-
- if (ySum <= 0) {
- // dashArrayY is 0, draw nothing
- return;
- }
-
- var y = -lineBlockLengthY;
- var yId = 0;
- var yIdTotal = 0;
- var xId0 = 0;
-
- while (y < pSize.height) {
- if (yId % 2 === 0) {
- var symbolYId = yIdTotal / 2 % symbolArray.length;
- var x = 0;
- var xId1 = 0;
- var xId1Total = 0;
-
- while (x < pSize.width * 2) {
- var xSum = 0;
-
- for (var i = 0; i < dashArrayX[xId0].length; ++i) {
- xSum += dashArrayX[xId0][i];
- }
-
- if (xSum <= 0) {
- // Skip empty line
- break;
- } // E.g., [15, 5, 20, 5] draws only for 15 and 20
-
-
- if (xId1 % 2 === 0) {
- var size = (1 - decalOpt.symbolSize) * 0.5;
- var left = x + dashArrayX[xId0][xId1] * size;
- var top_1 = y + dashArrayY[yId] * size;
- var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize;
- var height = dashArrayY[yId] * decalOpt.symbolSize;
- var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length;
- brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]);
- }
-
- x += dashArrayX[xId0][xId1];
- ++xId1Total;
- ++xId1;
-
- if (xId1 === dashArrayX[xId0].length) {
- xId1 = 0;
- }
- }
-
- ++xId0;
-
- if (xId0 === dashArrayX.length) {
- xId0 = 0;
- }
- }
-
- y += dashArrayY[yId];
- ++yIdTotal;
- ++yId;
-
- if (yId === dashArrayY.length) {
- yId = 0;
- }
- }
-
- function brushSymbol(x, y, width, height, symbolType) {
- var scale = isSVG ? 1 : dpr;
- var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect);
-
- if (isSVG) {
- svgRoot.appendChild(zr.painter.paintOne(symbol));
- } else {
- // Paint to canvas for all other renderers.
- brushSingle(ctx, symbol);
- }
- }
- }
- }
- }
- /**
- * Convert symbol array into normalized array
- *
- * @param {string | (string | string[])[]} symbol symbol input
- * @return {string[][]} normolized symbol array
- */
-
- function normalizeSymbolArray(symbol) {
- if (!symbol || symbol.length === 0) {
- return [['rect']];
- }
-
- if (typeof symbol === 'string') {
- return [[symbol]];
- }
-
- var isAllString = true;
-
- for (var i = 0; i < symbol.length; ++i) {
- if (typeof symbol[i] !== 'string') {
- isAllString = false;
- break;
- }
- }
-
- if (isAllString) {
- return normalizeSymbolArray([symbol]);
- }
-
- var result = [];
-
- for (var i = 0; i < symbol.length; ++i) {
- if (typeof symbol[i] === 'string') {
- result.push([symbol[i]]);
- } else {
- result.push(symbol[i]);
- }
- }
-
- return result;
- }
- /**
- * Convert dash input into dashArray
- *
- * @param {DecalDashArrayX} dash dash input
- * @return {number[][]} normolized dash array
- */
-
-
- function normalizeDashArrayX(dash) {
- if (!dash || dash.length === 0) {
- return [[0, 0]];
- }
-
- if (typeof dash === 'number') {
- var dashValue = Math.ceil(dash);
- return [[dashValue, dashValue]];
- }
- /**
- * [20, 5] should be normalized into [[20, 5]],
- * while [20, [5, 10]] should be normalized into [[20, 20], [5, 10]]
- */
-
-
- var isAllNumber = true;
-
- for (var i = 0; i < dash.length; ++i) {
- if (typeof dash[i] !== 'number') {
- isAllNumber = false;
- break;
- }
- }
-
- if (isAllNumber) {
- return normalizeDashArrayX([dash]);
- }
-
- var result = [];
-
- for (var i = 0; i < dash.length; ++i) {
- if (typeof dash[i] === 'number') {
- var dashValue = Math.ceil(dash[i]);
- result.push([dashValue, dashValue]);
- } else {
- var dashValue = map(dash[i], function (n) {
- return Math.ceil(n);
- });
-
- if (dashValue.length % 2 === 1) {
- // [4, 2, 1] means |---- - -- |---- - -- |
- // so normalize it to be [4, 2, 1, 4, 2, 1]
- result.push(dashValue.concat(dashValue));
- } else {
- result.push(dashValue);
- }
- }
- }
-
- return result;
- }
- /**
- * Convert dash input into dashArray
- *
- * @param {DecalDashArrayY} dash dash input
- * @return {number[]} normolized dash array
- */
-
-
- function normalizeDashArrayY(dash) {
- if (!dash || typeof dash === 'object' && dash.length === 0) {
- return [0, 0];
- }
-
- if (typeof dash === 'number') {
- var dashValue_1 = Math.ceil(dash);
- return [dashValue_1, dashValue_1];
- }
-
- var dashValue = map(dash, function (n) {
- return Math.ceil(n);
- });
- return dash.length % 2 ? dashValue.concat(dashValue) : dashValue;
- }
- /**
- * Get block length of each line. A block is the length of dash line and space.
- * For example, a line with [4, 1] has a dash line of 4 and a space of 1 after
- * that, so the block length of this line is 5.
- *
- * @param {number[][]} dash dash arrary of X or Y
- * @return {number[]} block length of each line
- */
-
-
- function getLineBlockLengthX(dash) {
- return map(dash, function (line) {
- return getLineBlockLengthY(line);
- });
- }
-
- function getLineBlockLengthY(dash) {
- var blockLength = 0;
-
- for (var i = 0; i < dash.length; ++i) {
- blockLength += dash[i];
- }
-
- if (dash.length % 2 === 1) {
- // [4, 2, 1] means |---- - -- |---- - -- |
- // So total length is (4 + 2 + 1) * 2
- return blockLength * 2;
- }
-
- return blockLength;
- }
-
- function decalVisual(ecModel, api) {
- ecModel.eachRawSeries(function (seriesModel) {
- if (ecModel.isSeriesFiltered(seriesModel)) {
- return;
- }
-
- var data = seriesModel.getData();
-
- if (data.hasItemVisual()) {
- data.each(function (idx) {
- var decal = data.getItemVisual(idx, 'decal');
-
- if (decal) {
- var itemStyle = data.ensureUniqueItemVisual(idx, 'style');
- itemStyle.decal = createOrUpdatePatternFromDecal(decal, api);
- }
- });
- }
-
- var decal = data.getVisual('decal');
-
- if (decal) {
- var style = data.getVisual('style');
- style.decal = createOrUpdatePatternFromDecal(decal, api);
- }
- });
- }
-
- function parseXML(svg) {
- if (isString(svg)) {
- var parser = new DOMParser();
- svg = parser.parseFromString(svg, 'text/xml');
- }
- var svgNode = svg;
- if (svgNode.nodeType === 9) {
- svgNode = svgNode.firstChild;
- }
- while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) {
- svgNode = svgNode.nextSibling;
- }
- return svgNode;
- }
-
- var nodeParsers;
- var INHERITABLE_STYLE_ATTRIBUTES_MAP = {
- 'fill': 'fill',
- 'stroke': 'stroke',
- 'stroke-width': 'lineWidth',
- 'opacity': 'opacity',
- 'fill-opacity': 'fillOpacity',
- 'stroke-opacity': 'strokeOpacity',
- 'stroke-dasharray': 'lineDash',
- 'stroke-dashoffset': 'lineDashOffset',
- 'stroke-linecap': 'lineCap',
- 'stroke-linejoin': 'lineJoin',
- 'stroke-miterlimit': 'miterLimit',
- 'font-family': 'fontFamily',
- 'font-size': 'fontSize',
- 'font-style': 'fontStyle',
- 'font-weight': 'fontWeight',
- 'text-anchor': 'textAlign',
- 'visibility': 'visibility',
- 'display': 'display'
- };
- var INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS = keys(INHERITABLE_STYLE_ATTRIBUTES_MAP);
- var SELF_STYLE_ATTRIBUTES_MAP = {
- 'alignment-baseline': 'textBaseline',
- 'stop-color': 'stopColor'
- };
- var SELF_STYLE_ATTRIBUTES_MAP_KEYS = keys(SELF_STYLE_ATTRIBUTES_MAP);
- var SVGParser = (function () {
- function SVGParser() {
- this._defs = {};
- this._root = null;
- }
- SVGParser.prototype.parse = function (xml, opt) {
- opt = opt || {};
- var svg = parseXML(xml);
- if (!svg) {
- throw new Error('Illegal svg');
- }
- this._defsUsePending = [];
- var root = new Group();
- this._root = root;
- var named = [];
- var viewBox = svg.getAttribute('viewBox') || '';
- var width = parseFloat((svg.getAttribute('width') || opt.width));
- var height = parseFloat((svg.getAttribute('height') || opt.height));
- isNaN(width) && (width = null);
- isNaN(height) && (height = null);
- parseAttributes(svg, root, null, true, false);
- var child = svg.firstChild;
- while (child) {
- this._parseNode(child, root, named, null, false, false);
- child = child.nextSibling;
- }
- applyDefs(this._defs, this._defsUsePending);
- this._defsUsePending = [];
- var viewBoxRect;
- var viewBoxTransform;
- if (viewBox) {
- var viewBoxArr = splitNumberSequence(viewBox);
- if (viewBoxArr.length >= 4) {
- viewBoxRect = {
- x: parseFloat((viewBoxArr[0] || 0)),
- y: parseFloat((viewBoxArr[1] || 0)),
- width: parseFloat(viewBoxArr[2]),
- height: parseFloat(viewBoxArr[3])
- };
- }
- }
- if (viewBoxRect && width != null && height != null) {
- viewBoxTransform = makeViewBoxTransform(viewBoxRect, { x: 0, y: 0, width: width, height: height });
- if (!opt.ignoreViewBox) {
- var elRoot = root;
- root = new Group();
- root.add(elRoot);
- elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale;
- elRoot.x = viewBoxTransform.x;
- elRoot.y = viewBoxTransform.y;
- }
- }
- if (!opt.ignoreRootClip && width != null && height != null) {
- root.setClipPath(new Rect({
- shape: { x: 0, y: 0, width: width, height: height }
- }));
- }
- return {
- root: root,
- width: width,
- height: height,
- viewBoxRect: viewBoxRect,
- viewBoxTransform: viewBoxTransform,
- named: named
- };
- };
- SVGParser.prototype._parseNode = function (xmlNode, parentGroup, named, namedFrom, isInDefs, isInText) {
- var nodeName = xmlNode.nodeName.toLowerCase();
- var el;
- var namedFromForSub = namedFrom;
- if (nodeName === 'defs') {
- isInDefs = true;
- }
- if (nodeName === 'text') {
- isInText = true;
- }
- if (nodeName === 'defs' || nodeName === 'switch') {
- el = parentGroup;
- }
- else {
- if (!isInDefs) {
- var parser_1 = nodeParsers[nodeName];
- if (parser_1 && hasOwn(nodeParsers, nodeName)) {
- el = parser_1.call(this, xmlNode, parentGroup);
- var nameAttr = xmlNode.getAttribute('name');
- if (nameAttr) {
- var newNamed = {
- name: nameAttr,
- namedFrom: null,
- svgNodeTagLower: nodeName,
- el: el
- };
- named.push(newNamed);
- if (nodeName === 'g') {
- namedFromForSub = newNamed;
- }
- }
- else if (namedFrom) {
- named.push({
- name: namedFrom.name,
- namedFrom: namedFrom,
- svgNodeTagLower: nodeName,
- el: el
- });
- }
- parentGroup.add(el);
- }
- }
- var parser = paintServerParsers[nodeName];
- if (parser && hasOwn(paintServerParsers, nodeName)) {
- var def = parser.call(this, xmlNode);
- var id = xmlNode.getAttribute('id');
- if (id) {
- this._defs[id] = def;
- }
- }
- }
- if (el && el.isGroup) {
- var child = xmlNode.firstChild;
- while (child) {
- if (child.nodeType === 1) {
- this._parseNode(child, el, named, namedFromForSub, isInDefs, isInText);
- }
- else if (child.nodeType === 3 && isInText) {
- this._parseText(child, el);
- }
- child = child.nextSibling;
- }
- }
- };
- SVGParser.prototype._parseText = function (xmlNode, parentGroup) {
- var text = new TSpan({
- style: {
- text: xmlNode.textContent
- },
- silent: true,
- x: this._textX || 0,
- y: this._textY || 0
- });
- inheritStyle(parentGroup, text);
- parseAttributes(xmlNode, text, this._defsUsePending, false, false);
- applyTextAlignment(text, parentGroup);
- var textStyle = text.style;
- var fontSize = textStyle.fontSize;
- if (fontSize && fontSize < 9) {
- textStyle.fontSize = 9;
- text.scaleX *= fontSize / 9;
- text.scaleY *= fontSize / 9;
- }
- var font = (textStyle.fontSize || textStyle.fontFamily) && [
- textStyle.fontStyle,
- textStyle.fontWeight,
- (textStyle.fontSize || 12) + 'px',
- textStyle.fontFamily || 'sans-serif'
- ].join(' ');
- textStyle.font = font;
- var rect = text.getBoundingRect();
- this._textX += rect.width;
- parentGroup.add(text);
- return text;
- };
- SVGParser.internalField = (function () {
- nodeParsers = {
- 'g': function (xmlNode, parentGroup) {
- var g = new Group();
- inheritStyle(parentGroup, g);
- parseAttributes(xmlNode, g, this._defsUsePending, false, false);
- return g;
- },
- 'rect': function (xmlNode, parentGroup) {
- var rect = new Rect();
- inheritStyle(parentGroup, rect);
- parseAttributes(xmlNode, rect, this._defsUsePending, false, false);
- rect.setShape({
- x: parseFloat(xmlNode.getAttribute('x') || '0'),
- y: parseFloat(xmlNode.getAttribute('y') || '0'),
- width: parseFloat(xmlNode.getAttribute('width') || '0'),
- height: parseFloat(xmlNode.getAttribute('height') || '0')
- });
- rect.silent = true;
- return rect;
- },
- 'circle': function (xmlNode, parentGroup) {
- var circle = new Circle();
- inheritStyle(parentGroup, circle);
- parseAttributes(xmlNode, circle, this._defsUsePending, false, false);
- circle.setShape({
- cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
- cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
- r: parseFloat(xmlNode.getAttribute('r') || '0')
- });
- circle.silent = true;
- return circle;
- },
- 'line': function (xmlNode, parentGroup) {
- var line = new Line();
- inheritStyle(parentGroup, line);
- parseAttributes(xmlNode, line, this._defsUsePending, false, false);
- line.setShape({
- x1: parseFloat(xmlNode.getAttribute('x1') || '0'),
- y1: parseFloat(xmlNode.getAttribute('y1') || '0'),
- x2: parseFloat(xmlNode.getAttribute('x2') || '0'),
- y2: parseFloat(xmlNode.getAttribute('y2') || '0')
- });
- line.silent = true;
- return line;
- },
- 'ellipse': function (xmlNode, parentGroup) {
- var ellipse = new Ellipse();
- inheritStyle(parentGroup, ellipse);
- parseAttributes(xmlNode, ellipse, this._defsUsePending, false, false);
- ellipse.setShape({
- cx: parseFloat(xmlNode.getAttribute('cx') || '0'),
- cy: parseFloat(xmlNode.getAttribute('cy') || '0'),
- rx: parseFloat(xmlNode.getAttribute('rx') || '0'),
- ry: parseFloat(xmlNode.getAttribute('ry') || '0')
- });
- ellipse.silent = true;
- return ellipse;
- },
- 'polygon': function (xmlNode, parentGroup) {
- var pointsStr = xmlNode.getAttribute('points');
- var pointsArr;
- if (pointsStr) {
- pointsArr = parsePoints(pointsStr);
- }
- var polygon = new Polygon({
- shape: {
- points: pointsArr || []
- },
- silent: true
- });
- inheritStyle(parentGroup, polygon);
- parseAttributes(xmlNode, polygon, this._defsUsePending, false, false);
- return polygon;
- },
- 'polyline': function (xmlNode, parentGroup) {
- var pointsStr = xmlNode.getAttribute('points');
- var pointsArr;
- if (pointsStr) {
- pointsArr = parsePoints(pointsStr);
- }
- var polyline = new Polyline({
- shape: {
- points: pointsArr || []
- },
- silent: true
- });
- inheritStyle(parentGroup, polyline);
- parseAttributes(xmlNode, polyline, this._defsUsePending, false, false);
- return polyline;
- },
- 'image': function (xmlNode, parentGroup) {
- var img = new ZRImage();
- inheritStyle(parentGroup, img);
- parseAttributes(xmlNode, img, this._defsUsePending, false, false);
- img.setStyle({
- image: xmlNode.getAttribute('xlink:href'),
- x: +xmlNode.getAttribute('x'),
- y: +xmlNode.getAttribute('y'),
- width: +xmlNode.getAttribute('width'),
- height: +xmlNode.getAttribute('height')
- });
- img.silent = true;
- return img;
- },
- 'text': function (xmlNode, parentGroup) {
- var x = xmlNode.getAttribute('x') || '0';
- var y = xmlNode.getAttribute('y') || '0';
- var dx = xmlNode.getAttribute('dx') || '0';
- var dy = xmlNode.getAttribute('dy') || '0';
- this._textX = parseFloat(x) + parseFloat(dx);
- this._textY = parseFloat(y) + parseFloat(dy);
- var g = new Group();
- inheritStyle(parentGroup, g);
- parseAttributes(xmlNode, g, this._defsUsePending, false, true);
- return g;
- },
- 'tspan': function (xmlNode, parentGroup) {
- var x = xmlNode.getAttribute('x');
- var y = xmlNode.getAttribute('y');
- if (x != null) {
- this._textX = parseFloat(x);
- }
- if (y != null) {
- this._textY = parseFloat(y);
- }
- var dx = xmlNode.getAttribute('dx') || '0';
- var dy = xmlNode.getAttribute('dy') || '0';
- var g = new Group();
- inheritStyle(parentGroup, g);
- parseAttributes(xmlNode, g, this._defsUsePending, false, true);
- this._textX += parseFloat(dx);
- this._textY += parseFloat(dy);
- return g;
- },
- 'path': function (xmlNode, parentGroup) {
- var d = xmlNode.getAttribute('d') || '';
- var path = createFromString(d);
- inheritStyle(parentGroup, path);
- parseAttributes(xmlNode, path, this._defsUsePending, false, false);
- path.silent = true;
- return path;
- }
- };
- })();
- return SVGParser;
- }());
- var paintServerParsers = {
- 'lineargradient': function (xmlNode) {
- var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10);
- var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10);
- var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10);
- var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10);
- var gradient = new LinearGradient(x1, y1, x2, y2);
- parsePaintServerUnit(xmlNode, gradient);
- parseGradientColorStops(xmlNode, gradient);
- return gradient;
- },
- 'radialgradient': function (xmlNode) {
- var cx = parseInt(xmlNode.getAttribute('cx') || '0', 10);
- var cy = parseInt(xmlNode.getAttribute('cy') || '0', 10);
- var r = parseInt(xmlNode.getAttribute('r') || '0', 10);
- var gradient = new RadialGradient(cx, cy, r);
- parsePaintServerUnit(xmlNode, gradient);
- parseGradientColorStops(xmlNode, gradient);
- return gradient;
- }
- };
- function parsePaintServerUnit(xmlNode, gradient) {
- var gradientUnits = xmlNode.getAttribute('gradientUnits');
- if (gradientUnits === 'userSpaceOnUse') {
- gradient.global = true;
- }
- }
- function parseGradientColorStops(xmlNode, gradient) {
- var stop = xmlNode.firstChild;
- while (stop) {
- if (stop.nodeType === 1
- && stop.nodeName.toLocaleLowerCase() === 'stop') {
- var offsetStr = stop.getAttribute('offset');
- var offset = void 0;
- if (offsetStr && offsetStr.indexOf('%') > 0) {
- offset = parseInt(offsetStr, 10) / 100;
- }
- else if (offsetStr) {
- offset = parseFloat(offsetStr);
- }
- else {
- offset = 0;
- }
- var styleVals = {};
- parseInlineStyle(stop, styleVals, styleVals);
- var stopColor = styleVals.stopColor
- || stop.getAttribute('stop-color')
- || '#000000';
- gradient.colorStops.push({
- offset: offset,
- color: stopColor
- });
- }
- stop = stop.nextSibling;
- }
- }
- function inheritStyle(parent, child) {
- if (parent && parent.__inheritedStyle) {
- if (!child.__inheritedStyle) {
- child.__inheritedStyle = {};
- }
- defaults(child.__inheritedStyle, parent.__inheritedStyle);
- }
- }
- function parsePoints(pointsString) {
- var list = splitNumberSequence(pointsString);
- var points = [];
- for (var i = 0; i < list.length; i += 2) {
- var x = parseFloat(list[i]);
- var y = parseFloat(list[i + 1]);
- points.push([x, y]);
- }
- return points;
- }
- function parseAttributes(xmlNode, el, defsUsePending, onlyInlineStyle, isTextGroup) {
- var disp = el;
- var inheritedStyle = disp.__inheritedStyle = disp.__inheritedStyle || {};
- var selfStyle = {};
- if (xmlNode.nodeType === 1) {
- parseTransformAttribute(xmlNode, el);
- parseInlineStyle(xmlNode, inheritedStyle, selfStyle);
- if (!onlyInlineStyle) {
- parseAttributeStyle(xmlNode, inheritedStyle, selfStyle);
- }
- }
- disp.style = disp.style || {};
- if (inheritedStyle.fill != null) {
- disp.style.fill = getFillStrokeStyle(disp, 'fill', inheritedStyle.fill, defsUsePending);
- }
- if (inheritedStyle.stroke != null) {
- disp.style.stroke = getFillStrokeStyle(disp, 'stroke', inheritedStyle.stroke, defsUsePending);
- }
- each([
- 'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize'
- ], function (propName) {
- if (inheritedStyle[propName] != null) {
- disp.style[propName] = parseFloat(inheritedStyle[propName]);
- }
- });
- each([
- 'lineDashOffset', 'lineCap', 'lineJoin', 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign'
- ], function (propName) {
- if (inheritedStyle[propName] != null) {
- disp.style[propName] = inheritedStyle[propName];
- }
- });
- if (isTextGroup) {
- disp.__selfStyle = selfStyle;
- }
- if (inheritedStyle.lineDash) {
- disp.style.lineDash = map(splitNumberSequence(inheritedStyle.lineDash), function (str) {
- return parseFloat(str);
- });
- }
- if (inheritedStyle.visibility === 'hidden' || inheritedStyle.visibility === 'collapse') {
- disp.invisible = true;
- }
- if (inheritedStyle.display === 'none') {
- disp.ignore = true;
- }
- }
- function applyTextAlignment(text, parentGroup) {
- var parentSelfStyle = parentGroup.__selfStyle;
- if (parentSelfStyle) {
- var textBaseline = parentSelfStyle.textBaseline;
- var zrTextBaseline = textBaseline;
- if (!textBaseline || textBaseline === 'auto') {
- zrTextBaseline = 'alphabetic';
- }
- else if (textBaseline === 'baseline') {
- zrTextBaseline = 'alphabetic';
- }
- else if (textBaseline === 'before-edge' || textBaseline === 'text-before-edge') {
- zrTextBaseline = 'top';
- }
- else if (textBaseline === 'after-edge' || textBaseline === 'text-after-edge') {
- zrTextBaseline = 'bottom';
- }
- else if (textBaseline === 'central' || textBaseline === 'mathematical') {
- zrTextBaseline = 'middle';
- }
- text.style.textBaseline = zrTextBaseline;
- }
- var parentInheritedStyle = parentGroup.__inheritedStyle;
- if (parentInheritedStyle) {
- var textAlign = parentInheritedStyle.textAlign;
- var zrTextAlign = textAlign;
- if (textAlign) {
- if (textAlign === 'middle') {
- zrTextAlign = 'center';
- }
- text.style.textAlign = zrTextAlign;
- }
- }
- }
- var urlRegex = /^url\(\s*#(.*?)\)/;
- function getFillStrokeStyle(el, method, str, defsUsePending) {
- var urlMatch = str && str.match(urlRegex);
- if (urlMatch) {
- var url = trim(urlMatch[1]);
- defsUsePending.push([el, method, url]);
- return;
- }
- if (str === 'none') {
- str = null;
- }
- return str;
- }
- function applyDefs(defs, defsUsePending) {
- for (var i = 0; i < defsUsePending.length; i++) {
- var item = defsUsePending[i];
- item[0].style[item[1]] = defs[item[2]];
- }
- }
- var numberReg$1 = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g;
- function splitNumberSequence(rawStr) {
- return rawStr.match(numberReg$1) || [];
- }
- var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.eE,]*)\)/g;
- var DEGREE_TO_ANGLE = Math.PI / 180;
- function parseTransformAttribute(xmlNode, node) {
- var transform = xmlNode.getAttribute('transform');
- if (transform) {
- transform = transform.replace(/,/g, ' ');
- var transformOps_1 = [];
- var mt = null;
- transform.replace(transformRegex, function (str, type, value) {
- transformOps_1.push(type, value);
- return '';
- });
- for (var i = transformOps_1.length - 1; i > 0; i -= 2) {
- var value = transformOps_1[i];
- var type = transformOps_1[i - 1];
- var valueArr = splitNumberSequence(value);
- mt = mt || create$1();
- switch (type) {
- case 'translate':
- translate(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]);
- break;
- case 'scale':
- scale$1(mt, mt, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]);
- break;
- case 'rotate':
- rotate(mt, mt, -parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
- break;
- case 'skewX':
- var sx = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
- mul$1(mt, [1, 0, sx, 1, 0, 0], mt);
- break;
- case 'skewY':
- var sy = Math.tan(parseFloat(valueArr[0]) * DEGREE_TO_ANGLE);
- mul$1(mt, [1, sy, 0, 1, 0, 0], mt);
- break;
- case 'matrix':
- mt[0] = parseFloat(valueArr[0]);
- mt[1] = parseFloat(valueArr[1]);
- mt[2] = parseFloat(valueArr[2]);
- mt[3] = parseFloat(valueArr[3]);
- mt[4] = parseFloat(valueArr[4]);
- mt[5] = parseFloat(valueArr[5]);
- break;
- }
- }
- node.setLocalTransform(mt);
- }
- }
- var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g;
- function parseInlineStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
- var style = xmlNode.getAttribute('style');
- if (!style) {
- return;
- }
- styleRegex.lastIndex = 0;
- var styleRegResult;
- while ((styleRegResult = styleRegex.exec(style)) != null) {
- var svgStlAttr = styleRegResult[1];
- var zrInheritableStlAttr = hasOwn(INHERITABLE_STYLE_ATTRIBUTES_MAP, svgStlAttr)
- ? INHERITABLE_STYLE_ATTRIBUTES_MAP[svgStlAttr]
- : null;
- if (zrInheritableStlAttr) {
- inheritableStyleResult[zrInheritableStlAttr] = styleRegResult[2];
- }
- var zrSelfStlAttr = hasOwn(SELF_STYLE_ATTRIBUTES_MAP, svgStlAttr)
- ? SELF_STYLE_ATTRIBUTES_MAP[svgStlAttr]
- : null;
- if (zrSelfStlAttr) {
- selfStyleResult[zrSelfStlAttr] = styleRegResult[2];
- }
- }
- }
- function parseAttributeStyle(xmlNode, inheritableStyleResult, selfStyleResult) {
- for (var i = 0; i < INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
- var svgAttrName = INHERITABLE_STYLE_ATTRIBUTES_MAP_KEYS[i];
- var attrValue = xmlNode.getAttribute(svgAttrName);
- if (attrValue != null) {
- inheritableStyleResult[INHERITABLE_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
- }
- }
- for (var i = 0; i < SELF_STYLE_ATTRIBUTES_MAP_KEYS.length; i++) {
- var svgAttrName = SELF_STYLE_ATTRIBUTES_MAP_KEYS[i];
- var attrValue = xmlNode.getAttribute(svgAttrName);
- if (attrValue != null) {
- selfStyleResult[SELF_STYLE_ATTRIBUTES_MAP[svgAttrName]] = attrValue;
- }
- }
- }
- function makeViewBoxTransform(viewBoxRect, boundingRect) {
- var scaleX = boundingRect.width / viewBoxRect.width;
- var scaleY = boundingRect.height / viewBoxRect.height;
- var scale = Math.min(scaleX, scaleY);
- return {
- scale: scale,
- x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2),
- y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2)
- };
- }
- function parseSVG(xml, opt) {
- var parser = new SVGParser();
- return parser.parse(xml, opt);
- }
-
- var EPSILON$3 = 1e-8;
- function isAroundEqual$1(a, b) {
- return Math.abs(a - b) < EPSILON$3;
- }
- function contain$1(points, x, y) {
- var w = 0;
- var p = points[0];
- if (!p) {
- return false;
- }
- for (var i = 1; i < points.length; i++) {
- var p2 = points[i];
- w += windingLine(p[0], p[1], p2[0], p2[1], x, y);
- p = p2;
- }
- var p0 = points[0];
- if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) {
- w += windingLine(p[0], p[1], p0[0], p0[1], x, y);
- }
- return w !== 0;
- }
-
- var TMP_TRANSFORM = [];
-
- var Region =
- /** @class */
- function () {
- function Region(name) {
- this.name = name;
- }
- /**
- * Get center point in data unit. That is,
- * for GeoJSONRegion, the unit is lat/lng,
- * for GeoSVGRegion, the unit is SVG local coord.
- */
-
-
- Region.prototype.getCenter = function () {
- return;
- };
-
- return Region;
- }();
-
- var GeoJSONRegion =
- /** @class */
- function (_super) {
- __extends(GeoJSONRegion, _super);
-
- function GeoJSONRegion(name, geometries, cp) {
- var _this = _super.call(this, name) || this;
-
- _this.type = 'geoJSON';
- _this.geometries = geometries;
-
- if (!cp) {
- var rect = _this.getBoundingRect();
-
- cp = [rect.x + rect.width / 2, rect.y + rect.height / 2];
- } else {
- cp = [cp[0], cp[1]];
- }
-
- _this._center = cp;
- return _this;
- }
-
- GeoJSONRegion.prototype.getBoundingRect = function () {
- var rect = this._rect;
-
- if (rect) {
- return rect;
- }
-
- var MAX_NUMBER = Number.MAX_VALUE;
- var min$1 = [MAX_NUMBER, MAX_NUMBER];
- var max$1 = [-MAX_NUMBER, -MAX_NUMBER];
- var min2 = [];
- var max2 = [];
- var geometries = this.geometries;
- var i = 0;
-
- for (; i < geometries.length; i++) {
- // Only support polygon
- if (geometries[i].type !== 'polygon') {
- continue;
- } // Doesn't consider hole
-
-
- var exterior = geometries[i].exterior;
- fromPoints(exterior, min2, max2);
- min(min$1, min$1, min2);
- max(max$1, max$1, max2);
- } // No data
-
-
- if (i === 0) {
- min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0;
- }
-
- return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]);
- };
-
- GeoJSONRegion.prototype.contain = function (coord) {
- var rect = this.getBoundingRect();
- var geometries = this.geometries;
-
- if (!rect.contain(coord[0], coord[1])) {
- return false;
- }
-
- loopGeo: for (var i = 0, len = geometries.length; i < len; i++) {
- // Only support polygon.
- if (geometries[i].type !== 'polygon') {
- continue;
- }
-
- var exterior = geometries[i].exterior;
- var interiors = geometries[i].interiors;
-
- if (contain$1(exterior, coord[0], coord[1])) {
- // Not in the region if point is in the hole.
- for (var k = 0; k < (interiors ? interiors.length : 0); k++) {
- if (contain$1(interiors[k], coord[0], coord[1])) {
- continue loopGeo;
- }
- }
-
- return true;
- }
- }
-
- return false;
- };
-
- GeoJSONRegion.prototype.transformTo = function (x, y, width, height) {
- var rect = this.getBoundingRect();
- var aspect = rect.width / rect.height;
-
- if (!width) {
- width = aspect * height;
- } else if (!height) {
- height = width / aspect;
- }
-
- var target = new BoundingRect(x, y, width, height);
- var transform = rect.calculateTransform(target);
- var geometries = this.geometries;
-
- for (var i = 0; i < geometries.length; i++) {
- // Only support polygon.
- if (geometries[i].type !== 'polygon') {
- continue;
- }
-
- var exterior = geometries[i].exterior;
- var interiors = geometries[i].interiors;
-
- for (var p = 0; p < exterior.length; p++) {
- applyTransform(exterior[p], exterior[p], transform);
- }
-
- for (var h = 0; h < (interiors ? interiors.length : 0); h++) {
- for (var p = 0; p < interiors[h].length; p++) {
- applyTransform(interiors[h][p], interiors[h][p], transform);
- }
- }
- }
-
- rect = this._rect;
- rect.copy(target); // Update center
-
- this._center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
- };
-
- GeoJSONRegion.prototype.cloneShallow = function (name) {
- name == null && (name = this.name);
- var newRegion = new GeoJSONRegion(name, this.geometries, this._center);
- newRegion._rect = this._rect;
- newRegion.transformTo = null; // Simply avoid to be called.
-
- return newRegion;
- };
-
- GeoJSONRegion.prototype.getCenter = function () {
- return this._center;
- };
-
- GeoJSONRegion.prototype.setCenter = function (center) {
- this._center = center;
- };
-
- return GeoJSONRegion;
- }(Region);
-
- var GeoSVGRegion =
- /** @class */
- function (_super) {
- __extends(GeoSVGRegion, _super);
-
- function GeoSVGRegion(name, elOnlyForCalculate) {
- var _this = _super.call(this, name) || this;
-
- _this.type = 'geoSVG';
- _this._elOnlyForCalculate = elOnlyForCalculate;
- return _this;
- }
-
- GeoSVGRegion.prototype.getCenter = function () {
- var center = this._center;
-
- if (!center) {
- // In most cases there are no need to calculate this center.
- // So calculate only when called.
- center = this._center = this._calculateCenter();
- }
-
- return center;
- };
-
- GeoSVGRegion.prototype._calculateCenter = function () {
- var el = this._elOnlyForCalculate;
- var rect = el.getBoundingRect();
- var center = [rect.x + rect.width / 2, rect.y + rect.height / 2];
- var mat = identity(TMP_TRANSFORM);
- var target = el;
-
- while (target && !target.isGeoSVGGraphicRoot) {
- mul$1(mat, target.getLocalTransform(), mat);
- target = target.parent;
- }
-
- invert(mat, mat);
- applyTransform(center, center, mat);
- return center;
- };
-
- return GeoSVGRegion;
- }(Region);
-
- /**
- * "region available" means that: enable users to set attribute `name="xxx"` on those tags
- * to make it be a region.
- * 1. region styles and its label styles can be defined in echarts opton:
- * ```js
- * geo: {
- * regions: [{
- * name: 'xxx',
- * itemStyle: { ... },
- * label: { ... }
- * }, {
- * ...
- * },
- * ...]
- * };
- * ```
- * 2. name can be duplicated in different SVG tag. All of the tags with the same name share
- * a region option. For exampel if there are two representing two lung lobes. They have
- * no common parents but both of them need to display label "lung" inside.
- */
-
- var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path', // are also enabled becuase some SVG might paint text itself,
- // but still need to trigger events or tooltip.
- 'text', 'tspan', // is also enabled because this case: if multiple tags share one name
- // and need label displayed, every tags will display the name, which is not
- // expected. So we can put them into a . Thereby only one label
- // displayed and located based on the bounding rect of the .
- 'g']);
-
- var GeoSVGResource =
- /** @class */
- function () {
- function GeoSVGResource(mapName, svg) {
- this.type = 'geoSVG'; // All used graphics. key: hostKey, value: root
-
- this._usedGraphicMap = createHashMap(); // All unused graphics.
-
- this._freedGraphics = [];
- this._mapName = mapName; // Only perform parse to XML object here, which might be time
- // consiming for large SVG.
- // Although convert XML to zrender element is also time consiming,
- // if we do it here, the clone of zrender elements has to be
- // required. So we do it once for each geo instance, util real
- // performance issues call for optimizing it.
-
- this._parsedXML = parseXML(svg);
- }
-
- GeoSVGResource.prototype.load = function ()
- /* nameMap: NameMap */
- {
- // In the "load" stage, graphic need to be built to
- // get boundingRect for geo coordinate system.
- var firstGraphic = this._firstGraphic; // Create the return data structure only when first graphic created.
- // Because they will be used in geo coordinate system update stage,
- // and `regions` will be mounted at `geo` coordinate system,
- // in which there is no "view" info, so that it should better not to
- // make references to graphic elements.
-
- if (!firstGraphic) {
- firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML);
-
- this._freedGraphics.push(firstGraphic);
-
- this._boundingRect = this._firstGraphic.boundingRect.clone(); // PENDING: `nameMap` will not be supported until some real requirement come.
- // if (nameMap) {
- // named = applyNameMap(named, nameMap);
- // }
-
- var _a = createRegions(firstGraphic.named),
- regions = _a.regions,
- regionsMap = _a.regionsMap;
-
- this._regions = regions;
- this._regionsMap = regionsMap;
- }
-
- return {
- boundingRect: this._boundingRect,
- regions: this._regions,
- regionsMap: this._regionsMap
- };
- };
-
- GeoSVGResource.prototype._buildGraphic = function (svgXML) {
- var result;
- var rootFromParse;
-
- try {
- result = svgXML && parseSVG(svgXML, {
- ignoreViewBox: true,
- ignoreRootClip: true
- }) || {};
- rootFromParse = result.root;
- assert(rootFromParse != null);
- } catch (e) {
- throw new Error('Invalid svg format\n' + e.message);
- } // Note: we keep the covenant that the root has no transform. So always add an extra root.
-
-
- var root = new Group();
- root.add(rootFromParse);
- root.isGeoSVGGraphicRoot = true; // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX]
- //
- // Consider: `