前端初始化
This commit is contained in:
+250
@@ -0,0 +1,250 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { __extends } from "tslib";
|
||||
import { round, mathRound, mathMin, getPrecision } from '../util/number.js';
|
||||
import { addCommas } from '../util/format.js';
|
||||
import Scale from './Scale.js';
|
||||
import { getIntervalPrecision } from './helper.js';
|
||||
import { getBreaksUnsafe, getScaleBreakHelper, hasBreaks, simplyParseBreakOption } from './break.js';
|
||||
import { assert, clone } from 'zrender/lib/core/util.js';
|
||||
import { getMinorTicks } from './minorTicks.js';
|
||||
import { getScaleExtentForTickUnsafe, initBreakOrLinearMapper } from './scaleMapper.js';
|
||||
import { warn } from '../util/log.js';
|
||||
var IntervalScale = /** @class */function (_super) {
|
||||
__extends(IntervalScale, _super);
|
||||
function IntervalScale(setting) {
|
||||
var _this = _super.call(this) || this;
|
||||
_this.type = 'interval';
|
||||
_this.parse = IntervalScale.parse;
|
||||
setting = setting || {};
|
||||
var breakParsed = simplyParseBreakOption(_this, setting);
|
||||
var res = initBreakOrLinearMapper(_this, breakParsed, null);
|
||||
// @ts-ignore
|
||||
_this.brk = res.brk;
|
||||
_this._cfg = {
|
||||
interval: 0,
|
||||
intervalPrecision: 2,
|
||||
intervalCount: undefined,
|
||||
niceExtent: undefined
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
IntervalScale.parse = function (val) {
|
||||
// `Scale#parse` (and its overrids) are typically applied at the axis values input
|
||||
// in echarts option. e.g., `axis.min/max`, `dataZoom.min/max`, etc.
|
||||
// but `series.data` is not included, which uses `dataValueHelper.ts`#`parseDataValue`.
|
||||
// `Scale#parse` originally introduced in fb8c813215098b9d2458966229bb95c510883d5e
|
||||
// at 2016 for dataZoom start/end settings (See `parseAxisModelMinMax`).
|
||||
//
|
||||
// Historically `scale/Interval.ts` returns the input value directly. But numeric
|
||||
// values (such as a number-like string '123') effectively passed through here and
|
||||
// were involved in calculations, which was error-prone and inconsistent with the
|
||||
// declared TS return type. Previously such issues are fixed separately in different
|
||||
// places case by case (such as #2475).
|
||||
//
|
||||
// Now, we perform actual parse to ensure its `number` type here. The parsing rule
|
||||
// follows the series data parsing rule (`dataValueHelper.ts`#`parseDataValue`)
|
||||
// and maintains compatibility as much as possible (thus a more strict parsing
|
||||
// `number.ts`#`numericToNumber` is not used here.)
|
||||
//
|
||||
// FIXME: `ScaleDataValue` also need to be modified to include numeric string type,
|
||||
// since it effectively does.
|
||||
return val == null || val === '' ? NaN
|
||||
// If string (like '-'), using '+' parse to NaN
|
||||
// If object, also parse to NaN
|
||||
: Number(val);
|
||||
};
|
||||
IntervalScale.prototype.getConfig = function () {
|
||||
return clone(this._cfg);
|
||||
};
|
||||
IntervalScale.prototype.setConfig = function (cfg) {
|
||||
var extent = getScaleExtentForTickUnsafe(this);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
assert(cfg.interval != null);
|
||||
if (cfg.intervalCount != null) {
|
||||
assert(cfg.intervalCount >= -1 && cfg.intervalPrecision != null
|
||||
// Do not support intervalCount on axis break currently.
|
||||
&& !hasBreaks(this));
|
||||
}
|
||||
if (cfg.niceExtent != null) {
|
||||
assert(isFinite(cfg.niceExtent[0]) && isFinite(cfg.niceExtent[1]));
|
||||
assert(extent[0] <= cfg.niceExtent[0] && cfg.niceExtent[1] <= extent[1]);
|
||||
assert(round(cfg.niceExtent[0] - cfg.niceExtent[1], getPrecision(cfg.interval)) <= cfg.interval);
|
||||
}
|
||||
}
|
||||
// Reset all.
|
||||
this._cfg = cfg = clone(cfg);
|
||||
if (cfg.niceExtent == null) {
|
||||
// Dropped the auto calculated niceExtent and use user-set extent.
|
||||
// We assume users want to set both interval and extent to get a better result.
|
||||
cfg.niceExtent = extent.slice();
|
||||
}
|
||||
if (cfg.intervalPrecision == null) {
|
||||
cfg.intervalPrecision = getIntervalPrecision(cfg.interval);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* In ascending order.
|
||||
*/
|
||||
IntervalScale.prototype.getTicks = function (opt) {
|
||||
opt = opt || {};
|
||||
var cfg = this._cfg;
|
||||
var interval = cfg.interval;
|
||||
var extent = getScaleExtentForTickUnsafe(this);
|
||||
var niceExtent = cfg.niceExtent;
|
||||
var intervalPrecision = cfg.intervalPrecision;
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
var brk = this.brk;
|
||||
var brkAvailable = scaleBreakHelper && brk;
|
||||
var ticks = [];
|
||||
// If interval is 0, return [];
|
||||
if (!interval) {
|
||||
return ticks;
|
||||
}
|
||||
if (opt.breakTicks === 'only_break' && brkAvailable) {
|
||||
scaleBreakHelper.addBreaksToTicks(ticks, brk.breaks, extent);
|
||||
return ticks;
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
assert(niceExtent != null);
|
||||
}
|
||||
// [CAVEAT]: If changing this logic, must sync it to `axisAlignTicks.ts`.
|
||||
// A fail-safe is required since `interval` can be user specified, or for the case
|
||||
// that using dataZoom toolbox and zoom repeatedly.
|
||||
var safeLimit = 3000;
|
||||
if (extent[0] < niceExtent[0]) {
|
||||
ticks.push({
|
||||
value: opt.expandToNicedExtent ? round(niceExtent[0] - interval, intervalPrecision) : extent[0]
|
||||
});
|
||||
}
|
||||
var estimateNiceMultiple = function (tickVal, targetTick) {
|
||||
return mathRound((targetTick - tickVal) / interval);
|
||||
};
|
||||
var intervalCount = cfg.intervalCount;
|
||||
for (var tick = niceExtent[0], niceTickIdx = 0;; niceTickIdx++) {
|
||||
// Consider case `_extent: [5.2, 5.8], _niceExtent: [6, 5], interval: 1`,
|
||||
// `_intervalCount` makes sense iff `-1`.
|
||||
// Consider case `_extent: [5, 5.8], _niceExtent: [5, 5], interval: 1`,
|
||||
// `_intervalCount` makes sense iff `0`.
|
||||
if (intervalCount == null) {
|
||||
if (tick > niceExtent[1] || !isFinite(tick) || !isFinite(niceExtent[1])) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (niceTickIdx > intervalCount) {
|
||||
// nice ticks number should be `intervalCount + 1`
|
||||
break;
|
||||
}
|
||||
// Consider cumulative error, especially caused by rounding, the last nice
|
||||
// `tick` may be less than or greater than `niceExtent[1]` slightly.
|
||||
tick = mathMin(tick, niceExtent[1]);
|
||||
if (niceTickIdx === intervalCount) {
|
||||
tick = niceExtent[1];
|
||||
}
|
||||
}
|
||||
ticks.push({
|
||||
value: tick
|
||||
});
|
||||
// Avoid rounding error
|
||||
tick = round(tick + interval, intervalPrecision);
|
||||
if (brk) {
|
||||
var moreMultiple = brk.calcNiceTickMultiple(tick, estimateNiceMultiple);
|
||||
if (moreMultiple >= 0) {
|
||||
tick = round(tick + moreMultiple * interval, intervalPrecision);
|
||||
}
|
||||
}
|
||||
if (ticks.length > 0 && tick === ticks[ticks.length - 1].value) {
|
||||
// Consider out of safe float point, e.g.,
|
||||
// -3711126.9907707 + 2e-10 === -3711126.9907707
|
||||
break;
|
||||
}
|
||||
if (ticks.length > safeLimit) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warn('Exceed safe limit in IntervalScale["getTicks"].');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
// Consider this case: the last item of ticks is smaller
|
||||
// than niceExtent[1] and niceExtent[1] === extent[1].
|
||||
var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceExtent[1];
|
||||
if (extent[1] > lastNiceTick) {
|
||||
ticks.push({
|
||||
value: opt.expandToNicedExtent ? round(lastNiceTick + interval, intervalPrecision) : extent[1]
|
||||
});
|
||||
}
|
||||
if (brkAvailable) {
|
||||
scaleBreakHelper.pruneTicksByBreak(opt.pruneByBreak, ticks, brk.breaks, function (item) {
|
||||
return item.value;
|
||||
}, cfg.interval, extent);
|
||||
}
|
||||
if (brkAvailable && opt.breakTicks !== 'none') {
|
||||
scaleBreakHelper.addBreaksToTicks(ticks, brk.breaks, extent);
|
||||
}
|
||||
return ticks;
|
||||
};
|
||||
IntervalScale.prototype.getMinorTicks = function (splitNumber) {
|
||||
return getMinorTicks(this, splitNumber, getBreaksUnsafe(this), this._cfg.interval);
|
||||
};
|
||||
IntervalScale.prototype.getLabel = function (tick, opt) {
|
||||
if (tick == null) {
|
||||
return '';
|
||||
}
|
||||
var precision = opt && opt.precision;
|
||||
if (precision == null) {
|
||||
precision = getPrecision(tick.value) || 0;
|
||||
} else if (precision === 'auto') {
|
||||
// Should be more precise then tick.
|
||||
precision = this._cfg.intervalPrecision;
|
||||
}
|
||||
// (1) If `precision` is set, 12.005 should be display as '12.00500'.
|
||||
// (2) Use `round` (toFixed) to avoid scientific notation like '3.5e-7'.
|
||||
var dataNum = round(tick.value, precision, true);
|
||||
return addCommas(dataNum);
|
||||
};
|
||||
IntervalScale.type = 'interval';
|
||||
return IntervalScale;
|
||||
}(Scale);
|
||||
Scale.registerClass(IntervalScale);
|
||||
export default IntervalScale;
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { __extends } from "tslib";
|
||||
import Scale from './Scale.js';
|
||||
import IntervalScale from './Interval.js';
|
||||
import { logScalePowTick, logScaleLogTick } from './helper.js';
|
||||
import { getBreaksUnsafe, getScaleBreakHelper } from './break.js';
|
||||
import { getMinorTicks } from './minorTicks.js';
|
||||
import { decorateScaleMapper, enableScaleMapperFreeze, SCALE_EXTENT_KIND_EFFECTIVE, SCALE_MAPPER_DEPTH_OUT_OF_BREAK } from './scaleMapper.js';
|
||||
import { map } from 'zrender/lib/core/util.js';
|
||||
import { isValidBoundsForExtent } from '../util/model.js';
|
||||
import { isNullableNumberFinite } from '../util/number.js';
|
||||
var LOOKUP_IDX_EXTENT_START = 0;
|
||||
var LOOKUP_IDX_EXTENT_END = 1;
|
||||
var LOOKUP_IDX_BREAK_START = 2;
|
||||
/**
|
||||
* @final NEVER inherit me!
|
||||
*/
|
||||
var LogScale = /** @class */function (_super) {
|
||||
__extends(LogScale, _super);
|
||||
function LogScale(setting) {
|
||||
var _this = _super.call(this) || this;
|
||||
_this.type = 'log';
|
||||
_this.parse = IntervalScale.parse;
|
||||
_this.base = setting.logBase || 10;
|
||||
var lookupFrom = [];
|
||||
var lookupTo = [];
|
||||
var lookup = _this._lookup = {
|
||||
from: lookupFrom,
|
||||
to: lookupTo
|
||||
};
|
||||
lookupFrom[LOOKUP_IDX_EXTENT_START] = lookupFrom[LOOKUP_IDX_EXTENT_END] = lookupTo[LOOKUP_IDX_EXTENT_START] = lookupTo[LOOKUP_IDX_EXTENT_END] = NaN;
|
||||
decorateScaleMapper(_this, LogScale.mapperMethods);
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
var breakOption = setting.breakOption;
|
||||
var out = {
|
||||
lookup: lookup
|
||||
};
|
||||
if (scaleBreakHelper) {
|
||||
scaleBreakHelper.parseAxisBreakOptionInwardTransform(breakOption, _this, {
|
||||
noNegative: true
|
||||
}, LOOKUP_IDX_BREAK_START, out);
|
||||
}
|
||||
_this.powStub = new IntervalScale({
|
||||
breakParsed: out.original
|
||||
});
|
||||
_this.intervalStub = new IntervalScale({
|
||||
breakParsed: out.transformed
|
||||
});
|
||||
enableScaleMapperFreeze(_this, _this.intervalStub);
|
||||
return _this;
|
||||
}
|
||||
LogScale.prototype.getTicks = function (opt) {
|
||||
var base = this.base;
|
||||
var powStub = this.powStub;
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
var intervalStub = this.intervalStub;
|
||||
var intervalExtent = intervalStub.getExtent();
|
||||
var powExtent = powStub.getExtent();
|
||||
var powOpt = {
|
||||
lookup: {
|
||||
from: intervalExtent,
|
||||
to: powExtent
|
||||
}
|
||||
};
|
||||
return map(intervalStub.getTicks(opt || {}), function (tick) {
|
||||
var val = tick.value;
|
||||
var powVal = logScalePowTick(val, base, powOpt);
|
||||
var vBreak;
|
||||
if (scaleBreakHelper) {
|
||||
var brkPowResult = scaleBreakHelper.getTicksBreakOutwardTransform(this, tick, getBreaksUnsafe(powStub), this._lookup);
|
||||
if (brkPowResult) {
|
||||
vBreak = brkPowResult.vBreak;
|
||||
powVal = brkPowResult.tickVal;
|
||||
}
|
||||
}
|
||||
return {
|
||||
value: powVal,
|
||||
"break": vBreak
|
||||
};
|
||||
}, this);
|
||||
};
|
||||
LogScale.prototype.getMinorTicks = function (splitNumber) {
|
||||
return getMinorTicks(this, splitNumber, getBreaksUnsafe(this.powStub),
|
||||
// NOTE: minor ticks are in the log scale value to visually hint users "logarithm".
|
||||
this.intervalStub.getConfig().interval);
|
||||
};
|
||||
LogScale.prototype.getLabel = function (data, opt) {
|
||||
return this.intervalStub.getLabel(data, opt);
|
||||
};
|
||||
LogScale.type = 'log';
|
||||
LogScale.mapperMethods = {
|
||||
needTransform: function () {
|
||||
return true;
|
||||
},
|
||||
normalize: function (val) {
|
||||
return this.intervalStub.normalize(logScaleLogTick(val, this.base));
|
||||
},
|
||||
scale: function (val) {
|
||||
// PENDING: Input `intervalStub.getExtent()` and `powStub.getExtent()` may
|
||||
// break monotonicity. Do not do it until real problems found.
|
||||
return logScalePowTick(this.intervalStub.scale(val), this.base, null);
|
||||
},
|
||||
transformIn: function (val, opt) {
|
||||
val = logScaleLogTick(val, this.base);
|
||||
return opt && opt.depth === SCALE_MAPPER_DEPTH_OUT_OF_BREAK ? val : this.intervalStub.transformIn(val, opt);
|
||||
},
|
||||
transformOut: function (val, opt) {
|
||||
var depth = opt ? opt.depth : null;
|
||||
tmpTransformOutOpt1.depth = depth;
|
||||
tmpTransformOutOpt2.lookup = this._lookup;
|
||||
return logScalePowTick(depth === SCALE_MAPPER_DEPTH_OUT_OF_BREAK ? val : this.intervalStub.transformOut(val, tmpTransformOutOpt1), this.base, tmpTransformOutOpt2);
|
||||
},
|
||||
contain: function (val) {
|
||||
return this.powStub.contain(val);
|
||||
},
|
||||
/**
|
||||
* NOTICE: The caller should ensure `start` and `end` are both non-negative.
|
||||
*/
|
||||
setExtent: function (start, end) {
|
||||
this.setExtent2(SCALE_EXTENT_KIND_EFFECTIVE, start, end);
|
||||
},
|
||||
setExtent2: function (kind, start, end) {
|
||||
if (!isValidBoundsForExtent(start, end) || start <= 0 || end <= 0) {
|
||||
return;
|
||||
}
|
||||
var lookupTo = tmpNotUsedArr;
|
||||
var lookupFrom = tmpNotUsedArr;
|
||||
if (kind === SCALE_EXTENT_KIND_EFFECTIVE) {
|
||||
var lookup = this._lookup;
|
||||
lookupTo = lookup.to;
|
||||
lookupFrom = lookup.from;
|
||||
}
|
||||
this.powStub.setExtent2(kind, lookupTo[LOOKUP_IDX_EXTENT_START] = start, lookupTo[LOOKUP_IDX_EXTENT_END] = end);
|
||||
var base = this.base;
|
||||
this.intervalStub.setExtent2(kind, lookupFrom[LOOKUP_IDX_EXTENT_START] = logScaleLogTick(start, base), lookupFrom[LOOKUP_IDX_EXTENT_END] = logScaleLogTick(end, base));
|
||||
},
|
||||
getFilter: function () {
|
||||
return {
|
||||
g: 0
|
||||
};
|
||||
},
|
||||
sanitize: function (value, dataExtent) {
|
||||
// Conservative - if dataExtent is invalid, do not sanitize.
|
||||
if (isValidBoundsForExtent(dataExtent[0], dataExtent[1]) && isNullableNumberFinite(value) && value <= 0) {
|
||||
// `DataStore` has ensured that `dataExtent` is valid for LogScale.
|
||||
value = dataExtent[0];
|
||||
}
|
||||
return value;
|
||||
},
|
||||
getDefaultStartValue: function () {
|
||||
return 1;
|
||||
},
|
||||
getExtent: function () {
|
||||
return this.powStub.getExtent();
|
||||
},
|
||||
getExtentUnsafe: function (kind, depth) {
|
||||
return depth === null ? this.powStub.getExtentUnsafe(kind, null) : this.intervalStub.getExtentUnsafe(kind, depth);
|
||||
}
|
||||
};
|
||||
return LogScale;
|
||||
}(Scale);
|
||||
Scale.registerClass(LogScale);
|
||||
var tmpTransformOutOpt1 = {};
|
||||
var tmpTransformOutOpt2 = {};
|
||||
var tmpNotUsedArr = [];
|
||||
export default LogScale;
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { __extends } from "tslib";
|
||||
/**
|
||||
* Linear continuous scale
|
||||
* http://en.wikipedia.org/wiki/Level_of_measurement
|
||||
*/
|
||||
import Scale from './Scale.js';
|
||||
import OrdinalMeta from '../data/OrdinalMeta.js';
|
||||
import { isArray, map, isObject, isString } from 'zrender/lib/core/util.js';
|
||||
import { mathMin, mathRound } from '../util/number.js';
|
||||
import { decorateScaleMapper, enableScaleMapperFreeze, getScaleExtentForTickUnsafe, initBreakOrLinearMapper } from './scaleMapper.js';
|
||||
import { ordinalScaleCreateTicks } from './helper.js';
|
||||
var OrdinalScale = /** @class */function (_super) {
|
||||
__extends(OrdinalScale, _super);
|
||||
function OrdinalScale(setting) {
|
||||
var _this = _super.call(this) || this;
|
||||
_this.type = 'ordinal';
|
||||
_this.parse = OrdinalScale.parse;
|
||||
decorateScaleMapper(_this, OrdinalScale.decoratedMethods);
|
||||
var ordinalMeta = setting.ordinalMeta;
|
||||
// Caution: Should not use instanceof, consider ec-extensions using
|
||||
// import approach to get OrdinalMeta class.
|
||||
if (!ordinalMeta) {
|
||||
ordinalMeta = new OrdinalMeta({});
|
||||
}
|
||||
if (isArray(ordinalMeta)) {
|
||||
ordinalMeta = new OrdinalMeta({
|
||||
categories: map(ordinalMeta, function (item) {
|
||||
return isObject(item) ? item.value : item;
|
||||
})
|
||||
});
|
||||
}
|
||||
_this._ordinalMeta = ordinalMeta;
|
||||
// Create an interval LinearScaleMapper, and decorate it.
|
||||
var res = initBreakOrLinearMapper(null, null,
|
||||
// Do not support break in OrdinalScale yet.
|
||||
setting.extent || [0, ordinalMeta.categories.length - 1]);
|
||||
_this._mapper = res.mapper;
|
||||
enableScaleMapperFreeze(_this, res.mapper);
|
||||
return _this;
|
||||
}
|
||||
OrdinalScale.parse = function (val) {
|
||||
// Caution: Math.round(null) will return `0` rather than `NaN`
|
||||
if (val == null) {
|
||||
val = NaN;
|
||||
} else if (isString(val)) {
|
||||
val = this._ordinalMeta.getOrdinal(val);
|
||||
if (val == null) {
|
||||
val = NaN;
|
||||
}
|
||||
} else {
|
||||
// The val from user input might be float.
|
||||
val = mathRound(val);
|
||||
}
|
||||
return val;
|
||||
};
|
||||
/**
|
||||
* PENDING: currently this method is not used.
|
||||
* `makeCategoryTicks` is effectively used.
|
||||
*/
|
||||
OrdinalScale.prototype.getTicks = function () {
|
||||
var ticks = [];
|
||||
ordinalScaleCreateTicks(this, 0, function (tick) {
|
||||
ticks.push(tick);
|
||||
});
|
||||
return ticks;
|
||||
};
|
||||
OrdinalScale.prototype.getMinorTicks = function (splitNumber) {
|
||||
// Not support.
|
||||
return;
|
||||
};
|
||||
/**
|
||||
* @see `Ordinal['_ordinalNumbersByTick']`
|
||||
*/
|
||||
OrdinalScale.prototype.setSortInfo = function (info) {
|
||||
if (info == null) {
|
||||
this._ordinalNumbersByTick = this._ticksByOrdinalNumber = null;
|
||||
return;
|
||||
}
|
||||
var infoOrdinalNumbers = info.ordinalNumbers;
|
||||
var ordinalsByTick = this._ordinalNumbersByTick = [];
|
||||
var ticksByOrdinal = this._ticksByOrdinalNumber = [];
|
||||
// Unnecessary support negative tick in `realtimeSort`.
|
||||
var tickNum = 0;
|
||||
var allCategoryLen = this._ordinalMeta.categories.length;
|
||||
for (var len = mathMin(allCategoryLen, infoOrdinalNumbers.length); tickNum < len; ++tickNum) {
|
||||
var ordinalNumber = ordinalsByTick[tickNum] = infoOrdinalNumbers[tickNum];
|
||||
ticksByOrdinal[ordinalNumber] = tickNum;
|
||||
}
|
||||
// Handle that `series.data` only covers part of the `axis.category.data`.
|
||||
var unusedOrdinal = 0;
|
||||
for (; tickNum < allCategoryLen; ++tickNum) {
|
||||
while (ticksByOrdinal[unusedOrdinal] != null) {
|
||||
unusedOrdinal++;
|
||||
}
|
||||
;
|
||||
ordinalsByTick[tickNum] = unusedOrdinal;
|
||||
ticksByOrdinal[unusedOrdinal] = tickNum;
|
||||
}
|
||||
};
|
||||
OrdinalScale.prototype._getTickNumber = function (ordinal) {
|
||||
var ticksByOrdinalNumber = this._ticksByOrdinalNumber;
|
||||
// also support ordinal out of range of `ordinalMeta.categories.length`,
|
||||
// where ordinal numbers are used as tick value directly.
|
||||
return ticksByOrdinalNumber && ordinal >= 0 && ordinal < ticksByOrdinalNumber.length ? ticksByOrdinalNumber[ordinal] : ordinal;
|
||||
};
|
||||
/**
|
||||
* @usage
|
||||
* ```js
|
||||
* const ordinalNumber = ordinalScale.getRawOrdinalNumber(tick.value);
|
||||
* // case0
|
||||
* const rawOrdinalValue = axisModel.getCategories()[ordinalNumber];
|
||||
* // case1
|
||||
* const rawOrdinalValue = this._ordinalMeta.categories[ordinalNumber];
|
||||
* // case2
|
||||
* const coord = axis.dataToCoord(ordinalNumber);
|
||||
* ```
|
||||
*
|
||||
* value may be out of range, e.g., when axis max is larger than `ordinalMeta.categories.length`,
|
||||
* where ordinal numbers are used as tick value directly.
|
||||
*/
|
||||
OrdinalScale.prototype.getRawOrdinalNumber = function (tickValue) {
|
||||
var ordinalNumbersByTick = this._ordinalNumbersByTick;
|
||||
return ordinalNumbersByTick && tickValue >= 0 && tickValue < ordinalNumbersByTick.length ? ordinalNumbersByTick[tickValue] : tickValue;
|
||||
};
|
||||
/**
|
||||
* Get item on tick
|
||||
*/
|
||||
OrdinalScale.prototype.getLabel = function (tick) {
|
||||
if (!this.isBlank()) {
|
||||
var ordinalNumber = this.getRawOrdinalNumber(tick.value);
|
||||
var category = this._ordinalMeta.categories[ordinalNumber];
|
||||
// Note that if no data, ordinalMeta.categories is an empty array.
|
||||
// Return empty if it's not exist.
|
||||
return category == null ? '' : category + '';
|
||||
}
|
||||
};
|
||||
/**
|
||||
* NOTICE: This is different from `.getOrdinalMeta().length` when extent
|
||||
* is specified by `xxxAxis.min/max` or by `dataZoom`.
|
||||
*/
|
||||
OrdinalScale.prototype.count = function () {
|
||||
var extent = getScaleExtentForTickUnsafe(this._mapper);
|
||||
return extent[1] - extent[0] + 1;
|
||||
};
|
||||
OrdinalScale.prototype.getOrdinalMeta = function () {
|
||||
return this._ordinalMeta;
|
||||
};
|
||||
OrdinalScale.type = 'ordinal';
|
||||
OrdinalScale.decoratedMethods = {
|
||||
needTransform: function () {
|
||||
return this._mapper.needTransform();
|
||||
},
|
||||
contain: function (val) {
|
||||
return this._mapper.contain(this._getTickNumber(val)) && val >= 0 && val < this._ordinalMeta.categories.length;
|
||||
},
|
||||
normalize: function (val) {
|
||||
return this._mapper.normalize(this._getTickNumber(val));
|
||||
},
|
||||
scale: function (val) {
|
||||
return this.getRawOrdinalNumber(mathRound(this._mapper.scale(val)));
|
||||
},
|
||||
transformIn: function (val, opt) {
|
||||
return this._mapper.transformIn(this._getTickNumber(val), opt);
|
||||
},
|
||||
transformOut: function (val, opt) {
|
||||
return this.getRawOrdinalNumber(this._mapper.transformOut(val, opt));
|
||||
},
|
||||
getExtent: function () {
|
||||
return this._mapper.getExtent();
|
||||
},
|
||||
getExtentUnsafe: function (kind, depth) {
|
||||
return this._mapper.getExtentUnsafe(kind, depth);
|
||||
},
|
||||
/**
|
||||
* NOTICE: OrdinalScale extent should always originates from
|
||||
* `[0, ordinalMeta.categories.length - 1]`, regardless of min/max of `series.data`.
|
||||
* But settings like `xxxAxis.min/max` can still modify the extent.
|
||||
* It is handled by constructor of `ScaleRawExtentInfo`.
|
||||
*/
|
||||
setExtent: function (start, end) {
|
||||
return this._mapper.setExtent(start, end);
|
||||
},
|
||||
setExtent2: function (kind, start, end) {
|
||||
return this._mapper.setExtent2(kind, start, end);
|
||||
}
|
||||
};
|
||||
return OrdinalScale;
|
||||
}(Scale);
|
||||
Scale.registerClass(OrdinalScale);
|
||||
export default OrdinalScale;
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import * as clazzUtil from '../util/clazz.js';
|
||||
var Scale = /** @class */function () {
|
||||
function Scale() {}
|
||||
/**
|
||||
* When axis extent depends on data and no data exists,
|
||||
* axis ticks should not be drawn, which is named 'blank'.
|
||||
*
|
||||
* @final NEVER override!
|
||||
*/
|
||||
Scale.prototype.isBlank = function () {
|
||||
return this._isBlank;
|
||||
};
|
||||
/**
|
||||
* When axis extent depends on data and no data exists,
|
||||
* axis ticks should not be drawn, which is named 'blank'.
|
||||
*
|
||||
* @final NEVER override!
|
||||
*/
|
||||
Scale.prototype.setBlank = function (isBlank) {
|
||||
this._isBlank = isBlank;
|
||||
};
|
||||
return Scale;
|
||||
}();
|
||||
clazzUtil.enableClassManagement(Scale);
|
||||
export default Scale;
|
||||
+582
@@ -0,0 +1,582 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { __extends } from "tslib";
|
||||
/*
|
||||
* A third-party license is embedded for some of the code in this file:
|
||||
* The "scaleLevels" was originally copied from "d3.js" with some
|
||||
* modifications made for this project.
|
||||
* (See more details in the comment on the definition of "scaleLevels" below.)
|
||||
* The use of the source code of this file is also subject to the terms
|
||||
* and consitions of the license of "d3.js" (BSD-3Clause, see
|
||||
* </licenses/LICENSE-d3>).
|
||||
*/
|
||||
// [About UTC and local time zone]:
|
||||
// In most cases, `number.parseDate` will treat input data string as local time
|
||||
// (except time zone is specified in time string). And `format.formateTime` returns
|
||||
// local time by default. option.useUTC is false by default. This design has
|
||||
// considered these common cases:
|
||||
// (1) Time that is persistent in server is in UTC, but it is needed to be displayed
|
||||
// in local time by default.
|
||||
// (2) By default, the input data string (e.g., '2011-01-02') should be displayed
|
||||
// as its original time, without any time difference.
|
||||
import * as numberUtil from '../util/number.js';
|
||||
import { ONE_SECOND, ONE_MINUTE, ONE_HOUR, ONE_DAY, ONE_YEAR, format, leveledFormat, timeUnits, fullLeveledFormatter, getPrimaryTimeUnit, isPrimaryTimeUnit, getDefaultFormatPrecisionOfInterval, fullYearGetterName, monthSetterName, fullYearSetterName, dateSetterName, hoursGetterName, hoursSetterName, minutesSetterName, secondsSetterName, millisecondsSetterName, monthGetterName, dateGetterName, minutesGetterName, secondsGetterName, millisecondsGetterName, getUnitFromValue, primaryTimeUnits, roundTime } from '../util/time.js';
|
||||
import { ensureValidSplitNumber } from './helper.js';
|
||||
import Scale from './Scale.js';
|
||||
import { warn } from '../util/log.js';
|
||||
import { each, filter, indexOf, isNumber, map } from 'zrender/lib/core/util.js';
|
||||
import { getBreaksUnsafe, getScaleBreakHelper, simplyParseBreakOption } from './break.js';
|
||||
import { getMinorTicks } from './minorTicks.js';
|
||||
import { getScaleLinearSpanEffective, getScaleExtentForTickUnsafe, initBreakOrLinearMapper } from './scaleMapper.js';
|
||||
import { removeDuplicates, removeDuplicatesGetKeyFromValueProp } from '../util/model.js';
|
||||
// FIXME 公用?
|
||||
var bisect = function (a, x, lo, hi) {
|
||||
while (lo < hi) {
|
||||
var mid = lo + hi >>> 1;
|
||||
if (a[mid][1] < x) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
};
|
||||
var TimeScale = /** @class */function (_super) {
|
||||
__extends(TimeScale, _super);
|
||||
function TimeScale(setting) {
|
||||
var _this = _super.call(this) || this;
|
||||
_this.type = 'time';
|
||||
_this.parse = TimeScale.parse;
|
||||
_this._locale = setting.locale;
|
||||
_this._useUTC = setting.useUTC;
|
||||
_this._interval = 0;
|
||||
var breakParsed = simplyParseBreakOption(_this, setting);
|
||||
var res = initBreakOrLinearMapper(_this, breakParsed, null);
|
||||
// @ts-ignore
|
||||
_this.brk = res.brk;
|
||||
return _this;
|
||||
}
|
||||
/**
|
||||
* Get label is mainly for other components like dataZoom, tooltip.
|
||||
*/
|
||||
TimeScale.prototype.getLabel = function (tick) {
|
||||
return format(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, this._useUTC, this._locale);
|
||||
};
|
||||
TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) {
|
||||
return leveledFormat(tick, idx, labelFormatter, this._locale, this._useUTC);
|
||||
};
|
||||
TimeScale.prototype.getTicks = function (opt) {
|
||||
opt = opt || {};
|
||||
var interval = this._interval;
|
||||
var extent = getScaleExtentForTickUnsafe(this);
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
var brk = this.brk;
|
||||
var brkAvailable = scaleBreakHelper && brk;
|
||||
var ticks = [];
|
||||
// If interval is 0, return [];
|
||||
if (!interval) {
|
||||
return ticks;
|
||||
}
|
||||
var useUTC = this._useUTC;
|
||||
if (brkAvailable && opt.breakTicks === 'only_break') {
|
||||
getScaleBreakHelper().addBreaksToTicks(ticks, brk.breaks, extent);
|
||||
return ticks;
|
||||
}
|
||||
ticks = createIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent, getScaleLinearSpanEffective(this), brk);
|
||||
var upperUnitIndex = primaryTimeUnits.length - 1;
|
||||
var maxLevel = 0;
|
||||
each(ticks, function (tick) {
|
||||
if (tick.time) {
|
||||
upperUnitIndex = Math.min(upperUnitIndex, indexOf(primaryTimeUnits, tick.time.upperTimeUnit));
|
||||
maxLevel = Math.max(maxLevel, tick.time.level);
|
||||
}
|
||||
});
|
||||
if (brkAvailable) {
|
||||
getScaleBreakHelper().pruneTicksByBreak(opt.pruneByBreak, ticks, brk.breaks, function (item) {
|
||||
return item.value;
|
||||
}, this._approxInterval, extent);
|
||||
}
|
||||
if (brkAvailable && opt.breakTicks !== 'none') {
|
||||
getScaleBreakHelper().addBreaksToTicks(ticks, brk.breaks, extent, function (trimmedBrk) {
|
||||
// @see `parseTimeAxisLabelFormatterDictionary`.
|
||||
var lowerBrkUnitIndex = Math.max(indexOf(primaryTimeUnits, getUnitFromValue(trimmedBrk.vmin, useUTC)), indexOf(primaryTimeUnits, getUnitFromValue(trimmedBrk.vmax, useUTC)));
|
||||
var upperBrkUnitIndex = 0;
|
||||
for (var unitIdx = 0; unitIdx < primaryTimeUnits.length; unitIdx++) {
|
||||
if (!isPrimaryUnitValueAndGreaterSame(primaryTimeUnits[unitIdx], trimmedBrk.vmin, trimmedBrk.vmax, useUTC)) {
|
||||
upperBrkUnitIndex = unitIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var upperIdx = Math.min(upperBrkUnitIndex, upperUnitIndex);
|
||||
var lowerIdx = Math.max(upperIdx, lowerBrkUnitIndex);
|
||||
return {
|
||||
level: maxLevel,
|
||||
lowerTimeUnit: primaryTimeUnits[lowerIdx],
|
||||
upperTimeUnit: primaryTimeUnits[upperIdx]
|
||||
};
|
||||
});
|
||||
}
|
||||
return ticks;
|
||||
};
|
||||
TimeScale.prototype.getMinorTicks = function (splitNumber) {
|
||||
return getMinorTicks(this, splitNumber, getBreaksUnsafe(this), this._interval);
|
||||
};
|
||||
TimeScale.prototype.setTimeInterval = function (opt) {
|
||||
this._interval = opt.interval;
|
||||
this._approxInterval = opt.approxInterval;
|
||||
this._minLevelUnit = opt.minLevelUnit;
|
||||
};
|
||||
TimeScale.parse = function (val) {
|
||||
// `val` might be a float (e.g., calculated from percent), so call `round`.
|
||||
return isNumber(val) ? Math.round(val) : +numberUtil.parseDate(val);
|
||||
};
|
||||
TimeScale.type = 'time';
|
||||
return TimeScale;
|
||||
}(Scale);
|
||||
/**
|
||||
* This implementation was originally copied from "d3.js"
|
||||
* <https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/time/scale.js>
|
||||
* with some modifications made for this program.
|
||||
* See the license statement at the head of this file.
|
||||
*/
|
||||
var scaleIntervals = [
|
||||
// Format interval
|
||||
['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR] // 1Y
|
||||
];
|
||||
function isPrimaryUnitValueAndGreaterSame(unit, valueA, valueB, isUTC) {
|
||||
return roundTime(new Date(valueA), unit, isUTC).getTime() === roundTime(new Date(valueB), unit, isUTC).getTime();
|
||||
}
|
||||
// function isUnitValueSame(
|
||||
// unit: PrimaryTimeUnit,
|
||||
// valueA: number,
|
||||
// valueB: number,
|
||||
// isUTC: boolean
|
||||
// ): boolean {
|
||||
// const dateA = numberUtil.parseDate(valueA) as any;
|
||||
// const dateB = numberUtil.parseDate(valueB) as any;
|
||||
// const isSame = (unit: PrimaryTimeUnit) => {
|
||||
// return getUnitValue(dateA, unit, isUTC)
|
||||
// === getUnitValue(dateB, unit, isUTC);
|
||||
// };
|
||||
// const isSameYear = () => isSame('year');
|
||||
// // const isSameHalfYear = () => isSameYear() && isSame('half-year');
|
||||
// // const isSameQuater = () => isSameYear() && isSame('quarter');
|
||||
// const isSameMonth = () => isSameYear() && isSame('month');
|
||||
// const isSameDay = () => isSameMonth() && isSame('day');
|
||||
// // const isSameHalfDay = () => isSameDay() && isSame('half-day');
|
||||
// const isSameHour = () => isSameDay() && isSame('hour');
|
||||
// const isSameMinute = () => isSameHour() && isSame('minute');
|
||||
// const isSameSecond = () => isSameMinute() && isSame('second');
|
||||
// const isSameMilliSecond = () => isSameSecond() && isSame('millisecond');
|
||||
// switch (unit) {
|
||||
// case 'year':
|
||||
// return isSameYear();
|
||||
// case 'month':
|
||||
// return isSameMonth();
|
||||
// case 'day':
|
||||
// return isSameDay();
|
||||
// case 'hour':
|
||||
// return isSameHour();
|
||||
// case 'minute':
|
||||
// return isSameMinute();
|
||||
// case 'second':
|
||||
// return isSameSecond();
|
||||
// case 'millisecond':
|
||||
// return isSameMilliSecond();
|
||||
// }
|
||||
// }
|
||||
// const primaryUnitGetters = {
|
||||
// year: fullYearGetterName(),
|
||||
// month: monthGetterName(),
|
||||
// day: dateGetterName(),
|
||||
// hour: hoursGetterName(),
|
||||
// minute: minutesGetterName(),
|
||||
// second: secondsGetterName(),
|
||||
// millisecond: millisecondsGetterName()
|
||||
// };
|
||||
// const primaryUnitUTCGetters = {
|
||||
// year: fullYearGetterName(true),
|
||||
// month: monthGetterName(true),
|
||||
// day: dateGetterName(true),
|
||||
// hour: hoursGetterName(true),
|
||||
// minute: minutesGetterName(true),
|
||||
// second: secondsGetterName(true),
|
||||
// millisecond: millisecondsGetterName(true)
|
||||
// };
|
||||
// function moveTick(date: Date, unitName: TimeUnit, step: number, isUTC: boolean) {
|
||||
// step = step || 1;
|
||||
// switch (getPrimaryTimeUnit(unitName)) {
|
||||
// case 'year':
|
||||
// date[fullYearSetterName(isUTC)](date[fullYearGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'month':
|
||||
// date[monthSetterName(isUTC)](date[monthGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'day':
|
||||
// date[dateSetterName(isUTC)](date[dateGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'hour':
|
||||
// date[hoursSetterName(isUTC)](date[hoursGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'minute':
|
||||
// date[minutesSetterName(isUTC)](date[minutesGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'second':
|
||||
// date[secondsSetterName(isUTC)](date[secondsGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// case 'millisecond':
|
||||
// date[millisecondsSetterName(isUTC)](date[millisecondsGetterName(isUTC)]() + step);
|
||||
// break;
|
||||
// }
|
||||
// return date.getTime();
|
||||
// }
|
||||
// const DATE_INTERVALS = [[8, 7.5], [4, 3.5], [2, 1.5]];
|
||||
// const MONTH_INTERVALS = [[6, 5.5], [3, 2.5], [2, 1.5]];
|
||||
// const MINUTES_SECONDS_INTERVALS = [[30, 30], [20, 20], [15, 15], [10, 10], [5, 5], [2, 2]];
|
||||
function getDateInterval(approxInterval, daysInMonth) {
|
||||
approxInterval /= ONE_DAY;
|
||||
return approxInterval > 16 ? 16
|
||||
// Math.floor(daysInMonth / 2) + 1 // In this case we only want one tick between two months.
|
||||
: approxInterval > 7.5 ? 7 // TODO week 7 or day 8?
|
||||
: approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1;
|
||||
}
|
||||
function getMonthInterval(approxInterval) {
|
||||
var APPROX_ONE_MONTH = 30 * ONE_DAY;
|
||||
approxInterval /= APPROX_ONE_MONTH;
|
||||
return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1;
|
||||
}
|
||||
function getHourInterval(approxInterval) {
|
||||
approxInterval /= ONE_HOUR;
|
||||
return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1;
|
||||
}
|
||||
function getMinutesAndSecondsInterval(approxInterval, isMinutes) {
|
||||
approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND;
|
||||
return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1;
|
||||
}
|
||||
function getMillisecondsInterval(approxInterval) {
|
||||
// If less than 1, the getTicks loop will inevitably deed loop and read safeLimit.
|
||||
return numberUtil.mathMax(numberUtil.nice(approxInterval, true), 1);
|
||||
}
|
||||
// e.g., if the input unit is 'day', start calculate ticks from the first day of
|
||||
// that month to make ticks "nice".
|
||||
function getFirstTimestampOfUnit(timestamp, unitName, isUTC) {
|
||||
var upperUnitIdx = Math.max(0, indexOf(primaryTimeUnits, unitName) - 1);
|
||||
return roundTime(new Date(timestamp), primaryTimeUnits[upperUnitIdx], isUTC).getTime();
|
||||
}
|
||||
function createEstimateNiceMultiple(setMethodName, dateMethodInterval) {
|
||||
var tmpDate = new Date(0);
|
||||
tmpDate[setMethodName](1);
|
||||
var tmpTime = tmpDate.getTime();
|
||||
tmpDate[setMethodName](1 + dateMethodInterval);
|
||||
var approxTimeInterval = tmpDate.getTime() - tmpTime;
|
||||
return function (tickVal, targetValue) {
|
||||
// Only in month that accurate result can not get by division of
|
||||
// timestamp interval, but no need accurate here.
|
||||
return Math.max(0, Math.round((targetValue - tickVal) / approxTimeInterval));
|
||||
};
|
||||
}
|
||||
function createIntervalTicks(bottomUnitName, approxInterval, isUTC, extent, innermostSpan, brk) {
|
||||
// A fail-safe is required since `interval` can be user specified, or for the case
|
||||
// that using dataZoom toolbox and zoom repeatedly.
|
||||
var safeLimit = 3000;
|
||||
var unitNames = timeUnits;
|
||||
var iter = 0;
|
||||
function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) {
|
||||
var estimateNiceMultiple = createEstimateNiceMultiple(setMethodName, interval);
|
||||
var dateTime = minTimestamp;
|
||||
var date = new Date(dateTime);
|
||||
// if (isDate) {
|
||||
// d -= 1; // Starts with 0; PENDING
|
||||
// }
|
||||
while (dateTime < maxTimestamp && dateTime <= extent[1]) {
|
||||
out.push({
|
||||
value: dateTime
|
||||
});
|
||||
if (iter++ > safeLimit) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warn('Exceed safe limit in TimeScale["getTicks"].');
|
||||
}
|
||||
break;
|
||||
}
|
||||
date[setMethodName](date[getMethodName]() + interval);
|
||||
dateTime = date.getTime();
|
||||
if (brk) {
|
||||
var moreMultiple = brk.calcNiceTickMultiple(dateTime, estimateNiceMultiple);
|
||||
if (moreMultiple > 0) {
|
||||
date[setMethodName](date[getMethodName]() + moreMultiple * interval);
|
||||
dateTime = date.getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
// This extra tick is for calculating ticks of next level. Will not been added to the final result
|
||||
out.push({
|
||||
value: dateTime,
|
||||
// extent[1] should be added; deduplication will be performed later.
|
||||
notAdd: dateTime > extent[1]
|
||||
});
|
||||
}
|
||||
function addLevelTicks(unitName, lastLevelTicks, levelTicks) {
|
||||
var newAddedTicks = [];
|
||||
var isFirstLevel = !lastLevelTicks.length;
|
||||
if (isPrimaryUnitValueAndGreaterSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) {
|
||||
return;
|
||||
}
|
||||
if (isFirstLevel) {
|
||||
lastLevelTicks = [{
|
||||
value: getFirstTimestampOfUnit(extent[0], unitName, isUTC)
|
||||
}, {
|
||||
value: extent[1]
|
||||
}];
|
||||
}
|
||||
for (var i = 0; i < lastLevelTicks.length - 1; i++) {
|
||||
var startTick = lastLevelTicks[i].value;
|
||||
var endTick = lastLevelTicks[i + 1].value;
|
||||
if (startTick === endTick) {
|
||||
continue;
|
||||
}
|
||||
var interval = void 0;
|
||||
var getterName = void 0;
|
||||
var setterName = void 0;
|
||||
var isDate = false;
|
||||
switch (unitName) {
|
||||
case 'year':
|
||||
interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365));
|
||||
getterName = fullYearGetterName(isUTC);
|
||||
setterName = fullYearSetterName(isUTC);
|
||||
break;
|
||||
case 'half-year':
|
||||
case 'quarter':
|
||||
case 'month':
|
||||
interval = getMonthInterval(approxInterval);
|
||||
getterName = monthGetterName(isUTC);
|
||||
setterName = monthSetterName(isUTC);
|
||||
break;
|
||||
case 'week': // PENDING If week is added. Ignore day.
|
||||
case 'half-week':
|
||||
case 'day':
|
||||
interval = getDateInterval(approxInterval, 31); // Use 32 days and let interval been 16
|
||||
getterName = dateGetterName(isUTC);
|
||||
setterName = dateSetterName(isUTC);
|
||||
isDate = true;
|
||||
break;
|
||||
case 'half-day':
|
||||
case 'quarter-day':
|
||||
case 'hour':
|
||||
interval = getHourInterval(approxInterval);
|
||||
getterName = hoursGetterName(isUTC);
|
||||
setterName = hoursSetterName(isUTC);
|
||||
break;
|
||||
case 'minute':
|
||||
interval = getMinutesAndSecondsInterval(approxInterval, true);
|
||||
getterName = minutesGetterName(isUTC);
|
||||
setterName = minutesSetterName(isUTC);
|
||||
break;
|
||||
case 'second':
|
||||
interval = getMinutesAndSecondsInterval(approxInterval, false);
|
||||
getterName = secondsGetterName(isUTC);
|
||||
setterName = secondsSetterName(isUTC);
|
||||
break;
|
||||
case 'millisecond':
|
||||
interval = getMillisecondsInterval(approxInterval);
|
||||
getterName = millisecondsGetterName(isUTC);
|
||||
setterName = millisecondsSetterName(isUTC);
|
||||
break;
|
||||
}
|
||||
// Notice: This expansion by `getFirstTimestampOfUnit` may cause too many ticks and
|
||||
// iteration. e.g., when three levels of ticks is displayed, which can be caused by
|
||||
// data zoom and axis breaks. Thus trim them here.
|
||||
if (endTick >= extent[0] && startTick <= extent[1]) {
|
||||
addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks);
|
||||
}
|
||||
if (unitName === 'year' && levelTicks.length > 1 && i === 0) {
|
||||
// Add nearest years to the left extent.
|
||||
levelTicks.unshift({
|
||||
value: levelTicks[0].value - interval
|
||||
});
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < newAddedTicks.length; i++) {
|
||||
levelTicks.push(newAddedTicks[i]);
|
||||
}
|
||||
}
|
||||
var levelsTicks = [];
|
||||
var currentLevelTicks = [];
|
||||
var tickCount = 0;
|
||||
var lastLevelTickCount = 0;
|
||||
for (var i = 0; i < unitNames.length; ++i) {
|
||||
var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]);
|
||||
if (!isPrimaryTimeUnit(unitNames[i])) {
|
||||
// TODO
|
||||
continue;
|
||||
}
|
||||
addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks);
|
||||
var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null;
|
||||
if (primaryTimeUnit !== nextPrimaryTimeUnit) {
|
||||
if (currentLevelTicks.length) {
|
||||
lastLevelTickCount = tickCount;
|
||||
// Remove the duplicate so the tick count can be precisely.
|
||||
currentLevelTicks.sort(function (a, b) {
|
||||
return a.value - b.value;
|
||||
});
|
||||
var levelTicksRemoveDuplicated = [];
|
||||
for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) {
|
||||
var tickValue = currentLevelTicks[i_1].value;
|
||||
if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) {
|
||||
levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]);
|
||||
if (tickValue >= extent[0] && tickValue <= extent[1]) {
|
||||
tickCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
var targetTickNum = innermostSpan / approxInterval;
|
||||
// Added too much in this level and not too less in last level
|
||||
if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) {
|
||||
break;
|
||||
}
|
||||
// Only treat primary time unit as one level.
|
||||
levelsTicks.push(levelTicksRemoveDuplicated);
|
||||
if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Reset if next unitName is primary
|
||||
currentLevelTicks = [];
|
||||
}
|
||||
}
|
||||
var levelsTicksInExtent = filter(map(levelsTicks, function (levelTicks) {
|
||||
return filter(levelTicks, function (tick) {
|
||||
return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd;
|
||||
});
|
||||
}), function (levelTicks) {
|
||||
return levelTicks.length > 0;
|
||||
});
|
||||
var maxLevel = levelsTicksInExtent.length - 1;
|
||||
var ticks = [];
|
||||
for (var i = 0; i < levelsTicksInExtent.length; ++i) {
|
||||
var levelTicks = levelsTicksInExtent[i];
|
||||
for (var k = 0; k < levelTicks.length; ++k) {
|
||||
var unit = getUnitFromValue(levelTicks[k].value, isUTC);
|
||||
ticks.push({
|
||||
value: levelTicks[k].value,
|
||||
time: {
|
||||
level: maxLevel - i,
|
||||
upperTimeUnit: unit,
|
||||
lowerTimeUnit: unit
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// Remove duplicates, which may cause jitter of `splitArea` and other bad cases.
|
||||
removeDuplicates(ticks, removeDuplicatesGetKeyFromValueProp, null);
|
||||
ticks.sort(function (a, b) {
|
||||
return a.value - b.value;
|
||||
});
|
||||
var currMinTick = ticks[0];
|
||||
var currMaxTick = ticks[ticks.length - 1];
|
||||
var extent0Unit = getUnitFromValue(extent[0], isUTC);
|
||||
var extent1Unit = getUnitFromValue(extent[1], isUTC);
|
||||
if (!currMinTick || currMinTick.value > extent[0]) {
|
||||
ticks.unshift({
|
||||
value: extent[0],
|
||||
time: {
|
||||
level: 0,
|
||||
upperTimeUnit: extent0Unit,
|
||||
lowerTimeUnit: extent0Unit
|
||||
},
|
||||
notNice: true
|
||||
});
|
||||
}
|
||||
if (!currMaxTick || currMaxTick.value < extent[1]) {
|
||||
ticks.push({
|
||||
value: extent[1],
|
||||
time: {
|
||||
level: 0,
|
||||
upperTimeUnit: extent1Unit,
|
||||
lowerTimeUnit: extent1Unit
|
||||
},
|
||||
notNice: true
|
||||
});
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
export var calcNiceForTimeScale = function (scale, opt) {
|
||||
var extent = scale.getExtent();
|
||||
// If extent start and end are same, expand them
|
||||
if (extent[0] === extent[1]) {
|
||||
// Expand extent
|
||||
extent[0] -= ONE_DAY;
|
||||
extent[1] += ONE_DAY;
|
||||
}
|
||||
// If there are no data and extent are [Infinity, -Infinity]
|
||||
if (extent[1] === -Infinity && extent[0] === Infinity) {
|
||||
var d = new Date();
|
||||
extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||
extent[0] = extent[1] - ONE_DAY;
|
||||
}
|
||||
scale.setExtent(extent[0], extent[1]);
|
||||
var splitNumber = ensureValidSplitNumber(opt.splitNumber, 10);
|
||||
var approxInterval = getScaleLinearSpanEffective(scale) / splitNumber;
|
||||
var minInterval = opt.minInterval;
|
||||
var maxInterval = opt.maxInterval;
|
||||
if (minInterval != null && approxInterval < minInterval) {
|
||||
approxInterval = minInterval;
|
||||
}
|
||||
if (maxInterval != null && approxInterval > maxInterval) {
|
||||
approxInterval = maxInterval;
|
||||
}
|
||||
var scaleIntervalsLen = scaleIntervals.length;
|
||||
var idx = Math.min(bisect(scaleIntervals, approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1);
|
||||
// Interval that can be used to calculate ticks
|
||||
var interval = scaleIntervals[idx][1];
|
||||
// Min level used when picking ticks from top down.
|
||||
// We check one more level to avoid the ticks are to sparse in some case.
|
||||
var minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0];
|
||||
scale.setTimeInterval({
|
||||
approxInterval: approxInterval,
|
||||
interval: interval,
|
||||
minLevelUnit: minLevelUnit
|
||||
});
|
||||
};
|
||||
Scale.registerClass(TimeScale);
|
||||
export default TimeScale;
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
|
||||
/*
|
||||
* 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 _impl = null;
|
||||
export function registerScaleBreakHelperImpl(impl) {
|
||||
if (!_impl) {
|
||||
_impl = impl;
|
||||
}
|
||||
}
|
||||
export function getScaleBreakHelper() {
|
||||
return _impl;
|
||||
}
|
||||
export function simplyParseBreakOption(scale, opt) {
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
var breakOption = opt.breakOption;
|
||||
var breakParsed = opt.breakParsed;
|
||||
if (!breakParsed && scaleBreakHelper) {
|
||||
breakParsed = scaleBreakHelper.parseAxisBreakOption(breakOption, scale);
|
||||
}
|
||||
return breakParsed;
|
||||
}
|
||||
export function getBreaksUnsafe(scale) {
|
||||
var brk = scale.brk;
|
||||
return brk ? brk.breaks : [];
|
||||
}
|
||||
export function hasBreaks(scale) {
|
||||
var brk = scale.brk;
|
||||
return brk ? brk.hasBreaks() : false;
|
||||
}
|
||||
+651
@@ -0,0 +1,651 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { assert, clone, each, filter, find, isString, map, trim } from 'zrender/lib/core/util.js';
|
||||
import { error } from '../util/log.js';
|
||||
import { registerScaleBreakHelperImpl } from './break.js';
|
||||
import { mathMax, mathMin, mathRound } from '../util/number.js';
|
||||
import { decorateScaleMapper, enableScaleMapperFreeze, initLinearScaleMapper, SCALE_EXTENT_KIND_EFFECTIVE, SCALE_MAPPER_DEPTH_OUT_OF_BREAK } from './scaleMapper.js';
|
||||
import { isValidBoundsForExtent } from '../util/model.js';
|
||||
var BreakScaleMapperImpl = /** @class */function () {
|
||||
function BreakScaleMapperImpl(breakParsed, initialExtent) {
|
||||
decorateScaleMapper(this, BreakScaleMapperImpl.decoratedMethods);
|
||||
this._outOfBrk = initLinearScaleMapper(null, initialExtent);
|
||||
var mapper = this._linear = initLinearScaleMapper(null, initialExtent);
|
||||
enableScaleMapperFreeze(this, mapper);
|
||||
this.breaks = breakParsed && breakParsed.breaks || [];
|
||||
}
|
||||
BreakScaleMapperImpl.prototype.hasBreaks = function () {
|
||||
return !!this.breaks.length;
|
||||
};
|
||||
/**
|
||||
* When iteratively generating ticks by nice interval, currently the `interval`, which is
|
||||
* calculated by break-elapsed extent span, is probably very small comparing to the original
|
||||
* extent, leading to a large number of iteration and tick generation, even over `safeLimit`.
|
||||
* Thus stepping over breaks is necessary in that loop.
|
||||
*
|
||||
* "Nice" should be ensured on ticks when step over the breaks. Thus this method returns
|
||||
* a integer multiple of the "nice tick interval".
|
||||
*
|
||||
* This method does little work; it is just for unifying and restricting the behavior.
|
||||
*/
|
||||
BreakScaleMapperImpl.prototype.calcNiceTickMultiple = function (tickVal, estimateNiceMultiple) {
|
||||
for (var idx = 0; idx < this.breaks.length; idx++) {
|
||||
var brk = this.breaks[idx];
|
||||
if (brk.vmin < tickVal && tickVal < brk.vmax) {
|
||||
var multiple = estimateNiceMultiple(tickVal, brk.vmax);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// If not, it may cause dead loop or not nice tick.
|
||||
assert(multiple >= 0 && mathRound(multiple) === multiple);
|
||||
}
|
||||
return multiple;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
BreakScaleMapperImpl.decoratedMethods = {
|
||||
needTransform: function () {
|
||||
return !this.breaks.length;
|
||||
},
|
||||
getExtent: function () {
|
||||
return this._outOfBrk.getExtent();
|
||||
},
|
||||
getExtentUnsafe: function (kind, depth) {
|
||||
return depth == null || depth === SCALE_MAPPER_DEPTH_OUT_OF_BREAK ? this._outOfBrk.getExtentUnsafe(kind, null) : this._linear.getExtentUnsafe(kind, null);
|
||||
},
|
||||
setExtent: function (start, end) {
|
||||
this.setExtent2(SCALE_EXTENT_KIND_EFFECTIVE, start, end);
|
||||
},
|
||||
setExtent2: function (kind, start, end) {
|
||||
if (isValidBoundsForExtent(start, end)) {
|
||||
if (kind === SCALE_EXTENT_KIND_EFFECTIVE) {
|
||||
updateAxisBreakGapReal(this, [start, end]);
|
||||
}
|
||||
this._outOfBrk.setExtent2(kind, start, end);
|
||||
this._linear.setExtent2(kind, this.transformIn(start, null), this.transformIn(end, null));
|
||||
}
|
||||
},
|
||||
normalize: function (val) {
|
||||
return this._linear.normalize(this.transformIn(val, null));
|
||||
},
|
||||
scale: function (val) {
|
||||
return this.transformOut(this._linear.scale(val), null);
|
||||
},
|
||||
contain: function (val) {
|
||||
return this._outOfBrk.contain(val);
|
||||
},
|
||||
/**
|
||||
* a.k.a., "elapse"
|
||||
* Suppose:
|
||||
* AXIS_BREAK_LAST_BREAK_END_BASE: 0
|
||||
* AXIS_BREAK_ELAPSED_BASE: 0
|
||||
* breaks: [
|
||||
* {start: -400, end: -300, gap: 27},
|
||||
* {start: -100, end: 100, gap: 10},
|
||||
* {start: 200, end: 400, gap: 300},
|
||||
* ]
|
||||
* The mapping will be:
|
||||
* | |
|
||||
* 400 + -> + 237
|
||||
* | | | | (gap: 300)
|
||||
* 200 + -> + -63
|
||||
* | |
|
||||
* 100 + -> + -163
|
||||
* | | | | (gap: 10)
|
||||
* -100 + -> + -173
|
||||
* | |
|
||||
* -300 + -> + -373
|
||||
* | | | | (gap: 27)
|
||||
* -400 + -> + -400
|
||||
* | |
|
||||
* origianl elapsed
|
||||
*
|
||||
* Note:
|
||||
* `transformIn` and `transformOut` has nothing to do with "scale extent" - out of extent is supported.
|
||||
*/
|
||||
transformIn: function (val, opt) {
|
||||
if (opt && opt.depth === SCALE_MAPPER_DEPTH_OUT_OF_BREAK) {
|
||||
return val;
|
||||
}
|
||||
// If the value is in the break, return the normalized value in the break
|
||||
var elapsedVal = AXIS_BREAK_ELAPSED_BASE;
|
||||
var lastBreakEnd = AXIS_BREAK_LAST_BREAK_END_BASE;
|
||||
var stillOver = true;
|
||||
for (var i = 0; i < this.breaks.length; i++) {
|
||||
var brk = this.breaks[i];
|
||||
if (val <= brk.vmax) {
|
||||
if (val > brk.vmin) {
|
||||
elapsedVal += brk.vmin - lastBreakEnd + (val - brk.vmin) / (brk.vmax - brk.vmin) * brk.gapReal;
|
||||
} else {
|
||||
elapsedVal += val - lastBreakEnd;
|
||||
}
|
||||
lastBreakEnd = brk.vmax;
|
||||
stillOver = false;
|
||||
break;
|
||||
}
|
||||
elapsedVal += brk.vmin - lastBreakEnd + brk.gapReal;
|
||||
lastBreakEnd = brk.vmax;
|
||||
}
|
||||
if (stillOver) {
|
||||
elapsedVal += val - lastBreakEnd;
|
||||
}
|
||||
return elapsedVal;
|
||||
},
|
||||
/**
|
||||
* @see transformIn
|
||||
* a.k.a., "unelapse"
|
||||
*/
|
||||
transformOut: function (elapsedVal, opt) {
|
||||
if (opt && opt.depth === SCALE_MAPPER_DEPTH_OUT_OF_BREAK) {
|
||||
return elapsedVal;
|
||||
}
|
||||
var lastElapsedEnd = AXIS_BREAK_ELAPSED_BASE;
|
||||
var lastBreakEnd = AXIS_BREAK_LAST_BREAK_END_BASE;
|
||||
var stillOver = true;
|
||||
var unelapsedVal = 0;
|
||||
for (var i = 0; i < this.breaks.length; i++) {
|
||||
var brk = this.breaks[i];
|
||||
var elapsedStart = lastElapsedEnd + brk.vmin - lastBreakEnd;
|
||||
var elapsedEnd = elapsedStart + brk.gapReal;
|
||||
if (elapsedVal <= elapsedEnd) {
|
||||
if (elapsedVal > elapsedStart) {
|
||||
unelapsedVal = brk.vmin + (elapsedVal - elapsedStart) / (elapsedEnd - elapsedStart) * (brk.vmax - brk.vmin);
|
||||
} else {
|
||||
unelapsedVal = lastBreakEnd + elapsedVal - lastElapsedEnd;
|
||||
}
|
||||
lastBreakEnd = brk.vmax;
|
||||
stillOver = false;
|
||||
break;
|
||||
}
|
||||
lastElapsedEnd = elapsedEnd;
|
||||
lastBreakEnd = brk.vmax;
|
||||
}
|
||||
if (stillOver) {
|
||||
unelapsedVal = lastBreakEnd + elapsedVal - lastElapsedEnd;
|
||||
}
|
||||
return unelapsedVal;
|
||||
}
|
||||
};
|
||||
return BreakScaleMapperImpl;
|
||||
}();
|
||||
;
|
||||
function createBreakScaleMapper(breakParsed, initialExtent) {
|
||||
return new BreakScaleMapperImpl(breakParsed, initialExtent);
|
||||
}
|
||||
// Both can start with any finite value, and are not necessarily equal. But they need to
|
||||
// be the same in `axisBreakElapse` and `axisBreakUnelapse` respectively.
|
||||
var AXIS_BREAK_ELAPSED_BASE = 0;
|
||||
var AXIS_BREAK_LAST_BREAK_END_BASE = 0;
|
||||
/**
|
||||
* `gapReal` in brkMapper.breaks will be calculated.
|
||||
*/
|
||||
function updateAxisBreakGapReal(brkMapper, scaleExtent) {
|
||||
// Considered the effect:
|
||||
// - Use dataZoom to move some of the breaks outside the extent.
|
||||
// - Some scenarios that `series.clip: false`.
|
||||
//
|
||||
// How to calculate `prctBrksGapRealSum`:
|
||||
// Based on the formula:
|
||||
// xxx.span = brk.vmax - brk.vmin
|
||||
// xxx.tpPrct.val / xxx.tpAbs.val means ParsedAxisBreak['gapParsed']['val']
|
||||
// .S/.E means a break that is semi in scaleExtent[0] or scaleExtent[1]
|
||||
// valP = (
|
||||
// + (fullyInExtBrksSum.tpAbs.gapReal - fullyInExtBrksSum.tpAbs.span)
|
||||
// + (semiInExtBrk.S.tpAbs.gapReal - semiInExtBrk.S.tpAbs.span) * semiInExtBrk.S.tpAbs.inExtFrac
|
||||
// + (semiInExtBrk.E.tpAbs.gapReal - semiInExtBrk.E.tpAbs.span) * semiInExtBrk.E.tpAbs.inExtFrac
|
||||
// )
|
||||
// valQ = (
|
||||
// - fullyInExtBrksSum.tpPrct.span
|
||||
// - semiInExtBrk.S.tpPrct.span * semiInExtBrk.S.tpPrct.inExtFrac
|
||||
// - semiInExtBrk.E.tpPrct.span * semiInExtBrk.E.tpPrct.inExtFrac
|
||||
// )
|
||||
// gapPrctSum = sum(xxx.tpPrct.val)
|
||||
// gapPrctSum = prctBrksGapRealSum / (
|
||||
// + (scaleExtent[1] - scaleExtent[0]) + valP + valQ
|
||||
// + fullyInExtBrksSum.tpPrct.gapReal
|
||||
// + semiInExtBrk.S.tpPrct.gapReal * semiInExtBrk.S.tpPrct.inExtFrac
|
||||
// + semiInExtBrk.E.tpPrct.gapReal * semiInExtBrk.E.tpPrct.inExtFrac
|
||||
// )
|
||||
// Assume:
|
||||
// xxx.tpPrct.gapReal = xxx.tpPrct.val / gapPrctSum * prctBrksGapRealSum
|
||||
// (NOTE: This is not accurate when semi-in-extent break exist because its
|
||||
// proportion is not linear, but this assumption approximately works.)
|
||||
// Derived as follows:
|
||||
// prctBrksGapRealSum = gapPrctSum * ( (scaleExtent[1] - scaleExtent[0]) + valP + valQ )
|
||||
// / (1
|
||||
// - fullyInExtBrksSum.tpPrct.val
|
||||
// - semiInExtBrk.S.tpPrct.val * semiInExtBrk.S.tpPrct.inExtFrac
|
||||
// - semiInExtBrk.E.tpPrct.val * semiInExtBrk.E.tpPrct.inExtFrac
|
||||
// )
|
||||
var gapPrctSum = 0;
|
||||
var fullyInExtBrksSum = {
|
||||
tpAbs: {
|
||||
span: 0,
|
||||
val: 0
|
||||
},
|
||||
tpPrct: {
|
||||
span: 0,
|
||||
val: 0
|
||||
}
|
||||
};
|
||||
var init = function () {
|
||||
return {
|
||||
has: false,
|
||||
span: NaN,
|
||||
inExtFrac: NaN,
|
||||
val: NaN
|
||||
};
|
||||
};
|
||||
var semiInExtBrk = {
|
||||
S: {
|
||||
tpAbs: init(),
|
||||
tpPrct: init()
|
||||
},
|
||||
E: {
|
||||
tpAbs: init(),
|
||||
tpPrct: init()
|
||||
}
|
||||
};
|
||||
each(brkMapper.breaks, function (brk) {
|
||||
var gapParsed = brk.gapParsed;
|
||||
if (gapParsed.type === 'tpPrct') {
|
||||
gapPrctSum += gapParsed.val;
|
||||
}
|
||||
var clampedBrk = clampBreakByExtent(brk, scaleExtent);
|
||||
if (clampedBrk) {
|
||||
var vminClamped = clampedBrk.vmin !== brk.vmin;
|
||||
var vmaxClamped = clampedBrk.vmax !== brk.vmax;
|
||||
var clampedSpan = clampedBrk.vmax - clampedBrk.vmin;
|
||||
if (vminClamped && vmaxClamped) {
|
||||
// Do nothing, which simply makes the result `gapReal` cover the entire scaleExtent.
|
||||
// This transform is not consistent with the other cases but practically works.
|
||||
} else if (vminClamped || vmaxClamped) {
|
||||
var sOrE = vminClamped ? 'S' : 'E';
|
||||
semiInExtBrk[sOrE][gapParsed.type].has = true;
|
||||
semiInExtBrk[sOrE][gapParsed.type].span = clampedSpan;
|
||||
semiInExtBrk[sOrE][gapParsed.type].inExtFrac = clampedSpan / (brk.vmax - brk.vmin);
|
||||
semiInExtBrk[sOrE][gapParsed.type].val = gapParsed.val;
|
||||
} else {
|
||||
fullyInExtBrksSum[gapParsed.type].span += clampedSpan;
|
||||
fullyInExtBrksSum[gapParsed.type].val += gapParsed.val;
|
||||
}
|
||||
}
|
||||
});
|
||||
var prctBrksGapRealSum = gapPrctSum * (0 + (scaleExtent[1] - scaleExtent[0]) + (fullyInExtBrksSum.tpAbs.val - fullyInExtBrksSum.tpAbs.span) + (semiInExtBrk.S.tpAbs.has ? (semiInExtBrk.S.tpAbs.val - semiInExtBrk.S.tpAbs.span) * semiInExtBrk.S.tpAbs.inExtFrac : 0) + (semiInExtBrk.E.tpAbs.has ? (semiInExtBrk.E.tpAbs.val - semiInExtBrk.E.tpAbs.span) * semiInExtBrk.E.tpAbs.inExtFrac : 0) - fullyInExtBrksSum.tpPrct.span - (semiInExtBrk.S.tpPrct.has ? semiInExtBrk.S.tpPrct.span * semiInExtBrk.S.tpPrct.inExtFrac : 0) - (semiInExtBrk.E.tpPrct.has ? semiInExtBrk.E.tpPrct.span * semiInExtBrk.E.tpPrct.inExtFrac : 0)) / (1 - fullyInExtBrksSum.tpPrct.val - (semiInExtBrk.S.tpPrct.has ? semiInExtBrk.S.tpPrct.val * semiInExtBrk.S.tpPrct.inExtFrac : 0) - (semiInExtBrk.E.tpPrct.has ? semiInExtBrk.E.tpPrct.val * semiInExtBrk.E.tpPrct.inExtFrac : 0));
|
||||
each(brkMapper.breaks, function (brk) {
|
||||
var gapParsed = brk.gapParsed;
|
||||
if (gapParsed.type === 'tpPrct') {
|
||||
brk.gapReal = gapPrctSum !== 0
|
||||
// prctBrksGapRealSum is supposed to be non-negative but add a safe guard
|
||||
? mathMax(prctBrksGapRealSum, 0) * gapParsed.val / gapPrctSum : 0;
|
||||
}
|
||||
if (gapParsed.type === 'tpAbs') {
|
||||
brk.gapReal = gapParsed.val;
|
||||
}
|
||||
if (brk.gapReal == null) {
|
||||
brk.gapReal = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
function pruneTicksByBreak(pruneByBreak, ticks, breaks, getValue, interval, scaleExtent) {
|
||||
if (pruneByBreak === 'no') {
|
||||
return;
|
||||
}
|
||||
each(breaks, function (brk) {
|
||||
// break.vmin/vmax that out of extent must not impact the visible of
|
||||
// normal ticks and labels.
|
||||
var clampedBrk = clampBreakByExtent(brk, scaleExtent);
|
||||
if (!clampedBrk) {
|
||||
return;
|
||||
}
|
||||
// Remove some normal ticks to avoid zigzag shapes overlapping with split lines
|
||||
// and to avoid break labels overlapping with normal tick labels (thouth it can
|
||||
// also be avoided by `axisLabel.hideOverlap`).
|
||||
// It's OK to O(n^2) since the number of `ticks` are small.
|
||||
for (var j = ticks.length - 1; j >= 0; j--) {
|
||||
var tick = ticks[j];
|
||||
var val = getValue(tick);
|
||||
// 1. Ensure there is no ticks inside `break.vmin` and `break.vmax`.
|
||||
// 2. Use an empirically gap value here. Theoritically `zigzagAmplitude` is
|
||||
// supposed to be involved to provide better precision but it will brings
|
||||
// more complexity. The empirically gap value is conservative because break
|
||||
// labels and normal tick lables are prone to overlapping.
|
||||
var gap = interval * 3 / 4;
|
||||
if (val > clampedBrk.vmin - gap && val < clampedBrk.vmax + gap && (pruneByBreak !== 'preserve_extent_bound' || val !== scaleExtent[0] && val !== scaleExtent[1])) {
|
||||
ticks.splice(j, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function addBreaksToTicks(
|
||||
// The input ticks should be in accending order.
|
||||
ticks, breaks, scaleExtent,
|
||||
// Keep the break ends at the same level to avoid an awkward appearance.
|
||||
getTimeProps) {
|
||||
each(breaks, function (brk) {
|
||||
var clampedBrk = clampBreakByExtent(brk, scaleExtent);
|
||||
if (!clampedBrk) {
|
||||
return;
|
||||
}
|
||||
// - When neight `break.vmin` nor `break.vmax` is in scale extent,
|
||||
// break label should not be displayed and we do not add them to the result.
|
||||
// - When only one of `break.vmin` and `break.vmax` is inside the extent and the
|
||||
// other is outsite, we comply with the extent and display only part of the breaks area,
|
||||
// because the extent might be determined by user settings (such as `axis.min/max`)
|
||||
ticks.push({
|
||||
value: clampedBrk.vmin,
|
||||
"break": {
|
||||
type: 'vmin',
|
||||
parsedBreak: clampedBrk
|
||||
},
|
||||
time: getTimeProps ? getTimeProps(clampedBrk) : undefined
|
||||
});
|
||||
// When gap is 0, start tick overlap with end tick, but we still count both of them. Break
|
||||
// area shape can address that overlapping. `axisLabel` need draw both start and end separately,
|
||||
// otherwise it brings complexity to the logic of label overlapping resolving (e.g., when label
|
||||
// rotated), and introduces inconsistency to users in `axisLabel.formatter` between gap is 0 or not.
|
||||
ticks.push({
|
||||
value: clampedBrk.vmax,
|
||||
"break": {
|
||||
type: 'vmax',
|
||||
parsedBreak: clampedBrk
|
||||
},
|
||||
time: getTimeProps ? getTimeProps(clampedBrk) : undefined
|
||||
});
|
||||
});
|
||||
if (breaks.length) {
|
||||
ticks.sort(function (a, b) {
|
||||
return a.value - b.value;
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If break and extent does not intersect, return null/undefined.
|
||||
* If the intersection is only a point at scaleExtent[0] or scaleExtent[1], return null/undefined.
|
||||
*/
|
||||
function clampBreakByExtent(brk, scaleExtent) {
|
||||
var vmin = mathMax(brk.vmin, scaleExtent[0]);
|
||||
var vmax = mathMin(brk.vmax, scaleExtent[1]);
|
||||
return vmin < vmax || vmin === vmax && vmin > scaleExtent[0] && vmin < scaleExtent[1] ? {
|
||||
vmin: vmin,
|
||||
vmax: vmax,
|
||||
breakOption: brk.breakOption,
|
||||
gapParsed: brk.gapParsed,
|
||||
gapReal: brk.gapReal
|
||||
} : null;
|
||||
}
|
||||
function parseAxisBreakOption(
|
||||
// raw user input breaks, retrieved from axis model.
|
||||
breakOptionList, scale, opt) {
|
||||
var parsedBreaks = [];
|
||||
if (!breakOptionList) {
|
||||
return {
|
||||
breaks: parsedBreaks
|
||||
};
|
||||
}
|
||||
function validatePercent(normalizedPercent, msg) {
|
||||
if (normalizedPercent >= 0 && normalizedPercent < 1 - 1e-5) {
|
||||
// Avoid division error.
|
||||
return true;
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error(msg + " must be >= 0 and < 1, rather than " + normalizedPercent + " .");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
each(breakOptionList, function (brkOption) {
|
||||
if (!brkOption || brkOption.start == null || brkOption.end == null) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error('The input axis breaks start/end should not be empty.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (brkOption.isExpanded) {
|
||||
return;
|
||||
}
|
||||
var parsedBrk = {
|
||||
breakOption: clone(brkOption),
|
||||
vmin: scale.parse(brkOption.start),
|
||||
vmax: scale.parse(brkOption.end),
|
||||
gapParsed: {
|
||||
type: 'tpAbs',
|
||||
val: 0
|
||||
},
|
||||
gapReal: null
|
||||
};
|
||||
if (brkOption.gap != null) {
|
||||
var isPrct = false;
|
||||
if (isString(brkOption.gap)) {
|
||||
var trimmedGap = trim(brkOption.gap);
|
||||
if (trimmedGap.match(/%$/)) {
|
||||
var normalizedPercent = parseFloat(trimmedGap) / 100;
|
||||
if (!validatePercent(normalizedPercent, 'Percent gap')) {
|
||||
normalizedPercent = 0;
|
||||
}
|
||||
parsedBrk.gapParsed.type = 'tpPrct';
|
||||
parsedBrk.gapParsed.val = normalizedPercent;
|
||||
isPrct = true;
|
||||
}
|
||||
}
|
||||
if (!isPrct) {
|
||||
var absolute = scale.parse(brkOption.gap);
|
||||
if (!isFinite(absolute) || absolute < 0) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Axis breaks gap must positive finite rather than (" + brkOption.gap + ").");
|
||||
}
|
||||
absolute = 0;
|
||||
}
|
||||
parsedBrk.gapParsed.type = 'tpAbs';
|
||||
parsedBrk.gapParsed.val = absolute;
|
||||
}
|
||||
}
|
||||
if (parsedBrk.vmin === parsedBrk.vmax) {
|
||||
parsedBrk.gapParsed.type = 'tpAbs';
|
||||
parsedBrk.gapParsed.val = 0;
|
||||
}
|
||||
if (opt && opt.noNegative) {
|
||||
each(['vmin', 'vmax'], function (se) {
|
||||
if (parsedBrk[se] < 0) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error("Axis break." + se + " must not be negative.");
|
||||
}
|
||||
parsedBrk[se] = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Ascending numerical order is the prerequisite of the calculation in Scale#normalize.
|
||||
// User are allowed to input desending vmin/vmax for simplifying the usage.
|
||||
if (parsedBrk.vmin > parsedBrk.vmax) {
|
||||
var tmp = parsedBrk.vmax;
|
||||
parsedBrk.vmax = parsedBrk.vmin;
|
||||
parsedBrk.vmin = tmp;
|
||||
}
|
||||
parsedBreaks.push(parsedBrk);
|
||||
});
|
||||
// Ascending numerical order is the prerequisite of the calculation in Scale#normalize.
|
||||
parsedBreaks.sort(function (item1, item2) {
|
||||
return item1.vmin - item2.vmin;
|
||||
});
|
||||
// Make sure that the intervals in breaks are not overlap.
|
||||
var lastEnd = -Infinity;
|
||||
each(parsedBreaks, function (brk, idx) {
|
||||
if (lastEnd > brk.vmin) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
error('Axis breaks must not overlap.');
|
||||
}
|
||||
parsedBreaks[idx] = null;
|
||||
}
|
||||
lastEnd = brk.vmax;
|
||||
});
|
||||
return {
|
||||
breaks: filter(parsedBreaks, function (brk) {
|
||||
return !!brk;
|
||||
})
|
||||
};
|
||||
}
|
||||
function identifyAxisBreak(brk, identifier) {
|
||||
return serializeAxisBreakIdentifier(identifier) === serializeAxisBreakIdentifier(brk);
|
||||
}
|
||||
function serializeAxisBreakIdentifier(identifier) {
|
||||
// We use user input start/end to identify break. Considered cases like `start: new Date(xxx)`,
|
||||
// Theoretically `Scale#parse` should be used here, but not used currently to reduce dependencies,
|
||||
// since simply converting to string happens to be correct.
|
||||
return identifier.start + '_\0_' + identifier.end;
|
||||
}
|
||||
/**
|
||||
* - A break pair represents `[vmin, vmax]`,
|
||||
* - Only both vmin and vmax item exist, they are counted as a pair.
|
||||
*/
|
||||
function retrieveAxisBreakPairs(itemList, getVisualAxisBreak, returnIdx) {
|
||||
var idxPairList = [];
|
||||
each(itemList, function (el, idx) {
|
||||
var vBreak = getVisualAxisBreak(el);
|
||||
if (vBreak && vBreak.type === 'vmin') {
|
||||
idxPairList.push([idx]);
|
||||
}
|
||||
});
|
||||
each(itemList, function (el, idx) {
|
||||
var vBreak = getVisualAxisBreak(el);
|
||||
if (vBreak && vBreak.type === 'vmax') {
|
||||
var idxPair = find(idxPairList,
|
||||
// parsedBreak may be changed, can only use breakOption to match them.
|
||||
function (pr) {
|
||||
return identifyAxisBreak(getVisualAxisBreak(itemList[pr[0]]).parsedBreak.breakOption, vBreak.parsedBreak.breakOption);
|
||||
});
|
||||
idxPair && idxPair.push(idx);
|
||||
}
|
||||
});
|
||||
var result = [];
|
||||
each(idxPairList, function (idxPair) {
|
||||
if (idxPair.length === 2) {
|
||||
result.push(returnIdx ? idxPair : [itemList[idxPair[0]], itemList[idxPair[1]]]);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function getTicksBreakOutwardTransform(scale, tick, outermostBreaks, lookup) {
|
||||
if (!tick["break"]) {
|
||||
return;
|
||||
}
|
||||
var brk = tick["break"].parsedBreak;
|
||||
var originalBrkItem = find(outermostBreaks, function (brk) {
|
||||
return identifyAxisBreak(brk.breakOption, tick["break"].parsedBreak.breakOption);
|
||||
});
|
||||
// NOTE: `tick.break` may have been clamped by scale extent.
|
||||
var opt = {
|
||||
lookup: lookup,
|
||||
depth: SCALE_MAPPER_DEPTH_OUT_OF_BREAK
|
||||
};
|
||||
var vmin = scale.transformOut(brk.vmin, opt);
|
||||
var vmax = scale.transformOut(brk.vmax, opt);
|
||||
var parsedBreak = {
|
||||
vmin: vmin,
|
||||
vmax: vmax,
|
||||
breakOption: brk.breakOption,
|
||||
gapParsed: clone(originalBrkItem.gapParsed),
|
||||
gapReal: brk.gapReal
|
||||
};
|
||||
return {
|
||||
tickVal: parsedBreak[tick["break"].type],
|
||||
vBreak: {
|
||||
type: tick["break"].type,
|
||||
parsedBreak: parsedBreak
|
||||
}
|
||||
};
|
||||
}
|
||||
function parseAxisBreakOptionInwardTransform(breakOptionList, scale, parseOpt, lookupStartIdx, out) {
|
||||
out.original = parseAxisBreakOption(breakOptionList, scale, parseOpt);
|
||||
var transformed = out.transformed = parseAxisBreakOption(breakOptionList, scale, parseOpt);
|
||||
var lookup = out.lookup;
|
||||
transformed.breaks = map(transformed.breaks, function (brk, idx) {
|
||||
var transOpt = {
|
||||
depth: SCALE_MAPPER_DEPTH_OUT_OF_BREAK
|
||||
};
|
||||
var vmin = scale.transformIn(brk.vmin, transOpt);
|
||||
var vmax = scale.transformIn(brk.vmax, transOpt);
|
||||
var gapParsed = {
|
||||
type: brk.gapParsed.type,
|
||||
val: brk.gapParsed.type === 'tpAbs' ? scale.transformIn(brk.vmin + brk.gapParsed.val, transOpt) - vmin : brk.gapParsed.val
|
||||
};
|
||||
lookup.from[lookupStartIdx + idx] = vmin;
|
||||
lookup.to[lookupStartIdx + idx] = brk.vmin;
|
||||
lookup.from[lookupStartIdx + idx + 1] = vmax;
|
||||
lookup.to[lookupStartIdx + idx + 1] = brk.vmax;
|
||||
return {
|
||||
vmin: vmin,
|
||||
vmax: vmax,
|
||||
gapParsed: gapParsed,
|
||||
gapReal: brk.gapReal,
|
||||
breakOption: brk.breakOption
|
||||
};
|
||||
});
|
||||
}
|
||||
var BREAK_MIN_MAX_TO_PARAM = {
|
||||
vmin: 'start',
|
||||
vmax: 'end'
|
||||
};
|
||||
function makeAxisLabelFormatterParamBreak(extraParam, vBreak) {
|
||||
if (vBreak) {
|
||||
extraParam = extraParam || {};
|
||||
extraParam["break"] = {
|
||||
type: BREAK_MIN_MAX_TO_PARAM[vBreak.type],
|
||||
start: vBreak.parsedBreak.vmin,
|
||||
end: vBreak.parsedBreak.vmax
|
||||
};
|
||||
}
|
||||
return extraParam;
|
||||
}
|
||||
export function installScaleBreakHelper() {
|
||||
registerScaleBreakHelperImpl({
|
||||
createBreakScaleMapper: createBreakScaleMapper,
|
||||
pruneTicksByBreak: pruneTicksByBreak,
|
||||
addBreaksToTicks: addBreaksToTicks,
|
||||
parseAxisBreakOption: parseAxisBreakOption,
|
||||
identifyAxisBreak: identifyAxisBreak,
|
||||
serializeAxisBreakIdentifier: serializeAxisBreakIdentifier,
|
||||
retrieveAxisBreakPairs: retrieveAxisBreakPairs,
|
||||
getTicksBreakOutwardTransform: getTicksBreakOutwardTransform,
|
||||
parseAxisBreakOptionInwardTransform: parseAxisBreakOptionInwardTransform,
|
||||
makeAxisLabelFormatterParamBreak: makeAxisLabelFormatterParamBreak
|
||||
});
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { getPrecision, round, nice, quantityExponent, mathPow, mathMax, mathRound, mathLog, mathAbs, mathFloor, mathCeil } from '../util/number.js';
|
||||
import { isValidNumberForExtent } from '../util/model.js';
|
||||
import { getScaleExtentForTickUnsafe } from './scaleMapper.js';
|
||||
/**
|
||||
* See also method `nice` in `src/util/number.ts`.
|
||||
*/
|
||||
// export function isValueNice(val: number) {
|
||||
// const exp10 = Math.pow(10, quantityExponent(Math.abs(val)));
|
||||
// const f = Math.abs(round(val / exp10, 0));
|
||||
// return f === 0
|
||||
// || f === 1
|
||||
// || f === 2
|
||||
// || f === 3
|
||||
// || f === 5;
|
||||
// }
|
||||
export function isIntervalOrLogScale(scale) {
|
||||
return isIntervalScale(scale) || isLogScale(scale);
|
||||
}
|
||||
export function isIntervalOrTimeScale(scale) {
|
||||
return isIntervalScale(scale) || isTimeScale(scale);
|
||||
}
|
||||
export function isIntervalScale(scale) {
|
||||
return scale.type === 'interval';
|
||||
}
|
||||
export function isTimeScale(scale) {
|
||||
return scale.type === 'time';
|
||||
}
|
||||
export function isLogScale(scale) {
|
||||
return scale.type === 'log';
|
||||
}
|
||||
export function isOrdinalScale(scale) {
|
||||
return scale.type === 'ordinal';
|
||||
}
|
||||
/**
|
||||
* @param extent Both extent[0] and extent[1] should be valid number.
|
||||
* Should be extent[0] < extent[1].
|
||||
* @param splitNumber splitNumber should be >= 1.
|
||||
*/
|
||||
export function intervalScaleNiceTicks(extent, spanWithBreaks, splitNumber, minInterval, maxInterval) {
|
||||
var result = {};
|
||||
var interval = result.interval = nice(spanWithBreaks / splitNumber, true);
|
||||
if (minInterval != null && interval < minInterval) {
|
||||
interval = result.interval = minInterval;
|
||||
}
|
||||
if (maxInterval != null && interval > maxInterval) {
|
||||
interval = result.interval = maxInterval;
|
||||
}
|
||||
var precision = result.intervalPrecision = getIntervalPrecision(interval);
|
||||
// Niced extent inside original extent
|
||||
result.niceTickExtent = [round(mathCeil(extent[0] / interval) * interval, precision), round(mathFloor(extent[1] / interval) * interval, precision)];
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* The input `niceInterval` should be generated
|
||||
* from `nice` method in `src/util/number.ts`, or
|
||||
* from `increaseInterval` itself.
|
||||
*/
|
||||
export function increaseInterval(niceInterval) {
|
||||
var exponent = quantityExponent(niceInterval);
|
||||
// No rounding error in Math.pow(10, integer).
|
||||
var exp10 = mathPow(10, exponent);
|
||||
// Fix IEEE 754 float rounding error
|
||||
var f = mathRound(niceInterval / exp10);
|
||||
if (!f) {
|
||||
f = 1;
|
||||
} else if (f === 2) {
|
||||
f = 3;
|
||||
} else if (f === 3) {
|
||||
f = 5;
|
||||
} else {
|
||||
// f is 1 or 5
|
||||
f *= 2;
|
||||
}
|
||||
// Fix IEEE 754 float rounding error
|
||||
return round(f * exp10, -exponent);
|
||||
}
|
||||
export function getIntervalPrecision(niceInterval) {
|
||||
// Tow more digital for tick.
|
||||
// NOTE: `2` was introduced in commit `af2a2a9f6303081d7c3b52f0a38add07b4c6e0c7`;
|
||||
// it works on "nice" interval, but seems not necessarily mathematically required.
|
||||
return getPrecision(niceInterval) + 2;
|
||||
}
|
||||
/**
|
||||
* NOTE:
|
||||
* - If `val` is `NaN`, return `NaN`.
|
||||
* - If `val` is `0`, return `-Infinity`.
|
||||
* - If `val` is negative, return `NaN`.
|
||||
*
|
||||
* @see {DataStore#getDataExtent} It handles non-positive values for logarithm scale.
|
||||
*/
|
||||
export function logScaleLogTick(val, base) {
|
||||
// NOTE:
|
||||
// - rounding error may happen above, typically expecting `log10(1000)` but actually
|
||||
// getting `2.9999999999999996`, but generally it does not matter since they are not
|
||||
// used to display.
|
||||
// - Consider backward compatibility and other log bases, do not use `Math.log10`.
|
||||
return mathLog(val) / mathLog(base);
|
||||
}
|
||||
/**
|
||||
* Cumulative rounding errors cause the logarithm operation to become non-invertible by simply exponentiation.
|
||||
* - `Math.pow(10, integer)` itself has no rounding error. But,
|
||||
* - If `linearTickVal` is generated internally by `calcNiceTicks`, it may be still "not nice" (not an integer)
|
||||
* when it is `extent[i]`.
|
||||
* - If `linearTickVal` is generated outside (e.g., by `scaleCalcAlign`) and set by `setExtent`,
|
||||
* `logScaleLogTick` may already have introduced rounding errors even for "nice" values.
|
||||
* But invertible is required when the original `extent[i]` need to be respected, or "nice" ticks need to be
|
||||
* displayed instead of something like `5.999999999999999`, which is addressed in this function.
|
||||
* See also `#4158`.
|
||||
*
|
||||
* [CAUTION]:
|
||||
* Monotonicity may be broken on extent ends - callers must make sure it does not matter.
|
||||
*/
|
||||
export function logScalePowTick(
|
||||
// `tickVal` should be in the linear space.
|
||||
linearTickVal, base, opt) {
|
||||
var lookup = opt && opt.lookup;
|
||||
if (lookup) {
|
||||
for (var i = 0; i < lookup.from.length; i++) {
|
||||
if (linearTickVal === lookup.from[i]) {
|
||||
return lookup.to[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return mathPow(base, linearTickVal);
|
||||
}
|
||||
/**
|
||||
* For `IntervalScale`, convert `rawExtent` to:
|
||||
* - Be no non-finite number.
|
||||
* - Be `extent[0] < extent[1]`- no equal; otherwise, additional handling is required
|
||||
* in "nice" and "align" ticks.
|
||||
*/
|
||||
export function intervalScaleEnsureValidExtent(rawExtent, fixMinMax, rawExtentResult) {
|
||||
var extent = rawExtent.slice();
|
||||
// PENDING:
|
||||
// This implementation is not rigorous, but has long been in use.
|
||||
// If extent start and end are same, expand them
|
||||
if (extent[0] === extent[1]) {
|
||||
// If `containShape`, the extent must be evenly distributed to both sides;
|
||||
// otherwise, shape (e.g., bars) may be overflow and clipped.
|
||||
var containShapeRequired = rawExtentResult && rawExtentResult.ctnShp;
|
||||
if (extent[0] !== 0) {
|
||||
// Expand extent
|
||||
// Note that extents can be both negative. See #13154
|
||||
var expandSize = mathAbs(extent[0]);
|
||||
// In the fowllowing case
|
||||
// Axis has been fixed max 100
|
||||
// Plus data are all 100 and axis extent are [100, 100].
|
||||
// Extend to the both side will cause expanded max is larger than fixed max.
|
||||
// So only expand to the smaller side.
|
||||
if (!fixMinMax[1]) {
|
||||
extent[1] += expandSize / 2;
|
||||
extent[0] -= expandSize / 2;
|
||||
} else {
|
||||
extent[0] -= expandSize / 2;
|
||||
}
|
||||
} else {
|
||||
if (containShapeRequired) {
|
||||
extent[0] = -1;
|
||||
extent[1] = 1;
|
||||
} else {
|
||||
extent[1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// For example, if there are no series data, extent may be `[Infinity, -Infinity]` here.
|
||||
if (!isValidNumberForExtent(extent[0]) || !isValidNumberForExtent(extent[1])) {
|
||||
extent[0] = 0;
|
||||
extent[1] = 1;
|
||||
}
|
||||
if (extent[1] < extent[0]) {
|
||||
extent.reverse();
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
export function extentDiffers(extent1, extent2) {
|
||||
return [extent1[0] !== extent2[0], extent1[1] !== extent2[1]];
|
||||
}
|
||||
export function ensureValidSplitNumber(rawSplitNumber, defaultSplitNumber) {
|
||||
rawSplitNumber = rawSplitNumber || defaultSplitNumber;
|
||||
return mathRound(mathMax(rawSplitNumber, 1));
|
||||
}
|
||||
/**
|
||||
* NOTE: The result can have only one item, e.g., when `extent[0] === extent[1]`
|
||||
* and `categoryInterval === 0`.
|
||||
*/
|
||||
export function ordinalScaleCreateTicks(ordinalScale,
|
||||
// `categoryInterval` is the number part of `CategoryTickLabelSplitIntervalOption`.
|
||||
categoryInterval, addItem) {
|
||||
var extent = getScaleExtentForTickUnsafe(ordinalScale);
|
||||
var startTick = extent[0];
|
||||
var tickCount = ordinalScale.count();
|
||||
var step = Math.max((categoryInterval || 0) + 1, 1);
|
||||
// Calculate start tick based on zero if possible to keep label consistent
|
||||
// while zooming and moving while interval > 0. Otherwise the selection
|
||||
// of displayable ticks and symbols probably keep changing.
|
||||
if (startTick !== 0 && step > 1 && tickCount / step > 2) {
|
||||
startTick = Math.round(Math.ceil(startTick / step) * step);
|
||||
}
|
||||
// min max labels may be excluded if `startTick > 0`, but they should be always
|
||||
// included and the label display strategy is adopted uniformly later in `AxisBuilder`.
|
||||
if (startTick !== extent[0]) {
|
||||
addItemInternally(extent[0], true, true);
|
||||
}
|
||||
var tickValue = startTick;
|
||||
for (; tickValue <= extent[1]; tickValue += step) {
|
||||
addItemInternally(tickValue, false, tickValue === extent[0] || tickValue === extent[1]);
|
||||
}
|
||||
if (tickValue - step !== extent[1]) {
|
||||
addItemInternally(extent[1], true, true);
|
||||
}
|
||||
function addItemInternally(tickValue, offInterval, isExtentBoundary) {
|
||||
addItem({
|
||||
value: tickValue,
|
||||
offInterval: offInterval
|
||||
}, isExtentBoundary);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { round } from '../util/number.js';
|
||||
import { getScaleBreakHelper } from './break.js';
|
||||
import { getIntervalPrecision } from './helper.js';
|
||||
export function getMinorTicks(scale, splitNumber, breaks, scaleInterval) {
|
||||
var ticks = scale.getTicks({
|
||||
expandToNicedExtent: true
|
||||
});
|
||||
// NOTE: In log-scale, do not support minor ticks when breaks exist.
|
||||
// because currently log-scale minor ticks is calculated based on raw values
|
||||
// rather than log-transformed value, due to an odd effect when breaks exist.
|
||||
var minorTicks = [];
|
||||
var extent = scale.getExtent();
|
||||
for (var i = 1; i < ticks.length; i++) {
|
||||
var nextTick = ticks[i];
|
||||
var prevTick = ticks[i - 1];
|
||||
if (prevTick["break"] || nextTick["break"]) {
|
||||
// Do not build minor ticks to the adjacent ticks to breaks ticks,
|
||||
// since the interval might be irregular.
|
||||
continue;
|
||||
}
|
||||
var count = 0;
|
||||
var minorTicksGroup = [];
|
||||
var interval = nextTick.value - prevTick.value;
|
||||
var minorInterval = interval / splitNumber;
|
||||
var minorIntervalPrecision = getIntervalPrecision(minorInterval);
|
||||
while (count < splitNumber - 1) {
|
||||
var minorTick = round(prevTick.value + (count + 1) * minorInterval, minorIntervalPrecision);
|
||||
// For the first and last interval. The count may be less than splitNumber.
|
||||
if (minorTick > extent[0] && minorTick < extent[1]) {
|
||||
minorTicksGroup.push(minorTick);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
scaleBreakHelper && scaleBreakHelper.pruneTicksByBreak('auto', minorTicksGroup, breaks, function (value) {
|
||||
return value;
|
||||
}, scaleInterval, extent);
|
||||
minorTicks.push(minorTicksGroup);
|
||||
}
|
||||
return minorTicks;
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { assert, bind, each, extend, keys, noop } from 'zrender/lib/core/util.js';
|
||||
import { initExtentForUnion, isValidBoundsForExtent } from '../util/model.js';
|
||||
import { getScaleBreakHelper } from './break.js';
|
||||
import { error } from '../util/log.js';
|
||||
export var SCALE_EXTENT_KIND_EFFECTIVE = 0;
|
||||
export var SCALE_EXTENT_KIND_MAPPING = 1;
|
||||
var SCALE_MAPPER_METHOD_NAMES_MAP = {
|
||||
needTransform: 1,
|
||||
normalize: 1,
|
||||
scale: 1,
|
||||
transformIn: 1,
|
||||
transformOut: 1,
|
||||
contain: 1,
|
||||
getExtent: 1,
|
||||
getExtentUnsafe: 1,
|
||||
setExtent: 1,
|
||||
setExtent2: 1,
|
||||
getFilter: 1,
|
||||
sanitize: 1,
|
||||
getDefaultStartValue: 1,
|
||||
freeze: 1
|
||||
};
|
||||
var SCALE_MAPPER_METHOD_NAMES = keys(SCALE_MAPPER_METHOD_NAMES_MAP);
|
||||
export var SCALE_MAPPER_DEPTH_OUT_OF_BREAK = 2;
|
||||
export var SCALE_MAPPER_DEPTH_INNERMOST = 3;
|
||||
export function initBreakOrLinearMapper(
|
||||
// If input `null/undefined`, a mapper will be created.
|
||||
mapper, breakParsed, initialExtent) {
|
||||
var brk;
|
||||
mapper = mapper || {};
|
||||
var scaleBreakHelper = getScaleBreakHelper();
|
||||
if (scaleBreakHelper) {
|
||||
var brkMapper_1 = scaleBreakHelper.createBreakScaleMapper(breakParsed, initialExtent);
|
||||
if (brkMapper_1.hasBreaks()) {
|
||||
// Some `ScaleMapper` methods (such as `normalize`) needs to be fast for large data
|
||||
// when no breaks, so mount break methods only when breaks really exist.
|
||||
each(SCALE_MAPPER_METHOD_NAMES, function (methodName) {
|
||||
if (brkMapper_1[methodName]) {
|
||||
mapper[methodName] = bind(brkMapper_1[methodName], brkMapper_1);
|
||||
}
|
||||
});
|
||||
brk = brkMapper_1;
|
||||
}
|
||||
}
|
||||
if (brk == null) {
|
||||
initLinearScaleMapper(mapper, initialExtent);
|
||||
}
|
||||
return {
|
||||
brk: brk,
|
||||
mapper: mapper
|
||||
};
|
||||
}
|
||||
export function decorateScaleMapper(host, decoratedMapperMethods) {
|
||||
each(SCALE_MAPPER_METHOD_NAMES, function (methodName) {
|
||||
host[methodName] = decoratedMapperMethods[methodName];
|
||||
});
|
||||
}
|
||||
export function enableScaleMapperFreeze(host, subMapper) {
|
||||
host.freeze = noop;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
host.freeze = function () {
|
||||
subMapper.freeze();
|
||||
};
|
||||
}
|
||||
;
|
||||
}
|
||||
export function getScaleExtentForTickUnsafe(mapper) {
|
||||
return mapper.getExtentUnsafe(SCALE_EXTENT_KIND_EFFECTIVE, SCALE_MAPPER_DEPTH_OUT_OF_BREAK);
|
||||
}
|
||||
export function getScaleExtentForMappingUnsafe(mapper,
|
||||
// NullUndefined means the outermost space.
|
||||
depth) {
|
||||
return mapper.getExtentUnsafe(SCALE_EXTENT_KIND_MAPPING, depth) || mapper.getExtentUnsafe(SCALE_EXTENT_KIND_EFFECTIVE, depth);
|
||||
}
|
||||
export function getScaleLinearSpanForMapping(mapper) {
|
||||
var extent = getScaleExtentForMappingUnsafe(mapper, SCALE_MAPPER_DEPTH_INNERMOST);
|
||||
return extent[1] - extent[0];
|
||||
}
|
||||
export function getScaleLinearSpanEffective(mapper) {
|
||||
var extent = mapper.getExtentUnsafe(SCALE_EXTENT_KIND_EFFECTIVE, SCALE_MAPPER_DEPTH_INNERMOST);
|
||||
return extent[1] - extent[0];
|
||||
}
|
||||
export function initLinearScaleMapper(
|
||||
// If input `null/undefined`, a mapper will be created.
|
||||
mapper, initialExtent) {
|
||||
var linearMapper = mapper || {};
|
||||
var extendList = [];
|
||||
// @ts-ignore
|
||||
linearMapper._extents = extendList;
|
||||
extendList[SCALE_EXTENT_KIND_EFFECTIVE] = initialExtent ? initialExtent.slice() : initExtentForUnion();
|
||||
extend(linearMapper, linearScaleMapperMethods);
|
||||
return linearMapper;
|
||||
}
|
||||
var linearScaleMapperMethods = {
|
||||
needTransform: function () {
|
||||
return false;
|
||||
},
|
||||
normalize: function (val) {
|
||||
var extent = this._extents[SCALE_EXTENT_KIND_MAPPING] || this._extents[SCALE_EXTENT_KIND_EFFECTIVE];
|
||||
if (extent[1] === extent[0]) {
|
||||
return 0.5;
|
||||
}
|
||||
return (val - extent[0]) / (extent[1] - extent[0]);
|
||||
},
|
||||
scale: function (val) {
|
||||
var extent = this._extents[SCALE_EXTENT_KIND_MAPPING] || this._extents[SCALE_EXTENT_KIND_EFFECTIVE];
|
||||
return val * (extent[1] - extent[0]) + extent[0];
|
||||
},
|
||||
transformIn: function (val) {
|
||||
return val;
|
||||
},
|
||||
transformOut: function (val) {
|
||||
return val;
|
||||
},
|
||||
contain: function (val) {
|
||||
// This method is typically used in axis trigger and markers.
|
||||
// Users may be confused if the extent is restricted to `SCALE_EXTENT_KIND_EFFECTIVE`.
|
||||
var extent = getScaleExtentForMappingUnsafe(this, null);
|
||||
return val >= extent[0] && val <= extent[1];
|
||||
},
|
||||
getExtent: function () {
|
||||
return this._extents[SCALE_EXTENT_KIND_EFFECTIVE].slice();
|
||||
},
|
||||
getExtentUnsafe: function (kind) {
|
||||
return this._extents[kind];
|
||||
},
|
||||
setExtent: function (start, end) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
assert(!this._frozen);
|
||||
}
|
||||
writeExtent(this._extents, SCALE_EXTENT_KIND_EFFECTIVE, start, end);
|
||||
},
|
||||
setExtent2: function (kind, start, end) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
assert(!this._frozen);
|
||||
}
|
||||
var extentList = this._extents;
|
||||
if (!extentList[kind]) {
|
||||
extentList[kind] = extentList[SCALE_EXTENT_KIND_EFFECTIVE].slice();
|
||||
}
|
||||
writeExtent(extentList, kind, start, end);
|
||||
},
|
||||
freeze: function () {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// @ts-ignore
|
||||
this._frozen = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
function writeExtent(extentList, kind, start, end) {
|
||||
// NOTE: `NaN` should be excluded. e.g., `scaleRawExtentInfo.resultMinMax` may be `[NaN, NaN]`.
|
||||
if (isValidBoundsForExtent(start, end)) {
|
||||
extentList[kind][0] = start;
|
||||
extentList[kind][1] = end;
|
||||
} else {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// PENDING: should use `assert` after fixing all invalid calls.
|
||||
if (start != null && end != null && start <= end) {
|
||||
error("Invalid setExtent call - start: " + start + ", end: " + end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ------ END: Linear Scale Mapper ------
|
||||
Reference in New Issue
Block a user