UNPKG

klinecharts

Version:

Lightweight k-line chart built with html5 canvas

1,281 lines (1,227 loc) 670 kB
/** * @license * KLineChart v10.0.1 * Copyright (c) 2019 lihu. * Licensed under Apache License 2.0 https://www.apache.org/licenses/LICENSE-2.0 */ /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** * Licensed 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. */ // biome-ignore lint/suspicious/noExplicitAny: This recursive utility accepts arbitrary object shapes. function merge(target, source) { if (!isObject(target) && !isObject(source)) { return; } for (var key in source) { // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is unavailable for the ES5 target. if (Object.prototype.hasOwnProperty.call(source, key)) { var targetProp = target[key]; var sourceProp = source[key]; if (isObject(sourceProp) && isObject(targetProp)) { merge(targetProp, sourceProp); } else { target[key] = clone(sourceProp); } } } } function clone(target) { if (!isObject(target)) { return target; } // biome-ignore lint/suspicious/noExplicitAny: The cloned container is populated dynamically. var copy = null; if (isArray(target)) { copy = []; } else { copy = {}; } for (var key in target) { // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is unavailable for the ES5 target. if (Object.prototype.hasOwnProperty.call(target, key)) { var v = target[key]; if (isObject(v)) { copy[key] = clone(v); } else { copy[key] = v; } } } return copy; } function isArray(value) { return Object.prototype.toString.call(value) === '[object Array]'; } function isFunction(value) { return typeof value === 'function'; } function isObject(value) { return typeof value === 'object' && isValid(value); } function isNumber(value) { return typeof value === 'number' && Number.isFinite(value); } function isValid(value) { return value !== null && value !== undefined; } function isBoolean(value) { return typeof value === 'boolean'; } function isString(value) { return typeof value === 'string'; } /** * Licensed 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 DEFAULT_REQUEST_ID = -1; function requestAnimationFrame(fn) { if (isFunction(window.requestAnimationFrame)) { return window.requestAnimationFrame(fn); } return window.setTimeout(fn, 20); } function cancelAnimationFrame(id) { if (isFunction(window.cancelAnimationFrame)) { window.cancelAnimationFrame(id); } else { window.clearTimeout(id); } } /** * Licensed 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 Animation = /** @class */ (function () { function Animation(options) { this._options = { duration: 500, iterationCount: 1 }; this._currentIterationCount = 0; this._running = false; this._requestAnimationId = DEFAULT_REQUEST_ID; this._time = 0; merge(this._options, options); } Animation.prototype._loop = function () { var _this = this; this._running = true; this._time = performance.now(); var step = function (timestamp) { var _a; _this._requestAnimationId = DEFAULT_REQUEST_ID; if (_this._running) { var time = typeof timestamp === 'number' ? timestamp : performance.now(); var diffTime = Math.max(0, time - _this._time); if (diffTime < _this._options.duration) { (_a = _this._doFrameCallback) === null || _a === void 0 ? void 0 : _a.call(_this, diffTime); if (_this._running && _this._requestAnimationId === DEFAULT_REQUEST_ID) { _this._requestAnimationId = requestAnimationFrame(step); } } else { _this.stop(); _this._currentIterationCount++; if (_this._currentIterationCount < _this._options.iterationCount) { _this._loop(); } } } }; this._requestAnimationId = requestAnimationFrame(step); }; Animation.prototype.doFrame = function (callback) { this._doFrameCallback = callback; return this; }; Animation.prototype.setDuration = function (duration) { this._options.duration = duration; return this; }; Animation.prototype.setIterationCount = function (iterationCount) { this._options.iterationCount = iterationCount; return this; }; Animation.prototype.start = function () { if (!this._running) { this._currentIterationCount = 0; this._loop(); } }; Animation.prototype.stop = function () { var _a; if (this._running) { this.cancel(); (_a = this._doFrameCallback) === null || _a === void 0 ? void 0 : _a.call(this, this._options.duration); } this._running = false; }; Animation.prototype.cancel = function () { if (this._requestAnimationId !== DEFAULT_REQUEST_ID) { cancelAnimationFrame(this._requestAnimationId); this._requestAnimationId = DEFAULT_REQUEST_ID; } this._running = false; }; return Animation; }()); /** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function createDefaultBounding(bounding) { var defaultBounding = { width: 0, height: 0, left: 0, right: 0, top: 0, bottom: 0 }; if (isValid(bounding)) { merge(defaultBounding, bounding); } return defaultBounding; } /** * Licensed 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 measureCtx = null; /** * Get pixel ratio * @param canvas * @returns {number} */ function getPixelRatio(canvas) { var _a, _b; return (_b = (_a = canvas.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.devicePixelRatio) !== null && _b !== void 0 ? _b : 1; } function createFont(size, weight, family) { return "".concat(weight !== null && weight !== void 0 ? weight : 'normal', " ").concat(size !== null && size !== void 0 ? size : 12, "px ").concat(family !== null && family !== void 0 ? family : 'Helvetica Neue'); } /** * Measure the width of text * @param text * @returns {number} */ function calcTextWidth(text, size, weight, family) { if (!isValid(measureCtx)) { var canvas = document.createElement('canvas'); var pixelRatio = getPixelRatio(canvas); measureCtx = canvas.getContext('2d'); measureCtx.scale(pixelRatio, pixelRatio); } measureCtx.font = createFont(size, weight, family); return Math.round(measureCtx.measureText(text).width); } /** * Licensed 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. */ /** * Create dom * @param tagName * @param styles * @return {*} */ function createDom(tagName, styles) { var _a; var dom = document.createElement(tagName); var s = styles !== null && styles !== void 0 ? styles : {}; // biome-ignore lint/suspicious/useGuardForIn: CSSStyleDeclaration keys are copied intentionally. for (var key in s) { dom.style[key] = (_a = s[key]) !== null && _a !== void 0 ? _a : ''; } return dom; } /** * Licensed 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 baseId = 1; var prevIdTimestamp = Date.now(); function createId(prefix) { var timestamp = Date.now(); if (timestamp === prevIdTimestamp) { ++baseId; } else { baseId = 1; } prevIdTimestamp = timestamp; return "".concat(prefix !== null && prefix !== void 0 ? prefix : '').concat(timestamp, "_").concat(baseId); } /** * Licensed 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. */ // @ts-nocheck var DEV = process.env.NODE_ENV === 'development'; function log(templateText, tagStyle, messageStyle, api, invalidParam, append) { if (DEV) { var apiStr = api !== '' ? "Call api `".concat(api, "`").concat(invalidParam !== '' || append !== '' ? ', ' : '.') : ''; var invalidParamStr = invalidParam !== '' ? "invalid parameter `".concat(invalidParam, "`").concat(append !== '' ? ', ' : '.') : ''; var appendStr = append !== '' ? append : ''; console.log(templateText, tagStyle, messageStyle, apiStr, invalidParamStr, appendStr); } } function logWarn(api, invalidParam, append) { log('%c😑 klinecharts warning%c %s%s%s', 'padding:3px 4px;border-radius:2px;color:#ffffff;background-color:#FF9600', 'color:#FF9600', api, invalidParam, append !== null && append !== void 0 ? append : ''); } function logError(api, invalidParam, append) { log('%c😟 klinecharts error%c %s%s%s', 'padding:3px 4px;border-radius:2px;color:#ffffff;background-color:#F92855;', 'color:#F92855;', api, invalidParam, append ); } function logTag() { log('%c❤️ Welcome to klinecharts. Version is 10.0.1', 'border-radius:4px;border:dashed 1px #1677FF;line-height:70px;padding:0 20px;margin:16px 0;font-size:14px;color:#1677FF;', '', '', '', ''); } /** * Licensed 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. */ /** * Binary search for the nearest result * @param dataList * @param valueKey * @param targetValue * @return {number} */ function binarySearchNearest(dataList, valueKey, targetValue) { var left = 0; var right = 0; for (right = dataList.length - 1; left !== right;) { var midIndex = Math.floor((right + left) / 2); var mid = right - left; var midValue = dataList[midIndex][valueKey]; if (targetValue === dataList[left][valueKey]) { return left; } if (targetValue === dataList[right][valueKey]) { return right; } if (targetValue === midValue) { return midIndex; } if (targetValue > midValue) { left = midIndex; } else { right = midIndex; } if (mid <= 2) { break; } } return left; } /** * 优化数字 * @param value * @return {number|number} */ function nice(value) { var exponent = Math.floor(log10(value)); var exp10 = index10(exponent); var f = value / exp10; // 1 <= f < 10 var nf = 0; if (f < 1.5) { nf = 1; } else if (f < 2.5) { nf = 2; } else if (f < 3.5) { nf = 3; } else if (f < 4.5) { nf = 4; } else if (f < 5.5) { nf = 5; } else if (f < 6.5) { nf = 6; } else { nf = 8; } value = nf * exp10; return +value.toFixed(Math.abs(exponent)); } /** * Round * @param value * @param precision * @return {number} */ function round(value, precision) { precision = Math.max(0, precision !== null && precision !== void 0 ? precision : 0); var pow = Math.pow(10, precision); return Math.round(value * pow) / pow; } /** * Get precision * @param value * @return {number|number} */ function getPrecision(value) { var str = value.toString(); var eIndex = str.indexOf('e'); if (eIndex > 0) { var precision = +str.slice(eIndex + 1); return precision < 0 ? -precision : 0; } var dotIndex = str.indexOf('.'); return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; } function getMaxMin(dataList, maxKey, minKey) { var _a, _b; var maxMin = [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]; var dataLength = dataList.length; var index = 0; while (index < dataLength) { var data = dataList[index]; maxMin[0] = Math.max(((_a = data[maxKey]) !== null && _a !== void 0 ? _a : Number.MIN_SAFE_INTEGER), maxMin[0]); maxMin[1] = Math.min(((_b = data[minKey]) !== null && _b !== void 0 ? _b : Number.MAX_SAFE_INTEGER), maxMin[1]); ++index; } return maxMin; } /** * log10 * @param value * @return {number} */ function log10(value) { if (value === 0) { return 0; } return Math.log10(value); } /** * index 10 * @param value * @return {number} */ function index10(value) { return Math.pow(10, value); } /** * Licensed 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 SymbolDefaultPrecisionConstants = { PRICE: 2, VOLUME: 0 }; /** * Licensed 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 reEscapeChar = /\\(\\)?/g; var rePropName = new RegExp('[^.[\\]]+' + '|' + '\\[(?:' + '([^"\'][^[]*)' + '|' + '(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + ')\\]' + '|' + '(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))', 'g'); function formatValue(data, key, defaultValue) { if (isValid(data)) { var path_1 = []; key.replace(rePropName, function (subString) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } var k = subString; if (isValid(args[1])) { k = args[2].replace(reEscapeChar, '$1'); } else if (isValid(args[0])) { k = args[0].trim(); } path_1.push(k); return ''; }); var value = data; var index = 0; var length_1 = path_1.length; while (isValid(value) && index < length_1) { value = value === null || value === void 0 ? void 0 : value[path_1[index++]]; } return isValid(value) ? value : (defaultValue !== null && defaultValue !== void 0 ? defaultValue : '--'); } return defaultValue !== null && defaultValue !== void 0 ? defaultValue : '--'; } function formatTimestampToDateTime(dateTimeFormat, timestamp) { var date = {}; dateTimeFormat.formatToParts(new Date(timestamp)).forEach(function (_a) { var type = _a.type, value = _a.value; switch (type) { case 'year': { date.YYYY = value; break; } case 'month': { date.MM = value; break; } case 'day': { date.DD = value; break; } case 'hour': { date.HH = value === '24' ? '00' : value; break; } case 'minute': { date.mm = value; break; } case 'second': { date.ss = value; break; } } }); return date; } function formatTimestampByTemplate(dateTimeFormat, timestamp, template) { var date = formatTimestampToDateTime(dateTimeFormat, timestamp); return template.replace(/YYYY|MM|DD|HH|mm|ss/g, function (key) { return date[key]; }); } function formatPrecision(value, precision) { var v = +value; if (isNumber(v)) { return v.toFixed(precision !== null && precision !== void 0 ? precision : 2); } return "".concat(value); } function formatBigNumber(value) { var v = +value; if (isNumber(v)) { if (v > 1000000000) { return "".concat(+(v / 1000000000).toFixed(3), "B"); } if (v > 1000000) { return "".concat(+(v / 1000000).toFixed(3), "M"); } if (v > 1000) { return "".concat(+(v / 1000).toFixed(3), "K"); } } return "".concat(value); } function formatThousands(value, sign) { var vl = "".concat(value); if (sign.length === 0) { return vl; } if (vl.includes('.')) { var arr = vl.split('.'); return "".concat(arr[0].replace(/(\d)(?=(\d{3})+$)/g, function ($1) { return "".concat($1).concat(sign); }), ".").concat(arr[1]); } return vl.replace(/(\d)(?=(\d{3})+$)/g, function ($1) { return "".concat($1).concat(sign); }); } function formatFoldDecimal(value, threshold) { var vl = "".concat(value); var reg = new RegExp('\\.0{' + threshold + ',}[1-9][0-9]*$'); if (reg.test(vl)) { var result = vl.split('.'); var lastIndex = result.length - 1; var v = result[lastIndex]; var match = /0*/.exec(v); if (isValid(match)) { var count = match[0].length; result[lastIndex] = v.replace(/0*/, "0{".concat(count, "}")); return result.join('.'); } } return vl; } function formatTemplateString(template, params) { return template.replace(/\{(\w+)\}/g, function (_, key) { var value = params[key]; if (isValid(value)) { return value; } return "{".concat(key, "}"); }); } /** * Licensed 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 PaneIdConstants = { CANDLE: 'candle_pane', INDICATOR: 'indicator_pane_', X_AXIS: 'x_axis_pane' }; /** * Licensed 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 TICK_COUNT = 8; function getDefaultAxisRange() { return { from: 0, to: 0, range: 0, realFrom: 0, realTo: 0, realRange: 0, displayFrom: 0, displayTo: 0, displayRange: 0 }; } var AxisImp = /** @class */ (function () { function AxisImp(parent) { this.scrollZoomEnabled = true; this._range = getDefaultAxisRange(); this._prevRange = getDefaultAxisRange(); this._ticks = []; this._autoCalcTickFlag = true; this._parent = parent; } AxisImp.prototype.getParent = function () { return this._parent; }; AxisImp.prototype.buildTicks = function (force) { if (this._autoCalcTickFlag) { this._range = this.createRangeImp(); } if (this._prevRange.from !== this._range.from || this._prevRange.to !== this._range.to || force) { this._prevRange = this._range; this._ticks = this.createTicksImp(); return true; } return false; }; AxisImp.prototype.getTicks = function () { return this._ticks; }; AxisImp.prototype.setRange = function (range) { this._autoCalcTickFlag = false; this._range = range; }; AxisImp.prototype.getRange = function () { return this._range; }; AxisImp.prototype.setAutoCalcTickFlag = function (flag) { this._autoCalcTickFlag = flag; }; AxisImp.prototype.getAutoCalcTickFlag = function () { return this._autoCalcTickFlag; }; return AxisImp; }()); /** * Licensed 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 Y_AXIS_ID_PREFIX = 'yAxis_'; var YAxisImp = /** @class */ (function (_super) { __extends(YAxisImp, _super); function YAxisImp(parent, yAxis) { var _this = _super.call(this, parent) || this; _this.id = ''; _this.paneId = ''; _this.reverse = false; _this.inside = false; _this.position = 'right'; _this.gap = { top: 0.2, bottom: 0.1 }; _this.createRange = function (params) { return params.defaultRange; }; _this.minSpan = function (precision) { return index10(-precision); }; _this.valueToRealValue = function (value) { return value; }; _this.realValueToDisplayValue = function (value) { return value; }; _this.displayValueToRealValue = function (value) { return value; }; _this.realValueToValue = function (value) { return value; }; _this.displayValueToText = function (value, precision) { return formatPrecision(value, precision); }; var minSpan = yAxis.minSpan, valueToRealValue = yAxis.valueToRealValue, realValueToDisplayValue = yAxis.realValueToDisplayValue, displayValueToRealValue = yAxis.displayValueToRealValue, realValueToValue = yAxis.realValueToValue, displayValueToText = yAxis.displayValueToText, others = __rest(yAxis, ["minSpan", "valueToRealValue", "realValueToDisplayValue", "displayValueToRealValue", "realValueToValue", "displayValueToText"]); if (isFunction(minSpan)) { _this.minSpan = minSpan; } if (isFunction(valueToRealValue)) { _this.valueToRealValue = valueToRealValue; } if (isFunction(realValueToDisplayValue)) { _this.realValueToDisplayValue = realValueToDisplayValue; } if (isFunction(displayValueToRealValue)) { _this.displayValueToRealValue = displayValueToRealValue; } if (isFunction(realValueToValue)) { _this.realValueToValue = realValueToValue; } if (isFunction(displayValueToText)) { _this.displayValueToText = displayValueToText; } _this.override(others); return _this; } YAxisImp.prototype.override = function (yAxis) { var id = yAxis.id, name = yAxis.name, gap = yAxis.gap, others = __rest(yAxis, ["id", "name", "gap"]); if (isValid(id) && this.id.length === 0) { this.id = id; } if (!isString(this.name) && isString(name)) { this.name = name; } merge(this.gap, gap); merge(this, others); }; YAxisImp.prototype._getIndicatorsByYAxisIds = function () { var parent = this.getParent(); var ids = new Set([this.id]); if (parent.isManualYAxis(this.id)) { var defaultYAxisId = parent.getDefaultYAxisId(); if (isValid(defaultYAxisId)) { ids.add(defaultYAxisId); } } return parent .getChart() .getChartStore() .getIndicatorsByPaneId(parent.getId()) .filter(function (indicator) { return ids.has(indicator.yAxisId); }); }; YAxisImp.prototype._shouldUseCandleData = function () { var parent = this.getParent(); return this.isInCandle() && (parent.isDefaultYAxis(this.id) || parent.isManualYAxis(this.id)); }; YAxisImp.prototype.createRangeImp = function () { var _a, _b; var parent = this.getParent(); var chart = parent.getChart(); var chartStore = chart.getChartStore(); var paneId = parent.getId(); var min = Number.MAX_SAFE_INTEGER; var max = Number.MIN_SAFE_INTEGER; var shouldOhlc = false; var specifyMin = Number.MAX_SAFE_INTEGER; var specifyMax = Number.MIN_SAFE_INTEGER; var indicatorPrecision = Number.MAX_SAFE_INTEGER; var indicators = this._getIndicatorsByYAxisIds(); indicators.forEach(function (indicator) { shouldOhlc || (shouldOhlc = indicator.shouldOhlc); indicatorPrecision = Math.min(indicatorPrecision, indicator.precision); if (isNumber(indicator.minValue)) { specifyMin = Math.min(specifyMin, indicator.minValue); } if (isNumber(indicator.maxValue)) { specifyMax = Math.max(specifyMax, indicator.maxValue); } }); var precision = 4; var inCandle = this.isInCandle(); if (inCandle) { var pricePrecision = (_b = (_a = chartStore.getSymbol()) === null || _a === void 0 ? void 0 : _a.pricePrecision) !== null && _b !== void 0 ? _b : SymbolDefaultPrecisionConstants.PRICE; if (indicatorPrecision !== Number.MAX_SAFE_INTEGER) { precision = Math.min(indicatorPrecision, pricePrecision); } else { precision = pricePrecision; } } else { if (indicatorPrecision !== Number.MAX_SAFE_INTEGER) { precision = indicatorPrecision; } } var visibleRangeDataList = chartStore.getVisibleRangeDataList(); var candleStyles = chart.getStyles().candle; var isArea = candleStyles.type === 'area'; var areaValueKey = candleStyles.area.value; var shouldUseCandleData = this._shouldUseCandleData(); var shouldCompareHighLow = (shouldUseCandleData && !isArea) || (!inCandle && shouldOhlc); visibleRangeDataList.forEach(function (visibleData) { var dataIndex = visibleData.dataIndex; var data = visibleData.data.current; if (isValid(data)) { if (shouldCompareHighLow) { min = Math.min(min, data.low); max = Math.max(max, data.high); } if (shouldUseCandleData && isArea) { var value = data[areaValueKey]; if (isNumber(value)) { min = Math.min(min, value); max = Math.max(max, value); } } } indicators.forEach(function (_a) { var _b; var result = _a.result, figures = _a.figures; var data = (_b = result[dataIndex]) !== null && _b !== void 0 ? _b : {}; figures.forEach(function (figure) { var value = data[figure.key]; if (isNumber(value)) { min = Math.min(min, value); max = Math.max(max, value); } }); }); }); if (min !== Number.MAX_SAFE_INTEGER && max !== Number.MIN_SAFE_INTEGER) { min = Math.min(specifyMin, min); max = Math.max(specifyMax, max); } else { min = 0; max = 10; } var defaultDiff = max - min; var defaultRange = { from: min, to: max, range: defaultDiff, realFrom: min, realTo: max, realRange: defaultDiff, displayFrom: min, displayTo: max, displayRange: defaultDiff }; var range = this.createRange({ chart: chart, paneId: paneId, defaultRange: defaultRange }); var realFrom = range.realFrom; var realTo = range.realTo; var realRange = range.realRange; var minSpan = this.minSpan(precision); if (realFrom === realTo || realRange < minSpan) { var minCheck = specifyMin === realFrom; var maxCheck = specifyMax === realTo; var halfTickCount = TICK_COUNT / 2; realFrom = minCheck ? realFrom : maxCheck ? realFrom - TICK_COUNT * minSpan : realFrom - halfTickCount * minSpan; realTo = maxCheck ? realTo : minCheck ? realTo + TICK_COUNT * minSpan : realTo + halfTickCount * minSpan; } var height = this.getBounding().height; var _c = this.gap, top = _c.top, bottom = _c.bottom; var topRate = top; if (topRate >= 1) { topRate = topRate / height; } var bottomRate = bottom; if (bottomRate >= 1) { bottomRate = bottomRate / height; } realRange = realTo - realFrom; realFrom = realFrom - realRange * bottomRate; realTo = realTo + realRange * topRate; var from = this.realValueToValue(realFrom, { range: range }); var to = this.realValueToValue(realTo, { range: range }); var displayFrom = this.realValueToDisplayValue(realFrom, { range: range }); var displayTo = this.realValueToDisplayValue(realTo, { range: range }); return { from: from, to: to, range: to - from, realFrom: realFrom, realTo: realTo, realRange: realTo - realFrom, displayFrom: displayFrom, displayTo: displayTo, displayRange: displayTo - displayFrom }; }; /** * 是否是蜡烛图轴 * @return {boolean} */ YAxisImp.prototype.isInCandle = function () { return this.getParent().getId() === PaneIdConstants.CANDLE; }; /** * 是否从y轴0开始 * @return {boolean} */ YAxisImp.prototype.isFromZero = function () { return (this.position === 'left' && this.inside) || (this.position === 'right' && !this.inside); }; YAxisImp.prototype.createTicksImp = function () { var _this = this; var _a, _b; var range = this.getRange(); var displayFrom = range.displayFrom, displayTo = range.displayTo, displayRange = range.displayRange; var ticks = []; if (displayRange >= 0) { var interval = nice(displayRange / TICK_COUNT); var precision_1 = getPrecision(interval); var first = round(Math.ceil(displayFrom / interval) * interval, precision_1); var last = round(Math.floor(displayTo / interval) * interval, precision_1); var n = 0; var f = first; if (interval !== 0) { while (f <= last) { var v = f.toFixed(precision_1); ticks[n] = { text: v, coord: 0, value: v }; ++n; f += interval; } } } var pane = this.getParent(); var height = this.getBounding().height; var chartStore = pane.getChart().getChartStore(); var optimalTicks = []; var indicators = this._getIndicatorsByYAxisIds(); var styles = chartStore.getStyles(); var precision = 0; var shouldFormatBigNumber = false; if (this._shouldUseCandleData()) { precision = (_b = (_a = chartStore.getSymbol()) === null || _a === void 0 ? void 0 : _a.pricePrecision) !== null && _b !== void 0 ? _b : SymbolDefaultPrecisionConstants.PRICE; } else { indicators.forEach(function (indicator) { precision = Math.max(precision, indicator.precision); shouldFormatBigNumber || (shouldFormatBigNumber = indicator.shouldFormatBigNumber); }); } var formatter = chartStore.getInnerFormatter(); var thousandsSeparator = chartStore.getThousandsSeparator(); var decimalFold = chartStore.getDecimalFold(); var textHeight = styles.xAxis.tickText.size; var validY = NaN; ticks.forEach(function (_a) { var value = _a.value; var v = _this.displayValueToText(+value, precision); var y = _this.convertToPixel(_this.realValueToValue(_this.displayValueToRealValue(+value, { range: range }), { range: range })); if (shouldFormatBigNumber) { v = formatter.formatBigNumber(value); } v = decimalFold.format(thousandsSeparator.format(v)); var validYNumber = isNumber(validY); if (y > textHeight && y < height - textHeight && ((validYNumber && Math.abs(validY - y) > textHeight * 2) || !validYNumber)) { optimalTicks.push({ text: v, coord: y, value: value }); validY = y; } }); if (isFunction(this.createTicks)) { return this.createTicks({ range: this.getRange(), bounding: this.getBounding(), defaultTicks: optimalTicks }); } return optimalTicks; }; YAxisImp.prototype.getAutoSize = function () { var _a, _b; var pane = this.getParent(); var chart = pane.getChart(); var chartStore = chart.getChartStore(); var styles = chartStore.getStyles(); var yAxisStyles = styles.yAxis; var width = yAxisStyles.size; if (width !== 'auto') { return width; } var yAxisWidth = 0; if (yAxisStyles.show) { if (yAxisStyles.axisLine.show) { yAxisWidth += yAxisStyles.axisLine.size; } if (yAxisStyles.tickLine.show) { yAxisWidth += yAxisStyles.tickLine.length; } if (yAxisStyles.tickText.show) { var textWidth_1 = 0; this.getTicks().forEach(function (tick) { textWidth_1 = Math.max(textWidth_1, calcTextWidth(tick.text, yAxisStyles.tickText.size, yAxisStyles.tickText.weight, yAxisStyles.tickText.family)); }); yAxisWidth += yAxisStyles.tickText.marginStart + yAxisStyles.tickText.marginEnd + textWidth_1; } } var priceMarkStyles = styles.candle.priceMark; var lastPriceMarkTextVisible = priceMarkStyles.show && priceMarkStyles.last.show && priceMarkStyles.last.text.show; var lastPriceTextWidth = 0; var crosshairStyles = styles.crosshair; var crosshairHorizontalTextVisible = crosshairStyles.show && crosshairStyles.horizontal.show && crosshairStyles.horizontal.text.show; var crosshairHorizontalTextWidth = 0; if (lastPriceMarkTextVisible || crosshairHorizontalTextVisible) { var pricePrecision = (_b = (_a = chartStore.getSymbol()) === null || _a === void 0 ? void 0 : _a.pricePrecision) !== null && _b !== void 0 ? _b : SymbolDefaultPrecisionConstants.PRICE; var max = this.getRange().displayTo; if (lastPriceMarkTextVisible) { var dataList = chartStore.getDataList(); var data_1 = dataList[dataList.length - 1]; if (isValid(data_1)) { var _c = priceMarkStyles.last.text, paddingLeft = _c.paddingLeft, paddingRight = _c.paddingRight, size = _c.size, family = _c.family, weight = _c.weight; lastPriceTextWidth = paddingLeft + calcTextWidth(formatPrecision(data_1.close, pricePrecision), size, weight, family) + paddingRight; var formatExtendText_1 = chartStore.getInnerFormatter().formatExtendText; priceMarkStyles.last.extendTexts.forEach(function (item, index) { var text = formatExtendText_1({ type: 'last_price', data: data_1, index: index }); if (text.length > 0 && item.show) { lastPriceTextWidth = Math.max(lastPriceTextWidth, item.paddingLeft + calcTextWidth(text, item.size, item.weight, item.family) + item.paddingRight); } }); } } if (crosshairHorizontalTextVisible) { var indicators = this._getIndicatorsByYAxisIds(); var indicatorPrecision_1 = 0; var shouldFormatBigNumber_1 = false; indicators.forEach(function (indicator) { indicatorPrecision_1 = Math.max(indicator.precision, indicatorPrecision_1); shouldFormatBigNumber_1 || (shouldFormatBigNumber_1 = indicator.shouldFormatBigNumber); }); var precision = 2; if (this._shouldUseCandleData()) { var lastValueMarkStyles = styles.indicator.lastValueMark; if (lastValueMarkStyles.show && lastValueMarkStyles.text.show) { precision = Math.max(indicatorPrecision_1, pricePrecision); } else { precision = pricePrecision; } } else { precision = indicatorPrecision_1; } var valueText = formatPrecision(max, precision); if (shouldFormatBigNumber_1) { valueText = chartStore.getInnerFormatter().formatBigNumber(valueText); } valueText = chartStore.getDecimalFold().format(valueText); crosshairHorizontalTextWidth += crosshairStyles.horizontal.text.paddingLeft + crosshairStyles.horizontal.text.paddingRight + crosshairStyles.horizontal.text.borderSize * 2 + calcTextWidth(valueText, crosshairStyles.horizontal.text.size, crosshairStyles.horizontal.text.weight, crosshairStyles.horizontal.text.family); } } return Math.max(yAxisWidth, lastPriceTextWidth, crosshairHorizontalTextWidth); }; YAxisImp.prototype.getBounding = function () { var _a, _b; return (_b = (_a = this.getParent().getYAxisWidgetById(this.id)) === null || _a === void 0 ? void 0 : _a.getBounding()) !== null && _b !== void 0 ? _b : this.getParent().getMainWidget().getBounding(); }; YAxisImp.prototype.convertFromPixel = function (pixel) { var height = this.getBounding().height; var range = this.getRange(); var realFrom = range.realFrom, realRange = range.realRange; var rate = this.reverse ? pixel / height : 1 - pixel / height; var realValue = rate * realRange + realFrom