UNPKG

1.65 MBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.F2 = {}));
5}(this, (function (exports) { 'use strict';
6
7 /******************************************************************************
8 Copyright (c) Microsoft Corporation.
9
10 Permission to use, copy, modify, and/or distribute this software for any
11 purpose with or without fee is hereby granted.
12
13 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 PERFORMANCE OF THIS SOFTWARE.
20 ***************************************************************************** */
21 /* global Reflect, Promise, SuppressedError, Symbol */
22
23 var extendStatics = function(d, b) {
24 extendStatics = Object.setPrototypeOf ||
25 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
26 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
27 return extendStatics(d, b);
28 };
29
30 function __extends(d, b) {
31 if (typeof b !== "function" && b !== null)
32 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
33 extendStatics(d, b);
34 function __() { this.constructor = d; }
35 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
36 }
37
38 var __assign = function() {
39 __assign = Object.assign || function __assign(t) {
40 for (var s, i = 1, n = arguments.length; i < n; i++) {
41 s = arguments[i];
42 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
43 }
44 return t;
45 };
46 return __assign.apply(this, arguments);
47 };
48
49 function __rest(s, e) {
50 var t = {};
51 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52 t[p] = s[p];
53 if (s != null && typeof Object.getOwnPropertySymbols === "function")
54 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56 t[p[i]] = s[p[i]];
57 }
58 return t;
59 }
60
61 function __awaiter(thisArg, _arguments, P, generator) {
62 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
63 return new (P || (P = Promise))(function (resolve, reject) {
64 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
65 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
66 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
67 step((generator = generator.apply(thisArg, _arguments || [])).next());
68 });
69 }
70
71 function __generator(thisArg, body) {
72 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
73 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
74 function verb(n) { return function (v) { return step([n, v]); }; }
75 function step(op) {
76 if (f) throw new TypeError("Generator is already executing.");
77 while (g && (g = 0, op[0] && (_ = 0)), _) try {
78 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;
79 if (y = 0, t) op = [op[0] & 2, t.value];
80 switch (op[0]) {
81 case 0: case 1: t = op; break;
82 case 4: _.label++; return { value: op[1], done: false };
83 case 5: _.label++; y = op[1]; op = [0]; continue;
84 case 7: op = _.ops.pop(); _.trys.pop(); continue;
85 default:
86 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
87 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
88 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
89 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
90 if (t[2]) _.ops.pop();
91 _.trys.pop(); continue;
92 }
93 op = body.call(thisArg, _);
94 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
95 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
96 }
97 }
98
99 function __values(o) {
100 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
101 if (m) return m.call(o);
102 if (o && typeof o.length === "number") return {
103 next: function () {
104 if (o && i >= o.length) o = void 0;
105 return { value: o && o[i++], done: !o };
106 }
107 };
108 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
109 }
110
111 function __read(o, n) {
112 var m = typeof Symbol === "function" && o[Symbol.iterator];
113 if (!m) return o;
114 var i = m.call(o), r, ar = [], e;
115 try {
116 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
117 }
118 catch (error) { e = { error: error }; }
119 finally {
120 try {
121 if (r && !r.done && (m = i["return"])) m.call(i);
122 }
123 finally { if (e) throw e.error; }
124 }
125 return ar;
126 }
127
128 function __spreadArray(to, from, pack) {
129 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
130 if (ar || !(i in from)) {
131 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
132 ar[i] = from[i];
133 }
134 }
135 return to.concat(ar || Array.prototype.slice.call(from));
136 }
137
138 var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
139 var e = new Error(message);
140 return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
141 };
142
143 var isArrayLike = function (value) {
144 /**
145 * isArrayLike([1, 2, 3]) => true
146 * isArrayLike(document.body.children) => true
147 * isArrayLike('abc') => true
148 * isArrayLike(Function) => false
149 */
150 return value !== null && typeof value !== 'function' && isFinite(value.length);
151 };
152
153 var filter = function (arr, func) {
154 if (!isArrayLike(arr)) {
155 return arr;
156 }
157 var result = [];
158 for (var index = 0; index < arr.length; index++) {
159 var value = arr[index];
160 if (func(value, index)) {
161 result.push(value);
162 }
163 }
164 return result;
165 };
166
167 /**
168 * @see https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_isfunction
169 */
170 var isFunction = (function (value) {
171 return typeof value === 'function';
172 });
173
174 // isFinite,
175 var isNil = function (value) {
176 /**
177 * isNil(null) => true
178 * isNil() => true
179 */
180 return value === null || value === undefined;
181 };
182
183 var toString = {}.toString;
184 var isType = function (value, type) { return toString.call(value) === '[object ' + type + ']'; };
185
186 var isArray = (function (value) {
187 return Array.isArray ? Array.isArray(value) : isType(value, 'Array');
188 });
189
190 var isObject = (function (value) {
191 /**
192 * isObject({}) => true
193 * isObject([1, 2, 3]) => true
194 * isObject(Function) => true
195 * isObject(null) => false
196 */
197 var type = typeof value;
198 return (value !== null && type === 'object') || type === 'function';
199 });
200
201 function each(elements, func) {
202 if (!elements) {
203 return;
204 }
205 var rst;
206 if (isArray(elements)) {
207 for (var i = 0, len = elements.length; i < len; i++) {
208 rst = func(elements[i], i);
209 if (rst === false) {
210 break;
211 }
212 }
213 }
214 else if (isObject(elements)) {
215 for (var k in elements) {
216 if (elements.hasOwnProperty(k)) {
217 rst = func(elements[k], k);
218 if (rst === false) {
219 break;
220 }
221 }
222 }
223 }
224 }
225
226 var keys = Object.keys
227 ? function (obj) { return Object.keys(obj); }
228 : function (obj) {
229 var result = [];
230 each(obj, function (value, key) {
231 if (!(isFunction(obj) && key === 'prototype')) {
232 result.push(key);
233 }
234 });
235 return result;
236 };
237
238 function isMatch(obj, attrs) {
239 var _keys = keys(attrs);
240 var length = _keys.length;
241 if (isNil(obj))
242 return !length;
243 for (var i = 0; i < length; i += 1) {
244 var key = _keys[i];
245 if (attrs[key] !== obj[key] || !(key in obj)) {
246 return false;
247 }
248 }
249 return true;
250 }
251
252 var isObjectLike = function (value) {
253 /**
254 * isObjectLike({}) => true
255 * isObjectLike([1, 2, 3]) => true
256 * isObjectLike(Function) => false
257 * isObjectLike(null) => false
258 */
259 return typeof value === 'object' && value !== null;
260 };
261
262 var isPlainObject = function (value) {
263 /**
264 * isObjectLike(new Foo) => false
265 * isObjectLike([1, 2, 3]) => false
266 * isObjectLike({ x: 0, y: 0 }) => true
267 * isObjectLike(Object.create(null)) => true
268 */
269 if (!isObjectLike(value) || !isType(value, 'Object')) {
270 return false;
271 }
272 if (Object.getPrototypeOf(value) === null) {
273 return true;
274 }
275 var proto = value;
276 while (Object.getPrototypeOf(proto) !== null) {
277 proto = Object.getPrototypeOf(proto);
278 }
279 return Object.getPrototypeOf(value) === proto;
280 };
281
282 function find(arr, predicate) {
283 if (!isArray(arr))
284 return null;
285 var _predicate;
286 if (isFunction(predicate)) {
287 _predicate = predicate;
288 }
289 if (isPlainObject(predicate)) {
290 _predicate = function (a) { return isMatch(a, predicate); };
291 }
292 if (_predicate) {
293 for (var i = 0; i < arr.length; i += 1) {
294 if (_predicate(arr[i])) {
295 return arr[i];
296 }
297 }
298 }
299 return null;
300 }
301
302 function findIndex(arr, predicate, fromIndex) {
303 if (fromIndex === void 0) { fromIndex = 0; }
304 for (var i = fromIndex; i < arr.length; i++) {
305 if (predicate(arr[i], i)) {
306 // 找到终止循环
307 return i;
308 }
309 }
310 return -1;
311 }
312
313 /**
314 * Flattens `array` a single level deep.
315 *
316 * @param {Array} arr The array to flatten.
317 * @return {Array} Returns the new flattened array.
318 * @example
319 *
320 * flatten([1, [2, [3, [4]], 5]]); // => [1, 2, [3, [4]], 5]
321 */
322 var flatten = function (arr) {
323 if (!isArray(arr)) {
324 return [];
325 }
326 var rst = [];
327 for (var i = 0; i < arr.length; i++) {
328 rst = rst.concat(arr[i]);
329 }
330 return rst;
331 };
332
333 /**
334 * @param {Array} arr The array to iterate over.
335 * @return {*} Returns the maximum value.
336 * @example
337 *
338 * max([1, 2]);
339 * // => 2
340 *
341 * max([]);
342 * // => undefined
343 *
344 * const data = new Array(1250010).fill(1).map((d,idx) => idx);
345 *
346 * max(data);
347 * // => 1250010
348 * // Math.max(...data) will encounter "Maximum call stack size exceeded" error
349 */
350 var max = (function (arr) {
351 if (!isArray(arr)) {
352 return undefined;
353 }
354 return arr.reduce(function (prev, curr) {
355 return Math.max(prev, curr);
356 }, arr[0]);
357 });
358
359 /**
360 * @param {Array} arr The array to iterate over.
361 * @return {*} Returns the minimum value.
362 * @example
363 *
364 * min([1, 2]);
365 * // => 1
366 *
367 * min([]);
368 * // => undefined
369 *
370 * const data = new Array(1250010).fill(1).map((d,idx) => idx);
371 *
372 * min(data);
373 * // => 1250010
374 * // Math.min(...data) will encounter "Maximum call stack size exceeded" error
375 */
376 var min = (function (arr) {
377 if (!isArray(arr)) {
378 return undefined;
379 }
380 return arr.reduce(function (prev, curr) {
381 return Math.min(prev, curr);
382 }, arr[0]);
383 });
384
385 var getRange = function (values) {
386 // 存在 NaN 时,min,max 判定会出问题
387 var filterValues = values.filter(function (v) { return !isNaN(v); });
388 if (!filterValues.length) {
389 // 如果没有数值则直接返回0
390 return {
391 min: 0,
392 max: 0,
393 };
394 }
395 if (isArray(values[0])) {
396 var tmp = [];
397 for (var i = 0; i < values.length; i++) {
398 tmp = tmp.concat(values[i]);
399 }
400 filterValues = tmp;
401 }
402 var max$1 = max(filterValues);
403 var min$1 = min(filterValues);
404 return {
405 min: min$1,
406 max: max$1,
407 };
408 };
409
410 var reduce = function (arr, fn, init) {
411 if (!isArray(arr) && !isPlainObject(arr)) {
412 return arr;
413 }
414 var result = init;
415 each(arr, function (data, i) {
416 result = fn(result, data, i);
417 });
418 return result;
419 };
420
421 var isString = (function (str) {
422 return isType(str, 'String');
423 });
424
425 var valuesOfKey = (function (data, name) {
426 var rst = [];
427 var tmpMap = {};
428 for (var i = 0; i < data.length; i++) {
429 var obj = data[i];
430 var value = obj[name];
431 if (!isNil(value)) {
432 // flatten
433 if (!isArray(value)) {
434 value = [value];
435 }
436 for (var j = 0; j < value.length; j++) {
437 var val = value[j];
438 // unique
439 if (!tmpMap[val]) {
440 rst.push(val);
441 tmpMap[val] = true;
442 }
443 }
444 }
445 }
446 return rst;
447 });
448
449 function head(o) {
450 if (isArrayLike(o)) {
451 return o[0];
452 }
453 return undefined;
454 }
455
456 function last(o) {
457 if (isArrayLike(o)) {
458 var arr = o;
459 return arr[arr.length - 1];
460 }
461 return undefined;
462 }
463
464 var hasOwnProperty = Object.prototype.hasOwnProperty;
465 function groupBy(data, condition) {
466 if (!condition || !isArray(data)) {
467 return {};
468 }
469 var result = {};
470 // 兼容方法和 字符串的写法
471 var predicate = isFunction(condition) ? condition : function (item) { return item[condition]; };
472 var key;
473 for (var i = 0; i < data.length; i++) {
474 var item = data[i];
475 key = predicate(item);
476 if (hasOwnProperty.call(result, key)) {
477 result[key].push(item);
478 }
479 else {
480 result[key] = [item];
481 }
482 }
483 return result;
484 }
485
486 /**
487 * 将数据分组成 map
488 * @param data
489 * @param condition
490 */
491 function groupToMap(data, condition) {
492 if (!condition) {
493 return {
494 0: data,
495 };
496 }
497 if (!isFunction(condition)) {
498 // 如果是字符串,则按照 a*b 风格成数组
499 var paramscondition_1 = isArray(condition) ? condition : condition.replace(/\s+/g, '').split('*');
500 condition = function (row) {
501 var unique = '_'; // 避免出现数字作为Key的情况,会进行按照数字的排序
502 // 根据字段列表的值,拼接成 key
503 for (var i = 0, l = paramscondition_1.length; i < l; i++) {
504 unique += row[paramscondition_1[i]] && row[paramscondition_1[i]].toString();
505 }
506 return unique;
507 };
508 }
509 return groupBy(data, condition);
510 }
511
512 var group = (function (data, condition) {
513 if (!condition) {
514 // 没有条件,则自身改成数组
515 return [data];
516 }
517 var groups = groupToMap(data, condition);
518 var array = [];
519 for (var i in groups) {
520 array.push(groups[i]);
521 }
522 return array;
523 });
524
525 var clamp = function (a, min, max) {
526 if (a < min) {
527 return min;
528 }
529 else if (a > max) {
530 return max;
531 }
532 return a;
533 };
534
535 /**
536 * 判断是否数字
537 * @return {Boolean} 是否数字
538 */
539 var isNumber = function (value) {
540 return isType(value, 'Number');
541 };
542
543 var PRECISION = 0.00001; // numbers less than this is considered as 0
544 function isNumberEqual(a, b, precision) {
545 if (precision === void 0) { precision = PRECISION; }
546 return Math.abs(a - b) < precision;
547 }
548
549 var mod = function (n, m) {
550 return ((n % m) + m) % m;
551 };
552
553 var toString$1 = (function (value) {
554 if (isNil(value))
555 return '';
556 return value.toString();
557 });
558
559 var upperFirst = function (value) {
560 var str = toString$1(value);
561 return str.charAt(0).toUpperCase() + str.substring(1);
562 };
563
564 var toString$2 = {}.toString;
565 var getType = function (value) {
566 return toString$2
567 .call(value)
568 .replace(/^\[object /, '')
569 .replace(/]$/, '');
570 };
571
572 /**
573 * 是否是布尔类型
574 *
575 * @param {Object} value 测试的值
576 * @return {Boolean}
577 */
578 var isBoolean = function (value) {
579 return isType(value, 'Boolean');
580 };
581
582 var isDate = function (value) {
583 return isType(value, 'Date');
584 };
585
586 var isNull = function (value) {
587 return value === null;
588 };
589
590 var objectProto = Object.prototype;
591 var isPrototype = function (value) {
592 var Ctor = value && value.constructor;
593 var proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto;
594 return value === proto;
595 };
596
597 var isUndefined = function (value) {
598 return value === undefined;
599 };
600
601 // FIXME: Mutable param should be forbidden in static lang.
602 function _mix(dist, obj) {
603 for (var key in obj) {
604 if (obj.hasOwnProperty(key) && key !== 'constructor' && obj[key] !== undefined) {
605 dist[key] = obj[key];
606 }
607 }
608 }
609 function mix(dist, src1, src2, src3) {
610 if (src1)
611 _mix(dist, src1);
612 if (src2)
613 _mix(dist, src2);
614 if (src3)
615 _mix(dist, src3);
616 return dist;
617 }
618
619 var clone = function (obj) {
620 if (typeof obj !== 'object' || obj === null) {
621 return obj;
622 }
623 var rst;
624 if (isArray(obj)) {
625 rst = [];
626 for (var i = 0, l = obj.length; i < l; i++) {
627 if (typeof obj[i] === 'object' && obj[i] != null) {
628 rst[i] = clone(obj[i]);
629 }
630 else {
631 rst[i] = obj[i];
632 }
633 }
634 }
635 else {
636 rst = {};
637 for (var k in obj) {
638 if (typeof obj[k] === 'object' && obj[k] != null) {
639 rst[k] = clone(obj[k]);
640 }
641 else {
642 rst[k] = obj[k];
643 }
644 }
645 }
646 return rst;
647 };
648
649 var MAX_MIX_LEVEL = 5;
650 function hasOwn(object, property) {
651 if (Object.hasOwn) {
652 return Object.hasOwn(object, property);
653 }
654 if (object == null) {
655 throw new TypeError('Cannot convert undefined or null to object');
656 }
657 return Object.prototype.hasOwnProperty.call(Object(object), property);
658 }
659 function _deepMix(dist, src, level, maxLevel) {
660 level = level || 0;
661 maxLevel = maxLevel || MAX_MIX_LEVEL;
662 for (var key in src) {
663 if (hasOwn(src, key)) {
664 var value = src[key];
665 if (value !== null && isPlainObject(value)) {
666 if (!isPlainObject(dist[key])) {
667 dist[key] = {};
668 }
669 if (level < maxLevel) {
670 _deepMix(dist[key], value, level + 1, maxLevel);
671 }
672 else {
673 dist[key] = src[key];
674 }
675 }
676 else if (isArray(value)) {
677 dist[key] = [];
678 dist[key] = dist[key].concat(value);
679 }
680 else if (value !== undefined) {
681 dist[key] = value;
682 }
683 }
684 }
685 }
686 // todo 重写
687 var deepMix = function (rst) {
688 var args = [];
689 for (var _i = 1; _i < arguments.length; _i++) {
690 args[_i - 1] = arguments[_i];
691 }
692 for (var i = 0; i < args.length; i += 1) {
693 _deepMix(rst, args[i]);
694 }
695 return rst;
696 };
697
698 var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
699 function isEmpty(value) {
700 /**
701 * isEmpty(null) => true
702 * isEmpty() => true
703 * isEmpty(true) => true
704 * isEmpty(1) => true
705 * isEmpty([1, 2, 3]) => false
706 * isEmpty('abc') => false
707 * isEmpty({ a: 1 }) => false
708 */
709 if (isNil(value)) {
710 return true;
711 }
712 if (isArrayLike(value)) {
713 return !value.length;
714 }
715 var type = getType(value);
716 if (type === 'Map' || type === 'Set') {
717 return !value.size;
718 }
719 if (isPrototype(value)) {
720 return !Object.keys(value).length;
721 }
722 for (var key in value) {
723 if (hasOwnProperty$1.call(value, key)) {
724 return false;
725 }
726 }
727 return true;
728 }
729
730 var isEqual = function (value, other) {
731 if (value === other) {
732 return true;
733 }
734 if (!value || !other) {
735 return false;
736 }
737 if (isString(value) || isString(other)) {
738 return false;
739 }
740 if (isArrayLike(value) || isArrayLike(other)) {
741 if (value.length !== other.length) {
742 return false;
743 }
744 var rst = true;
745 for (var i = 0; i < value.length; i++) {
746 rst = isEqual(value[i], other[i]);
747 if (!rst) {
748 break;
749 }
750 }
751 return rst;
752 }
753 if (isObjectLike(value) || isObjectLike(other)) {
754 var valueKeys = Object.keys(value);
755 var otherKeys = Object.keys(other);
756 if (valueKeys.length !== otherKeys.length) {
757 return false;
758 }
759 var rst = true;
760 for (var i = 0; i < valueKeys.length; i++) {
761 rst = isEqual(value[valueKeys[i]], other[valueKeys[i]]);
762 if (!rst) {
763 break;
764 }
765 }
766 return rst;
767 }
768 return false;
769 };
770
771 var map = function (arr, func) {
772 if (!isArrayLike(arr)) {
773 // @ts-ignore
774 return arr;
775 }
776 var result = [];
777 for (var index = 0; index < arr.length; index++) {
778 var value = arr[index];
779 result.push(func(value, index));
780 }
781 return result;
782 };
783
784 var identity = function (v) { return v; };
785 var mapValues = (function (object, func) {
786 if (func === void 0) { func = identity; }
787 var r = {};
788 if (isObject(object) && !isNil(object)) {
789 Object.keys(object).forEach(function (key) {
790 // @ts-ignore
791 r[key] = func(object[key], key);
792 });
793 }
794 return r;
795 });
796
797 /**
798 * https://github.com/developit/dlv/blob/master/index.js
799 * @param obj
800 * @param key
801 * @param defaultValue
802 */
803 var get = (function (obj, key, defaultValue) {
804 var p = 0;
805 var keyArr = isString(key) ? key.split('.') : key;
806 while (obj && p < keyArr.length) {
807 obj = obj[keyArr[p++]];
808 }
809 return obj === undefined || p < keyArr.length ? defaultValue : obj;
810 });
811
812 var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
813 var pick = (function (object, keys) {
814 if (object === null || !isPlainObject(object)) {
815 return {};
816 }
817 var result = {};
818 each(keys, function (key) {
819 if (hasOwnProperty$2.call(object, key)) {
820 result[key] = object[key];
821 }
822 });
823 return result;
824 });
825
826 var omit = (function (obj, keys) {
827 return reduce(obj, function (r, curr, key) {
828 if (!keys.includes(key)) {
829 r[key] = curr;
830 }
831 return r;
832 }, {});
833 });
834
835 /**
836 * k-v 存储
837 */
838 var default_1 = /** @class */ (function () {
839 function default_1() {
840 this.map = {};
841 }
842 default_1.prototype.has = function (key) {
843 return this.map[key] !== undefined;
844 };
845 default_1.prototype.get = function (key, def) {
846 var v = this.map[key];
847 return v === undefined ? def : v;
848 };
849 default_1.prototype.set = function (key, value) {
850 this.map[key] = value;
851 };
852 default_1.prototype.clear = function () {
853 this.map = {};
854 };
855 default_1.prototype.delete = function (key) {
856 delete this.map[key];
857 };
858 default_1.prototype.size = function () {
859 return Object.keys(this.map).length;
860 };
861 return default_1;
862 }());
863
864 /**
865 * Common utilities
866 * @module glMatrix
867 */
868 // Configuration Constants
869 var EPSILON = 0.000001;
870 var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
871 if (!Math.hypot) Math.hypot = function () {
872 var y = 0,
873 i = arguments.length;
874
875 while (i--) {
876 y += arguments[i] * arguments[i];
877 }
878
879 return Math.sqrt(y);
880 };
881
882 /**
883 * Rotates a mat2d by the given angle
884 *
885 * @param {mat2d} out the receiving matrix
886 * @param {ReadonlyMat2d} a the matrix to rotate
887 * @param {Number} rad the angle to rotate the matrix by
888 * @returns {mat2d} out
889 */
890
891 function rotate(out, a, rad) {
892 var a0 = a[0],
893 a1 = a[1],
894 a2 = a[2],
895 a3 = a[3],
896 a4 = a[4],
897 a5 = a[5];
898 var s = Math.sin(rad);
899 var c = Math.cos(rad);
900 out[0] = a0 * c + a2 * s;
901 out[1] = a1 * c + a3 * s;
902 out[2] = a0 * -s + a2 * c;
903 out[3] = a1 * -s + a3 * c;
904 out[4] = a4;
905 out[5] = a5;
906 return out;
907 }
908
909 /**
910 * 3x3 Matrix
911 * @module mat3
912 */
913
914 /**
915 * Creates a new identity mat3
916 *
917 * @returns {mat3} a new 3x3 matrix
918 */
919
920 function create() {
921 var out = new ARRAY_TYPE(9);
922
923 if (ARRAY_TYPE != Float32Array) {
924 out[1] = 0;
925 out[2] = 0;
926 out[3] = 0;
927 out[5] = 0;
928 out[6] = 0;
929 out[7] = 0;
930 }
931
932 out[0] = 1;
933 out[4] = 1;
934 out[8] = 1;
935 return out;
936 }
937 /**
938 * Copies the upper-left 3x3 values into the given mat3.
939 *
940 * @param {mat3} out the receiving 3x3 matrix
941 * @param {ReadonlyMat4} a the source 4x4 matrix
942 * @returns {mat3} out
943 */
944
945 function fromMat4(out, a) {
946 out[0] = a[0];
947 out[1] = a[1];
948 out[2] = a[2];
949 out[3] = a[4];
950 out[4] = a[5];
951 out[5] = a[6];
952 out[6] = a[8];
953 out[7] = a[9];
954 out[8] = a[10];
955 return out;
956 }
957 /**
958 * Create a new mat3 with the given values
959 *
960 * @param {Number} m00 Component in column 0, row 0 position (index 0)
961 * @param {Number} m01 Component in column 0, row 1 position (index 1)
962 * @param {Number} m02 Component in column 0, row 2 position (index 2)
963 * @param {Number} m10 Component in column 1, row 0 position (index 3)
964 * @param {Number} m11 Component in column 1, row 1 position (index 4)
965 * @param {Number} m12 Component in column 1, row 2 position (index 5)
966 * @param {Number} m20 Component in column 2, row 0 position (index 6)
967 * @param {Number} m21 Component in column 2, row 1 position (index 7)
968 * @param {Number} m22 Component in column 2, row 2 position (index 8)
969 * @returns {mat3} A new mat3
970 */
971
972 function fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
973 var out = new ARRAY_TYPE(9);
974 out[0] = m00;
975 out[1] = m01;
976 out[2] = m02;
977 out[3] = m10;
978 out[4] = m11;
979 out[5] = m12;
980 out[6] = m20;
981 out[7] = m21;
982 out[8] = m22;
983 return out;
984 }
985
986 /**
987 * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.
988 * @module mat4
989 */
990
991 /**
992 * Creates a new identity mat4
993 *
994 * @returns {mat4} a new 4x4 matrix
995 */
996
997 function create$1() {
998 var out = new ARRAY_TYPE(16);
999
1000 if (ARRAY_TYPE != Float32Array) {
1001 out[1] = 0;
1002 out[2] = 0;
1003 out[3] = 0;
1004 out[4] = 0;
1005 out[6] = 0;
1006 out[7] = 0;
1007 out[8] = 0;
1008 out[9] = 0;
1009 out[11] = 0;
1010 out[12] = 0;
1011 out[13] = 0;
1012 out[14] = 0;
1013 }
1014
1015 out[0] = 1;
1016 out[5] = 1;
1017 out[10] = 1;
1018 out[15] = 1;
1019 return out;
1020 }
1021 /**
1022 * Creates a new mat4 initialized with values from an existing matrix
1023 *
1024 * @param {ReadonlyMat4} a matrix to clone
1025 * @returns {mat4} a new 4x4 matrix
1026 */
1027
1028 function clone$1(a) {
1029 var out = new ARRAY_TYPE(16);
1030 out[0] = a[0];
1031 out[1] = a[1];
1032 out[2] = a[2];
1033 out[3] = a[3];
1034 out[4] = a[4];
1035 out[5] = a[5];
1036 out[6] = a[6];
1037 out[7] = a[7];
1038 out[8] = a[8];
1039 out[9] = a[9];
1040 out[10] = a[10];
1041 out[11] = a[11];
1042 out[12] = a[12];
1043 out[13] = a[13];
1044 out[14] = a[14];
1045 out[15] = a[15];
1046 return out;
1047 }
1048 /**
1049 * Copy the values from one mat4 to another
1050 *
1051 * @param {mat4} out the receiving matrix
1052 * @param {ReadonlyMat4} a the source matrix
1053 * @returns {mat4} out
1054 */
1055
1056 function copy(out, a) {
1057 out[0] = a[0];
1058 out[1] = a[1];
1059 out[2] = a[2];
1060 out[3] = a[3];
1061 out[4] = a[4];
1062 out[5] = a[5];
1063 out[6] = a[6];
1064 out[7] = a[7];
1065 out[8] = a[8];
1066 out[9] = a[9];
1067 out[10] = a[10];
1068 out[11] = a[11];
1069 out[12] = a[12];
1070 out[13] = a[13];
1071 out[14] = a[14];
1072 out[15] = a[15];
1073 return out;
1074 }
1075 /**
1076 * Create a new mat4 with the given values
1077 *
1078 * @param {Number} m00 Component in column 0, row 0 position (index 0)
1079 * @param {Number} m01 Component in column 0, row 1 position (index 1)
1080 * @param {Number} m02 Component in column 0, row 2 position (index 2)
1081 * @param {Number} m03 Component in column 0, row 3 position (index 3)
1082 * @param {Number} m10 Component in column 1, row 0 position (index 4)
1083 * @param {Number} m11 Component in column 1, row 1 position (index 5)
1084 * @param {Number} m12 Component in column 1, row 2 position (index 6)
1085 * @param {Number} m13 Component in column 1, row 3 position (index 7)
1086 * @param {Number} m20 Component in column 2, row 0 position (index 8)
1087 * @param {Number} m21 Component in column 2, row 1 position (index 9)
1088 * @param {Number} m22 Component in column 2, row 2 position (index 10)
1089 * @param {Number} m23 Component in column 2, row 3 position (index 11)
1090 * @param {Number} m30 Component in column 3, row 0 position (index 12)
1091 * @param {Number} m31 Component in column 3, row 1 position (index 13)
1092 * @param {Number} m32 Component in column 3, row 2 position (index 14)
1093 * @param {Number} m33 Component in column 3, row 3 position (index 15)
1094 * @returns {mat4} A new mat4
1095 */
1096
1097 function fromValues$1(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
1098 var out = new ARRAY_TYPE(16);
1099 out[0] = m00;
1100 out[1] = m01;
1101 out[2] = m02;
1102 out[3] = m03;
1103 out[4] = m10;
1104 out[5] = m11;
1105 out[6] = m12;
1106 out[7] = m13;
1107 out[8] = m20;
1108 out[9] = m21;
1109 out[10] = m22;
1110 out[11] = m23;
1111 out[12] = m30;
1112 out[13] = m31;
1113 out[14] = m32;
1114 out[15] = m33;
1115 return out;
1116 }
1117 /**
1118 * Set the components of a mat4 to the given values
1119 *
1120 * @param {mat4} out the receiving matrix
1121 * @param {Number} m00 Component in column 0, row 0 position (index 0)
1122 * @param {Number} m01 Component in column 0, row 1 position (index 1)
1123 * @param {Number} m02 Component in column 0, row 2 position (index 2)
1124 * @param {Number} m03 Component in column 0, row 3 position (index 3)
1125 * @param {Number} m10 Component in column 1, row 0 position (index 4)
1126 * @param {Number} m11 Component in column 1, row 1 position (index 5)
1127 * @param {Number} m12 Component in column 1, row 2 position (index 6)
1128 * @param {Number} m13 Component in column 1, row 3 position (index 7)
1129 * @param {Number} m20 Component in column 2, row 0 position (index 8)
1130 * @param {Number} m21 Component in column 2, row 1 position (index 9)
1131 * @param {Number} m22 Component in column 2, row 2 position (index 10)
1132 * @param {Number} m23 Component in column 2, row 3 position (index 11)
1133 * @param {Number} m30 Component in column 3, row 0 position (index 12)
1134 * @param {Number} m31 Component in column 3, row 1 position (index 13)
1135 * @param {Number} m32 Component in column 3, row 2 position (index 14)
1136 * @param {Number} m33 Component in column 3, row 3 position (index 15)
1137 * @returns {mat4} out
1138 */
1139
1140 function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {
1141 out[0] = m00;
1142 out[1] = m01;
1143 out[2] = m02;
1144 out[3] = m03;
1145 out[4] = m10;
1146 out[5] = m11;
1147 out[6] = m12;
1148 out[7] = m13;
1149 out[8] = m20;
1150 out[9] = m21;
1151 out[10] = m22;
1152 out[11] = m23;
1153 out[12] = m30;
1154 out[13] = m31;
1155 out[14] = m32;
1156 out[15] = m33;
1157 return out;
1158 }
1159 /**
1160 * Set a mat4 to the identity matrix
1161 *
1162 * @param {mat4} out the receiving matrix
1163 * @returns {mat4} out
1164 */
1165
1166 function identity$1(out) {
1167 out[0] = 1;
1168 out[1] = 0;
1169 out[2] = 0;
1170 out[3] = 0;
1171 out[4] = 0;
1172 out[5] = 1;
1173 out[6] = 0;
1174 out[7] = 0;
1175 out[8] = 0;
1176 out[9] = 0;
1177 out[10] = 1;
1178 out[11] = 0;
1179 out[12] = 0;
1180 out[13] = 0;
1181 out[14] = 0;
1182 out[15] = 1;
1183 return out;
1184 }
1185 /**
1186 * Transpose the values of a mat4
1187 *
1188 * @param {mat4} out the receiving matrix
1189 * @param {ReadonlyMat4} a the source matrix
1190 * @returns {mat4} out
1191 */
1192
1193 function transpose(out, a) {
1194 // If we are transposing ourselves we can skip a few steps but have to cache some values
1195 if (out === a) {
1196 var a01 = a[1],
1197 a02 = a[2],
1198 a03 = a[3];
1199 var a12 = a[6],
1200 a13 = a[7];
1201 var a23 = a[11];
1202 out[1] = a[4];
1203 out[2] = a[8];
1204 out[3] = a[12];
1205 out[4] = a01;
1206 out[6] = a[9];
1207 out[7] = a[13];
1208 out[8] = a02;
1209 out[9] = a12;
1210 out[11] = a[14];
1211 out[12] = a03;
1212 out[13] = a13;
1213 out[14] = a23;
1214 } else {
1215 out[0] = a[0];
1216 out[1] = a[4];
1217 out[2] = a[8];
1218 out[3] = a[12];
1219 out[4] = a[1];
1220 out[5] = a[5];
1221 out[6] = a[9];
1222 out[7] = a[13];
1223 out[8] = a[2];
1224 out[9] = a[6];
1225 out[10] = a[10];
1226 out[11] = a[14];
1227 out[12] = a[3];
1228 out[13] = a[7];
1229 out[14] = a[11];
1230 out[15] = a[15];
1231 }
1232
1233 return out;
1234 }
1235 /**
1236 * Inverts a mat4
1237 *
1238 * @param {mat4} out the receiving matrix
1239 * @param {ReadonlyMat4} a the source matrix
1240 * @returns {mat4} out
1241 */
1242
1243 function invert(out, a) {
1244 var a00 = a[0],
1245 a01 = a[1],
1246 a02 = a[2],
1247 a03 = a[3];
1248 var a10 = a[4],
1249 a11 = a[5],
1250 a12 = a[6],
1251 a13 = a[7];
1252 var a20 = a[8],
1253 a21 = a[9],
1254 a22 = a[10],
1255 a23 = a[11];
1256 var a30 = a[12],
1257 a31 = a[13],
1258 a32 = a[14],
1259 a33 = a[15];
1260 var b00 = a00 * a11 - a01 * a10;
1261 var b01 = a00 * a12 - a02 * a10;
1262 var b02 = a00 * a13 - a03 * a10;
1263 var b03 = a01 * a12 - a02 * a11;
1264 var b04 = a01 * a13 - a03 * a11;
1265 var b05 = a02 * a13 - a03 * a12;
1266 var b06 = a20 * a31 - a21 * a30;
1267 var b07 = a20 * a32 - a22 * a30;
1268 var b08 = a20 * a33 - a23 * a30;
1269 var b09 = a21 * a32 - a22 * a31;
1270 var b10 = a21 * a33 - a23 * a31;
1271 var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
1272
1273 var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
1274
1275 if (!det) {
1276 return null;
1277 }
1278
1279 det = 1.0 / det;
1280 out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
1281 out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
1282 out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
1283 out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
1284 out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
1285 out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
1286 out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
1287 out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
1288 out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
1289 out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
1290 out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
1291 out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
1292 out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
1293 out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
1294 out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
1295 out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
1296 return out;
1297 }
1298 /**
1299 * Calculates the adjugate of a mat4
1300 *
1301 * @param {mat4} out the receiving matrix
1302 * @param {ReadonlyMat4} a the source matrix
1303 * @returns {mat4} out
1304 */
1305
1306 function adjoint(out, a) {
1307 var a00 = a[0],
1308 a01 = a[1],
1309 a02 = a[2],
1310 a03 = a[3];
1311 var a10 = a[4],
1312 a11 = a[5],
1313 a12 = a[6],
1314 a13 = a[7];
1315 var a20 = a[8],
1316 a21 = a[9],
1317 a22 = a[10],
1318 a23 = a[11];
1319 var a30 = a[12],
1320 a31 = a[13],
1321 a32 = a[14],
1322 a33 = a[15];
1323 out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);
1324 out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
1325 out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);
1326 out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
1327 out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
1328 out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);
1329 out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
1330 out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);
1331 out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);
1332 out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
1333 out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);
1334 out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
1335 out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
1336 out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);
1337 out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
1338 out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);
1339 return out;
1340 }
1341 /**
1342 * Calculates the determinant of a mat4
1343 *
1344 * @param {ReadonlyMat4} a the source matrix
1345 * @returns {Number} determinant of a
1346 */
1347
1348 function determinant(a) {
1349 var a00 = a[0],
1350 a01 = a[1],
1351 a02 = a[2],
1352 a03 = a[3];
1353 var a10 = a[4],
1354 a11 = a[5],
1355 a12 = a[6],
1356 a13 = a[7];
1357 var a20 = a[8],
1358 a21 = a[9],
1359 a22 = a[10],
1360 a23 = a[11];
1361 var a30 = a[12],
1362 a31 = a[13],
1363 a32 = a[14],
1364 a33 = a[15];
1365 var b00 = a00 * a11 - a01 * a10;
1366 var b01 = a00 * a12 - a02 * a10;
1367 var b02 = a00 * a13 - a03 * a10;
1368 var b03 = a01 * a12 - a02 * a11;
1369 var b04 = a01 * a13 - a03 * a11;
1370 var b05 = a02 * a13 - a03 * a12;
1371 var b06 = a20 * a31 - a21 * a30;
1372 var b07 = a20 * a32 - a22 * a30;
1373 var b08 = a20 * a33 - a23 * a30;
1374 var b09 = a21 * a32 - a22 * a31;
1375 var b10 = a21 * a33 - a23 * a31;
1376 var b11 = a22 * a33 - a23 * a32; // Calculate the determinant
1377
1378 return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
1379 }
1380 /**
1381 * Multiplies two mat4s
1382 *
1383 * @param {mat4} out the receiving matrix
1384 * @param {ReadonlyMat4} a the first operand
1385 * @param {ReadonlyMat4} b the second operand
1386 * @returns {mat4} out
1387 */
1388
1389 function multiply(out, a, b) {
1390 var a00 = a[0],
1391 a01 = a[1],
1392 a02 = a[2],
1393 a03 = a[3];
1394 var a10 = a[4],
1395 a11 = a[5],
1396 a12 = a[6],
1397 a13 = a[7];
1398 var a20 = a[8],
1399 a21 = a[9],
1400 a22 = a[10],
1401 a23 = a[11];
1402 var a30 = a[12],
1403 a31 = a[13],
1404 a32 = a[14],
1405 a33 = a[15]; // Cache only the current line of the second matrix
1406
1407 var b0 = b[0],
1408 b1 = b[1],
1409 b2 = b[2],
1410 b3 = b[3];
1411 out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
1412 out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
1413 out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
1414 out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
1415 b0 = b[4];
1416 b1 = b[5];
1417 b2 = b[6];
1418 b3 = b[7];
1419 out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
1420 out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
1421 out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
1422 out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
1423 b0 = b[8];
1424 b1 = b[9];
1425 b2 = b[10];
1426 b3 = b[11];
1427 out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
1428 out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
1429 out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
1430 out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
1431 b0 = b[12];
1432 b1 = b[13];
1433 b2 = b[14];
1434 b3 = b[15];
1435 out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
1436 out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
1437 out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
1438 out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
1439 return out;
1440 }
1441 /**
1442 * Translate a mat4 by the given vector
1443 *
1444 * @param {mat4} out the receiving matrix
1445 * @param {ReadonlyMat4} a the matrix to translate
1446 * @param {ReadonlyVec3} v vector to translate by
1447 * @returns {mat4} out
1448 */
1449
1450 function translate(out, a, v) {
1451 var x = v[0],
1452 y = v[1],
1453 z = v[2];
1454 var a00, a01, a02, a03;
1455 var a10, a11, a12, a13;
1456 var a20, a21, a22, a23;
1457
1458 if (a === out) {
1459 out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
1460 out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
1461 out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
1462 out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
1463 } else {
1464 a00 = a[0];
1465 a01 = a[1];
1466 a02 = a[2];
1467 a03 = a[3];
1468 a10 = a[4];
1469 a11 = a[5];
1470 a12 = a[6];
1471 a13 = a[7];
1472 a20 = a[8];
1473 a21 = a[9];
1474 a22 = a[10];
1475 a23 = a[11];
1476 out[0] = a00;
1477 out[1] = a01;
1478 out[2] = a02;
1479 out[3] = a03;
1480 out[4] = a10;
1481 out[5] = a11;
1482 out[6] = a12;
1483 out[7] = a13;
1484 out[8] = a20;
1485 out[9] = a21;
1486 out[10] = a22;
1487 out[11] = a23;
1488 out[12] = a00 * x + a10 * y + a20 * z + a[12];
1489 out[13] = a01 * x + a11 * y + a21 * z + a[13];
1490 out[14] = a02 * x + a12 * y + a22 * z + a[14];
1491 out[15] = a03 * x + a13 * y + a23 * z + a[15];
1492 }
1493
1494 return out;
1495 }
1496 /**
1497 * Scales the mat4 by the dimensions in the given vec3 not using vectorization
1498 *
1499 * @param {mat4} out the receiving matrix
1500 * @param {ReadonlyMat4} a the matrix to scale
1501 * @param {ReadonlyVec3} v the vec3 to scale the matrix by
1502 * @returns {mat4} out
1503 **/
1504
1505 function scale(out, a, v) {
1506 var x = v[0],
1507 y = v[1],
1508 z = v[2];
1509 out[0] = a[0] * x;
1510 out[1] = a[1] * x;
1511 out[2] = a[2] * x;
1512 out[3] = a[3] * x;
1513 out[4] = a[4] * y;
1514 out[5] = a[5] * y;
1515 out[6] = a[6] * y;
1516 out[7] = a[7] * y;
1517 out[8] = a[8] * z;
1518 out[9] = a[9] * z;
1519 out[10] = a[10] * z;
1520 out[11] = a[11] * z;
1521 out[12] = a[12];
1522 out[13] = a[13];
1523 out[14] = a[14];
1524 out[15] = a[15];
1525 return out;
1526 }
1527 /**
1528 * Rotates a mat4 by the given angle around the given axis
1529 *
1530 * @param {mat4} out the receiving matrix
1531 * @param {ReadonlyMat4} a the matrix to rotate
1532 * @param {Number} rad the angle to rotate the matrix by
1533 * @param {ReadonlyVec3} axis the axis to rotate around
1534 * @returns {mat4} out
1535 */
1536
1537 function rotate$1(out, a, rad, axis) {
1538 var x = axis[0],
1539 y = axis[1],
1540 z = axis[2];
1541 var len = Math.hypot(x, y, z);
1542 var s, c, t;
1543 var a00, a01, a02, a03;
1544 var a10, a11, a12, a13;
1545 var a20, a21, a22, a23;
1546 var b00, b01, b02;
1547 var b10, b11, b12;
1548 var b20, b21, b22;
1549
1550 if (len < EPSILON) {
1551 return null;
1552 }
1553
1554 len = 1 / len;
1555 x *= len;
1556 y *= len;
1557 z *= len;
1558 s = Math.sin(rad);
1559 c = Math.cos(rad);
1560 t = 1 - c;
1561 a00 = a[0];
1562 a01 = a[1];
1563 a02 = a[2];
1564 a03 = a[3];
1565 a10 = a[4];
1566 a11 = a[5];
1567 a12 = a[6];
1568 a13 = a[7];
1569 a20 = a[8];
1570 a21 = a[9];
1571 a22 = a[10];
1572 a23 = a[11]; // Construct the elements of the rotation matrix
1573
1574 b00 = x * x * t + c;
1575 b01 = y * x * t + z * s;
1576 b02 = z * x * t - y * s;
1577 b10 = x * y * t - z * s;
1578 b11 = y * y * t + c;
1579 b12 = z * y * t + x * s;
1580 b20 = x * z * t + y * s;
1581 b21 = y * z * t - x * s;
1582 b22 = z * z * t + c; // Perform rotation-specific matrix multiplication
1583
1584 out[0] = a00 * b00 + a10 * b01 + a20 * b02;
1585 out[1] = a01 * b00 + a11 * b01 + a21 * b02;
1586 out[2] = a02 * b00 + a12 * b01 + a22 * b02;
1587 out[3] = a03 * b00 + a13 * b01 + a23 * b02;
1588 out[4] = a00 * b10 + a10 * b11 + a20 * b12;
1589 out[5] = a01 * b10 + a11 * b11 + a21 * b12;
1590 out[6] = a02 * b10 + a12 * b11 + a22 * b12;
1591 out[7] = a03 * b10 + a13 * b11 + a23 * b12;
1592 out[8] = a00 * b20 + a10 * b21 + a20 * b22;
1593 out[9] = a01 * b20 + a11 * b21 + a21 * b22;
1594 out[10] = a02 * b20 + a12 * b21 + a22 * b22;
1595 out[11] = a03 * b20 + a13 * b21 + a23 * b22;
1596
1597 if (a !== out) {
1598 // If the source and destination differ, copy the unchanged last row
1599 out[12] = a[12];
1600 out[13] = a[13];
1601 out[14] = a[14];
1602 out[15] = a[15];
1603 }
1604
1605 return out;
1606 }
1607 /**
1608 * Rotates a matrix by the given angle around the X axis
1609 *
1610 * @param {mat4} out the receiving matrix
1611 * @param {ReadonlyMat4} a the matrix to rotate
1612 * @param {Number} rad the angle to rotate the matrix by
1613 * @returns {mat4} out
1614 */
1615
1616 function rotateX(out, a, rad) {
1617 var s = Math.sin(rad);
1618 var c = Math.cos(rad);
1619 var a10 = a[4];
1620 var a11 = a[5];
1621 var a12 = a[6];
1622 var a13 = a[7];
1623 var a20 = a[8];
1624 var a21 = a[9];
1625 var a22 = a[10];
1626 var a23 = a[11];
1627
1628 if (a !== out) {
1629 // If the source and destination differ, copy the unchanged rows
1630 out[0] = a[0];
1631 out[1] = a[1];
1632 out[2] = a[2];
1633 out[3] = a[3];
1634 out[12] = a[12];
1635 out[13] = a[13];
1636 out[14] = a[14];
1637 out[15] = a[15];
1638 } // Perform axis-specific matrix multiplication
1639
1640
1641 out[4] = a10 * c + a20 * s;
1642 out[5] = a11 * c + a21 * s;
1643 out[6] = a12 * c + a22 * s;
1644 out[7] = a13 * c + a23 * s;
1645 out[8] = a20 * c - a10 * s;
1646 out[9] = a21 * c - a11 * s;
1647 out[10] = a22 * c - a12 * s;
1648 out[11] = a23 * c - a13 * s;
1649 return out;
1650 }
1651 /**
1652 * Rotates a matrix by the given angle around the Y axis
1653 *
1654 * @param {mat4} out the receiving matrix
1655 * @param {ReadonlyMat4} a the matrix to rotate
1656 * @param {Number} rad the angle to rotate the matrix by
1657 * @returns {mat4} out
1658 */
1659
1660 function rotateY(out, a, rad) {
1661 var s = Math.sin(rad);
1662 var c = Math.cos(rad);
1663 var a00 = a[0];
1664 var a01 = a[1];
1665 var a02 = a[2];
1666 var a03 = a[3];
1667 var a20 = a[8];
1668 var a21 = a[9];
1669 var a22 = a[10];
1670 var a23 = a[11];
1671
1672 if (a !== out) {
1673 // If the source and destination differ, copy the unchanged rows
1674 out[4] = a[4];
1675 out[5] = a[5];
1676 out[6] = a[6];
1677 out[7] = a[7];
1678 out[12] = a[12];
1679 out[13] = a[13];
1680 out[14] = a[14];
1681 out[15] = a[15];
1682 } // Perform axis-specific matrix multiplication
1683
1684
1685 out[0] = a00 * c - a20 * s;
1686 out[1] = a01 * c - a21 * s;
1687 out[2] = a02 * c - a22 * s;
1688 out[3] = a03 * c - a23 * s;
1689 out[8] = a00 * s + a20 * c;
1690 out[9] = a01 * s + a21 * c;
1691 out[10] = a02 * s + a22 * c;
1692 out[11] = a03 * s + a23 * c;
1693 return out;
1694 }
1695 /**
1696 * Rotates a matrix by the given angle around the Z axis
1697 *
1698 * @param {mat4} out the receiving matrix
1699 * @param {ReadonlyMat4} a the matrix to rotate
1700 * @param {Number} rad the angle to rotate the matrix by
1701 * @returns {mat4} out
1702 */
1703
1704 function rotateZ(out, a, rad) {
1705 var s = Math.sin(rad);
1706 var c = Math.cos(rad);
1707 var a00 = a[0];
1708 var a01 = a[1];
1709 var a02 = a[2];
1710 var a03 = a[3];
1711 var a10 = a[4];
1712 var a11 = a[5];
1713 var a12 = a[6];
1714 var a13 = a[7];
1715
1716 if (a !== out) {
1717 // If the source and destination differ, copy the unchanged last row
1718 out[8] = a[8];
1719 out[9] = a[9];
1720 out[10] = a[10];
1721 out[11] = a[11];
1722 out[12] = a[12];
1723 out[13] = a[13];
1724 out[14] = a[14];
1725 out[15] = a[15];
1726 } // Perform axis-specific matrix multiplication
1727
1728
1729 out[0] = a00 * c + a10 * s;
1730 out[1] = a01 * c + a11 * s;
1731 out[2] = a02 * c + a12 * s;
1732 out[3] = a03 * c + a13 * s;
1733 out[4] = a10 * c - a00 * s;
1734 out[5] = a11 * c - a01 * s;
1735 out[6] = a12 * c - a02 * s;
1736 out[7] = a13 * c - a03 * s;
1737 return out;
1738 }
1739 /**
1740 * Creates a matrix from a vector translation
1741 * This is equivalent to (but much faster than):
1742 *
1743 * mat4.identity(dest);
1744 * mat4.translate(dest, dest, vec);
1745 *
1746 * @param {mat4} out mat4 receiving operation result
1747 * @param {ReadonlyVec3} v Translation vector
1748 * @returns {mat4} out
1749 */
1750
1751 function fromTranslation(out, v) {
1752 out[0] = 1;
1753 out[1] = 0;
1754 out[2] = 0;
1755 out[3] = 0;
1756 out[4] = 0;
1757 out[5] = 1;
1758 out[6] = 0;
1759 out[7] = 0;
1760 out[8] = 0;
1761 out[9] = 0;
1762 out[10] = 1;
1763 out[11] = 0;
1764 out[12] = v[0];
1765 out[13] = v[1];
1766 out[14] = v[2];
1767 out[15] = 1;
1768 return out;
1769 }
1770 /**
1771 * Creates a matrix from a vector scaling
1772 * This is equivalent to (but much faster than):
1773 *
1774 * mat4.identity(dest);
1775 * mat4.scale(dest, dest, vec);
1776 *
1777 * @param {mat4} out mat4 receiving operation result
1778 * @param {ReadonlyVec3} v Scaling vector
1779 * @returns {mat4} out
1780 */
1781
1782 function fromScaling(out, v) {
1783 out[0] = v[0];
1784 out[1] = 0;
1785 out[2] = 0;
1786 out[3] = 0;
1787 out[4] = 0;
1788 out[5] = v[1];
1789 out[6] = 0;
1790 out[7] = 0;
1791 out[8] = 0;
1792 out[9] = 0;
1793 out[10] = v[2];
1794 out[11] = 0;
1795 out[12] = 0;
1796 out[13] = 0;
1797 out[14] = 0;
1798 out[15] = 1;
1799 return out;
1800 }
1801 /**
1802 * Creates a matrix from a given angle around a given axis
1803 * This is equivalent to (but much faster than):
1804 *
1805 * mat4.identity(dest);
1806 * mat4.rotate(dest, dest, rad, axis);
1807 *
1808 * @param {mat4} out mat4 receiving operation result
1809 * @param {Number} rad the angle to rotate the matrix by
1810 * @param {ReadonlyVec3} axis the axis to rotate around
1811 * @returns {mat4} out
1812 */
1813
1814 function fromRotation(out, rad, axis) {
1815 var x = axis[0],
1816 y = axis[1],
1817 z = axis[2];
1818 var len = Math.hypot(x, y, z);
1819 var s, c, t;
1820
1821 if (len < EPSILON) {
1822 return null;
1823 }
1824
1825 len = 1 / len;
1826 x *= len;
1827 y *= len;
1828 z *= len;
1829 s = Math.sin(rad);
1830 c = Math.cos(rad);
1831 t = 1 - c; // Perform rotation-specific matrix multiplication
1832
1833 out[0] = x * x * t + c;
1834 out[1] = y * x * t + z * s;
1835 out[2] = z * x * t - y * s;
1836 out[3] = 0;
1837 out[4] = x * y * t - z * s;
1838 out[5] = y * y * t + c;
1839 out[6] = z * y * t + x * s;
1840 out[7] = 0;
1841 out[8] = x * z * t + y * s;
1842 out[9] = y * z * t - x * s;
1843 out[10] = z * z * t + c;
1844 out[11] = 0;
1845 out[12] = 0;
1846 out[13] = 0;
1847 out[14] = 0;
1848 out[15] = 1;
1849 return out;
1850 }
1851 /**
1852 * Creates a matrix from the given angle around the X axis
1853 * This is equivalent to (but much faster than):
1854 *
1855 * mat4.identity(dest);
1856 * mat4.rotateX(dest, dest, rad);
1857 *
1858 * @param {mat4} out mat4 receiving operation result
1859 * @param {Number} rad the angle to rotate the matrix by
1860 * @returns {mat4} out
1861 */
1862
1863 function fromXRotation(out, rad) {
1864 var s = Math.sin(rad);
1865 var c = Math.cos(rad); // Perform axis-specific matrix multiplication
1866
1867 out[0] = 1;
1868 out[1] = 0;
1869 out[2] = 0;
1870 out[3] = 0;
1871 out[4] = 0;
1872 out[5] = c;
1873 out[6] = s;
1874 out[7] = 0;
1875 out[8] = 0;
1876 out[9] = -s;
1877 out[10] = c;
1878 out[11] = 0;
1879 out[12] = 0;
1880 out[13] = 0;
1881 out[14] = 0;
1882 out[15] = 1;
1883 return out;
1884 }
1885 /**
1886 * Creates a matrix from the given angle around the Y axis
1887 * This is equivalent to (but much faster than):
1888 *
1889 * mat4.identity(dest);
1890 * mat4.rotateY(dest, dest, rad);
1891 *
1892 * @param {mat4} out mat4 receiving operation result
1893 * @param {Number} rad the angle to rotate the matrix by
1894 * @returns {mat4} out
1895 */
1896
1897 function fromYRotation(out, rad) {
1898 var s = Math.sin(rad);
1899 var c = Math.cos(rad); // Perform axis-specific matrix multiplication
1900
1901 out[0] = c;
1902 out[1] = 0;
1903 out[2] = -s;
1904 out[3] = 0;
1905 out[4] = 0;
1906 out[5] = 1;
1907 out[6] = 0;
1908 out[7] = 0;
1909 out[8] = s;
1910 out[9] = 0;
1911 out[10] = c;
1912 out[11] = 0;
1913 out[12] = 0;
1914 out[13] = 0;
1915 out[14] = 0;
1916 out[15] = 1;
1917 return out;
1918 }
1919 /**
1920 * Creates a matrix from the given angle around the Z axis
1921 * This is equivalent to (but much faster than):
1922 *
1923 * mat4.identity(dest);
1924 * mat4.rotateZ(dest, dest, rad);
1925 *
1926 * @param {mat4} out mat4 receiving operation result
1927 * @param {Number} rad the angle to rotate the matrix by
1928 * @returns {mat4} out
1929 */
1930
1931 function fromZRotation(out, rad) {
1932 var s = Math.sin(rad);
1933 var c = Math.cos(rad); // Perform axis-specific matrix multiplication
1934
1935 out[0] = c;
1936 out[1] = s;
1937 out[2] = 0;
1938 out[3] = 0;
1939 out[4] = -s;
1940 out[5] = c;
1941 out[6] = 0;
1942 out[7] = 0;
1943 out[8] = 0;
1944 out[9] = 0;
1945 out[10] = 1;
1946 out[11] = 0;
1947 out[12] = 0;
1948 out[13] = 0;
1949 out[14] = 0;
1950 out[15] = 1;
1951 return out;
1952 }
1953 /**
1954 * Creates a matrix from a quaternion rotation and vector translation
1955 * This is equivalent to (but much faster than):
1956 *
1957 * mat4.identity(dest);
1958 * mat4.translate(dest, vec);
1959 * let quatMat = mat4.create();
1960 * quat4.toMat4(quat, quatMat);
1961 * mat4.multiply(dest, quatMat);
1962 *
1963 * @param {mat4} out mat4 receiving operation result
1964 * @param {quat4} q Rotation quaternion
1965 * @param {ReadonlyVec3} v Translation vector
1966 * @returns {mat4} out
1967 */
1968
1969 function fromRotationTranslation(out, q, v) {
1970 // Quaternion math
1971 var x = q[0],
1972 y = q[1],
1973 z = q[2],
1974 w = q[3];
1975 var x2 = x + x;
1976 var y2 = y + y;
1977 var z2 = z + z;
1978 var xx = x * x2;
1979 var xy = x * y2;
1980 var xz = x * z2;
1981 var yy = y * y2;
1982 var yz = y * z2;
1983 var zz = z * z2;
1984 var wx = w * x2;
1985 var wy = w * y2;
1986 var wz = w * z2;
1987 out[0] = 1 - (yy + zz);
1988 out[1] = xy + wz;
1989 out[2] = xz - wy;
1990 out[3] = 0;
1991 out[4] = xy - wz;
1992 out[5] = 1 - (xx + zz);
1993 out[6] = yz + wx;
1994 out[7] = 0;
1995 out[8] = xz + wy;
1996 out[9] = yz - wx;
1997 out[10] = 1 - (xx + yy);
1998 out[11] = 0;
1999 out[12] = v[0];
2000 out[13] = v[1];
2001 out[14] = v[2];
2002 out[15] = 1;
2003 return out;
2004 }
2005 /**
2006 * Creates a new mat4 from a dual quat.
2007 *
2008 * @param {mat4} out Matrix
2009 * @param {ReadonlyQuat2} a Dual Quaternion
2010 * @returns {mat4} mat4 receiving operation result
2011 */
2012
2013 function fromQuat2(out, a) {
2014 var translation = new ARRAY_TYPE(3);
2015 var bx = -a[0],
2016 by = -a[1],
2017 bz = -a[2],
2018 bw = a[3],
2019 ax = a[4],
2020 ay = a[5],
2021 az = a[6],
2022 aw = a[7];
2023 var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense
2024
2025 if (magnitude > 0) {
2026 translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;
2027 translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;
2028 translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;
2029 } else {
2030 translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;
2031 translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;
2032 translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;
2033 }
2034
2035 fromRotationTranslation(out, a, translation);
2036 return out;
2037 }
2038 /**
2039 * Returns the translation vector component of a transformation
2040 * matrix. If a matrix is built with fromRotationTranslation,
2041 * the returned vector will be the same as the translation vector
2042 * originally supplied.
2043 * @param {vec3} out Vector to receive translation component
2044 * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
2045 * @return {vec3} out
2046 */
2047
2048 function getTranslation(out, mat) {
2049 out[0] = mat[12];
2050 out[1] = mat[13];
2051 out[2] = mat[14];
2052 return out;
2053 }
2054 /**
2055 * Returns the scaling factor component of a transformation
2056 * matrix. If a matrix is built with fromRotationTranslationScale
2057 * with a normalized Quaternion paramter, the returned vector will be
2058 * the same as the scaling vector
2059 * originally supplied.
2060 * @param {vec3} out Vector to receive scaling factor component
2061 * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
2062 * @return {vec3} out
2063 */
2064
2065 function getScaling(out, mat) {
2066 var m11 = mat[0];
2067 var m12 = mat[1];
2068 var m13 = mat[2];
2069 var m21 = mat[4];
2070 var m22 = mat[5];
2071 var m23 = mat[6];
2072 var m31 = mat[8];
2073 var m32 = mat[9];
2074 var m33 = mat[10];
2075 out[0] = Math.hypot(m11, m12, m13);
2076 out[1] = Math.hypot(m21, m22, m23);
2077 out[2] = Math.hypot(m31, m32, m33);
2078 return out;
2079 }
2080 /**
2081 * Returns a quaternion representing the rotational component
2082 * of a transformation matrix. If a matrix is built with
2083 * fromRotationTranslation, the returned quaternion will be the
2084 * same as the quaternion originally supplied.
2085 * @param {quat} out Quaternion to receive the rotation component
2086 * @param {ReadonlyMat4} mat Matrix to be decomposed (input)
2087 * @return {quat} out
2088 */
2089
2090 function getRotation(out, mat) {
2091 var scaling = new ARRAY_TYPE(3);
2092 getScaling(scaling, mat);
2093 var is1 = 1 / scaling[0];
2094 var is2 = 1 / scaling[1];
2095 var is3 = 1 / scaling[2];
2096 var sm11 = mat[0] * is1;
2097 var sm12 = mat[1] * is2;
2098 var sm13 = mat[2] * is3;
2099 var sm21 = mat[4] * is1;
2100 var sm22 = mat[5] * is2;
2101 var sm23 = mat[6] * is3;
2102 var sm31 = mat[8] * is1;
2103 var sm32 = mat[9] * is2;
2104 var sm33 = mat[10] * is3;
2105 var trace = sm11 + sm22 + sm33;
2106 var S = 0;
2107
2108 if (trace > 0) {
2109 S = Math.sqrt(trace + 1.0) * 2;
2110 out[3] = 0.25 * S;
2111 out[0] = (sm23 - sm32) / S;
2112 out[1] = (sm31 - sm13) / S;
2113 out[2] = (sm12 - sm21) / S;
2114 } else if (sm11 > sm22 && sm11 > sm33) {
2115 S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;
2116 out[3] = (sm23 - sm32) / S;
2117 out[0] = 0.25 * S;
2118 out[1] = (sm12 + sm21) / S;
2119 out[2] = (sm31 + sm13) / S;
2120 } else if (sm22 > sm33) {
2121 S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;
2122 out[3] = (sm31 - sm13) / S;
2123 out[0] = (sm12 + sm21) / S;
2124 out[1] = 0.25 * S;
2125 out[2] = (sm23 + sm32) / S;
2126 } else {
2127 S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;
2128 out[3] = (sm12 - sm21) / S;
2129 out[0] = (sm31 + sm13) / S;
2130 out[1] = (sm23 + sm32) / S;
2131 out[2] = 0.25 * S;
2132 }
2133
2134 return out;
2135 }
2136 /**
2137 * Creates a matrix from a quaternion rotation, vector translation and vector scale
2138 * This is equivalent to (but much faster than):
2139 *
2140 * mat4.identity(dest);
2141 * mat4.translate(dest, vec);
2142 * let quatMat = mat4.create();
2143 * quat4.toMat4(quat, quatMat);
2144 * mat4.multiply(dest, quatMat);
2145 * mat4.scale(dest, scale)
2146 *
2147 * @param {mat4} out mat4 receiving operation result
2148 * @param {quat4} q Rotation quaternion
2149 * @param {ReadonlyVec3} v Translation vector
2150 * @param {ReadonlyVec3} s Scaling vector
2151 * @returns {mat4} out
2152 */
2153
2154 function fromRotationTranslationScale(out, q, v, s) {
2155 // Quaternion math
2156 var x = q[0],
2157 y = q[1],
2158 z = q[2],
2159 w = q[3];
2160 var x2 = x + x;
2161 var y2 = y + y;
2162 var z2 = z + z;
2163 var xx = x * x2;
2164 var xy = x * y2;
2165 var xz = x * z2;
2166 var yy = y * y2;
2167 var yz = y * z2;
2168 var zz = z * z2;
2169 var wx = w * x2;
2170 var wy = w * y2;
2171 var wz = w * z2;
2172 var sx = s[0];
2173 var sy = s[1];
2174 var sz = s[2];
2175 out[0] = (1 - (yy + zz)) * sx;
2176 out[1] = (xy + wz) * sx;
2177 out[2] = (xz - wy) * sx;
2178 out[3] = 0;
2179 out[4] = (xy - wz) * sy;
2180 out[5] = (1 - (xx + zz)) * sy;
2181 out[6] = (yz + wx) * sy;
2182 out[7] = 0;
2183 out[8] = (xz + wy) * sz;
2184 out[9] = (yz - wx) * sz;
2185 out[10] = (1 - (xx + yy)) * sz;
2186 out[11] = 0;
2187 out[12] = v[0];
2188 out[13] = v[1];
2189 out[14] = v[2];
2190 out[15] = 1;
2191 return out;
2192 }
2193 /**
2194 * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
2195 * This is equivalent to (but much faster than):
2196 *
2197 * mat4.identity(dest);
2198 * mat4.translate(dest, vec);
2199 * mat4.translate(dest, origin);
2200 * let quatMat = mat4.create();
2201 * quat4.toMat4(quat, quatMat);
2202 * mat4.multiply(dest, quatMat);
2203 * mat4.scale(dest, scale)
2204 * mat4.translate(dest, negativeOrigin);
2205 *
2206 * @param {mat4} out mat4 receiving operation result
2207 * @param {quat4} q Rotation quaternion
2208 * @param {ReadonlyVec3} v Translation vector
2209 * @param {ReadonlyVec3} s Scaling vector
2210 * @param {ReadonlyVec3} o The origin vector around which to scale and rotate
2211 * @returns {mat4} out
2212 */
2213
2214 function fromRotationTranslationScaleOrigin(out, q, v, s, o) {
2215 // Quaternion math
2216 var x = q[0],
2217 y = q[1],
2218 z = q[2],
2219 w = q[3];
2220 var x2 = x + x;
2221 var y2 = y + y;
2222 var z2 = z + z;
2223 var xx = x * x2;
2224 var xy = x * y2;
2225 var xz = x * z2;
2226 var yy = y * y2;
2227 var yz = y * z2;
2228 var zz = z * z2;
2229 var wx = w * x2;
2230 var wy = w * y2;
2231 var wz = w * z2;
2232 var sx = s[0];
2233 var sy = s[1];
2234 var sz = s[2];
2235 var ox = o[0];
2236 var oy = o[1];
2237 var oz = o[2];
2238 var out0 = (1 - (yy + zz)) * sx;
2239 var out1 = (xy + wz) * sx;
2240 var out2 = (xz - wy) * sx;
2241 var out4 = (xy - wz) * sy;
2242 var out5 = (1 - (xx + zz)) * sy;
2243 var out6 = (yz + wx) * sy;
2244 var out8 = (xz + wy) * sz;
2245 var out9 = (yz - wx) * sz;
2246 var out10 = (1 - (xx + yy)) * sz;
2247 out[0] = out0;
2248 out[1] = out1;
2249 out[2] = out2;
2250 out[3] = 0;
2251 out[4] = out4;
2252 out[5] = out5;
2253 out[6] = out6;
2254 out[7] = 0;
2255 out[8] = out8;
2256 out[9] = out9;
2257 out[10] = out10;
2258 out[11] = 0;
2259 out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);
2260 out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);
2261 out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);
2262 out[15] = 1;
2263 return out;
2264 }
2265 /**
2266 * Calculates a 4x4 matrix from the given quaternion
2267 *
2268 * @param {mat4} out mat4 receiving operation result
2269 * @param {ReadonlyQuat} q Quaternion to create matrix from
2270 *
2271 * @returns {mat4} out
2272 */
2273
2274 function fromQuat(out, q) {
2275 var x = q[0],
2276 y = q[1],
2277 z = q[2],
2278 w = q[3];
2279 var x2 = x + x;
2280 var y2 = y + y;
2281 var z2 = z + z;
2282 var xx = x * x2;
2283 var yx = y * x2;
2284 var yy = y * y2;
2285 var zx = z * x2;
2286 var zy = z * y2;
2287 var zz = z * z2;
2288 var wx = w * x2;
2289 var wy = w * y2;
2290 var wz = w * z2;
2291 out[0] = 1 - yy - zz;
2292 out[1] = yx + wz;
2293 out[2] = zx - wy;
2294 out[3] = 0;
2295 out[4] = yx - wz;
2296 out[5] = 1 - xx - zz;
2297 out[6] = zy + wx;
2298 out[7] = 0;
2299 out[8] = zx + wy;
2300 out[9] = zy - wx;
2301 out[10] = 1 - xx - yy;
2302 out[11] = 0;
2303 out[12] = 0;
2304 out[13] = 0;
2305 out[14] = 0;
2306 out[15] = 1;
2307 return out;
2308 }
2309 /**
2310 * Generates a frustum matrix with the given bounds
2311 *
2312 * @param {mat4} out mat4 frustum matrix will be written into
2313 * @param {Number} left Left bound of the frustum
2314 * @param {Number} right Right bound of the frustum
2315 * @param {Number} bottom Bottom bound of the frustum
2316 * @param {Number} top Top bound of the frustum
2317 * @param {Number} near Near bound of the frustum
2318 * @param {Number} far Far bound of the frustum
2319 * @returns {mat4} out
2320 */
2321
2322 function frustum(out, left, right, bottom, top, near, far) {
2323 var rl = 1 / (right - left);
2324 var tb = 1 / (top - bottom);
2325 var nf = 1 / (near - far);
2326 out[0] = near * 2 * rl;
2327 out[1] = 0;
2328 out[2] = 0;
2329 out[3] = 0;
2330 out[4] = 0;
2331 out[5] = near * 2 * tb;
2332 out[6] = 0;
2333 out[7] = 0;
2334 out[8] = (right + left) * rl;
2335 out[9] = (top + bottom) * tb;
2336 out[10] = (far + near) * nf;
2337 out[11] = -1;
2338 out[12] = 0;
2339 out[13] = 0;
2340 out[14] = far * near * 2 * nf;
2341 out[15] = 0;
2342 return out;
2343 }
2344 /**
2345 * Generates a perspective projection matrix with the given bounds.
2346 * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
2347 * which matches WebGL/OpenGL's clip volume.
2348 * Passing null/undefined/no value for far will generate infinite projection matrix.
2349 *
2350 * @param {mat4} out mat4 frustum matrix will be written into
2351 * @param {number} fovy Vertical field of view in radians
2352 * @param {number} aspect Aspect ratio. typically viewport width/height
2353 * @param {number} near Near bound of the frustum
2354 * @param {number} far Far bound of the frustum, can be null or Infinity
2355 * @returns {mat4} out
2356 */
2357
2358 function perspectiveNO(out, fovy, aspect, near, far) {
2359 var f = 1.0 / Math.tan(fovy / 2),
2360 nf;
2361 out[0] = f / aspect;
2362 out[1] = 0;
2363 out[2] = 0;
2364 out[3] = 0;
2365 out[4] = 0;
2366 out[5] = f;
2367 out[6] = 0;
2368 out[7] = 0;
2369 out[8] = 0;
2370 out[9] = 0;
2371 out[11] = -1;
2372 out[12] = 0;
2373 out[13] = 0;
2374 out[15] = 0;
2375
2376 if (far != null && far !== Infinity) {
2377 nf = 1 / (near - far);
2378 out[10] = (far + near) * nf;
2379 out[14] = 2 * far * near * nf;
2380 } else {
2381 out[10] = -1;
2382 out[14] = -2 * near;
2383 }
2384
2385 return out;
2386 }
2387 /**
2388 * Alias for {@link mat4.perspectiveNO}
2389 * @function
2390 */
2391
2392 var perspective = perspectiveNO;
2393 /**
2394 * Generates a perspective projection matrix suitable for WebGPU with the given bounds.
2395 * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
2396 * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
2397 * Passing null/undefined/no value for far will generate infinite projection matrix.
2398 *
2399 * @param {mat4} out mat4 frustum matrix will be written into
2400 * @param {number} fovy Vertical field of view in radians
2401 * @param {number} aspect Aspect ratio. typically viewport width/height
2402 * @param {number} near Near bound of the frustum
2403 * @param {number} far Far bound of the frustum, can be null or Infinity
2404 * @returns {mat4} out
2405 */
2406
2407 function perspectiveZO(out, fovy, aspect, near, far) {
2408 var f = 1.0 / Math.tan(fovy / 2),
2409 nf;
2410 out[0] = f / aspect;
2411 out[1] = 0;
2412 out[2] = 0;
2413 out[3] = 0;
2414 out[4] = 0;
2415 out[5] = f;
2416 out[6] = 0;
2417 out[7] = 0;
2418 out[8] = 0;
2419 out[9] = 0;
2420 out[11] = -1;
2421 out[12] = 0;
2422 out[13] = 0;
2423 out[15] = 0;
2424
2425 if (far != null && far !== Infinity) {
2426 nf = 1 / (near - far);
2427 out[10] = far * nf;
2428 out[14] = far * near * nf;
2429 } else {
2430 out[10] = -1;
2431 out[14] = -near;
2432 }
2433
2434 return out;
2435 }
2436 /**
2437 * Generates a perspective projection matrix with the given field of view.
2438 * This is primarily useful for generating projection matrices to be used
2439 * with the still experiemental WebVR API.
2440 *
2441 * @param {mat4} out mat4 frustum matrix will be written into
2442 * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
2443 * @param {number} near Near bound of the frustum
2444 * @param {number} far Far bound of the frustum
2445 * @returns {mat4} out
2446 */
2447
2448 function perspectiveFromFieldOfView(out, fov, near, far) {
2449 var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
2450 var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
2451 var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
2452 var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
2453 var xScale = 2.0 / (leftTan + rightTan);
2454 var yScale = 2.0 / (upTan + downTan);
2455 out[0] = xScale;
2456 out[1] = 0.0;
2457 out[2] = 0.0;
2458 out[3] = 0.0;
2459 out[4] = 0.0;
2460 out[5] = yScale;
2461 out[6] = 0.0;
2462 out[7] = 0.0;
2463 out[8] = -((leftTan - rightTan) * xScale * 0.5);
2464 out[9] = (upTan - downTan) * yScale * 0.5;
2465 out[10] = far / (near - far);
2466 out[11] = -1.0;
2467 out[12] = 0.0;
2468 out[13] = 0.0;
2469 out[14] = far * near / (near - far);
2470 out[15] = 0.0;
2471 return out;
2472 }
2473 /**
2474 * Generates a orthogonal projection matrix with the given bounds.
2475 * The near/far clip planes correspond to a normalized device coordinate Z range of [-1, 1],
2476 * which matches WebGL/OpenGL's clip volume.
2477 *
2478 * @param {mat4} out mat4 frustum matrix will be written into
2479 * @param {number} left Left bound of the frustum
2480 * @param {number} right Right bound of the frustum
2481 * @param {number} bottom Bottom bound of the frustum
2482 * @param {number} top Top bound of the frustum
2483 * @param {number} near Near bound of the frustum
2484 * @param {number} far Far bound of the frustum
2485 * @returns {mat4} out
2486 */
2487
2488 function orthoNO(out, left, right, bottom, top, near, far) {
2489 var lr = 1 / (left - right);
2490 var bt = 1 / (bottom - top);
2491 var nf = 1 / (near - far);
2492 out[0] = -2 * lr;
2493 out[1] = 0;
2494 out[2] = 0;
2495 out[3] = 0;
2496 out[4] = 0;
2497 out[5] = -2 * bt;
2498 out[6] = 0;
2499 out[7] = 0;
2500 out[8] = 0;
2501 out[9] = 0;
2502 out[10] = 2 * nf;
2503 out[11] = 0;
2504 out[12] = (left + right) * lr;
2505 out[13] = (top + bottom) * bt;
2506 out[14] = (far + near) * nf;
2507 out[15] = 1;
2508 return out;
2509 }
2510 /**
2511 * Alias for {@link mat4.orthoNO}
2512 * @function
2513 */
2514
2515 var ortho = orthoNO;
2516 /**
2517 * Generates a orthogonal projection matrix with the given bounds.
2518 * The near/far clip planes correspond to a normalized device coordinate Z range of [0, 1],
2519 * which matches WebGPU/Vulkan/DirectX/Metal's clip volume.
2520 *
2521 * @param {mat4} out mat4 frustum matrix will be written into
2522 * @param {number} left Left bound of the frustum
2523 * @param {number} right Right bound of the frustum
2524 * @param {number} bottom Bottom bound of the frustum
2525 * @param {number} top Top bound of the frustum
2526 * @param {number} near Near bound of the frustum
2527 * @param {number} far Far bound of the frustum
2528 * @returns {mat4} out
2529 */
2530
2531 function orthoZO(out, left, right, bottom, top, near, far) {
2532 var lr = 1 / (left - right);
2533 var bt = 1 / (bottom - top);
2534 var nf = 1 / (near - far);
2535 out[0] = -2 * lr;
2536 out[1] = 0;
2537 out[2] = 0;
2538 out[3] = 0;
2539 out[4] = 0;
2540 out[5] = -2 * bt;
2541 out[6] = 0;
2542 out[7] = 0;
2543 out[8] = 0;
2544 out[9] = 0;
2545 out[10] = nf;
2546 out[11] = 0;
2547 out[12] = (left + right) * lr;
2548 out[13] = (top + bottom) * bt;
2549 out[14] = near * nf;
2550 out[15] = 1;
2551 return out;
2552 }
2553 /**
2554 * Generates a look-at matrix with the given eye position, focal point, and up axis.
2555 * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.
2556 *
2557 * @param {mat4} out mat4 frustum matrix will be written into
2558 * @param {ReadonlyVec3} eye Position of the viewer
2559 * @param {ReadonlyVec3} center Point the viewer is looking at
2560 * @param {ReadonlyVec3} up vec3 pointing up
2561 * @returns {mat4} out
2562 */
2563
2564 function lookAt(out, eye, center, up) {
2565 var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
2566 var eyex = eye[0];
2567 var eyey = eye[1];
2568 var eyez = eye[2];
2569 var upx = up[0];
2570 var upy = up[1];
2571 var upz = up[2];
2572 var centerx = center[0];
2573 var centery = center[1];
2574 var centerz = center[2];
2575
2576 if (Math.abs(eyex - centerx) < EPSILON && Math.abs(eyey - centery) < EPSILON && Math.abs(eyez - centerz) < EPSILON) {
2577 return identity$1(out);
2578 }
2579
2580 z0 = eyex - centerx;
2581 z1 = eyey - centery;
2582 z2 = eyez - centerz;
2583 len = 1 / Math.hypot(z0, z1, z2);
2584 z0 *= len;
2585 z1 *= len;
2586 z2 *= len;
2587 x0 = upy * z2 - upz * z1;
2588 x1 = upz * z0 - upx * z2;
2589 x2 = upx * z1 - upy * z0;
2590 len = Math.hypot(x0, x1, x2);
2591
2592 if (!len) {
2593 x0 = 0;
2594 x1 = 0;
2595 x2 = 0;
2596 } else {
2597 len = 1 / len;
2598 x0 *= len;
2599 x1 *= len;
2600 x2 *= len;
2601 }
2602
2603 y0 = z1 * x2 - z2 * x1;
2604 y1 = z2 * x0 - z0 * x2;
2605 y2 = z0 * x1 - z1 * x0;
2606 len = Math.hypot(y0, y1, y2);
2607
2608 if (!len) {
2609 y0 = 0;
2610 y1 = 0;
2611 y2 = 0;
2612 } else {
2613 len = 1 / len;
2614 y0 *= len;
2615 y1 *= len;
2616 y2 *= len;
2617 }
2618
2619 out[0] = x0;
2620 out[1] = y0;
2621 out[2] = z0;
2622 out[3] = 0;
2623 out[4] = x1;
2624 out[5] = y1;
2625 out[6] = z1;
2626 out[7] = 0;
2627 out[8] = x2;
2628 out[9] = y2;
2629 out[10] = z2;
2630 out[11] = 0;
2631 out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
2632 out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
2633 out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
2634 out[15] = 1;
2635 return out;
2636 }
2637 /**
2638 * Generates a matrix that makes something look at something else.
2639 *
2640 * @param {mat4} out mat4 frustum matrix will be written into
2641 * @param {ReadonlyVec3} eye Position of the viewer
2642 * @param {ReadonlyVec3} center Point the viewer is looking at
2643 * @param {ReadonlyVec3} up vec3 pointing up
2644 * @returns {mat4} out
2645 */
2646
2647 function targetTo(out, eye, target, up) {
2648 var eyex = eye[0],
2649 eyey = eye[1],
2650 eyez = eye[2],
2651 upx = up[0],
2652 upy = up[1],
2653 upz = up[2];
2654 var z0 = eyex - target[0],
2655 z1 = eyey - target[1],
2656 z2 = eyez - target[2];
2657 var len = z0 * z0 + z1 * z1 + z2 * z2;
2658
2659 if (len > 0) {
2660 len = 1 / Math.sqrt(len);
2661 z0 *= len;
2662 z1 *= len;
2663 z2 *= len;
2664 }
2665
2666 var x0 = upy * z2 - upz * z1,
2667 x1 = upz * z0 - upx * z2,
2668 x2 = upx * z1 - upy * z0;
2669 len = x0 * x0 + x1 * x1 + x2 * x2;
2670
2671 if (len > 0) {
2672 len = 1 / Math.sqrt(len);
2673 x0 *= len;
2674 x1 *= len;
2675 x2 *= len;
2676 }
2677
2678 out[0] = x0;
2679 out[1] = x1;
2680 out[2] = x2;
2681 out[3] = 0;
2682 out[4] = z1 * x2 - z2 * x1;
2683 out[5] = z2 * x0 - z0 * x2;
2684 out[6] = z0 * x1 - z1 * x0;
2685 out[7] = 0;
2686 out[8] = z0;
2687 out[9] = z1;
2688 out[10] = z2;
2689 out[11] = 0;
2690 out[12] = eyex;
2691 out[13] = eyey;
2692 out[14] = eyez;
2693 out[15] = 1;
2694 return out;
2695 }
2696 /**
2697 * Returns a string representation of a mat4
2698 *
2699 * @param {ReadonlyMat4} a matrix to represent as a string
2700 * @returns {String} string representation of the matrix
2701 */
2702
2703 function str(a) {
2704 return "mat4(" + a[0] + ", " + a[1] + ", " + a[2] + ", " + a[3] + ", " + a[4] + ", " + a[5] + ", " + a[6] + ", " + a[7] + ", " + a[8] + ", " + a[9] + ", " + a[10] + ", " + a[11] + ", " + a[12] + ", " + a[13] + ", " + a[14] + ", " + a[15] + ")";
2705 }
2706 /**
2707 * Returns Frobenius norm of a mat4
2708 *
2709 * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of
2710 * @returns {Number} Frobenius norm
2711 */
2712
2713 function frob(a) {
2714 return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);
2715 }
2716 /**
2717 * Adds two mat4's
2718 *
2719 * @param {mat4} out the receiving matrix
2720 * @param {ReadonlyMat4} a the first operand
2721 * @param {ReadonlyMat4} b the second operand
2722 * @returns {mat4} out
2723 */
2724
2725 function add(out, a, b) {
2726 out[0] = a[0] + b[0];
2727 out[1] = a[1] + b[1];
2728 out[2] = a[2] + b[2];
2729 out[3] = a[3] + b[3];
2730 out[4] = a[4] + b[4];
2731 out[5] = a[5] + b[5];
2732 out[6] = a[6] + b[6];
2733 out[7] = a[7] + b[7];
2734 out[8] = a[8] + b[8];
2735 out[9] = a[9] + b[9];
2736 out[10] = a[10] + b[10];
2737 out[11] = a[11] + b[11];
2738 out[12] = a[12] + b[12];
2739 out[13] = a[13] + b[13];
2740 out[14] = a[14] + b[14];
2741 out[15] = a[15] + b[15];
2742 return out;
2743 }
2744 /**
2745 * Subtracts matrix b from matrix a
2746 *
2747 * @param {mat4} out the receiving matrix
2748 * @param {ReadonlyMat4} a the first operand
2749 * @param {ReadonlyMat4} b the second operand
2750 * @returns {mat4} out
2751 */
2752
2753 function subtract(out, a, b) {
2754 out[0] = a[0] - b[0];
2755 out[1] = a[1] - b[1];
2756 out[2] = a[2] - b[2];
2757 out[3] = a[3] - b[3];
2758 out[4] = a[4] - b[4];
2759 out[5] = a[5] - b[5];
2760 out[6] = a[6] - b[6];
2761 out[7] = a[7] - b[7];
2762 out[8] = a[8] - b[8];
2763 out[9] = a[9] - b[9];
2764 out[10] = a[10] - b[10];
2765 out[11] = a[11] - b[11];
2766 out[12] = a[12] - b[12];
2767 out[13] = a[13] - b[13];
2768 out[14] = a[14] - b[14];
2769 out[15] = a[15] - b[15];
2770 return out;
2771 }
2772 /**
2773 * Multiply each element of the matrix by a scalar.
2774 *
2775 * @param {mat4} out the receiving matrix
2776 * @param {ReadonlyMat4} a the matrix to scale
2777 * @param {Number} b amount to scale the matrix's elements by
2778 * @returns {mat4} out
2779 */
2780
2781 function multiplyScalar(out, a, b) {
2782 out[0] = a[0] * b;
2783 out[1] = a[1] * b;
2784 out[2] = a[2] * b;
2785 out[3] = a[3] * b;
2786 out[4] = a[4] * b;
2787 out[5] = a[5] * b;
2788 out[6] = a[6] * b;
2789 out[7] = a[7] * b;
2790 out[8] = a[8] * b;
2791 out[9] = a[9] * b;
2792 out[10] = a[10] * b;
2793 out[11] = a[11] * b;
2794 out[12] = a[12] * b;
2795 out[13] = a[13] * b;
2796 out[14] = a[14] * b;
2797 out[15] = a[15] * b;
2798 return out;
2799 }
2800 /**
2801 * Adds two mat4's after multiplying each element of the second operand by a scalar value.
2802 *
2803 * @param {mat4} out the receiving vector
2804 * @param {ReadonlyMat4} a the first operand
2805 * @param {ReadonlyMat4} b the second operand
2806 * @param {Number} scale the amount to scale b's elements by before adding
2807 * @returns {mat4} out
2808 */
2809
2810 function multiplyScalarAndAdd(out, a, b, scale) {
2811 out[0] = a[0] + b[0] * scale;
2812 out[1] = a[1] + b[1] * scale;
2813 out[2] = a[2] + b[2] * scale;
2814 out[3] = a[3] + b[3] * scale;
2815 out[4] = a[4] + b[4] * scale;
2816 out[5] = a[5] + b[5] * scale;
2817 out[6] = a[6] + b[6] * scale;
2818 out[7] = a[7] + b[7] * scale;
2819 out[8] = a[8] + b[8] * scale;
2820 out[9] = a[9] + b[9] * scale;
2821 out[10] = a[10] + b[10] * scale;
2822 out[11] = a[11] + b[11] * scale;
2823 out[12] = a[12] + b[12] * scale;
2824 out[13] = a[13] + b[13] * scale;
2825 out[14] = a[14] + b[14] * scale;
2826 out[15] = a[15] + b[15] * scale;
2827 return out;
2828 }
2829 /**
2830 * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)
2831 *
2832 * @param {ReadonlyMat4} a The first matrix.
2833 * @param {ReadonlyMat4} b The second matrix.
2834 * @returns {Boolean} True if the matrices are equal, false otherwise.
2835 */
2836
2837 function exactEquals(a, b) {
2838 return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
2839 }
2840 /**
2841 * Returns whether or not the matrices have approximately the same elements in the same position.
2842 *
2843 * @param {ReadonlyMat4} a The first matrix.
2844 * @param {ReadonlyMat4} b The second matrix.
2845 * @returns {Boolean} True if the matrices are equal, false otherwise.
2846 */
2847
2848 function equals(a, b) {
2849 var a0 = a[0],
2850 a1 = a[1],
2851 a2 = a[2],
2852 a3 = a[3];
2853 var a4 = a[4],
2854 a5 = a[5],
2855 a6 = a[6],
2856 a7 = a[7];
2857 var a8 = a[8],
2858 a9 = a[9],
2859 a10 = a[10],
2860 a11 = a[11];
2861 var a12 = a[12],
2862 a13 = a[13],
2863 a14 = a[14],
2864 a15 = a[15];
2865 var b0 = b[0],
2866 b1 = b[1],
2867 b2 = b[2],
2868 b3 = b[3];
2869 var b4 = b[4],
2870 b5 = b[5],
2871 b6 = b[6],
2872 b7 = b[7];
2873 var b8 = b[8],
2874 b9 = b[9],
2875 b10 = b[10],
2876 b11 = b[11];
2877 var b12 = b[12],
2878 b13 = b[13],
2879 b14 = b[14],
2880 b15 = b[15];
2881 return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));
2882 }
2883 /**
2884 * Alias for {@link mat4.multiply}
2885 * @function
2886 */
2887
2888 var mul = multiply;
2889 /**
2890 * Alias for {@link mat4.subtract}
2891 * @function
2892 */
2893
2894 var sub = subtract;
2895
2896 var mat4 = /*#__PURE__*/Object.freeze({
2897 __proto__: null,
2898 create: create$1,
2899 clone: clone$1,
2900 copy: copy,
2901 fromValues: fromValues$1,
2902 set: set,
2903 identity: identity$1,
2904 transpose: transpose,
2905 invert: invert,
2906 adjoint: adjoint,
2907 determinant: determinant,
2908 multiply: multiply,
2909 translate: translate,
2910 scale: scale,
2911 rotate: rotate$1,
2912 rotateX: rotateX,
2913 rotateY: rotateY,
2914 rotateZ: rotateZ,
2915 fromTranslation: fromTranslation,
2916 fromScaling: fromScaling,
2917 fromRotation: fromRotation,
2918 fromXRotation: fromXRotation,
2919 fromYRotation: fromYRotation,
2920 fromZRotation: fromZRotation,
2921 fromRotationTranslation: fromRotationTranslation,
2922 fromQuat2: fromQuat2,
2923 getTranslation: getTranslation,
2924 getScaling: getScaling,
2925 getRotation: getRotation,
2926 fromRotationTranslationScale: fromRotationTranslationScale,
2927 fromRotationTranslationScaleOrigin: fromRotationTranslationScaleOrigin,
2928 fromQuat: fromQuat,
2929 frustum: frustum,
2930 perspectiveNO: perspectiveNO,
2931 perspective: perspective,
2932 perspectiveZO: perspectiveZO,
2933 perspectiveFromFieldOfView: perspectiveFromFieldOfView,
2934 orthoNO: orthoNO,
2935 ortho: ortho,
2936 orthoZO: orthoZO,
2937 lookAt: lookAt,
2938 targetTo: targetTo,
2939 str: str,
2940 frob: frob,
2941 add: add,
2942 subtract: subtract,
2943 multiplyScalar: multiplyScalar,
2944 multiplyScalarAndAdd: multiplyScalarAndAdd,
2945 exactEquals: exactEquals,
2946 equals: equals,
2947 mul: mul,
2948 sub: sub
2949 });
2950
2951 /**
2952 * 3 Dimensional Vector
2953 * @module vec3
2954 */
2955
2956 /**
2957 * Creates a new, empty vec3
2958 *
2959 * @returns {vec3} a new 3D vector
2960 */
2961
2962 function create$2() {
2963 var out = new ARRAY_TYPE(3);
2964
2965 if (ARRAY_TYPE != Float32Array) {
2966 out[0] = 0;
2967 out[1] = 0;
2968 out[2] = 0;
2969 }
2970
2971 return out;
2972 }
2973 /**
2974 * Creates a new vec3 initialized with values from an existing vector
2975 *
2976 * @param {ReadonlyVec3} a vector to clone
2977 * @returns {vec3} a new 3D vector
2978 */
2979
2980 function clone$2(a) {
2981 var out = new ARRAY_TYPE(3);
2982 out[0] = a[0];
2983 out[1] = a[1];
2984 out[2] = a[2];
2985 return out;
2986 }
2987 /**
2988 * Calculates the length of a vec3
2989 *
2990 * @param {ReadonlyVec3} a vector to calculate length of
2991 * @returns {Number} length of a
2992 */
2993
2994 function length(a) {
2995 var x = a[0];
2996 var y = a[1];
2997 var z = a[2];
2998 return Math.hypot(x, y, z);
2999 }
3000 /**
3001 * Creates a new vec3 initialized with the given values
3002 *
3003 * @param {Number} x X component
3004 * @param {Number} y Y component
3005 * @param {Number} z Z component
3006 * @returns {vec3} a new 3D vector
3007 */
3008
3009 function fromValues$2(x, y, z) {
3010 var out = new ARRAY_TYPE(3);
3011 out[0] = x;
3012 out[1] = y;
3013 out[2] = z;
3014 return out;
3015 }
3016 /**
3017 * Copy the values from one vec3 to another
3018 *
3019 * @param {vec3} out the receiving vector
3020 * @param {ReadonlyVec3} a the source vector
3021 * @returns {vec3} out
3022 */
3023
3024 function copy$1(out, a) {
3025 out[0] = a[0];
3026 out[1] = a[1];
3027 out[2] = a[2];
3028 return out;
3029 }
3030 /**
3031 * Set the components of a vec3 to the given values
3032 *
3033 * @param {vec3} out the receiving vector
3034 * @param {Number} x X component
3035 * @param {Number} y Y component
3036 * @param {Number} z Z component
3037 * @returns {vec3} out
3038 */
3039
3040 function set$1(out, x, y, z) {
3041 out[0] = x;
3042 out[1] = y;
3043 out[2] = z;
3044 return out;
3045 }
3046 /**
3047 * Adds two vec3's
3048 *
3049 * @param {vec3} out the receiving vector
3050 * @param {ReadonlyVec3} a the first operand
3051 * @param {ReadonlyVec3} b the second operand
3052 * @returns {vec3} out
3053 */
3054
3055 function add$1(out, a, b) {
3056 out[0] = a[0] + b[0];
3057 out[1] = a[1] + b[1];
3058 out[2] = a[2] + b[2];
3059 return out;
3060 }
3061 /**
3062 * Subtracts vector b from vector a
3063 *
3064 * @param {vec3} out the receiving vector
3065 * @param {ReadonlyVec3} a the first operand
3066 * @param {ReadonlyVec3} b the second operand
3067 * @returns {vec3} out
3068 */
3069
3070 function subtract$1(out, a, b) {
3071 out[0] = a[0] - b[0];
3072 out[1] = a[1] - b[1];
3073 out[2] = a[2] - b[2];
3074 return out;
3075 }
3076 /**
3077 * Multiplies two vec3's
3078 *
3079 * @param {vec3} out the receiving vector
3080 * @param {ReadonlyVec3} a the first operand
3081 * @param {ReadonlyVec3} b the second operand
3082 * @returns {vec3} out
3083 */
3084
3085 function multiply$1(out, a, b) {
3086 out[0] = a[0] * b[0];
3087 out[1] = a[1] * b[1];
3088 out[2] = a[2] * b[2];
3089 return out;
3090 }
3091 /**
3092 * Scales a vec3 by a scalar number
3093 *
3094 * @param {vec3} out the receiving vector
3095 * @param {ReadonlyVec3} a the vector to scale
3096 * @param {Number} b amount to scale the vector by
3097 * @returns {vec3} out
3098 */
3099
3100 function scale$1(out, a, b) {
3101 out[0] = a[0] * b;
3102 out[1] = a[1] * b;
3103 out[2] = a[2] * b;
3104 return out;
3105 }
3106 /**
3107 * Normalize a vec3
3108 *
3109 * @param {vec3} out the receiving vector
3110 * @param {ReadonlyVec3} a vector to normalize
3111 * @returns {vec3} out
3112 */
3113
3114 function normalize(out, a) {
3115 var x = a[0];
3116 var y = a[1];
3117 var z = a[2];
3118 var len = x * x + y * y + z * z;
3119
3120 if (len > 0) {
3121 //TODO: evaluate use of glm_invsqrt here?
3122 len = 1 / Math.sqrt(len);
3123 }
3124
3125 out[0] = a[0] * len;
3126 out[1] = a[1] * len;
3127 out[2] = a[2] * len;
3128 return out;
3129 }
3130 /**
3131 * Calculates the dot product of two vec3's
3132 *
3133 * @param {ReadonlyVec3} a the first operand
3134 * @param {ReadonlyVec3} b the second operand
3135 * @returns {Number} dot product of a and b
3136 */
3137
3138 function dot(a, b) {
3139 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
3140 }
3141 /**
3142 * Computes the cross product of two vec3's
3143 *
3144 * @param {vec3} out the receiving vector
3145 * @param {ReadonlyVec3} a the first operand
3146 * @param {ReadonlyVec3} b the second operand
3147 * @returns {vec3} out
3148 */
3149
3150 function cross(out, a, b) {
3151 var ax = a[0],
3152 ay = a[1],
3153 az = a[2];
3154 var bx = b[0],
3155 by = b[1],
3156 bz = b[2];
3157 out[0] = ay * bz - az * by;
3158 out[1] = az * bx - ax * bz;
3159 out[2] = ax * by - ay * bx;
3160 return out;
3161 }
3162 /**
3163 * Performs a linear interpolation between two vec3's
3164 *
3165 * @param {vec3} out the receiving vector
3166 * @param {ReadonlyVec3} a the first operand
3167 * @param {ReadonlyVec3} b the second operand
3168 * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
3169 * @returns {vec3} out
3170 */
3171
3172 function lerp(out, a, b, t) {
3173 var ax = a[0];
3174 var ay = a[1];
3175 var az = a[2];
3176 out[0] = ax + t * (b[0] - ax);
3177 out[1] = ay + t * (b[1] - ay);
3178 out[2] = az + t * (b[2] - az);
3179 return out;
3180 }
3181 /**
3182 * Transforms the vec3 with a mat4.
3183 * 4th vector component is implicitly '1'
3184 *
3185 * @param {vec3} out the receiving vector
3186 * @param {ReadonlyVec3} a the vector to transform
3187 * @param {ReadonlyMat4} m matrix to transform with
3188 * @returns {vec3} out
3189 */
3190
3191 function transformMat4(out, a, m) {
3192 var x = a[0],
3193 y = a[1],
3194 z = a[2];
3195 var w = m[3] * x + m[7] * y + m[11] * z + m[15];
3196 w = w || 1.0;
3197 out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
3198 out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
3199 out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
3200 return out;
3201 }
3202 /**
3203 * Transforms the vec3 with a mat3.
3204 *
3205 * @param {vec3} out the receiving vector
3206 * @param {ReadonlyVec3} a the vector to transform
3207 * @param {ReadonlyMat3} m the 3x3 matrix to transform with
3208 * @returns {vec3} out
3209 */
3210
3211 function transformMat3(out, a, m) {
3212 var x = a[0],
3213 y = a[1],
3214 z = a[2];
3215 out[0] = x * m[0] + y * m[3] + z * m[6];
3216 out[1] = x * m[1] + y * m[4] + z * m[7];
3217 out[2] = x * m[2] + y * m[5] + z * m[8];
3218 return out;
3219 }
3220 /**
3221 * Transforms the vec3 with a quat
3222 * Can also be used for dual quaternions. (Multiply it with the real part)
3223 *
3224 * @param {vec3} out the receiving vector
3225 * @param {ReadonlyVec3} a the vector to transform
3226 * @param {ReadonlyQuat} q quaternion to transform with
3227 * @returns {vec3} out
3228 */
3229
3230 function transformQuat(out, a, q) {
3231 // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed
3232 var qx = q[0],
3233 qy = q[1],
3234 qz = q[2],
3235 qw = q[3];
3236 var x = a[0],
3237 y = a[1],
3238 z = a[2]; // var qvec = [qx, qy, qz];
3239 // var uv = vec3.cross([], qvec, a);
3240
3241 var uvx = qy * z - qz * y,
3242 uvy = qz * x - qx * z,
3243 uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);
3244
3245 var uuvx = qy * uvz - qz * uvy,
3246 uuvy = qz * uvx - qx * uvz,
3247 uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);
3248
3249 var w2 = qw * 2;
3250 uvx *= w2;
3251 uvy *= w2;
3252 uvz *= w2; // vec3.scale(uuv, uuv, 2);
3253
3254 uuvx *= 2;
3255 uuvy *= 2;
3256 uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));
3257
3258 out[0] = x + uvx + uuvx;
3259 out[1] = y + uvy + uuvy;
3260 out[2] = z + uvz + uuvz;
3261 return out;
3262 }
3263 /**
3264 * Returns whether or not the vectors have approximately the same elements in the same position.
3265 *
3266 * @param {ReadonlyVec3} a The first vector.
3267 * @param {ReadonlyVec3} b The second vector.
3268 * @returns {Boolean} True if the vectors are equal, false otherwise.
3269 */
3270
3271 function equals$1(a, b) {
3272 var a0 = a[0],
3273 a1 = a[1],
3274 a2 = a[2];
3275 var b0 = b[0],
3276 b1 = b[1],
3277 b2 = b[2];
3278 return Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));
3279 }
3280 /**
3281 * Alias for {@link vec3.length}
3282 * @function
3283 */
3284
3285 var len = length;
3286 /**
3287 * Perform some operation over an array of vec3s.
3288 *
3289 * @param {Array} a the array of vectors to iterate over
3290 * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
3291 * @param {Number} offset Number of elements to skip at the beginning of the array
3292 * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
3293 * @param {Function} fn Function to call for each vector in the array
3294 * @param {Object} [arg] additional argument to pass to fn
3295 * @returns {Array} a
3296 * @function
3297 */
3298
3299 var forEach = function () {
3300 var vec = create$2();
3301 return function (a, stride, offset, count, fn, arg) {
3302 var i, l;
3303
3304 if (!stride) {
3305 stride = 3;
3306 }
3307
3308 if (!offset) {
3309 offset = 0;
3310 }
3311
3312 if (count) {
3313 l = Math.min(count * stride + offset, a.length);
3314 } else {
3315 l = a.length;
3316 }
3317
3318 for (i = offset; i < l; i += stride) {
3319 vec[0] = a[i];
3320 vec[1] = a[i + 1];
3321 vec[2] = a[i + 2];
3322 fn(vec, vec, arg);
3323 a[i] = vec[0];
3324 a[i + 1] = vec[1];
3325 a[i + 2] = vec[2];
3326 }
3327
3328 return a;
3329 };
3330 }();
3331
3332 /**
3333 * 4 Dimensional Vector
3334 * @module vec4
3335 */
3336
3337 /**
3338 * Creates a new, empty vec4
3339 *
3340 * @returns {vec4} a new 4D vector
3341 */
3342
3343 function create$3() {
3344 var out = new ARRAY_TYPE(4);
3345
3346 if (ARRAY_TYPE != Float32Array) {
3347 out[0] = 0;
3348 out[1] = 0;
3349 out[2] = 0;
3350 out[3] = 0;
3351 }
3352
3353 return out;
3354 }
3355 /**
3356 * Creates a new vec4 initialized with the given values
3357 *
3358 * @param {Number} x X component
3359 * @param {Number} y Y component
3360 * @param {Number} z Z component
3361 * @param {Number} w W component
3362 * @returns {vec4} a new 4D vector
3363 */
3364
3365 function fromValues$3(x, y, z, w) {
3366 var out = new ARRAY_TYPE(4);
3367 out[0] = x;
3368 out[1] = y;
3369 out[2] = z;
3370 out[3] = w;
3371 return out;
3372 }
3373 /**
3374 * Copy the values from one vec4 to another
3375 *
3376 * @param {vec4} out the receiving vector
3377 * @param {ReadonlyVec4} a the source vector
3378 * @returns {vec4} out
3379 */
3380
3381 function copy$2(out, a) {
3382 out[0] = a[0];
3383 out[1] = a[1];
3384 out[2] = a[2];
3385 out[3] = a[3];
3386 return out;
3387 }
3388 /**
3389 * Normalize a vec4
3390 *
3391 * @param {vec4} out the receiving vector
3392 * @param {ReadonlyVec4} a vector to normalize
3393 * @returns {vec4} out
3394 */
3395
3396 function normalize$1(out, a) {
3397 var x = a[0];
3398 var y = a[1];
3399 var z = a[2];
3400 var w = a[3];
3401 var len = x * x + y * y + z * z + w * w;
3402
3403 if (len > 0) {
3404 len = 1 / Math.sqrt(len);
3405 }
3406
3407 out[0] = x * len;
3408 out[1] = y * len;
3409 out[2] = z * len;
3410 out[3] = w * len;
3411 return out;
3412 }
3413 /**
3414 * Transforms the vec4 with a mat4.
3415 *
3416 * @param {vec4} out the receiving vector
3417 * @param {ReadonlyVec4} a the vector to transform
3418 * @param {ReadonlyMat4} m matrix to transform with
3419 * @returns {vec4} out
3420 */
3421
3422 function transformMat4$1(out, a, m) {
3423 var x = a[0],
3424 y = a[1],
3425 z = a[2],
3426 w = a[3];
3427 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
3428 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
3429 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
3430 out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
3431 return out;
3432 }
3433 /**
3434 * Perform some operation over an array of vec4s.
3435 *
3436 * @param {Array} a the array of vectors to iterate over
3437 * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
3438 * @param {Number} offset Number of elements to skip at the beginning of the array
3439 * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
3440 * @param {Function} fn Function to call for each vector in the array
3441 * @param {Object} [arg] additional argument to pass to fn
3442 * @returns {Array} a
3443 * @function
3444 */
3445
3446 var forEach$1 = function () {
3447 var vec = create$3();
3448 return function (a, stride, offset, count, fn, arg) {
3449 var i, l;
3450
3451 if (!stride) {
3452 stride = 4;
3453 }
3454
3455 if (!offset) {
3456 offset = 0;
3457 }
3458
3459 if (count) {
3460 l = Math.min(count * stride + offset, a.length);
3461 } else {
3462 l = a.length;
3463 }
3464
3465 for (i = offset; i < l; i += stride) {
3466 vec[0] = a[i];
3467 vec[1] = a[i + 1];
3468 vec[2] = a[i + 2];
3469 vec[3] = a[i + 3];
3470 fn(vec, vec, arg);
3471 a[i] = vec[0];
3472 a[i + 1] = vec[1];
3473 a[i + 2] = vec[2];
3474 a[i + 3] = vec[3];
3475 }
3476
3477 return a;
3478 };
3479 }();
3480
3481 /**
3482 * Quaternion
3483 * @module quat
3484 */
3485
3486 /**
3487 * Creates a new identity quat
3488 *
3489 * @returns {quat} a new quaternion
3490 */
3491
3492 function create$4() {
3493 var out = new ARRAY_TYPE(4);
3494
3495 if (ARRAY_TYPE != Float32Array) {
3496 out[0] = 0;
3497 out[1] = 0;
3498 out[2] = 0;
3499 }
3500
3501 out[3] = 1;
3502 return out;
3503 }
3504 /**
3505 * Sets a quat from the given angle and rotation axis,
3506 * then returns it.
3507 *
3508 * @param {quat} out the receiving quaternion
3509 * @param {ReadonlyVec3} axis the axis around which to rotate
3510 * @param {Number} rad the angle in radians
3511 * @returns {quat} out
3512 **/
3513
3514 function setAxisAngle(out, axis, rad) {
3515 rad = rad * 0.5;
3516 var s = Math.sin(rad);
3517 out[0] = s * axis[0];
3518 out[1] = s * axis[1];
3519 out[2] = s * axis[2];
3520 out[3] = Math.cos(rad);
3521 return out;
3522 }
3523 /**
3524 * Multiplies two quat's
3525 *
3526 * @param {quat} out the receiving quaternion
3527 * @param {ReadonlyQuat} a the first operand
3528 * @param {ReadonlyQuat} b the second operand
3529 * @returns {quat} out
3530 */
3531
3532 function multiply$2(out, a, b) {
3533 var ax = a[0],
3534 ay = a[1],
3535 az = a[2],
3536 aw = a[3];
3537 var bx = b[0],
3538 by = b[1],
3539 bz = b[2],
3540 bw = b[3];
3541 out[0] = ax * bw + aw * bx + ay * bz - az * by;
3542 out[1] = ay * bw + aw * by + az * bx - ax * bz;
3543 out[2] = az * bw + aw * bz + ax * by - ay * bx;
3544 out[3] = aw * bw - ax * bx - ay * by - az * bz;
3545 return out;
3546 }
3547 /**
3548 * Performs a spherical linear interpolation between two quat
3549 *
3550 * @param {quat} out the receiving quaternion
3551 * @param {ReadonlyQuat} a the first operand
3552 * @param {ReadonlyQuat} b the second operand
3553 * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
3554 * @returns {quat} out
3555 */
3556
3557 function slerp(out, a, b, t) {
3558 // benchmarks:
3559 // http://jsperf.com/quaternion-slerp-implementations
3560 var ax = a[0],
3561 ay = a[1],
3562 az = a[2],
3563 aw = a[3];
3564 var bx = b[0],
3565 by = b[1],
3566 bz = b[2],
3567 bw = b[3];
3568 var omega, cosom, sinom, scale0, scale1; // calc cosine
3569
3570 cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)
3571
3572 if (cosom < 0.0) {
3573 cosom = -cosom;
3574 bx = -bx;
3575 by = -by;
3576 bz = -bz;
3577 bw = -bw;
3578 } // calculate coefficients
3579
3580
3581 if (1.0 - cosom > EPSILON) {
3582 // standard case (slerp)
3583 omega = Math.acos(cosom);
3584 sinom = Math.sin(omega);
3585 scale0 = Math.sin((1.0 - t) * omega) / sinom;
3586 scale1 = Math.sin(t * omega) / sinom;
3587 } else {
3588 // "from" and "to" quaternions are very close
3589 // ... so we can do a linear interpolation
3590 scale0 = 1.0 - t;
3591 scale1 = t;
3592 } // calculate final values
3593
3594
3595 out[0] = scale0 * ax + scale1 * bx;
3596 out[1] = scale0 * ay + scale1 * by;
3597 out[2] = scale0 * az + scale1 * bz;
3598 out[3] = scale0 * aw + scale1 * bw;
3599 return out;
3600 }
3601 /**
3602 * Calculates the inverse of a quat
3603 *
3604 * @param {quat} out the receiving quaternion
3605 * @param {ReadonlyQuat} a quat to calculate inverse of
3606 * @returns {quat} out
3607 */
3608
3609 function invert$1(out, a) {
3610 var a0 = a[0],
3611 a1 = a[1],
3612 a2 = a[2],
3613 a3 = a[3];
3614 var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
3615 var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
3616
3617 out[0] = -a0 * invDot;
3618 out[1] = -a1 * invDot;
3619 out[2] = -a2 * invDot;
3620 out[3] = a3 * invDot;
3621 return out;
3622 }
3623 /**
3624 * Creates a quaternion from the given 3x3 rotation matrix.
3625 *
3626 * NOTE: The resultant quaternion is not normalized, so you should be sure
3627 * to renormalize the quaternion yourself where necessary.
3628 *
3629 * @param {quat} out the receiving quaternion
3630 * @param {ReadonlyMat3} m rotation matrix
3631 * @returns {quat} out
3632 * @function
3633 */
3634
3635 function fromMat3(out, m) {
3636 // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
3637 // article "Quaternion Calculus and Fast Animation".
3638 var fTrace = m[0] + m[4] + m[8];
3639 var fRoot;
3640
3641 if (fTrace > 0.0) {
3642 // |w| > 1/2, may as well choose w > 1/2
3643 fRoot = Math.sqrt(fTrace + 1.0); // 2w
3644
3645 out[3] = 0.5 * fRoot;
3646 fRoot = 0.5 / fRoot; // 1/(4w)
3647
3648 out[0] = (m[5] - m[7]) * fRoot;
3649 out[1] = (m[6] - m[2]) * fRoot;
3650 out[2] = (m[1] - m[3]) * fRoot;
3651 } else {
3652 // |w| <= 1/2
3653 var i = 0;
3654 if (m[4] > m[0]) i = 1;
3655 if (m[8] > m[i * 3 + i]) i = 2;
3656 var j = (i + 1) % 3;
3657 var k = (i + 2) % 3;
3658 fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);
3659 out[i] = 0.5 * fRoot;
3660 fRoot = 0.5 / fRoot;
3661 out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;
3662 out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
3663 out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
3664 }
3665
3666 return out;
3667 }
3668 /**
3669 * Creates a quaternion from the given euler angle x, y, z.
3670 *
3671 * @param {quat} out the receiving quaternion
3672 * @param {x} Angle to rotate around X axis in degrees.
3673 * @param {y} Angle to rotate around Y axis in degrees.
3674 * @param {z} Angle to rotate around Z axis in degrees.
3675 * @returns {quat} out
3676 * @function
3677 */
3678
3679 function fromEuler(out, x, y, z) {
3680 var halfToRad = 0.5 * Math.PI / 180.0;
3681 x *= halfToRad;
3682 y *= halfToRad;
3683 z *= halfToRad;
3684 var sx = Math.sin(x);
3685 var cx = Math.cos(x);
3686 var sy = Math.sin(y);
3687 var cy = Math.cos(y);
3688 var sz = Math.sin(z);
3689 var cz = Math.cos(z);
3690 out[0] = sx * cy * cz - cx * sy * sz;
3691 out[1] = cx * sy * cz + sx * cy * sz;
3692 out[2] = cx * cy * sz - sx * sy * cz;
3693 out[3] = cx * cy * cz + sx * sy * sz;
3694 return out;
3695 }
3696 /**
3697 * Creates a new quat initialized with the given values
3698 *
3699 * @param {Number} x X component
3700 * @param {Number} y Y component
3701 * @param {Number} z Z component
3702 * @param {Number} w W component
3703 * @returns {quat} a new quaternion
3704 * @function
3705 */
3706
3707 var fromValues$4 = fromValues$3;
3708 /**
3709 * Copy the values from one quat to another
3710 *
3711 * @param {quat} out the receiving quaternion
3712 * @param {ReadonlyQuat} a the source quaternion
3713 * @returns {quat} out
3714 * @function
3715 */
3716
3717 var copy$3 = copy$2;
3718 /**
3719 * Alias for {@link quat.multiply}
3720 * @function
3721 */
3722
3723 var mul$1 = multiply$2;
3724 /**
3725 * Normalize a quat
3726 *
3727 * @param {quat} out the receiving quaternion
3728 * @param {ReadonlyQuat} a quaternion to normalize
3729 * @returns {quat} out
3730 * @function
3731 */
3732
3733 var normalize$2 = normalize$1;
3734 /**
3735 * Sets a quaternion to represent the shortest rotation from one
3736 * vector to another.
3737 *
3738 * Both vectors are assumed to be unit length.
3739 *
3740 * @param {quat} out the receiving quaternion.
3741 * @param {ReadonlyVec3} a the initial vector
3742 * @param {ReadonlyVec3} b the destination vector
3743 * @returns {quat} out
3744 */
3745
3746 var rotationTo = function () {
3747 var tmpvec3 = create$2();
3748 var xUnitVec3 = fromValues$2(1, 0, 0);
3749 var yUnitVec3 = fromValues$2(0, 1, 0);
3750 return function (out, a, b) {
3751 var dot$1 = dot(a, b);
3752
3753 if (dot$1 < -0.999999) {
3754 cross(tmpvec3, xUnitVec3, a);
3755 if (len(tmpvec3) < 0.000001) cross(tmpvec3, yUnitVec3, a);
3756 normalize(tmpvec3, tmpvec3);
3757 setAxisAngle(out, tmpvec3, Math.PI);
3758 return out;
3759 } else if (dot$1 > 0.999999) {
3760 out[0] = 0;
3761 out[1] = 0;
3762 out[2] = 0;
3763 out[3] = 1;
3764 return out;
3765 } else {
3766 cross(tmpvec3, a, b);
3767 out[0] = tmpvec3[0];
3768 out[1] = tmpvec3[1];
3769 out[2] = tmpvec3[2];
3770 out[3] = 1 + dot$1;
3771 return normalize$2(out, out);
3772 }
3773 };
3774 }();
3775 /**
3776 * Performs a spherical linear interpolation with two control points
3777 *
3778 * @param {quat} out the receiving quaternion
3779 * @param {ReadonlyQuat} a the first operand
3780 * @param {ReadonlyQuat} b the second operand
3781 * @param {ReadonlyQuat} c the third operand
3782 * @param {ReadonlyQuat} d the fourth operand
3783 * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
3784 * @returns {quat} out
3785 */
3786
3787 var sqlerp = function () {
3788 var temp1 = create$4();
3789 var temp2 = create$4();
3790 return function (out, a, b, c, d, t) {
3791 slerp(temp1, a, d, t);
3792 slerp(temp2, b, c, t);
3793 slerp(out, temp1, temp2, 2 * t * (1 - t));
3794 return out;
3795 };
3796 }();
3797 /**
3798 * Sets the specified quaternion with values corresponding to the given
3799 * axes. Each axis is a vec3 and is expected to be unit length and
3800 * perpendicular to all other specified axes.
3801 *
3802 * @param {ReadonlyVec3} view the vector representing the viewing direction
3803 * @param {ReadonlyVec3} right the vector representing the local "right" direction
3804 * @param {ReadonlyVec3} up the vector representing the local "up" direction
3805 * @returns {quat} out
3806 */
3807
3808 var setAxes = function () {
3809 var matr = create();
3810 return function (out, view, right, up) {
3811 matr[0] = right[0];
3812 matr[3] = right[1];
3813 matr[6] = right[2];
3814 matr[1] = up[0];
3815 matr[4] = up[1];
3816 matr[7] = up[2];
3817 matr[2] = -view[0];
3818 matr[5] = -view[1];
3819 matr[8] = -view[2];
3820 return normalize$2(out, fromMat3(out, matr));
3821 };
3822 }();
3823
3824 /**
3825 * 2 Dimensional Vector
3826 * @module vec2
3827 */
3828
3829 /**
3830 * Creates a new, empty vec2
3831 *
3832 * @returns {vec2} a new 2D vector
3833 */
3834
3835 function create$5() {
3836 var out = new ARRAY_TYPE(2);
3837
3838 if (ARRAY_TYPE != Float32Array) {
3839 out[0] = 0;
3840 out[1] = 0;
3841 }
3842
3843 return out;
3844 }
3845 /**
3846 * Creates a new vec2 initialized with the given values
3847 *
3848 * @param {Number} x X component
3849 * @param {Number} y Y component
3850 * @returns {vec2} a new 2D vector
3851 */
3852
3853 function fromValues$5(x, y) {
3854 var out = new ARRAY_TYPE(2);
3855 out[0] = x;
3856 out[1] = y;
3857 return out;
3858 }
3859 /**
3860 * Copy the values from one vec2 to another
3861 *
3862 * @param {vec2} out the receiving vector
3863 * @param {ReadonlyVec2} a the source vector
3864 * @returns {vec2} out
3865 */
3866
3867 function copy$4(out, a) {
3868 out[0] = a[0];
3869 out[1] = a[1];
3870 return out;
3871 }
3872 /**
3873 * Adds two vec2's
3874 *
3875 * @param {vec2} out the receiving vector
3876 * @param {ReadonlyVec2} a the first operand
3877 * @param {ReadonlyVec2} b the second operand
3878 * @returns {vec2} out
3879 */
3880
3881 function add$2(out, a, b) {
3882 out[0] = a[0] + b[0];
3883 out[1] = a[1] + b[1];
3884 return out;
3885 }
3886 /**
3887 * Subtracts vector b from vector a
3888 *
3889 * @param {vec2} out the receiving vector
3890 * @param {ReadonlyVec2} a the first operand
3891 * @param {ReadonlyVec2} b the second operand
3892 * @returns {vec2} out
3893 */
3894
3895 function subtract$2(out, a, b) {
3896 out[0] = a[0] - b[0];
3897 out[1] = a[1] - b[1];
3898 return out;
3899 }
3900 /**
3901 * Returns the minimum of two vec2's
3902 *
3903 * @param {vec2} out the receiving vector
3904 * @param {ReadonlyVec2} a the first operand
3905 * @param {ReadonlyVec2} b the second operand
3906 * @returns {vec2} out
3907 */
3908
3909 function min$1(out, a, b) {
3910 out[0] = Math.min(a[0], b[0]);
3911 out[1] = Math.min(a[1], b[1]);
3912 return out;
3913 }
3914 /**
3915 * Returns the maximum of two vec2's
3916 *
3917 * @param {vec2} out the receiving vector
3918 * @param {ReadonlyVec2} a the first operand
3919 * @param {ReadonlyVec2} b the second operand
3920 * @returns {vec2} out
3921 */
3922
3923 function max$1(out, a, b) {
3924 out[0] = Math.max(a[0], b[0]);
3925 out[1] = Math.max(a[1], b[1]);
3926 return out;
3927 }
3928 /**
3929 * Scales a vec2 by a scalar number
3930 *
3931 * @param {vec2} out the receiving vector
3932 * @param {ReadonlyVec2} a the vector to scale
3933 * @param {Number} b amount to scale the vector by
3934 * @returns {vec2} out
3935 */
3936
3937 function scale$2(out, a, b) {
3938 out[0] = a[0] * b;
3939 out[1] = a[1] * b;
3940 return out;
3941 }
3942 /**
3943 * Calculates the euclidian distance between two vec2's
3944 *
3945 * @param {ReadonlyVec2} a the first operand
3946 * @param {ReadonlyVec2} b the second operand
3947 * @returns {Number} distance between a and b
3948 */
3949
3950 function distance(a, b) {
3951 var x = b[0] - a[0],
3952 y = b[1] - a[1];
3953 return Math.hypot(x, y);
3954 }
3955 /**
3956 * Calculates the length of a vec2
3957 *
3958 * @param {ReadonlyVec2} a vector to calculate length of
3959 * @returns {Number} length of a
3960 */
3961
3962 function length$1(a) {
3963 var x = a[0],
3964 y = a[1];
3965 return Math.hypot(x, y);
3966 }
3967 /**
3968 * Normalize a vec2
3969 *
3970 * @param {vec2} out the receiving vector
3971 * @param {ReadonlyVec2} a vector to normalize
3972 * @returns {vec2} out
3973 */
3974
3975 function normalize$3(out, a) {
3976 var x = a[0],
3977 y = a[1];
3978 var len = x * x + y * y;
3979
3980 if (len > 0) {
3981 //TODO: evaluate use of glm_invsqrt here?
3982 len = 1 / Math.sqrt(len);
3983 }
3984
3985 out[0] = a[0] * len;
3986 out[1] = a[1] * len;
3987 return out;
3988 }
3989 /**
3990 * Calculates the dot product of two vec2's
3991 *
3992 * @param {ReadonlyVec2} a the first operand
3993 * @param {ReadonlyVec2} b the second operand
3994 * @returns {Number} dot product of a and b
3995 */
3996
3997 function dot$1(a, b) {
3998 return a[0] * b[0] + a[1] * b[1];
3999 }
4000 /**
4001 * Transforms the vec2 with a mat2d
4002 *
4003 * @param {vec2} out the receiving vector
4004 * @param {ReadonlyVec2} a the vector to transform
4005 * @param {ReadonlyMat2d} m matrix to transform with
4006 * @returns {vec2} out
4007 */
4008
4009 function transformMat2d(out, a, m) {
4010 var x = a[0],
4011 y = a[1];
4012 out[0] = m[0] * x + m[2] * y + m[4];
4013 out[1] = m[1] * x + m[3] * y + m[5];
4014 return out;
4015 }
4016 /**
4017 * Get the angle between two 2D vectors
4018 * @param {ReadonlyVec2} a The first operand
4019 * @param {ReadonlyVec2} b The second operand
4020 * @returns {Number} The angle in radians
4021 */
4022
4023 function angle(a, b) {
4024 var x1 = a[0],
4025 y1 = a[1],
4026 x2 = b[0],
4027 y2 = b[1],
4028 // mag is the product of the magnitudes of a and b
4029 mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2),
4030 // mag &&.. short circuits if mag == 0
4031 cosine = mag && (x1 * x2 + y1 * y2) / mag; // Math.min(Math.max(cosine, -1), 1) clamps the cosine between -1 and 1
4032
4033 return Math.acos(Math.min(Math.max(cosine, -1), 1));
4034 }
4035 /**
4036 * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===)
4037 *
4038 * @param {ReadonlyVec2} a The first vector.
4039 * @param {ReadonlyVec2} b The second vector.
4040 * @returns {Boolean} True if the vectors are equal, false otherwise.
4041 */
4042
4043 function exactEquals$1(a, b) {
4044 return a[0] === b[0] && a[1] === b[1];
4045 }
4046 /**
4047 * Alias for {@link vec2.subtract}
4048 * @function
4049 */
4050
4051 var sub$1 = subtract$2;
4052 /**
4053 * Perform some operation over an array of vec2s.
4054 *
4055 * @param {Array} a the array of vectors to iterate over
4056 * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
4057 * @param {Number} offset Number of elements to skip at the beginning of the array
4058 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
4059 * @param {Function} fn Function to call for each vector in the array
4060 * @param {Object} [arg] additional argument to pass to fn
4061 * @returns {Array} a
4062 * @function
4063 */
4064
4065 var forEach$2 = function () {
4066 var vec = create$5();
4067 return function (a, stride, offset, count, fn, arg) {
4068 var i, l;
4069
4070 if (!stride) {
4071 stride = 2;
4072 }
4073
4074 if (!offset) {
4075 offset = 0;
4076 }
4077
4078 if (count) {
4079 l = Math.min(count * stride + offset, a.length);
4080 } else {
4081 l = a.length;
4082 }
4083
4084 for (i = offset; i < l; i += stride) {
4085 vec[0] = a[i];
4086 vec[1] = a[i + 1];
4087 fn(vec, vec, arg);
4088 a[i] = vec[0];
4089 a[i + 1] = vec[1];
4090 }
4091
4092 return a;
4093 };
4094 }();
4095
4096 /**
4097 * Rounds the values of a `PathArray` instance to
4098 * a specified amount of decimals and returns it.
4099 */
4100 function roundPath(path, round) {
4101 if (round === 'off')
4102 return [].concat(path);
4103 // to round values to the power
4104 // the `round` value must be integer
4105 var pow = typeof round === 'number' && round >= 1 ? Math.pow(10, round) : 1;
4106 return path.map(function (pi) {
4107 var values = pi
4108 .slice(1)
4109 .map(Number)
4110 .map(function (n) { return (round ? Math.round(n * pow) / pow : Math.round(n)); });
4111 // @ts-ignore
4112 return [pi[0]].concat(values);
4113 });
4114 }
4115
4116 /**
4117 * Returns a valid `d` attribute string value created
4118 * by rounding values and concatenating the `pathArray` segments.
4119 */
4120 function path2String(path, round) {
4121 if (round === void 0) { round = 'off'; }
4122 return roundPath(path, round)
4123 .map(function (x) { return x[0] + x.slice(1).join(' '); })
4124 .join('');
4125 }
4126
4127 var paramsParser = {
4128 x1: 0,
4129 y1: 0,
4130 x2: 0,
4131 y2: 0,
4132 x: 0,
4133 y: 0,
4134 qx: null,
4135 qy: null,
4136 };
4137
4138 function fixArc(pathArray, allPathCommands, i) {
4139 if (pathArray[i].length > 7) {
4140 pathArray[i].shift();
4141 var pi = pathArray[i];
4142 // const ni = i + 1;
4143 var ni = i;
4144 while (pi.length) {
4145 // if created multiple C:s, their original seg is saved
4146 allPathCommands[i] = 'A';
4147 // @ts-ignore
4148 pathArray.splice((ni += 1), 0, ['C'].concat(pi.splice(0, 6)));
4149 }
4150 pathArray.splice(i, 1);
4151 }
4152 }
4153
4154 var paramsCount = {
4155 a: 7,
4156 c: 6,
4157 h: 1,
4158 l: 2,
4159 m: 2,
4160 r: 4,
4161 q: 4,
4162 s: 4,
4163 t: 2,
4164 v: 1,
4165 z: 0,
4166 };
4167
4168 /**
4169 * Iterates an array to check if it's an actual `PathArray`.
4170 */
4171 function isPathArray(path) {
4172 return (Array.isArray(path) &&
4173 path.every(function (seg) {
4174 var lk = seg[0].toLowerCase();
4175 return paramsCount[lk] === seg.length - 1 && 'achlmqstvz'.includes(lk);
4176 }));
4177 }
4178
4179 /**
4180 * Iterates an array to check if it's a `PathArray`
4181 * with all absolute values.
4182 */
4183 function isAbsoluteArray(path) {
4184 return (isPathArray(path) &&
4185 // @ts-ignore -- `isPathArray` also checks if it's `Array`
4186 path.every(function (_a) {
4187 var x = _a[0];
4188 return x === x.toUpperCase();
4189 }));
4190 }
4191
4192 /**
4193 * Iterates an array to check if it's a `PathArray`
4194 * with all segments are in non-shorthand notation
4195 * with absolute values.
4196 */
4197 function isNormalizedArray(path) {
4198 return isAbsoluteArray(path) && path.every(function (_a) {
4199 var pc = _a[0];
4200 return 'ACLMQZ'.includes(pc);
4201 });
4202 }
4203
4204 /**
4205 * Breaks the parsing of a pathString once a segment is finalized.
4206 */
4207 function finalizeSegment(path) {
4208 var pathCommand = path.pathValue[path.segmentStart];
4209 var LK = pathCommand.toLowerCase();
4210 var data = path.data;
4211 while (data.length >= paramsCount[LK]) {
4212 // overloaded `moveTo`
4213 // https://github.com/rveciana/svg-path-properties/blob/master/src/parse.ts
4214 if (LK === 'm' && data.length > 2) {
4215 // @ts-ignore
4216 path.segments.push([pathCommand].concat(data.splice(0, 2)));
4217 LK = 'l';
4218 pathCommand = pathCommand === 'm' ? 'l' : 'L';
4219 }
4220 else {
4221 // @ts-ignore
4222 path.segments.push([pathCommand].concat(data.splice(0, paramsCount[LK])));
4223 }
4224 if (!paramsCount[LK]) {
4225 break;
4226 }
4227 }
4228 }
4229
4230 /**
4231 * Validates an A (arc-to) specific path command value.
4232 * Usually a `large-arc-flag` or `sweep-flag`.
4233 */
4234 function scanFlag(path) {
4235 var index = path.index, pathValue = path.pathValue;
4236 var code = pathValue.charCodeAt(index);
4237 if (code === 0x30 /* 0 */) {
4238 path.param = 0;
4239 path.index += 1;
4240 return;
4241 }
4242 if (code === 0x31 /* 1 */) {
4243 path.param = 1;
4244 path.index += 1;
4245 return;
4246 }
4247 path.err = "[path-util]: invalid Arc flag \"" + pathValue[index] + "\", expecting 0 or 1 at index " + index;
4248 }
4249
4250 /**
4251 * Checks if the character is or belongs to a number.
4252 * [0-9]|+|-|.
4253 */
4254 function isDigitStart(code) {
4255 return ((code >= 48 && code <= 57) /* 0..9 */ || code === 0x2b /* + */ || code === 0x2d /* - */ || code === 0x2e); /* . */
4256 }
4257 function isDigit(code) {
4258 return code >= 48 && code <= 57; // 0..9
4259 }
4260
4261 /**
4262 * Validates every character of the path string,
4263 * every path command, negative numbers or floating point numbers.
4264 */
4265 function scanParam(path) {
4266 var max = path.max, pathValue = path.pathValue, start = path.index;
4267 var index = start;
4268 var zeroFirst = false;
4269 var hasCeiling = false;
4270 var hasDecimal = false;
4271 var hasDot = false;
4272 var ch;
4273 if (index >= max) {
4274 // path.err = 'SvgPath: missed param (at pos ' + index + ')';
4275 path.err = "[path-util]: Invalid path value at index " + index + ", \"pathValue\" is missing param";
4276 return;
4277 }
4278 ch = pathValue.charCodeAt(index);
4279 if (ch === 0x2b /* + */ || ch === 0x2d /* - */) {
4280 index += 1;
4281 // ch = (index < max) ? pathValue.charCodeAt(index) : 0;
4282 ch = pathValue.charCodeAt(index);
4283 }
4284 // This logic is shamelessly borrowed from Esprima
4285 // https://github.com/ariya/esprimas
4286 if (!isDigit(ch) && ch !== 0x2e /* . */) {
4287 // path.err = 'SvgPath: param should start with 0..9 or `.` (at pos ' + index + ')';
4288 path.err = "[path-util]: Invalid path value at index " + index + ", \"" + pathValue[index] + "\" is not a number";
4289 return;
4290 }
4291 if (ch !== 0x2e /* . */) {
4292 zeroFirst = ch === 0x30 /* 0 */;
4293 index += 1;
4294 ch = pathValue.charCodeAt(index);
4295 if (zeroFirst && index < max) {
4296 // decimal number starts with '0' such as '09' is illegal.
4297 if (ch && isDigit(ch)) {
4298 // path.err = 'SvgPath: numbers started with `0` such as `09`
4299 // are illegal (at pos ' + start + ')';
4300 path.err = "[path-util]: Invalid path value at index " + start + ", \"" + pathValue[start] + "\" illegal number";
4301 return;
4302 }
4303 }
4304 while (index < max && isDigit(pathValue.charCodeAt(index))) {
4305 index += 1;
4306 hasCeiling = true;
4307 }
4308 ch = pathValue.charCodeAt(index);
4309 }
4310 if (ch === 0x2e /* . */) {
4311 hasDot = true;
4312 index += 1;
4313 while (isDigit(pathValue.charCodeAt(index))) {
4314 index += 1;
4315 hasDecimal = true;
4316 }
4317 ch = pathValue.charCodeAt(index);
4318 }
4319 if (ch === 0x65 /* e */ || ch === 0x45 /* E */) {
4320 if (hasDot && !hasCeiling && !hasDecimal) {
4321 path.err = "[path-util]: Invalid path value at index " + index + ", \"" + pathValue[index] + "\" invalid float exponent";
4322 return;
4323 }
4324 index += 1;
4325 ch = pathValue.charCodeAt(index);
4326 if (ch === 0x2b /* + */ || ch === 0x2d /* - */) {
4327 index += 1;
4328 }
4329 if (index < max && isDigit(pathValue.charCodeAt(index))) {
4330 while (index < max && isDigit(pathValue.charCodeAt(index))) {
4331 index += 1;
4332 }
4333 }
4334 else {
4335 path.err = "[path-util]: Invalid path value at index " + index + ", \"" + pathValue[index] + "\" invalid integer exponent";
4336 return;
4337 }
4338 }
4339 path.index = index;
4340 path.param = +path.pathValue.slice(start, index);
4341 }
4342
4343 /**
4344 * Checks if the character is a space.
4345 */
4346 function isSpace(ch) {
4347 var specialSpaces = [
4348 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x202f,
4349 0x205f, 0x3000, 0xfeff,
4350 ];
4351 /* istanbul ignore next */
4352 return (ch === 0x0a ||
4353 ch === 0x0d ||
4354 ch === 0x2028 ||
4355 ch === 0x2029 || // Line terminators
4356 // White spaces
4357 ch === 0x20 ||
4358 ch === 0x09 ||
4359 ch === 0x0b ||
4360 ch === 0x0c ||
4361 ch === 0xa0 ||
4362 (ch >= 0x1680 && specialSpaces.includes(ch)));
4363 }
4364
4365 /**
4366 * Points the parser to the next character in the
4367 * path string every time it encounters any kind of
4368 * space character.
4369 */
4370 function skipSpaces(path) {
4371 var pathValue = path.pathValue, max = path.max;
4372 while (path.index < max && isSpace(pathValue.charCodeAt(path.index))) {
4373 path.index += 1;
4374 }
4375 }
4376
4377 /**
4378 * Checks if the character is a path command.
4379 */
4380 function isPathCommand(code) {
4381 // eslint-disable-next-line no-bitwise -- Impossible to satisfy
4382 switch (code | 0x20) {
4383 case 0x6d /* m */:
4384 case 0x7a /* z */:
4385 case 0x6c /* l */:
4386 case 0x68 /* h */:
4387 case 0x76 /* v */:
4388 case 0x63 /* c */:
4389 case 0x73 /* s */:
4390 case 0x71 /* q */:
4391 case 0x74 /* t */:
4392 case 0x61 /* a */:
4393 // case 0x72/* r */:
4394 return true;
4395 default:
4396 return false;
4397 }
4398 }
4399
4400 /**
4401 * Checks if the character is an A (arc-to) path command.
4402 */
4403 function isArcCommand(code) {
4404 return (code | 0x20) === 0x61;
4405 }
4406
4407 /**
4408 * Scans every character in the path string to determine
4409 * where a segment starts and where it ends.
4410 */
4411 function scanSegment(path) {
4412 var max = path.max, pathValue = path.pathValue, index = path.index;
4413 var cmdCode = pathValue.charCodeAt(index);
4414 var reqParams = paramsCount[pathValue[index].toLowerCase()];
4415 path.segmentStart = index;
4416 if (!isPathCommand(cmdCode)) {
4417 path.err = "[path-util]: Invalid path value \"" + pathValue[index] + "\" is not a path command";
4418 return;
4419 }
4420 path.index += 1;
4421 skipSpaces(path);
4422 path.data = [];
4423 if (!reqParams) {
4424 // Z
4425 finalizeSegment(path);
4426 return;
4427 }
4428 for (;;) {
4429 for (var i = reqParams; i > 0; i -= 1) {
4430 if (isArcCommand(cmdCode) && (i === 3 || i === 4))
4431 scanFlag(path);
4432 else
4433 scanParam(path);
4434 if (path.err.length) {
4435 return;
4436 }
4437 path.data.push(path.param);
4438 skipSpaces(path);
4439 // after ',' param is mandatory
4440 if (path.index < max && pathValue.charCodeAt(path.index) === 0x2c /* , */) {
4441 path.index += 1;
4442 skipSpaces(path);
4443 }
4444 }
4445 if (path.index >= path.max) {
4446 break;
4447 }
4448 // Stop on next segment
4449 if (!isDigitStart(pathValue.charCodeAt(path.index))) {
4450 break;
4451 }
4452 }
4453 finalizeSegment(path);
4454 }
4455
4456 /**
4457 * The `PathParser` is used by the `parsePathString` static method
4458 * to generate a `pathArray`.
4459 */
4460 var PathParser = /** @class */ (function () {
4461 function PathParser(pathString) {
4462 this.pathValue = pathString;
4463 // @ts-ignore
4464 this.segments = [];
4465 this.max = pathString.length;
4466 this.index = 0;
4467 this.param = 0.0;
4468 this.segmentStart = 0;
4469 this.data = [];
4470 this.err = '';
4471 }
4472 return PathParser;
4473 }());
4474
4475 /**
4476 * Parses a path string value and returns an array
4477 * of segments we like to call `pathArray`.
4478 */
4479 function parsePathString(pathInput) {
4480 if (isPathArray(pathInput)) {
4481 return [].concat(pathInput);
4482 }
4483 var path = new PathParser(pathInput);
4484 skipSpaces(path);
4485 while (path.index < path.max && !path.err.length) {
4486 scanSegment(path);
4487 }
4488 return path.err ? path.err : path.segments;
4489 }
4490
4491 function path2Absolute(pathInput) {
4492 if (isAbsoluteArray(pathInput)) {
4493 return [].concat(pathInput);
4494 }
4495 var path = parsePathString(pathInput);
4496 // if (!path || !path.length) {
4497 // return [['M', 0, 0]];
4498 // }
4499 var x = 0;
4500 var y = 0;
4501 var mx = 0;
4502 var my = 0;
4503 // @ts-ignore
4504 return path.map(function (segment) {
4505 var values = segment.slice(1).map(Number);
4506 var pathCommand = segment[0];
4507 var absCommand = pathCommand.toUpperCase();
4508 if (pathCommand === 'M') {
4509 x = values[0], y = values[1];
4510 mx = x;
4511 my = y;
4512 return ['M', x, y];
4513 }
4514 var absoluteSegment;
4515 if (pathCommand !== absCommand) {
4516 switch (absCommand) {
4517 case 'A':
4518 absoluteSegment = [
4519 absCommand,
4520 values[0],
4521 values[1],
4522 values[2],
4523 values[3],
4524 values[4],
4525 values[5] + x,
4526 values[6] + y,
4527 ];
4528 break;
4529 case 'V':
4530 absoluteSegment = [absCommand, values[0] + y];
4531 break;
4532 case 'H':
4533 absoluteSegment = [absCommand, values[0] + x];
4534 break;
4535 default: {
4536 // use brakets for `eslint: no-case-declaration`
4537 // https://stackoverflow.com/a/50753272/803358
4538 var absValues = values.map(function (n, j) { return n + (j % 2 ? y : x); });
4539 // for n, l, c, s, q, t
4540 // @ts-ignore
4541 absoluteSegment = [absCommand].concat(absValues);
4542 }
4543 }
4544 }
4545 else {
4546 // @ts-ignore
4547 absoluteSegment = [absCommand].concat(values);
4548 }
4549 var segLength = absoluteSegment.length;
4550 switch (absCommand) {
4551 case 'Z':
4552 x = mx;
4553 y = my;
4554 break;
4555 case 'H':
4556 x = absoluteSegment[1];
4557 break;
4558 case 'V':
4559 y = absoluteSegment[1];
4560 break;
4561 default:
4562 x = absoluteSegment[segLength - 2];
4563 y = absoluteSegment[segLength - 1];
4564 if (absCommand === 'M') {
4565 mx = x;
4566 my = y;
4567 }
4568 }
4569 return absoluteSegment;
4570 });
4571 }
4572
4573 /**
4574 * Normalizes a single segment of a `PathArray` object.
4575 * eg. H/V -> L, T -> Q
4576 */
4577 function normalizeSegment(segment, params) {
4578 var pathCommand = segment[0];
4579 var px1 = params.x1, py1 = params.y1, px2 = params.x2, py2 = params.y2;
4580 var values = segment.slice(1).map(Number);
4581 var result = segment;
4582 if (!'TQ'.includes(pathCommand)) {
4583 // optional but good to be cautious
4584 params.qx = null;
4585 params.qy = null;
4586 }
4587 if (pathCommand === 'H') {
4588 result = ['L', segment[1], py1];
4589 }
4590 else if (pathCommand === 'V') {
4591 result = ['L', px1, segment[1]];
4592 }
4593 else if (pathCommand === 'S') {
4594 var x1 = px1 * 2 - px2;
4595 var y1 = py1 * 2 - py2;
4596 params.x1 = x1;
4597 params.y1 = y1;
4598 result = ['C', x1, y1].concat(values);
4599 }
4600 else if (pathCommand === 'T') {
4601 var qx = px1 * 2 - params.qx;
4602 var qy = py1 * 2 - params.qy;
4603 params.qx = qx;
4604 params.qy = qy;
4605 result = ['Q', qx, qy].concat(values);
4606 }
4607 else if (pathCommand === 'Q') {
4608 var nqx = values[0], nqy = values[1];
4609 params.qx = nqx;
4610 params.qy = nqy;
4611 }
4612 return result;
4613 }
4614
4615 /**
4616 * @example
4617 * const path = 'M0 0 H50';
4618 * const normalizedPath = SVGPathCommander.normalizePath(path);
4619 * // result => [['M', 0, 0], ['L', 50, 0]]
4620 */
4621 function normalizePath(pathInput) {
4622 if (isNormalizedArray(pathInput)) {
4623 return [].concat(pathInput);
4624 }
4625 var path = path2Absolute(pathInput);
4626 var params = __assign({}, paramsParser);
4627 for (var i = 0; i < path.length; i += 1) {
4628 // Save current path command
4629 path[i] = normalizeSegment(path[i], params);
4630 var segment = path[i];
4631 var seglen = segment.length;
4632 params.x1 = +segment[seglen - 2];
4633 params.y1 = +segment[seglen - 1];
4634 params.x2 = +segment[seglen - 4] || params.x1;
4635 params.y2 = +segment[seglen - 3] || params.y1;
4636 }
4637 return path;
4638 }
4639
4640 /**
4641 * Iterates an array to check if it's a `PathArray`
4642 * with all C (cubic bezier) segments.
4643 *
4644 * @param {string | PathArray} path the `Array` to be checked
4645 * @returns {boolean} iteration result
4646 */
4647 function isCurveArray(path) {
4648 return isNormalizedArray(path) && path.every(function (_a) {
4649 var pc = _a[0];
4650 return 'MC'.includes(pc);
4651 });
4652 }
4653
4654 function rotateVector(x, y, rad) {
4655 var X = x * Math.cos(rad) - y * Math.sin(rad);
4656 var Y = x * Math.sin(rad) + y * Math.cos(rad);
4657 return { x: X, y: Y };
4658 }
4659
4660 /**
4661 * Converts A (arc-to) segments to C (cubic-bezier-to).
4662 *
4663 * For more information of where this math came from visit:
4664 * http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
4665 */
4666 function arcToCubic(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, recursive) {
4667 var x1 = X1;
4668 var y1 = Y1;
4669 var rx = RX;
4670 var ry = RY;
4671 var x2 = X2;
4672 var y2 = Y2;
4673 // for more information of where this Math came from visit:
4674 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
4675 var d120 = (Math.PI * 120) / 180;
4676 var rad = (Math.PI / 180) * (+angle || 0);
4677 /** @type {number[]} */
4678 var res = [];
4679 var xy;
4680 var f1;
4681 var f2;
4682 var cx;
4683 var cy;
4684 if (!recursive) {
4685 xy = rotateVector(x1, y1, -rad);
4686 x1 = xy.x;
4687 y1 = xy.y;
4688 xy = rotateVector(x2, y2, -rad);
4689 x2 = xy.x;
4690 y2 = xy.y;
4691 var x = (x1 - x2) / 2;
4692 var y = (y1 - y2) / 2;
4693 var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
4694 if (h > 1) {
4695 h = Math.sqrt(h);
4696 rx *= h;
4697 ry *= h;
4698 }
4699 var rx2 = rx * rx;
4700 var ry2 = ry * ry;
4701 var k = (LAF === SF ? -1 : 1) *
4702 Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
4703 cx = (k * rx * y) / ry + (x1 + x2) / 2;
4704 cy = (k * -ry * x) / rx + (y1 + y2) / 2;
4705 // eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
4706 f1 = Math.asin(((((y1 - cy) / ry) * Math.pow(10, 9)) >> 0) / Math.pow(10, 9));
4707 // eslint-disable-next-line no-bitwise -- Impossible to satisfy no-bitwise
4708 f2 = Math.asin(((((y2 - cy) / ry) * Math.pow(10, 9)) >> 0) / Math.pow(10, 9));
4709 f1 = x1 < cx ? Math.PI - f1 : f1;
4710 f2 = x2 < cx ? Math.PI - f2 : f2;
4711 if (f1 < 0)
4712 f1 = Math.PI * 2 + f1;
4713 if (f2 < 0)
4714 f2 = Math.PI * 2 + f2;
4715 if (SF && f1 > f2) {
4716 f1 -= Math.PI * 2;
4717 }
4718 if (!SF && f2 > f1) {
4719 f2 -= Math.PI * 2;
4720 }
4721 }
4722 else {
4723 f1 = recursive[0], f2 = recursive[1], cx = recursive[2], cy = recursive[3];
4724 }
4725 var df = f2 - f1;
4726 if (Math.abs(df) > d120) {
4727 var f2old = f2;
4728 var x2old = x2;
4729 var y2old = y2;
4730 f2 = f1 + d120 * (SF && f2 > f1 ? 1 : -1);
4731 x2 = cx + rx * Math.cos(f2);
4732 y2 = cy + ry * Math.sin(f2);
4733 res = arcToCubic(x2, y2, rx, ry, angle, 0, SF, x2old, y2old, [f2, f2old, cx, cy]);
4734 }
4735 df = f2 - f1;
4736 var c1 = Math.cos(f1);
4737 var s1 = Math.sin(f1);
4738 var c2 = Math.cos(f2);
4739 var s2 = Math.sin(f2);
4740 var t = Math.tan(df / 4);
4741 var hx = (4 / 3) * rx * t;
4742 var hy = (4 / 3) * ry * t;
4743 var m1 = [x1, y1];
4744 var m2 = [x1 + hx * s1, y1 - hy * c1];
4745 var m3 = [x2 + hx * s2, y2 - hy * c2];
4746 var m4 = [x2, y2];
4747 m2[0] = 2 * m1[0] - m2[0];
4748 m2[1] = 2 * m1[1] - m2[1];
4749 if (recursive) {
4750 return m2.concat(m3, m4, res);
4751 // return [...m2, ...m3, ...m4, ...res];
4752 }
4753 res = m2.concat(m3, m4, res);
4754 // res = [...m2, ...m3, ...m4, ...res];
4755 var newres = [];
4756 for (var i = 0, ii = res.length; i < ii; i += 1) {
4757 newres[i] = i % 2 ? rotateVector(res[i - 1], res[i], rad).y : rotateVector(res[i], res[i + 1], rad).x;
4758 }
4759 return newres;
4760 }
4761 // const TAU = Math.PI * 2;
4762 // const mapToEllipse = (
4763 // { x, y }: { x: number; y: number },
4764 // rx: number,
4765 // ry: number,
4766 // cosphi: number,
4767 // sinphi: number,
4768 // centerx: number,
4769 // centery: number,
4770 // ) => {
4771 // x *= rx;
4772 // y *= ry;
4773 // const xp = cosphi * x - sinphi * y;
4774 // const yp = sinphi * x + cosphi * y;
4775 // return {
4776 // x: xp + centerx,
4777 // y: yp + centery,
4778 // };
4779 // };
4780 // const approxUnitArc = (ang1: number, ang2: number) => {
4781 // // If 90 degree circular arc, use a constant
4782 // // as derived from http://spencermortensen.com/articles/bezier-circle
4783 // const a =
4784 // ang2 === 1.5707963267948966
4785 // ? 0.551915024494
4786 // : ang2 === -1.5707963267948966
4787 // ? -0.551915024494
4788 // : (4 / 3) * Math.tan(ang2 / 4);
4789 // const x1 = Math.cos(ang1);
4790 // const y1 = Math.sin(ang1);
4791 // const x2 = Math.cos(ang1 + ang2);
4792 // const y2 = Math.sin(ang1 + ang2);
4793 // return [
4794 // {
4795 // x: x1 - y1 * a,
4796 // y: y1 + x1 * a,
4797 // },
4798 // {
4799 // x: x2 + y2 * a,
4800 // y: y2 - x2 * a,
4801 // },
4802 // {
4803 // x: x2,
4804 // y: y2,
4805 // },
4806 // ];
4807 // };
4808 // const vectorAngle = (ux: number, uy: number, vx: number, vy: number) => {
4809 // const sign = ux * vy - uy * vx < 0 ? -1 : 1;
4810 // let dot = ux * vx + uy * vy;
4811 // if (dot > 1) {
4812 // dot = 1;
4813 // }
4814 // if (dot < -1) {
4815 // dot = -1;
4816 // }
4817 // return sign * Math.acos(dot);
4818 // };
4819 // const getArcCenter = (
4820 // px: any,
4821 // py: any,
4822 // cx: any,
4823 // cy: any,
4824 // rx: number,
4825 // ry: number,
4826 // largeArcFlag: number,
4827 // sweepFlag: number,
4828 // sinphi: number,
4829 // cosphi: number,
4830 // pxp: number,
4831 // pyp: number,
4832 // ) => {
4833 // const rxsq = Math.pow(rx, 2);
4834 // const rysq = Math.pow(ry, 2);
4835 // const pxpsq = Math.pow(pxp, 2);
4836 // const pypsq = Math.pow(pyp, 2);
4837 // let radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq;
4838 // if (radicant < 0) {
4839 // radicant = 0;
4840 // }
4841 // radicant /= rxsq * pypsq + rysq * pxpsq;
4842 // radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1);
4843 // const centerxp = ((radicant * rx) / ry) * pyp;
4844 // const centeryp = ((radicant * -ry) / rx) * pxp;
4845 // const centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2;
4846 // const centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2;
4847 // const vx1 = (pxp - centerxp) / rx;
4848 // const vy1 = (pyp - centeryp) / ry;
4849 // const vx2 = (-pxp - centerxp) / rx;
4850 // const vy2 = (-pyp - centeryp) / ry;
4851 // const ang1 = vectorAngle(1, 0, vx1, vy1);
4852 // let ang2 = vectorAngle(vx1, vy1, vx2, vy2);
4853 // if (sweepFlag === 0 && ang2 > 0) {
4854 // ang2 -= TAU;
4855 // }
4856 // if (sweepFlag === 1 && ang2 < 0) {
4857 // ang2 += TAU;
4858 // }
4859 // return [centerx, centery, ang1, ang2];
4860 // };
4861 // const arcToBezier = ({ px, py, cx, cy, rx, ry, xAxisRotation = 0, largeArcFlag = 0, sweepFlag = 0 }) => {
4862 // const curves = [];
4863 // if (rx === 0 || ry === 0) {
4864 // return [{ x1: 0, y1: 0, x2: 0, y2: 0, x: cx, y: cy }];
4865 // }
4866 // const sinphi = Math.sin((xAxisRotation * TAU) / 360);
4867 // const cosphi = Math.cos((xAxisRotation * TAU) / 360);
4868 // const pxp = (cosphi * (px - cx)) / 2 + (sinphi * (py - cy)) / 2;
4869 // const pyp = (-sinphi * (px - cx)) / 2 + (cosphi * (py - cy)) / 2;
4870 // if (pxp === 0 && pyp === 0) {
4871 // return [{ x1: 0, y1: 0, x2: 0, y2: 0, x: cx, y: cy }];
4872 // }
4873 // rx = Math.abs(rx);
4874 // ry = Math.abs(ry);
4875 // const lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2);
4876 // if (lambda > 1) {
4877 // rx *= Math.sqrt(lambda);
4878 // ry *= Math.sqrt(lambda);
4879 // }
4880 // let [centerx, centery, ang1, ang2] = getArcCenter(
4881 // px,
4882 // py,
4883 // cx,
4884 // cy,
4885 // rx,
4886 // ry,
4887 // largeArcFlag,
4888 // sweepFlag,
4889 // sinphi,
4890 // cosphi,
4891 // pxp,
4892 // pyp,
4893 // );
4894 // // If 'ang2' == 90.0000000001, then `ratio` will evaluate to
4895 // // 1.0000000001. This causes `segments` to be greater than one, which is an
4896 // // unecessary split, and adds extra points to the bezier curve. To alleviate
4897 // // this issue, we round to 1.0 when the ratio is close to 1.0.
4898 // let ratio = Math.abs(ang2) / (TAU / 4);
4899 // if (Math.abs(1.0 - ratio) < 0.0000001) {
4900 // ratio = 1.0;
4901 // }
4902 // const segments = Math.max(Math.ceil(ratio), 1);
4903 // ang2 /= segments;
4904 // for (let i = 0; i < segments; i++) {
4905 // curves.push(approxUnitArc(ang1, ang2));
4906 // ang1 += ang2;
4907 // }
4908 // return curves.map((curve) => {
4909 // const { x: x1, y: y1 } = mapToEllipse(curve[0], rx, ry, cosphi, sinphi, centerx, centery);
4910 // const { x: x2, y: y2 } = mapToEllipse(curve[1], rx, ry, cosphi, sinphi, centerx, centery);
4911 // const { x, y } = mapToEllipse(curve[2], rx, ry, cosphi, sinphi, centerx, centery);
4912 // return { x1, y1, x2, y2, x, y };
4913 // });
4914 // };
4915 // export function arcToCubic(
4916 // x1: number,
4917 // y1: number,
4918 // rx: number,
4919 // ry: number,
4920 // angle: number,
4921 // LAF: number,
4922 // SF: number,
4923 // x2: number,
4924 // y2: number,
4925 // ) {
4926 // const curves = arcToBezier({
4927 // px: x1,
4928 // py: y1,
4929 // cx: x2,
4930 // cy: y2,
4931 // rx,
4932 // ry,
4933 // xAxisRotation: angle,
4934 // largeArcFlag: LAF,
4935 // sweepFlag: SF,
4936 // });
4937 // return curves.reduce((prev, cur) => {
4938 // const { x1, y1, x2, y2, x, y } = cur;
4939 // prev.push(x1, y1, x2, y2, x, y);
4940 // return prev;
4941 // }, [] as number[]);
4942 // }
4943
4944 function quadToCubic(x1, y1, qx, qy, x2, y2) {
4945 var r13 = 1 / 3;
4946 var r23 = 2 / 3;
4947 return [
4948 r13 * x1 + r23 * qx,
4949 r13 * y1 + r23 * qy,
4950 r13 * x2 + r23 * qx,
4951 r13 * y2 + r23 * qy,
4952 x2,
4953 y2, // x,y
4954 ];
4955 }
4956
4957 function midPoint(a, b, t) {
4958 var ax = a[0];
4959 var ay = a[1];
4960 var bx = b[0];
4961 var by = b[1];
4962 return [ax + (bx - ax) * t, ay + (by - ay) * t];
4963 }
4964
4965 var lineToCubic = function (x1, y1, x2, y2) {
4966 var t = 0.5;
4967 var mid = midPoint([x1, y1], [x2, y2], t);
4968 return __spreadArray(__spreadArray([], mid, true), [x2, y2, x2, y2], false);
4969 };
4970
4971 function segmentToCubic(segment, params) {
4972 var pathCommand = segment[0];
4973 var values = segment.slice(1).map(Number);
4974 var x = values[0], y = values[1];
4975 var args;
4976 var px1 = params.x1, py1 = params.y1, px = params.x, py = params.y;
4977 if (!'TQ'.includes(pathCommand)) {
4978 params.qx = null;
4979 params.qy = null;
4980 }
4981 switch (pathCommand) {
4982 case 'M':
4983 params.x = x;
4984 params.y = y;
4985 return segment;
4986 case 'A':
4987 args = [px1, py1].concat(values);
4988 // @ts-ignore
4989 return ['C'].concat(arcToCubic(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]));
4990 case 'Q':
4991 params.qx = x;
4992 params.qy = y;
4993 args = [px1, py1].concat(values);
4994 // @ts-ignore
4995 return ['C'].concat(quadToCubic(args[0], args[1], args[2], args[3], args[4], args[5]));
4996 case 'L':
4997 // @ts-ignore
4998 return ['C'].concat(lineToCubic(px1, py1, x, y));
4999 case 'Z':
5000 // prevent NaN from divide 0
5001 if (px1 === px && py1 === py) {
5002 return ['C', px1, py1, px, py, px, py];
5003 }
5004 // @ts-ignore
5005 return ['C'].concat(lineToCubic(px1, py1, px, py));
5006 }
5007 return segment;
5008 }
5009
5010 // import { fixPath } from '../process/fix-path';
5011 function path2Curve(pathInput, needZCommandIndexes) {
5012 if (needZCommandIndexes === void 0) { needZCommandIndexes = false; }
5013 if (isCurveArray(pathInput)) {
5014 var cloned = [].concat(pathInput);
5015 if (needZCommandIndexes) {
5016 return [cloned, []];
5017 }
5018 else {
5019 return cloned;
5020 }
5021 }
5022 // fixPath will remove 'Z' command
5023 // const path = fixPath(normalizePath(pathInput));
5024 var path = normalizePath(pathInput);
5025 var params = __assign({}, paramsParser);
5026 var allPathCommands = [];
5027 var pathCommand = '';
5028 var ii = path.length;
5029 var segment;
5030 var seglen;
5031 var zCommandIndexes = [];
5032 for (var i = 0; i < ii; i += 1) {
5033 if (path[i])
5034 pathCommand = path[i][0];
5035 allPathCommands[i] = pathCommand;
5036 var curveSegment = segmentToCubic(path[i], params);
5037 path[i] = curveSegment;
5038 fixArc(path, allPathCommands, i);
5039 ii = path.length; // solves curveArrays ending in Z
5040 // keep Z command account for lineJoin
5041 // @see https://github.com/antvis/util/issues/68
5042 if (pathCommand === 'Z') {
5043 zCommandIndexes.push(i);
5044 }
5045 segment = path[i];
5046 seglen = segment.length;
5047 params.x1 = +segment[seglen - 2];
5048 params.y1 = +segment[seglen - 1];
5049 params.x2 = +segment[seglen - 4] || params.x1;
5050 params.y2 = +segment[seglen - 3] || params.y1;
5051 }
5052 // validate
5053 if (needZCommandIndexes) {
5054 return [path, zCommandIndexes];
5055 }
5056 else {
5057 return path;
5058 }
5059 }
5060
5061 function clonePath(path) {
5062 return path.map(function (x) { return (Array.isArray(x) ? [].concat(x) : x); });
5063 }
5064
5065 // reverse CURVE based pathArray segments only
5066 function reverseCurve(pathArray) {
5067 var rotatedCurve = pathArray
5068 .slice(1)
5069 .map(function (x, i, curveOnly) {
5070 // @ts-ignore
5071 return !i ? pathArray[0].slice(1).concat(x.slice(1)) : curveOnly[i - 1].slice(-2).concat(x.slice(1));
5072 })
5073 // @ts-ignore
5074 .map(function (x) { return x.map(function (y, i) { return x[x.length - i - 2 * (1 - (i % 2))]; }); })
5075 .reverse();
5076 return [['M'].concat(rotatedCurve[0].slice(0, 2))].concat(rotatedCurve.map(function (x) { return ['C'].concat(x.slice(2)); }));
5077 }
5078
5079 function distanceSquareRoot(a, b) {
5080 return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]));
5081 }
5082
5083 /**
5084 * Returns a {x,y} point at a given length, the total length and
5085 * the minimum and maximum {x,y} coordinates of a line (L,V,H,Z) segment.
5086 */
5087 function segmentLineFactory(x1, y1, x2, y2, distance) {
5088 var length = distanceSquareRoot([x1, y1], [x2, y2]);
5089 var point = { x: 0, y: 0 };
5090 if (typeof distance === 'number') {
5091 if (distance <= 0) {
5092 point = { x: x1, y: y1 };
5093 }
5094 else if (distance >= length) {
5095 point = { x: x2, y: y2 };
5096 }
5097 else {
5098 var _a = midPoint([x1, y1], [x2, y2], distance / length), x = _a[0], y = _a[1];
5099 point = { x: x, y: y };
5100 }
5101 }
5102 return {
5103 length: length,
5104 point: point,
5105 min: {
5106 x: Math.min(x1, x2),
5107 y: Math.min(y1, y2),
5108 },
5109 max: {
5110 x: Math.max(x1, x2),
5111 y: Math.max(y1, y2),
5112 },
5113 };
5114 }
5115
5116 function angleBetween(v0, v1) {
5117 var v0x = v0.x, v0y = v0.y;
5118 var v1x = v1.x, v1y = v1.y;
5119 var p = v0x * v1x + v0y * v1y;
5120 var n = Math.sqrt((Math.pow(v0x, 2) + Math.pow(v0y, 2)) * (Math.pow(v1x, 2) + Math.pow(v1y, 2)));
5121 var sign = v0x * v1y - v0y * v1x < 0 ? -1 : 1;
5122 var angle = sign * Math.acos(p / n);
5123 return angle;
5124 }
5125 /**
5126 * Returns a {x,y} point at a given length, the total length and
5127 * the minimum and maximum {x,y} coordinates of a C (cubic-bezier) segment.
5128 * @see https://github.com/MadLittleMods/svg-curve-lib/blob/master/src/js/svg-curve-lib.js
5129 */
5130 function getPointAtArcSegmentLength(x1, y1, RX, RY, angle, LAF, SF, x, y, t) {
5131 var abs = Math.abs, sin = Math.sin, cos = Math.cos, sqrt = Math.sqrt, PI = Math.PI;
5132 var rx = abs(RX);
5133 var ry = abs(RY);
5134 var xRot = ((angle % 360) + 360) % 360;
5135 var xRotRad = xRot * (PI / 180);
5136 if (x1 === x && y1 === y) {
5137 return { x: x1, y: y1 };
5138 }
5139 if (rx === 0 || ry === 0) {
5140 return segmentLineFactory(x1, y1, x, y, t).point;
5141 }
5142 var dx = (x1 - x) / 2;
5143 var dy = (y1 - y) / 2;
5144 var transformedPoint = {
5145 x: cos(xRotRad) * dx + sin(xRotRad) * dy,
5146 y: -sin(xRotRad) * dx + cos(xRotRad) * dy,
5147 };
5148 var radiiCheck = Math.pow(transformedPoint.x, 2) / Math.pow(rx, 2) + Math.pow(transformedPoint.y, 2) / Math.pow(ry, 2);
5149 if (radiiCheck > 1) {
5150 rx *= sqrt(radiiCheck);
5151 ry *= sqrt(radiiCheck);
5152 }
5153 var cSquareNumerator = Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) - Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
5154 var cSquareRootDenom = Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) + Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
5155 var cRadicand = cSquareNumerator / cSquareRootDenom;
5156 cRadicand = cRadicand < 0 ? 0 : cRadicand;
5157 var cCoef = (LAF !== SF ? 1 : -1) * sqrt(cRadicand);
5158 var transformedCenter = {
5159 x: cCoef * ((rx * transformedPoint.y) / ry),
5160 y: cCoef * (-(ry * transformedPoint.x) / rx),
5161 };
5162 var center = {
5163 x: cos(xRotRad) * transformedCenter.x - sin(xRotRad) * transformedCenter.y + (x1 + x) / 2,
5164 y: sin(xRotRad) * transformedCenter.x + cos(xRotRad) * transformedCenter.y + (y1 + y) / 2,
5165 };
5166 var startVector = {
5167 x: (transformedPoint.x - transformedCenter.x) / rx,
5168 y: (transformedPoint.y - transformedCenter.y) / ry,
5169 };
5170 var startAngle = angleBetween({ x: 1, y: 0 }, startVector);
5171 var endVector = {
5172 x: (-transformedPoint.x - transformedCenter.x) / rx,
5173 y: (-transformedPoint.y - transformedCenter.y) / ry,
5174 };
5175 var sweepAngle = angleBetween(startVector, endVector);
5176 if (!SF && sweepAngle > 0) {
5177 sweepAngle -= 2 * PI;
5178 }
5179 else if (SF && sweepAngle < 0) {
5180 sweepAngle += 2 * PI;
5181 }
5182 sweepAngle %= 2 * PI;
5183 var alpha = startAngle + sweepAngle * t;
5184 var ellipseComponentX = rx * cos(alpha);
5185 var ellipseComponentY = ry * sin(alpha);
5186 var point = {
5187 x: cos(xRotRad) * ellipseComponentX - sin(xRotRad) * ellipseComponentY + center.x,
5188 y: sin(xRotRad) * ellipseComponentX + cos(xRotRad) * ellipseComponentY + center.y,
5189 };
5190 // to be used later
5191 // point.ellipticalArcStartAngle = startAngle;
5192 // point.ellipticalArcEndAngle = startAngle + sweepAngle;
5193 // point.ellipticalArcAngle = alpha;
5194 // point.ellipticalArcCenter = center;
5195 // point.resultantRx = rx;
5196 // point.resultantRy = ry;
5197 return point;
5198 }
5199 /**
5200 * Returns a {x,y} point at a given length, the total length and
5201 * the shape minimum and maximum {x,y} coordinates of an A (arc-to) segment.
5202 *
5203 * For better performance, it can skip calculate bbox or length in some scenario.
5204 */
5205 function segmentArcFactory(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, distance, options) {
5206 var _a;
5207 var _b = options.bbox, bbox = _b === void 0 ? true : _b, _c = options.length, length = _c === void 0 ? true : _c, _d = options.sampleSize, sampleSize = _d === void 0 ? 30 : _d;
5208 var distanceIsNumber = typeof distance === 'number';
5209 var x = X1;
5210 var y = Y1;
5211 var LENGTH = 0;
5212 var prev = [x, y, LENGTH];
5213 var cur = [x, y];
5214 var t = 0;
5215 var POINT = { x: 0, y: 0 };
5216 var POINTS = [{ x: x, y: y }];
5217 if (distanceIsNumber && distance <= 0) {
5218 POINT = { x: x, y: y };
5219 }
5220 // bad perf when size > 100
5221 for (var j = 0; j <= sampleSize; j += 1) {
5222 t = j / sampleSize;
5223 (_a = getPointAtArcSegmentLength(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, t), x = _a.x, y = _a.y);
5224 if (bbox) {
5225 POINTS.push({ x: x, y: y });
5226 }
5227 if (length) {
5228 LENGTH += distanceSquareRoot(cur, [x, y]);
5229 }
5230 cur = [x, y];
5231 if (distanceIsNumber && LENGTH >= distance && distance > prev[2]) {
5232 var dv = (LENGTH - distance) / (LENGTH - prev[2]);
5233 POINT = {
5234 x: cur[0] * (1 - dv) + prev[0] * dv,
5235 y: cur[1] * (1 - dv) + prev[1] * dv,
5236 };
5237 }
5238 prev = [x, y, LENGTH];
5239 }
5240 if (distanceIsNumber && distance >= LENGTH) {
5241 POINT = { x: X2, y: Y2 };
5242 }
5243 return {
5244 length: LENGTH,
5245 point: POINT,
5246 min: {
5247 x: Math.min.apply(null, POINTS.map(function (n) { return n.x; })),
5248 y: Math.min.apply(null, POINTS.map(function (n) { return n.y; })),
5249 },
5250 max: {
5251 x: Math.max.apply(null, POINTS.map(function (n) { return n.x; })),
5252 y: Math.max.apply(null, POINTS.map(function (n) { return n.y; })),
5253 },
5254 };
5255 }
5256
5257 /**
5258 * Returns a {x,y} point at a given length, the total length and
5259 * the minimum and maximum {x,y} coordinates of a C (cubic-bezier) segment.
5260 */
5261 function getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t) {
5262 var t1 = 1 - t;
5263 return {
5264 x: Math.pow(t1, 3) * x1 + 3 * Math.pow(t1, 2) * t * c1x + 3 * t1 * Math.pow(t, 2) * c2x + Math.pow(t, 3) * x2,
5265 y: Math.pow(t1, 3) * y1 + 3 * Math.pow(t1, 2) * t * c1y + 3 * t1 * Math.pow(t, 2) * c2y + Math.pow(t, 3) * y2,
5266 };
5267 }
5268 /**
5269 * Returns the length of a C (cubic-bezier) segment
5270 * or an {x,y} point at a given length.
5271 */
5272 function segmentCubicFactory(x1, y1, c1x, c1y, c2x, c2y, x2, y2, distance, options) {
5273 var _a;
5274 var _b = options.bbox, bbox = _b === void 0 ? true : _b, _c = options.length, length = _c === void 0 ? true : _c, _d = options.sampleSize, sampleSize = _d === void 0 ? 10 : _d;
5275 var distanceIsNumber = typeof distance === 'number';
5276 var x = x1;
5277 var y = y1;
5278 var LENGTH = 0;
5279 var prev = [x, y, LENGTH];
5280 var cur = [x, y];
5281 var t = 0;
5282 var POINT = { x: 0, y: 0 };
5283 var POINTS = [{ x: x, y: y }];
5284 if (distanceIsNumber && distance <= 0) {
5285 POINT = { x: x, y: y };
5286 }
5287 // bad perf when size = 300
5288 for (var j = 0; j <= sampleSize; j += 1) {
5289 t = j / sampleSize;
5290 (_a = getPointAtCubicSegmentLength(x1, y1, c1x, c1y, c2x, c2y, x2, y2, t), x = _a.x, y = _a.y);
5291 if (bbox) {
5292 POINTS.push({ x: x, y: y });
5293 }
5294 if (length) {
5295 LENGTH += distanceSquareRoot(cur, [x, y]);
5296 }
5297 cur = [x, y];
5298 if (distanceIsNumber && LENGTH >= distance && distance > prev[2]) {
5299 var dv = (LENGTH - distance) / (LENGTH - prev[2]);
5300 POINT = {
5301 x: cur[0] * (1 - dv) + prev[0] * dv,
5302 y: cur[1] * (1 - dv) + prev[1] * dv,
5303 };
5304 }
5305 prev = [x, y, LENGTH];
5306 }
5307 if (distanceIsNumber && distance >= LENGTH) {
5308 POINT = { x: x2, y: y2 };
5309 }
5310 return {
5311 length: LENGTH,
5312 point: POINT,
5313 min: {
5314 x: Math.min.apply(null, POINTS.map(function (n) { return n.x; })),
5315 y: Math.min.apply(null, POINTS.map(function (n) { return n.y; })),
5316 },
5317 max: {
5318 x: Math.max.apply(null, POINTS.map(function (n) { return n.x; })),
5319 y: Math.max.apply(null, POINTS.map(function (n) { return n.y; })),
5320 },
5321 };
5322 }
5323
5324 /**
5325 * Returns the {x,y} coordinates of a point at a
5326 * given length of a quadratic-bezier segment.
5327 *
5328 * @see https://github.com/substack/point-at-length
5329 */
5330 function getPointAtQuadSegmentLength(x1, y1, cx, cy, x2, y2, t) {
5331 var t1 = 1 - t;
5332 return {
5333 x: Math.pow(t1, 2) * x1 + 2 * t1 * t * cx + Math.pow(t, 2) * x2,
5334 y: Math.pow(t1, 2) * y1 + 2 * t1 * t * cy + Math.pow(t, 2) * y2,
5335 };
5336 }
5337 /**
5338 * Returns a {x,y} point at a given length, the total length and
5339 * the minimum and maximum {x,y} coordinates of a Q (quadratic-bezier) segment.
5340 */
5341 function segmentQuadFactory(x1, y1, qx, qy, x2, y2, distance, options) {
5342 var _a;
5343 var _b = options.bbox, bbox = _b === void 0 ? true : _b, _c = options.length, length = _c === void 0 ? true : _c, _d = options.sampleSize, sampleSize = _d === void 0 ? 10 : _d;
5344 var distanceIsNumber = typeof distance === 'number';
5345 var x = x1;
5346 var y = y1;
5347 var LENGTH = 0;
5348 var prev = [x, y, LENGTH];
5349 var cur = [x, y];
5350 var t = 0;
5351 var POINT = { x: 0, y: 0 };
5352 var POINTS = [{ x: x, y: y }];
5353 if (distanceIsNumber && distance <= 0) {
5354 POINT = { x: x, y: y };
5355 }
5356 for (var j = 0; j <= sampleSize; j += 1) {
5357 t = j / sampleSize;
5358 (_a = getPointAtQuadSegmentLength(x1, y1, qx, qy, x2, y2, t), x = _a.x, y = _a.y);
5359 if (bbox) {
5360 POINTS.push({ x: x, y: y });
5361 }
5362 if (length) {
5363 LENGTH += distanceSquareRoot(cur, [x, y]);
5364 }
5365 cur = [x, y];
5366 if (distanceIsNumber && LENGTH >= distance && distance > prev[2]) {
5367 var dv = (LENGTH - distance) / (LENGTH - prev[2]);
5368 POINT = {
5369 x: cur[0] * (1 - dv) + prev[0] * dv,
5370 y: cur[1] * (1 - dv) + prev[1] * dv,
5371 };
5372 }
5373 prev = [x, y, LENGTH];
5374 }
5375 /* istanbul ignore else */
5376 if (distanceIsNumber && distance >= LENGTH) {
5377 POINT = { x: x2, y: y2 };
5378 }
5379 return {
5380 length: LENGTH,
5381 point: POINT,
5382 min: {
5383 x: Math.min.apply(null, POINTS.map(function (n) { return n.x; })),
5384 y: Math.min.apply(null, POINTS.map(function (n) { return n.y; })),
5385 },
5386 max: {
5387 x: Math.max.apply(null, POINTS.map(function (n) { return n.x; })),
5388 y: Math.max.apply(null, POINTS.map(function (n) { return n.y; })),
5389 },
5390 };
5391 }
5392
5393 /**
5394 * Returns a {x,y} point at a given length
5395 * of a shape, the shape total length and
5396 * the shape minimum and maximum {x,y} coordinates.
5397 */
5398 function pathLengthFactory(pathInput, distance, options) {
5399 var _a, _b, _c, _d, _e, _f;
5400 var path = normalizePath(pathInput);
5401 var distanceIsNumber = typeof distance === 'number';
5402 var isM;
5403 var data = [];
5404 var pathCommand;
5405 var x = 0;
5406 var y = 0;
5407 var mx = 0;
5408 var my = 0;
5409 var seg;
5410 var MIN = [];
5411 var MAX = [];
5412 var length = 0;
5413 var min = { x: 0, y: 0 };
5414 var max = min;
5415 var point = min;
5416 var POINT = min;
5417 var LENGTH = 0;
5418 for (var i = 0, ll = path.length; i < ll; i += 1) {
5419 seg = path[i];
5420 pathCommand = seg[0];
5421 isM = pathCommand === 'M';
5422 data = !isM ? [x, y].concat(seg.slice(1)) : data;
5423 // this segment is always ZERO
5424 /* istanbul ignore else */
5425 if (isM) {
5426 // remember mx, my for Z
5427 mx = seg[1], my = seg[2];
5428 min = { x: mx, y: my };
5429 max = min;
5430 length = 0;
5431 if (distanceIsNumber && distance < 0.001) {
5432 POINT = min;
5433 }
5434 }
5435 else if (pathCommand === 'L') {
5436 (_a = segmentLineFactory(data[0], data[1], data[2], data[3], (distance || 0) - LENGTH), length = _a.length, min = _a.min, max = _a.max, point = _a.point);
5437 }
5438 else if (pathCommand === 'A') {
5439 (_b = segmentArcFactory(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], (distance || 0) - LENGTH, options || {}), length = _b.length, min = _b.min, max = _b.max, point = _b.point);
5440 }
5441 else if (pathCommand === 'C') {
5442 (_c = segmentCubicFactory(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], (distance || 0) - LENGTH, options || {}), length = _c.length, min = _c.min, max = _c.max, point = _c.point);
5443 }
5444 else if (pathCommand === 'Q') {
5445 (_d = segmentQuadFactory(data[0], data[1], data[2], data[3], data[4], data[5], (distance || 0) - LENGTH, options || {}), length = _d.length, min = _d.min, max = _d.max, point = _d.point);
5446 }
5447 else if (pathCommand === 'Z') {
5448 data = [x, y, mx, my];
5449 (_e = segmentLineFactory(data[0], data[1], data[2], data[3], (distance || 0) - LENGTH), length = _e.length, min = _e.min, max = _e.max, point = _e.point);
5450 }
5451 if (distanceIsNumber && LENGTH < distance && LENGTH + length >= distance) {
5452 POINT = point;
5453 }
5454 MAX.push(max);
5455 MIN.push(min);
5456 LENGTH += length;
5457 _f = pathCommand !== 'Z' ? seg.slice(-2) : [mx, my], x = _f[0], y = _f[1];
5458 }
5459 // native `getPointAtLength` behavior when the given distance
5460 // is higher than total length
5461 if (distanceIsNumber && distance >= LENGTH) {
5462 POINT = { x: x, y: y };
5463 }
5464 return {
5465 length: LENGTH,
5466 point: POINT,
5467 min: {
5468 x: Math.min.apply(null, MIN.map(function (n) { return n.x; })),
5469 y: Math.min.apply(null, MIN.map(function (n) { return n.y; })),
5470 },
5471 max: {
5472 x: Math.max.apply(null, MAX.map(function (n) { return n.x; })),
5473 y: Math.max.apply(null, MAX.map(function (n) { return n.y; })),
5474 },
5475 };
5476 }
5477
5478 /**
5479 * Returns the shape total length, or the equivalent to `shape.getTotalLength()`.
5480 *
5481 * The `normalizePath` version is lighter, faster, more efficient and more accurate
5482 * with paths that are not `curveArray`.
5483 */
5484 function getTotalLength(pathInput, options) {
5485 return pathLengthFactory(pathInput, undefined, __assign(__assign({}, options), { bbox: false, length: true })).length;
5486 }
5487
5488 function getRotations(a) {
5489 var segCount = a.length;
5490 var pointCount = segCount - 1;
5491 return a.map(function (f, idx) {
5492 return a.map(function (p, i) {
5493 var oldSegIdx = idx + i;
5494 var seg;
5495 if (i === 0 || (a[oldSegIdx] && a[oldSegIdx][0] === 'M')) {
5496 seg = a[oldSegIdx];
5497 return ['M'].concat(seg.slice(-2));
5498 }
5499 if (oldSegIdx >= segCount)
5500 oldSegIdx -= pointCount;
5501 return a[oldSegIdx];
5502 });
5503 });
5504 }
5505 function getRotatedCurve(a, b) {
5506 var segCount = a.length - 1;
5507 var lineLengths = [];
5508 var computedIndex = 0;
5509 var sumLensSqrd = 0;
5510 var rotations = getRotations(a);
5511 rotations.forEach(function (r, i) {
5512 a.slice(1).forEach(function (s, j) {
5513 // @ts-ignore
5514 sumLensSqrd += distanceSquareRoot(a[(i + j) % segCount].slice(-2), b[j % segCount].slice(-2));
5515 });
5516 lineLengths[i] = sumLensSqrd;
5517 sumLensSqrd = 0;
5518 });
5519 computedIndex = lineLengths.indexOf(Math.min.apply(null, lineLengths));
5520 return rotations[computedIndex];
5521 }
5522
5523 /**
5524 * Returns the area of a single cubic-bezier segment.
5525 *
5526 * http://objectmix.com/graphics/133553-area-closed-bezier-curve.html
5527 */
5528 function getCubicSegArea(x1, y1, c1x, c1y, c2x, c2y, x2, y2) {
5529 // https://stackoverflow.com/a/15845996
5530 return ((3 *
5531 ((y2 - y1) * (c1x + c2x) -
5532 (x2 - x1) * (c1y + c2y) +
5533 c1y * (x1 - c2x) -
5534 c1x * (y1 - c2y) +
5535 y2 * (c2x + x1 / 3) -
5536 x2 * (c2y + y1 / 3))) /
5537 20);
5538 }
5539 /**
5540 * Returns the area of a shape.
5541 * @author Jürg Lehni & Jonathan Puckey
5542 *
5543 * @see https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
5544 */
5545 function getPathArea(path) {
5546 var x = 0;
5547 var y = 0;
5548 var len = 0;
5549 return path2Curve(path)
5550 .map(function (seg) {
5551 var _a;
5552 switch (seg[0]) {
5553 case 'M':
5554 x = seg[1], y = seg[2];
5555 return 0;
5556 default:
5557 // @ts-ignore
5558 var _b = seg.slice(1), c1x = _b[0], c1y = _b[1], c2x = _b[2], c2y = _b[3], x2 = _b[4], y2 = _b[5];
5559 len = getCubicSegArea(x, y, c1x, c1y, c2x, c2y, x2, y2);
5560 _a = seg.slice(-2), x = _a[0], y = _a[1];
5561 return len;
5562 }
5563 })
5564 .reduce(function (a, b) { return a + b; }, 0);
5565 }
5566 // export function getPathArea(pathArray: AbsoluteArray) {
5567 // let x = 0;
5568 // let y = 0;
5569 // let mx = 0;
5570 // let my = 0;
5571 // let len = 0;
5572 // return pathArray
5573 // .map((seg) => {
5574 // switch (seg[0]) {
5575 // case 'M':
5576 // case 'Z':
5577 // mx = seg[0] === 'M' ? seg[1] : mx;
5578 // my = seg[0] === 'M' ? seg[2] : my;
5579 // x = mx;
5580 // y = my;
5581 // return 0;
5582 // default:
5583 // // @ts-ignore
5584 // len = getCubicSegArea.apply(0, [x, y].concat(seg.slice(1)));
5585 // [x, y] = seg.slice(-2) as [number, number];
5586 // return len;
5587 // }
5588 // })
5589 // .reduce((a, b) => a + b, 0);
5590 // }
5591
5592 function getDrawDirection(pathArray) {
5593 return getPathArea(pathArray) >= 0;
5594 }
5595
5596 /**
5597 * Returns [x,y] coordinates of a point at a given length of a shape.
5598 */
5599 function getPointAtLength(pathInput, distance, options) {
5600 return pathLengthFactory(pathInput, distance, __assign(__assign({}, options), { bbox: false, length: true })).point;
5601 }
5602
5603 function splitCubic(pts, t) {
5604 if (t === void 0) { t = 0.5; }
5605 var p0 = pts.slice(0, 2);
5606 var p1 = pts.slice(2, 4);
5607 var p2 = pts.slice(4, 6);
5608 var p3 = pts.slice(6, 8);
5609 var p4 = midPoint(p0, p1, t);
5610 var p5 = midPoint(p1, p2, t);
5611 var p6 = midPoint(p2, p3, t);
5612 var p7 = midPoint(p4, p5, t);
5613 var p8 = midPoint(p5, p6, t);
5614 var p9 = midPoint(p7, p8, t);
5615 return [
5616 // @ts-ignore
5617 ['C'].concat(p4, p7, p9),
5618 // @ts-ignore
5619 ['C'].concat(p8, p6, p3),
5620 ];
5621 }
5622 function getCurveArray(segments) {
5623 return segments.map(function (segment, i, pathArray) {
5624 // @ts-ignore
5625 var segmentData = i && pathArray[i - 1].slice(-2).concat(segment.slice(1));
5626 // @ts-ignore
5627 var curveLength = i
5628 ? segmentCubicFactory(segmentData[0], segmentData[1], segmentData[2], segmentData[3], segmentData[4], segmentData[5], segmentData[6], segmentData[7], segmentData[8], { bbox: false }).length
5629 : 0;
5630 var subsegs;
5631 if (i) {
5632 // must be [segment,segment]
5633 subsegs = curveLength ? splitCubic(segmentData) : [segment, segment];
5634 }
5635 else {
5636 subsegs = [segment];
5637 }
5638 return {
5639 s: segment,
5640 ss: subsegs,
5641 l: curveLength,
5642 };
5643 });
5644 }
5645 function equalizeSegments(path1, path2, TL) {
5646 var c1 = getCurveArray(path1);
5647 var c2 = getCurveArray(path2);
5648 var L1 = c1.length;
5649 var L2 = c2.length;
5650 var l1 = c1.filter(function (x) { return x.l; }).length;
5651 var l2 = c2.filter(function (x) { return x.l; }).length;
5652 var m1 = c1.filter(function (x) { return x.l; }).reduce(function (a, _a) {
5653 var l = _a.l;
5654 return a + l;
5655 }, 0) / l1 || 0;
5656 var m2 = c2.filter(function (x) { return x.l; }).reduce(function (a, _a) {
5657 var l = _a.l;
5658 return a + l;
5659 }, 0) / l2 || 0;
5660 var tl = TL || Math.max(L1, L2);
5661 var mm = [m1, m2];
5662 var dif = [tl - L1, tl - L2];
5663 var canSplit = 0;
5664 var result = [c1, c2].map(function (x, i) {
5665 // @ts-ignore
5666 return x.l === tl
5667 ? x.map(function (y) { return y.s; })
5668 : x
5669 .map(function (y, j) {
5670 canSplit = j && dif[i] && y.l >= mm[i];
5671 dif[i] -= canSplit ? 1 : 0;
5672 return canSplit ? y.ss : [y.s];
5673 })
5674 .flat();
5675 });
5676 return result[0].length === result[1].length ? result : equalizeSegments(result[0], result[1], tl);
5677 }
5678
5679 var Component = /** @class */function () {
5680 function Component(props, context, updater) {
5681 this.isMounted = false;
5682 // State 内部私有属性
5683 this.destroyed = false;
5684 this.props = props;
5685 this.state = {};
5686 this.context = context;
5687 this.updater = updater;
5688 }
5689 Component.prototype.willMount = function () {};
5690 Component.prototype.didMount = function () {};
5691 Component.prototype.shouldUpdate = function (_nextProps) {
5692 return true;
5693 };
5694 Component.prototype.willReceiveProps = function (_props, _context) {};
5695 Component.prototype.willUpdate = function () {};
5696 Component.prototype.didUpdate = function () {};
5697 Component.prototype.render = function () {
5698 return null;
5699 };
5700 Component.prototype.willUnmount = function () {};
5701 Component.prototype.didUnmount = function () {};
5702 Component.prototype.setState = function (partialState, callback) {
5703 if (this.destroyed) {
5704 return;
5705 }
5706 this.updater.enqueueSetState(this, partialState, callback);
5707 };
5708 Component.prototype.forceUpdate = function (callback) {
5709 if (this.destroyed) {
5710 return;
5711 }
5712 this.updater.enqueueForceUpdate(this, {}, callback);
5713 };
5714 Component.prototype.setAnimate = function (animate) {
5715 this.animate = animate;
5716 this._vNode.animate = animate;
5717 };
5718 Component.prototype.destroy = function () {
5719 this.destroyed = true;
5720 this.animator = null;
5721 };
5722 return Component;
5723 }();
5724 // 标识是否是组件
5725 // @ts-ignore
5726 Component.prototype.isF2Component = true;
5727
5728 function cloneElement(element, props) {
5729 if (!element) return element;
5730 return __assign(__assign({}, element), {
5731 props: __assign(__assign({}, element.props), props)
5732 });
5733 }
5734 function map$1(children, fn) {
5735 if (!children) {
5736 return fn(children);
5737 }
5738 if (isArray(children)) {
5739 return children.map(function (child) {
5740 return map$1(child, fn);
5741 });
5742 }
5743 return fn(children);
5744 }
5745 function compareArray(nextElements, lastElements, callback) {
5746 var keyed = {};
5747 var nextLength = nextElements.length;
5748 var lastLength = lastElements.length;
5749 for (var i = 0, len = lastLength; i < len; i++) {
5750 var element = lastElements[i];
5751 if (element && !isNil(element.key)) {
5752 var key = element.key;
5753 keyed[key] = element;
5754 }
5755 }
5756 var result = [];
5757 // 比较元素
5758 for (var i = 0, len = nextLength; i < len; i++) {
5759 var element = nextElements[i];
5760 if (!element) {
5761 continue;
5762 }
5763 var key = element.key;
5764 var lastElement = void 0;
5765 // 有key值定义
5766 if (!isNil(element.key)) {
5767 lastElement = keyed[key];
5768 if (lastElement) delete keyed[key];
5769 } else {
5770 // 取相同位置的元素
5771 lastElement = lastElements[i];
5772 }
5773 // 没有直接返回
5774 if (!lastElement) {
5775 result.push(compare(element, null, callback));
5776 continue;
5777 }
5778 // 如果 lastElement 已经被处理过, next 处理成新增
5779 if (lastElement === null || lastElement === void 0 ? void 0 : lastElement.__processed) {
5780 result.push(compare(element, null, callback));
5781 continue;
5782 }
5783 // 标记 element 已经被处理过
5784 lastElement.__processed = true;
5785 result.push(compare(element, lastElement, callback));
5786 }
5787 // 处理 lastElements 里面还未被处理的元素
5788 for (var i = 0, len = lastLength; i < len; i++) {
5789 var lastElement = lastElements[i];
5790 if (!lastElement) {
5791 continue;
5792 }
5793 if (!(lastElement === null || lastElement === void 0 ? void 0 : lastElement.__processed)) {
5794 result.push(compare(null, lastElement, callback));
5795 } else {
5796 delete lastElement.__processed;
5797 }
5798 }
5799 return result;
5800 }
5801 // 比较2棵树
5802 function compare(nextElement, lastElement, callback) {
5803 // 有一个为空
5804 if (!nextElement || !lastElement) {
5805 return callback(nextElement, lastElement);
5806 }
5807 if (isArray(nextElement) || isArray(lastElement)) {
5808 var nextElementArray = isArray(nextElement) ? nextElement : [nextElement];
5809 var lastElementArray = isArray(lastElement) ? lastElement : [lastElement];
5810 return compareArray(nextElementArray, lastElementArray, callback);
5811 }
5812 return callback(nextElement, lastElement);
5813 }
5814 function toArray(element) {
5815 if (!element) {
5816 return element;
5817 }
5818 if (!isArray(element)) {
5819 return [element];
5820 }
5821 var newArray = [];
5822 for (var i = 0, len = element.length; i < len; i++) {
5823 var item = element[i];
5824 if (isArray(item)) {
5825 newArray = newArray.concat(toArray(item));
5826 } else {
5827 newArray.push(item);
5828 }
5829 }
5830 return newArray;
5831 }
5832 var Children = {
5833 cloneElement: cloneElement,
5834 map: map$1,
5835 toArray: toArray,
5836 compare: compare
5837 };
5838
5839 function getDefaultExportFromCjs (x) {
5840 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
5841 }
5842
5843 function createCommonjsModule(fn, basedir, module) {
5844 return module = {
5845 path: basedir,
5846 exports: {},
5847 require: function (path, base) {
5848 return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
5849 }
5850 }, fn(module, module.exports), module.exports;
5851 }
5852
5853 function commonjsRequire () {
5854 throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
5855 }
5856
5857 var eventemitter3 = createCommonjsModule(function (module) {
5858
5859 var has = Object.prototype.hasOwnProperty
5860 , prefix = '~';
5861
5862 /**
5863 * Constructor to create a storage for our `EE` objects.
5864 * An `Events` instance is a plain object whose properties are event names.
5865 *
5866 * @constructor
5867 * @private
5868 */
5869 function Events() {}
5870
5871 //
5872 // We try to not inherit from `Object.prototype`. In some engines creating an
5873 // instance in this way is faster than calling `Object.create(null)` directly.
5874 // If `Object.create(null)` is not supported we prefix the event names with a
5875 // character to make sure that the built-in object properties are not
5876 // overridden or used as an attack vector.
5877 //
5878 if (Object.create) {
5879 Events.prototype = Object.create(null);
5880
5881 //
5882 // This hack is needed because the `__proto__` property is still inherited in
5883 // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
5884 //
5885 if (!new Events().__proto__) prefix = false;
5886 }
5887
5888 /**
5889 * Representation of a single event listener.
5890 *
5891 * @param {Function} fn The listener function.
5892 * @param {*} context The context to invoke the listener with.
5893 * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
5894 * @constructor
5895 * @private
5896 */
5897 function EE(fn, context, once) {
5898 this.fn = fn;
5899 this.context = context;
5900 this.once = once || false;
5901 }
5902
5903 /**
5904 * Add a listener for a given event.
5905 *
5906 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5907 * @param {(String|Symbol)} event The event name.
5908 * @param {Function} fn The listener function.
5909 * @param {*} context The context to invoke the listener with.
5910 * @param {Boolean} once Specify if the listener is a one-time listener.
5911 * @returns {EventEmitter}
5912 * @private
5913 */
5914 function addListener(emitter, event, fn, context, once) {
5915 if (typeof fn !== 'function') {
5916 throw new TypeError('The listener must be a function');
5917 }
5918
5919 var listener = new EE(fn, context || emitter, once)
5920 , evt = prefix ? prefix + event : event;
5921
5922 if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
5923 else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
5924 else emitter._events[evt] = [emitter._events[evt], listener];
5925
5926 return emitter;
5927 }
5928
5929 /**
5930 * Clear event by name.
5931 *
5932 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
5933 * @param {(String|Symbol)} evt The Event name.
5934 * @private
5935 */
5936 function clearEvent(emitter, evt) {
5937 if (--emitter._eventsCount === 0) emitter._events = new Events();
5938 else delete emitter._events[evt];
5939 }
5940
5941 /**
5942 * Minimal `EventEmitter` interface that is molded against the Node.js
5943 * `EventEmitter` interface.
5944 *
5945 * @constructor
5946 * @public
5947 */
5948 function EventEmitter() {
5949 this._events = new Events();
5950 this._eventsCount = 0;
5951 }
5952
5953 /**
5954 * Return an array listing the events for which the emitter has registered
5955 * listeners.
5956 *
5957 * @returns {Array}
5958 * @public
5959 */
5960 EventEmitter.prototype.eventNames = function eventNames() {
5961 var names = []
5962 , events
5963 , name;
5964
5965 if (this._eventsCount === 0) return names;
5966
5967 for (name in (events = this._events)) {
5968 if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
5969 }
5970
5971 if (Object.getOwnPropertySymbols) {
5972 return names.concat(Object.getOwnPropertySymbols(events));
5973 }
5974
5975 return names;
5976 };
5977
5978 /**
5979 * Return the listeners registered for a given event.
5980 *
5981 * @param {(String|Symbol)} event The event name.
5982 * @returns {Array} The registered listeners.
5983 * @public
5984 */
5985 EventEmitter.prototype.listeners = function listeners(event) {
5986 var evt = prefix ? prefix + event : event
5987 , handlers = this._events[evt];
5988
5989 if (!handlers) return [];
5990 if (handlers.fn) return [handlers.fn];
5991
5992 for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
5993 ee[i] = handlers[i].fn;
5994 }
5995
5996 return ee;
5997 };
5998
5999 /**
6000 * Return the number of listeners listening to a given event.
6001 *
6002 * @param {(String|Symbol)} event The event name.
6003 * @returns {Number} The number of listeners.
6004 * @public
6005 */
6006 EventEmitter.prototype.listenerCount = function listenerCount(event) {
6007 var evt = prefix ? prefix + event : event
6008 , listeners = this._events[evt];
6009
6010 if (!listeners) return 0;
6011 if (listeners.fn) return 1;
6012 return listeners.length;
6013 };
6014
6015 /**
6016 * Calls each of the listeners registered for a given event.
6017 *
6018 * @param {(String|Symbol)} event The event name.
6019 * @returns {Boolean} `true` if the event had listeners, else `false`.
6020 * @public
6021 */
6022 EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
6023 var evt = prefix ? prefix + event : event;
6024
6025 if (!this._events[evt]) return false;
6026
6027 var listeners = this._events[evt]
6028 , len = arguments.length
6029 , args
6030 , i;
6031
6032 if (listeners.fn) {
6033 if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
6034
6035 switch (len) {
6036 case 1: return listeners.fn.call(listeners.context), true;
6037 case 2: return listeners.fn.call(listeners.context, a1), true;
6038 case 3: return listeners.fn.call(listeners.context, a1, a2), true;
6039 case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
6040 case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
6041 case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
6042 }
6043
6044 for (i = 1, args = new Array(len -1); i < len; i++) {
6045 args[i - 1] = arguments[i];
6046 }
6047
6048 listeners.fn.apply(listeners.context, args);
6049 } else {
6050 var length = listeners.length
6051 , j;
6052
6053 for (i = 0; i < length; i++) {
6054 if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
6055
6056 switch (len) {
6057 case 1: listeners[i].fn.call(listeners[i].context); break;
6058 case 2: listeners[i].fn.call(listeners[i].context, a1); break;
6059 case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
6060 case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
6061 default:
6062 if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
6063 args[j - 1] = arguments[j];
6064 }
6065
6066 listeners[i].fn.apply(listeners[i].context, args);
6067 }
6068 }
6069 }
6070
6071 return true;
6072 };
6073
6074 /**
6075 * Add a listener for a given event.
6076 *
6077 * @param {(String|Symbol)} event The event name.
6078 * @param {Function} fn The listener function.
6079 * @param {*} [context=this] The context to invoke the listener with.
6080 * @returns {EventEmitter} `this`.
6081 * @public
6082 */
6083 EventEmitter.prototype.on = function on(event, fn, context) {
6084 return addListener(this, event, fn, context, false);
6085 };
6086
6087 /**
6088 * Add a one-time listener for a given event.
6089 *
6090 * @param {(String|Symbol)} event The event name.
6091 * @param {Function} fn The listener function.
6092 * @param {*} [context=this] The context to invoke the listener with.
6093 * @returns {EventEmitter} `this`.
6094 * @public
6095 */
6096 EventEmitter.prototype.once = function once(event, fn, context) {
6097 return addListener(this, event, fn, context, true);
6098 };
6099
6100 /**
6101 * Remove the listeners of a given event.
6102 *
6103 * @param {(String|Symbol)} event The event name.
6104 * @param {Function} fn Only remove the listeners that match this function.
6105 * @param {*} context Only remove the listeners that have this context.
6106 * @param {Boolean} once Only remove one-time listeners.
6107 * @returns {EventEmitter} `this`.
6108 * @public
6109 */
6110 EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
6111 var evt = prefix ? prefix + event : event;
6112
6113 if (!this._events[evt]) return this;
6114 if (!fn) {
6115 clearEvent(this, evt);
6116 return this;
6117 }
6118
6119 var listeners = this._events[evt];
6120
6121 if (listeners.fn) {
6122 if (
6123 listeners.fn === fn &&
6124 (!once || listeners.once) &&
6125 (!context || listeners.context === context)
6126 ) {
6127 clearEvent(this, evt);
6128 }
6129 } else {
6130 for (var i = 0, events = [], length = listeners.length; i < length; i++) {
6131 if (
6132 listeners[i].fn !== fn ||
6133 (once && !listeners[i].once) ||
6134 (context && listeners[i].context !== context)
6135 ) {
6136 events.push(listeners[i]);
6137 }
6138 }
6139
6140 //
6141 // Reset the array, or remove it completely if we have no more listeners.
6142 //
6143 if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
6144 else clearEvent(this, evt);
6145 }
6146
6147 return this;
6148 };
6149
6150 /**
6151 * Remove all listeners, or those of the specified event.
6152 *
6153 * @param {(String|Symbol)} [event] The event name.
6154 * @returns {EventEmitter} `this`.
6155 * @public
6156 */
6157 EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
6158 var evt;
6159
6160 if (event) {
6161 evt = prefix ? prefix + event : event;
6162 if (this._events[evt]) clearEvent(this, evt);
6163 } else {
6164 this._events = new Events();
6165 this._eventsCount = 0;
6166 }
6167
6168 return this;
6169 };
6170
6171 //
6172 // Alias methods names because people roll like that.
6173 //
6174 EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
6175 EventEmitter.prototype.addListener = EventEmitter.prototype.on;
6176
6177 //
6178 // Expose the prefix.
6179 //
6180 EventEmitter.prefixed = prefix;
6181
6182 //
6183 // Allow `EventEmitter` to be imported as module namespace.
6184 //
6185 EventEmitter.EventEmitter = EventEmitter;
6186
6187 //
6188 // Expose the module.
6189 //
6190 {
6191 module.exports = EventEmitter;
6192 }
6193 });
6194
6195 function define(constructor, factory, prototype) {
6196 constructor.prototype = factory.prototype = prototype;
6197 prototype.constructor = constructor;
6198 }
6199
6200 function extend(parent, definition) {
6201 var prototype = Object.create(parent.prototype);
6202 for (var key in definition) prototype[key] = definition[key];
6203 return prototype;
6204 }
6205
6206 function Color() {}
6207
6208 var darker = 0.7;
6209 var brighter = 1 / darker;
6210
6211 var reI = "\\s*([+-]?\\d+)\\s*",
6212 reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
6213 reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
6214 reHex = /^#([0-9a-f]{3,8})$/,
6215 reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
6216 reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
6217 reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
6218 reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
6219 reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
6220 reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
6221
6222 var named = {
6223 aliceblue: 0xf0f8ff,
6224 antiquewhite: 0xfaebd7,
6225 aqua: 0x00ffff,
6226 aquamarine: 0x7fffd4,
6227 azure: 0xf0ffff,
6228 beige: 0xf5f5dc,
6229 bisque: 0xffe4c4,
6230 black: 0x000000,
6231 blanchedalmond: 0xffebcd,
6232 blue: 0x0000ff,
6233 blueviolet: 0x8a2be2,
6234 brown: 0xa52a2a,
6235 burlywood: 0xdeb887,
6236 cadetblue: 0x5f9ea0,
6237 chartreuse: 0x7fff00,
6238 chocolate: 0xd2691e,
6239 coral: 0xff7f50,
6240 cornflowerblue: 0x6495ed,
6241 cornsilk: 0xfff8dc,
6242 crimson: 0xdc143c,
6243 cyan: 0x00ffff,
6244 darkblue: 0x00008b,
6245 darkcyan: 0x008b8b,
6246 darkgoldenrod: 0xb8860b,
6247 darkgray: 0xa9a9a9,
6248 darkgreen: 0x006400,
6249 darkgrey: 0xa9a9a9,
6250 darkkhaki: 0xbdb76b,
6251 darkmagenta: 0x8b008b,
6252 darkolivegreen: 0x556b2f,
6253 darkorange: 0xff8c00,
6254 darkorchid: 0x9932cc,
6255 darkred: 0x8b0000,
6256 darksalmon: 0xe9967a,
6257 darkseagreen: 0x8fbc8f,
6258 darkslateblue: 0x483d8b,
6259 darkslategray: 0x2f4f4f,
6260 darkslategrey: 0x2f4f4f,
6261 darkturquoise: 0x00ced1,
6262 darkviolet: 0x9400d3,
6263 deeppink: 0xff1493,
6264 deepskyblue: 0x00bfff,
6265 dimgray: 0x696969,
6266 dimgrey: 0x696969,
6267 dodgerblue: 0x1e90ff,
6268 firebrick: 0xb22222,
6269 floralwhite: 0xfffaf0,
6270 forestgreen: 0x228b22,
6271 fuchsia: 0xff00ff,
6272 gainsboro: 0xdcdcdc,
6273 ghostwhite: 0xf8f8ff,
6274 gold: 0xffd700,
6275 goldenrod: 0xdaa520,
6276 gray: 0x808080,
6277 green: 0x008000,
6278 greenyellow: 0xadff2f,
6279 grey: 0x808080,
6280 honeydew: 0xf0fff0,
6281 hotpink: 0xff69b4,
6282 indianred: 0xcd5c5c,
6283 indigo: 0x4b0082,
6284 ivory: 0xfffff0,
6285 khaki: 0xf0e68c,
6286 lavender: 0xe6e6fa,
6287 lavenderblush: 0xfff0f5,
6288 lawngreen: 0x7cfc00,
6289 lemonchiffon: 0xfffacd,
6290 lightblue: 0xadd8e6,
6291 lightcoral: 0xf08080,
6292 lightcyan: 0xe0ffff,
6293 lightgoldenrodyellow: 0xfafad2,
6294 lightgray: 0xd3d3d3,
6295 lightgreen: 0x90ee90,
6296 lightgrey: 0xd3d3d3,
6297 lightpink: 0xffb6c1,
6298 lightsalmon: 0xffa07a,
6299 lightseagreen: 0x20b2aa,
6300 lightskyblue: 0x87cefa,
6301 lightslategray: 0x778899,
6302 lightslategrey: 0x778899,
6303 lightsteelblue: 0xb0c4de,
6304 lightyellow: 0xffffe0,
6305 lime: 0x00ff00,
6306 limegreen: 0x32cd32,
6307 linen: 0xfaf0e6,
6308 magenta: 0xff00ff,
6309 maroon: 0x800000,
6310 mediumaquamarine: 0x66cdaa,
6311 mediumblue: 0x0000cd,
6312 mediumorchid: 0xba55d3,
6313 mediumpurple: 0x9370db,
6314 mediumseagreen: 0x3cb371,
6315 mediumslateblue: 0x7b68ee,
6316 mediumspringgreen: 0x00fa9a,
6317 mediumturquoise: 0x48d1cc,
6318 mediumvioletred: 0xc71585,
6319 midnightblue: 0x191970,
6320 mintcream: 0xf5fffa,
6321 mistyrose: 0xffe4e1,
6322 moccasin: 0xffe4b5,
6323 navajowhite: 0xffdead,
6324 navy: 0x000080,
6325 oldlace: 0xfdf5e6,
6326 olive: 0x808000,
6327 olivedrab: 0x6b8e23,
6328 orange: 0xffa500,
6329 orangered: 0xff4500,
6330 orchid: 0xda70d6,
6331 palegoldenrod: 0xeee8aa,
6332 palegreen: 0x98fb98,
6333 paleturquoise: 0xafeeee,
6334 palevioletred: 0xdb7093,
6335 papayawhip: 0xffefd5,
6336 peachpuff: 0xffdab9,
6337 peru: 0xcd853f,
6338 pink: 0xffc0cb,
6339 plum: 0xdda0dd,
6340 powderblue: 0xb0e0e6,
6341 purple: 0x800080,
6342 rebeccapurple: 0x663399,
6343 red: 0xff0000,
6344 rosybrown: 0xbc8f8f,
6345 royalblue: 0x4169e1,
6346 saddlebrown: 0x8b4513,
6347 salmon: 0xfa8072,
6348 sandybrown: 0xf4a460,
6349 seagreen: 0x2e8b57,
6350 seashell: 0xfff5ee,
6351 sienna: 0xa0522d,
6352 silver: 0xc0c0c0,
6353 skyblue: 0x87ceeb,
6354 slateblue: 0x6a5acd,
6355 slategray: 0x708090,
6356 slategrey: 0x708090,
6357 snow: 0xfffafa,
6358 springgreen: 0x00ff7f,
6359 steelblue: 0x4682b4,
6360 tan: 0xd2b48c,
6361 teal: 0x008080,
6362 thistle: 0xd8bfd8,
6363 tomato: 0xff6347,
6364 turquoise: 0x40e0d0,
6365 violet: 0xee82ee,
6366 wheat: 0xf5deb3,
6367 white: 0xffffff,
6368 whitesmoke: 0xf5f5f5,
6369 yellow: 0xffff00,
6370 yellowgreen: 0x9acd32
6371 };
6372
6373 define(Color, color, {
6374 copy: function(channels) {
6375 return Object.assign(new this.constructor, this, channels);
6376 },
6377 displayable: function() {
6378 return this.rgb().displayable();
6379 },
6380 hex: color_formatHex, // Deprecated! Use color.formatHex.
6381 formatHex: color_formatHex,
6382 formatHsl: color_formatHsl,
6383 formatRgb: color_formatRgb,
6384 toString: color_formatRgb
6385 });
6386
6387 function color_formatHex() {
6388 return this.rgb().formatHex();
6389 }
6390
6391 function color_formatHsl() {
6392 return hslConvert(this).formatHsl();
6393 }
6394
6395 function color_formatRgb() {
6396 return this.rgb().formatRgb();
6397 }
6398
6399 function color(format) {
6400 var m, l;
6401 format = (format + "").trim().toLowerCase();
6402 return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
6403 : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00
6404 : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
6405 : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000
6406 : null) // invalid hex
6407 : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
6408 : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
6409 : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
6410 : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
6411 : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
6412 : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
6413 : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
6414 : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
6415 : null;
6416 }
6417
6418 function rgbn(n) {
6419 return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
6420 }
6421
6422 function rgba(r, g, b, a) {
6423 if (a <= 0) r = g = b = NaN;
6424 return new Rgb(r, g, b, a);
6425 }
6426
6427 function rgbConvert(o) {
6428 if (!(o instanceof Color)) o = color(o);
6429 if (!o) return new Rgb;
6430 o = o.rgb();
6431 return new Rgb(o.r, o.g, o.b, o.opacity);
6432 }
6433
6434 function rgb(r, g, b, opacity) {
6435 return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
6436 }
6437
6438 function Rgb(r, g, b, opacity) {
6439 this.r = +r;
6440 this.g = +g;
6441 this.b = +b;
6442 this.opacity = +opacity;
6443 }
6444
6445 define(Rgb, rgb, extend(Color, {
6446 brighter: function(k) {
6447 k = k == null ? brighter : Math.pow(brighter, k);
6448 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
6449 },
6450 darker: function(k) {
6451 k = k == null ? darker : Math.pow(darker, k);
6452 return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
6453 },
6454 rgb: function() {
6455 return this;
6456 },
6457 displayable: function() {
6458 return (-0.5 <= this.r && this.r < 255.5)
6459 && (-0.5 <= this.g && this.g < 255.5)
6460 && (-0.5 <= this.b && this.b < 255.5)
6461 && (0 <= this.opacity && this.opacity <= 1);
6462 },
6463 hex: rgb_formatHex, // Deprecated! Use color.formatHex.
6464 formatHex: rgb_formatHex,
6465 formatRgb: rgb_formatRgb,
6466 toString: rgb_formatRgb
6467 }));
6468
6469 function rgb_formatHex() {
6470 return "#" + hex(this.r) + hex(this.g) + hex(this.b);
6471 }
6472
6473 function rgb_formatRgb() {
6474 var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
6475 return (a === 1 ? "rgb(" : "rgba(")
6476 + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
6477 + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
6478 + Math.max(0, Math.min(255, Math.round(this.b) || 0))
6479 + (a === 1 ? ")" : ", " + a + ")");
6480 }
6481
6482 function hex(value) {
6483 value = Math.max(0, Math.min(255, Math.round(value) || 0));
6484 return (value < 16 ? "0" : "") + value.toString(16);
6485 }
6486
6487 function hsla(h, s, l, a) {
6488 if (a <= 0) h = s = l = NaN;
6489 else if (l <= 0 || l >= 1) h = s = NaN;
6490 else if (s <= 0) h = NaN;
6491 return new Hsl(h, s, l, a);
6492 }
6493
6494 function hslConvert(o) {
6495 if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
6496 if (!(o instanceof Color)) o = color(o);
6497 if (!o) return new Hsl;
6498 if (o instanceof Hsl) return o;
6499 o = o.rgb();
6500 var r = o.r / 255,
6501 g = o.g / 255,
6502 b = o.b / 255,
6503 min = Math.min(r, g, b),
6504 max = Math.max(r, g, b),
6505 h = NaN,
6506 s = max - min,
6507 l = (max + min) / 2;
6508 if (s) {
6509 if (r === max) h = (g - b) / s + (g < b) * 6;
6510 else if (g === max) h = (b - r) / s + 2;
6511 else h = (r - g) / s + 4;
6512 s /= l < 0.5 ? max + min : 2 - max - min;
6513 h *= 60;
6514 } else {
6515 s = l > 0 && l < 1 ? 0 : h;
6516 }
6517 return new Hsl(h, s, l, o.opacity);
6518 }
6519
6520 function hsl(h, s, l, opacity) {
6521 return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
6522 }
6523
6524 function Hsl(h, s, l, opacity) {
6525 this.h = +h;
6526 this.s = +s;
6527 this.l = +l;
6528 this.opacity = +opacity;
6529 }
6530
6531 define(Hsl, hsl, extend(Color, {
6532 brighter: function(k) {
6533 k = k == null ? brighter : Math.pow(brighter, k);
6534 return new Hsl(this.h, this.s, this.l * k, this.opacity);
6535 },
6536 darker: function(k) {
6537 k = k == null ? darker : Math.pow(darker, k);
6538 return new Hsl(this.h, this.s, this.l * k, this.opacity);
6539 },
6540 rgb: function() {
6541 var h = this.h % 360 + (this.h < 0) * 360,
6542 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
6543 l = this.l,
6544 m2 = l + (l < 0.5 ? l : 1 - l) * s,
6545 m1 = 2 * l - m2;
6546 return new Rgb(
6547 hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
6548 hsl2rgb(h, m1, m2),
6549 hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
6550 this.opacity
6551 );
6552 },
6553 displayable: function() {
6554 return (0 <= this.s && this.s <= 1 || isNaN(this.s))
6555 && (0 <= this.l && this.l <= 1)
6556 && (0 <= this.opacity && this.opacity <= 1);
6557 },
6558 formatHsl: function() {
6559 var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
6560 return (a === 1 ? "hsl(" : "hsla(")
6561 + (this.h || 0) + ", "
6562 + (this.s || 0) * 100 + "%, "
6563 + (this.l || 0) * 100 + "%"
6564 + (a === 1 ? ")" : ", " + a + ")");
6565 }
6566 }));
6567
6568 /* From FvD 13.37, CSS Color Module Level 3 */
6569 function hsl2rgb(h, m1, m2) {
6570 return (h < 60 ? m1 + (m2 - m1) * h / 60
6571 : h < 180 ? m2
6572 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
6573 : m1) * 255;
6574 }
6575
6576 function distance$1(x1, y1, x2, y2) {
6577 var dx = x1 - x2;
6578 var dy = y1 - y2;
6579 return Math.sqrt(dx * dx + dy * dy);
6580 }
6581 function getBBoxByArray(xArr, yArr) {
6582 var minX = Math.min.apply(Math, __spreadArray([], __read(xArr), false));
6583 var minY = Math.min.apply(Math, __spreadArray([], __read(yArr), false));
6584 var maxX = Math.max.apply(Math, __spreadArray([], __read(xArr), false));
6585 var maxY = Math.max.apply(Math, __spreadArray([], __read(yArr), false));
6586 return {
6587 x: minX,
6588 y: minY,
6589 width: maxX - minX,
6590 height: maxY - minY,
6591 };
6592 }
6593 // x 的极值
6594 function xExtrema(rx, ry, xRotation) {
6595 return Math.atan((-ry / rx) * Math.tan(xRotation));
6596 }
6597 // y 的极值
6598 function yExtrema(rx, ry, xRotation) {
6599 return Math.atan(ry / (rx * Math.tan(xRotation)));
6600 }
6601 // 根据角度求 x 坐标
6602 function xAt(cx, cy, rx, ry, xRotation, angle) {
6603 return (rx * Math.cos(xRotation) * Math.cos(angle) -
6604 ry * Math.sin(xRotation) * Math.sin(angle) +
6605 cx);
6606 }
6607 // 根据角度求 y 坐标
6608 function yAt(cx, cy, rx, ry, xRotation, angle) {
6609 return (rx * Math.sin(xRotation) * Math.cos(angle) +
6610 ry * Math.cos(xRotation) * Math.sin(angle) +
6611 cy);
6612 }
6613 function box$5(cx, cy, rx, ry, xRotation, startAngle, endAngle) {
6614 var xDim = xExtrema(rx, ry, xRotation);
6615 var minX = Infinity;
6616 var maxX = -Infinity;
6617 var xs = [startAngle, endAngle];
6618 for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
6619 var xAngle = xDim + i;
6620 if (startAngle < endAngle) {
6621 if (startAngle < xAngle && xAngle < endAngle) {
6622 xs.push(xAngle);
6623 }
6624 }
6625 else {
6626 if (endAngle < xAngle && xAngle < startAngle) {
6627 xs.push(xAngle);
6628 }
6629 }
6630 }
6631 for (var i = 0; i < xs.length; i++) {
6632 var x = xAt(cx, cy, rx, ry, xRotation, xs[i]);
6633 if (x < minX) {
6634 minX = x;
6635 }
6636 if (x > maxX) {
6637 maxX = x;
6638 }
6639 }
6640 var yDim = yExtrema(rx, ry, xRotation);
6641 var minY = Infinity;
6642 var maxY = -Infinity;
6643 var ys = [startAngle, endAngle];
6644 for (var i = -Math.PI * 2; i <= Math.PI * 2; i += Math.PI) {
6645 var yAngle = yDim + i;
6646 if (startAngle < endAngle) {
6647 if (startAngle < yAngle && yAngle < endAngle) {
6648 ys.push(yAngle);
6649 }
6650 }
6651 else {
6652 if (endAngle < yAngle && yAngle < startAngle) {
6653 ys.push(yAngle);
6654 }
6655 }
6656 }
6657 for (var i = 0; i < ys.length; i++) {
6658 var y = yAt(cx, cy, rx, ry, xRotation, ys[i]);
6659 if (y < minY) {
6660 minY = y;
6661 }
6662 if (y > maxY) {
6663 maxY = y;
6664 }
6665 }
6666 return {
6667 x: minX,
6668 y: minY,
6669 width: maxX - minX,
6670 height: maxY - minY,
6671 };
6672 }
6673
6674 var EPSILON$1 = 0.0001;
6675 /**
6676 * 使用牛顿切割法求最近的点
6677 * @param {number[]} xArr 点的 x 数组
6678 * @param {number[]} yArr 点的 y 数组
6679 * @param {number} x 指定的点 x
6680 * @param {number} y 指定的点 y
6681 * @param {Function} tCallback 差值函数
6682 */
6683 function nearestPoint$2(xArr, yArr, x, y, tCallback, length) {
6684 var t = -1;
6685 var d = Infinity;
6686 var v0 = [x, y];
6687 var segNum = 20;
6688 if (length && length > 200) {
6689 segNum = length / 10;
6690 }
6691 var increaseRate = 1 / segNum;
6692 var interval = increaseRate / 10;
6693 for (var i = 0; i <= segNum; i++) {
6694 var _t = i * increaseRate;
6695 var v1 = [
6696 tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([_t])), false)),
6697 tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([_t])), false)),
6698 ];
6699 var d1 = distance$1(v0[0], v0[1], v1[0], v1[1]);
6700 if (d1 < d) {
6701 t = _t;
6702 d = d1;
6703 }
6704 }
6705 // 提前终止
6706 if (t === 0) {
6707 return {
6708 x: xArr[0],
6709 y: yArr[0],
6710 };
6711 }
6712 if (t === 1) {
6713 var count = xArr.length;
6714 return {
6715 x: xArr[count - 1],
6716 y: yArr[count - 1],
6717 };
6718 }
6719 d = Infinity;
6720 for (var i = 0; i < 32; i++) {
6721 if (interval < EPSILON$1) {
6722 break;
6723 }
6724 var prev = t - interval;
6725 var next = t + interval;
6726 var v1 = [
6727 tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([prev])), false)),
6728 tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([prev])), false)),
6729 ];
6730 var d1 = distance$1(v0[0], v0[1], v1[0], v1[1]);
6731 if (prev >= 0 && d1 < d) {
6732 t = prev;
6733 d = d1;
6734 }
6735 else {
6736 var v2 = [
6737 tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([next])), false)),
6738 tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([next])), false)),
6739 ];
6740 var d2 = distance$1(v0[0], v0[1], v2[0], v2[1]);
6741 if (next <= 1 && d2 < d) {
6742 t = next;
6743 d = d2;
6744 }
6745 else {
6746 interval *= 0.5;
6747 }
6748 }
6749 }
6750 return {
6751 x: tCallback.apply(void 0, __spreadArray([], __read(xArr.concat([t])), false)),
6752 y: tCallback.apply(void 0, __spreadArray([], __read(yArr.concat([t])), false)),
6753 };
6754 }
6755 function length$4(x1, y1, x2, y2) {
6756 return distance$1(x1, y1, x2, y2);
6757 }
6758 function pointAt$3(x1, y1, x2, y2, t) {
6759 return {
6760 x: (1 - t) * x1 + t * x2,
6761 y: (1 - t) * y1 + t * y2,
6762 };
6763 }
6764 function pointToLine(x1, y1, x2, y2, x, y) {
6765 var d = [x2 - x1, y2 - y1];
6766 // 如果端点相等,则判定点到点的距离
6767 if (exactEquals$1(d, [0, 0])) {
6768 return Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
6769 }
6770 var u = [-d[1], d[0]];
6771 normalize$3(u, u);
6772 var a = [x - x1, y - y1];
6773 return Math.abs(dot$1(a, u));
6774 }
6775
6776 function cubicAt(p0, p1, p2, p3, t) {
6777 var onet = 1 - t; // t * t * t 的性能大概是 Math.pow(t, 3) 的三倍
6778 return (onet * onet * onet * p0 +
6779 3 * p1 * t * onet * onet +
6780 3 * p2 * t * t * onet +
6781 p3 * t * t * t);
6782 }
6783 function extrema$1(p0, p1, p2, p3) {
6784 var a = -3 * p0 + 9 * p1 - 9 * p2 + 3 * p3;
6785 var b = 6 * p0 - 12 * p1 + 6 * p2;
6786 var c = 3 * p1 - 3 * p0;
6787 var extremas = [];
6788 var t1;
6789 var t2;
6790 var discSqrt;
6791 if (isNumberEqual(a, 0)) {
6792 if (!isNumberEqual(b, 0)) {
6793 t1 = -c / b;
6794 if (t1 >= 0 && t1 <= 1) {
6795 extremas.push(t1);
6796 }
6797 }
6798 }
6799 else {
6800 var disc = b * b - 4 * a * c;
6801 if (isNumberEqual(disc, 0)) {
6802 extremas.push(-b / (2 * a));
6803 }
6804 else if (disc > 0) {
6805 discSqrt = Math.sqrt(disc);
6806 t1 = (-b + discSqrt) / (2 * a);
6807 t2 = (-b - discSqrt) / (2 * a);
6808 if (t1 >= 0 && t1 <= 1) {
6809 extremas.push(t1);
6810 }
6811 if (t2 >= 0 && t2 <= 1) {
6812 extremas.push(t2);
6813 }
6814 }
6815 }
6816 return extremas;
6817 }
6818 function box$3(x1, y1, x2, y2, x3, y3, x4, y4) {
6819 var xArr = [x1, x4];
6820 var yArr = [y1, y4];
6821 var xExtrema = extrema$1(x1, x2, x3, x4);
6822 var yExtrema = extrema$1(y1, y2, y3, y4);
6823 for (var i = 0; i < xExtrema.length; i++) {
6824 xArr.push(cubicAt(x1, x2, x3, x4, xExtrema[i]));
6825 }
6826 for (var i = 0; i < yExtrema.length; i++) {
6827 yArr.push(cubicAt(y1, y2, y3, y4, yExtrema[i]));
6828 }
6829 return getBBoxByArray(xArr, yArr);
6830 }
6831 function nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
6832 return nearestPoint$2([x1, x2, x3, x4], [y1, y2, y3, y4], x0, y0, cubicAt, length);
6833 }
6834 function pointDistance$3(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length) {
6835 var point = nearestPoint$1(x1, y1, x2, y2, x3, y3, x4, y4, x0, y0, length);
6836 return distance$1(point.x, point.y, x0, y0);
6837 }
6838 function lengthOfSegment(points) {
6839 if (points.length < 2) {
6840 return 0;
6841 }
6842 var totalLength = 0;
6843 for (var i = 0; i < points.length - 1; i++) {
6844 var from = points[i];
6845 var to = points[i + 1];
6846 totalLength += distance$1(from[0], from[1], to[0], to[1]);
6847 }
6848 return totalLength;
6849 }
6850 function length$2(points) {
6851 return lengthOfSegment(points);
6852 }
6853
6854 // 差值公式
6855 function quadraticAt(p0, p1, p2, t) {
6856 var onet = 1 - t;
6857 return onet * onet * p0 + 2 * t * onet * p1 + t * t * p2;
6858 }
6859 // 求极值
6860 function extrema(p0, p1, p2) {
6861 var a = p0 + p2 - 2 * p1;
6862 if (isNumberEqual(a, 0)) {
6863 return [0.5];
6864 }
6865 var rst = (p0 - p1) / a;
6866 if (rst <= 1 && rst >= 0) {
6867 return [rst];
6868 }
6869 return [];
6870 }
6871 function box(x1, y1, x2, y2, x3, y3) {
6872 var xExtrema = extrema(x1, x2, x3)[0];
6873 var yExtrema = extrema(y1, y2, y3)[0];
6874 // 控制点不加入 box 的计算
6875 var xArr = [x1, x3];
6876 var yArr = [y1, y3];
6877 if (xExtrema !== undefined) {
6878 xArr.push(quadraticAt(x1, x2, x3, xExtrema));
6879 }
6880 if (yExtrema !== undefined) {
6881 yArr.push(quadraticAt(y1, y2, y3, yExtrema));
6882 }
6883 return getBBoxByArray(xArr, yArr);
6884 }
6885 function nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0) {
6886 return nearestPoint$2([x1, x2, x3], [y1, y2, y3], x0, y0, quadraticAt);
6887 }
6888 function pointDistance(x1, y1, x2, y2, x3, y3, x0, y0) {
6889 var point = nearestPoint(x1, y1, x2, y2, x3, y3, x0, y0);
6890 return distance$1(point.x, point.y, x0, y0);
6891 }
6892
6893 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
6894
6895 var rbush = {exports: {}};
6896
6897 (function (module, exports) {
6898 (function (global, factory) {
6899 module.exports = factory() ;
6900 }(commonjsGlobal, function () {
6901 function quickselect(arr, k, left, right, compare) {
6902 quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
6903 }
6904
6905 function quickselectStep(arr, k, left, right, compare) {
6906
6907 while (right > left) {
6908 if (right - left > 600) {
6909 var n = right - left + 1;
6910 var m = k - left + 1;
6911 var z = Math.log(n);
6912 var s = 0.5 * Math.exp(2 * z / 3);
6913 var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
6914 var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
6915 var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
6916 quickselectStep(arr, k, newLeft, newRight, compare);
6917 }
6918
6919 var t = arr[k];
6920 var i = left;
6921 var j = right;
6922
6923 swap(arr, left, k);
6924 if (compare(arr[right], t) > 0) { swap(arr, left, right); }
6925
6926 while (i < j) {
6927 swap(arr, i, j);
6928 i++;
6929 j--;
6930 while (compare(arr[i], t) < 0) { i++; }
6931 while (compare(arr[j], t) > 0) { j--; }
6932 }
6933
6934 if (compare(arr[left], t) === 0) { swap(arr, left, j); }
6935 else {
6936 j++;
6937 swap(arr, j, right);
6938 }
6939
6940 if (j <= k) { left = j + 1; }
6941 if (k <= j) { right = j - 1; }
6942 }
6943 }
6944
6945 function swap(arr, i, j) {
6946 var tmp = arr[i];
6947 arr[i] = arr[j];
6948 arr[j] = tmp;
6949 }
6950
6951 function defaultCompare(a, b) {
6952 return a < b ? -1 : a > b ? 1 : 0;
6953 }
6954
6955 var RBush = function RBush(maxEntries) {
6956 if ( maxEntries === void 0 ) maxEntries = 9;
6957
6958 // max entries in a node is 9 by default; min node fill is 40% for best performance
6959 this._maxEntries = Math.max(4, maxEntries);
6960 this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
6961 this.clear();
6962 };
6963
6964 RBush.prototype.all = function all () {
6965 return this._all(this.data, []);
6966 };
6967
6968 RBush.prototype.search = function search (bbox) {
6969 var node = this.data;
6970 var result = [];
6971
6972 if (!intersects(bbox, node)) { return result; }
6973
6974 var toBBox = this.toBBox;
6975 var nodesToSearch = [];
6976
6977 while (node) {
6978 for (var i = 0; i < node.children.length; i++) {
6979 var child = node.children[i];
6980 var childBBox = node.leaf ? toBBox(child) : child;
6981
6982 if (intersects(bbox, childBBox)) {
6983 if (node.leaf) { result.push(child); }
6984 else if (contains(bbox, childBBox)) { this._all(child, result); }
6985 else { nodesToSearch.push(child); }
6986 }
6987 }
6988 node = nodesToSearch.pop();
6989 }
6990
6991 return result;
6992 };
6993
6994 RBush.prototype.collides = function collides (bbox) {
6995 var node = this.data;
6996
6997 if (!intersects(bbox, node)) { return false; }
6998
6999 var nodesToSearch = [];
7000 while (node) {
7001 for (var i = 0; i < node.children.length; i++) {
7002 var child = node.children[i];
7003 var childBBox = node.leaf ? this.toBBox(child) : child;
7004
7005 if (intersects(bbox, childBBox)) {
7006 if (node.leaf || contains(bbox, childBBox)) { return true; }
7007 nodesToSearch.push(child);
7008 }
7009 }
7010 node = nodesToSearch.pop();
7011 }
7012
7013 return false;
7014 };
7015
7016 RBush.prototype.load = function load (data) {
7017 if (!(data && data.length)) { return this; }
7018
7019 if (data.length < this._minEntries) {
7020 for (var i = 0; i < data.length; i++) {
7021 this.insert(data[i]);
7022 }
7023 return this;
7024 }
7025
7026 // recursively build the tree with the given data from scratch using OMT algorithm
7027 var node = this._build(data.slice(), 0, data.length - 1, 0);
7028
7029 if (!this.data.children.length) {
7030 // save as is if tree is empty
7031 this.data = node;
7032
7033 } else if (this.data.height === node.height) {
7034 // split root if trees have the same height
7035 this._splitRoot(this.data, node);
7036
7037 } else {
7038 if (this.data.height < node.height) {
7039 // swap trees if inserted one is bigger
7040 var tmpNode = this.data;
7041 this.data = node;
7042 node = tmpNode;
7043 }
7044
7045 // insert the small tree into the large tree at appropriate level
7046 this._insert(node, this.data.height - node.height - 1, true);
7047 }
7048
7049 return this;
7050 };
7051
7052 RBush.prototype.insert = function insert (item) {
7053 if (item) { this._insert(item, this.data.height - 1); }
7054 return this;
7055 };
7056
7057 RBush.prototype.clear = function clear () {
7058 this.data = createNode([]);
7059 return this;
7060 };
7061
7062 RBush.prototype.remove = function remove (item, equalsFn) {
7063 if (!item) { return this; }
7064
7065 var node = this.data;
7066 var bbox = this.toBBox(item);
7067 var path = [];
7068 var indexes = [];
7069 var i, parent, goingUp;
7070
7071 // depth-first iterative tree traversal
7072 while (node || path.length) {
7073
7074 if (!node) { // go up
7075 node = path.pop();
7076 parent = path[path.length - 1];
7077 i = indexes.pop();
7078 goingUp = true;
7079 }
7080
7081 if (node.leaf) { // check current node
7082 var index = findItem(item, node.children, equalsFn);
7083
7084 if (index !== -1) {
7085 // item found, remove the item and condense tree upwards
7086 node.children.splice(index, 1);
7087 path.push(node);
7088 this._condense(path);
7089 return this;
7090 }
7091 }
7092
7093 if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
7094 path.push(node);
7095 indexes.push(i);
7096 i = 0;
7097 parent = node;
7098 node = node.children[0];
7099
7100 } else if (parent) { // go right
7101 i++;
7102 node = parent.children[i];
7103 goingUp = false;
7104
7105 } else { node = null; } // nothing found
7106 }
7107
7108 return this;
7109 };
7110
7111 RBush.prototype.toBBox = function toBBox (item) { return item; };
7112
7113 RBush.prototype.compareMinX = function compareMinX (a, b) { return a.minX - b.minX; };
7114 RBush.prototype.compareMinY = function compareMinY (a, b) { return a.minY - b.minY; };
7115
7116 RBush.prototype.toJSON = function toJSON () { return this.data; };
7117
7118 RBush.prototype.fromJSON = function fromJSON (data) {
7119 this.data = data;
7120 return this;
7121 };
7122
7123 RBush.prototype._all = function _all (node, result) {
7124 var nodesToSearch = [];
7125 while (node) {
7126 if (node.leaf) { result.push.apply(result, node.children); }
7127 else { nodesToSearch.push.apply(nodesToSearch, node.children); }
7128
7129 node = nodesToSearch.pop();
7130 }
7131 return result;
7132 };
7133
7134 RBush.prototype._build = function _build (items, left, right, height) {
7135
7136 var N = right - left + 1;
7137 var M = this._maxEntries;
7138 var node;
7139
7140 if (N <= M) {
7141 // reached leaf level; return leaf
7142 node = createNode(items.slice(left, right + 1));
7143 calcBBox(node, this.toBBox);
7144 return node;
7145 }
7146
7147 if (!height) {
7148 // target height of the bulk-loaded tree
7149 height = Math.ceil(Math.log(N) / Math.log(M));
7150
7151 // target number of root entries to maximize storage utilization
7152 M = Math.ceil(N / Math.pow(M, height - 1));
7153 }
7154
7155 node = createNode([]);
7156 node.leaf = false;
7157 node.height = height;
7158
7159 // split the items into M mostly square tiles
7160
7161 var N2 = Math.ceil(N / M);
7162 var N1 = N2 * Math.ceil(Math.sqrt(M));
7163
7164 multiSelect(items, left, right, N1, this.compareMinX);
7165
7166 for (var i = left; i <= right; i += N1) {
7167
7168 var right2 = Math.min(i + N1 - 1, right);
7169
7170 multiSelect(items, i, right2, N2, this.compareMinY);
7171
7172 for (var j = i; j <= right2; j += N2) {
7173
7174 var right3 = Math.min(j + N2 - 1, right2);
7175
7176 // pack each entry recursively
7177 node.children.push(this._build(items, j, right3, height - 1));
7178 }
7179 }
7180
7181 calcBBox(node, this.toBBox);
7182
7183 return node;
7184 };
7185
7186 RBush.prototype._chooseSubtree = function _chooseSubtree (bbox, node, level, path) {
7187 while (true) {
7188 path.push(node);
7189
7190 if (node.leaf || path.length - 1 === level) { break; }
7191
7192 var minArea = Infinity;
7193 var minEnlargement = Infinity;
7194 var targetNode = (void 0);
7195
7196 for (var i = 0; i < node.children.length; i++) {
7197 var child = node.children[i];
7198 var area = bboxArea(child);
7199 var enlargement = enlargedArea(bbox, child) - area;
7200
7201 // choose entry with the least area enlargement
7202 if (enlargement < minEnlargement) {
7203 minEnlargement = enlargement;
7204 minArea = area < minArea ? area : minArea;
7205 targetNode = child;
7206
7207 } else if (enlargement === minEnlargement) {
7208 // otherwise choose one with the smallest area
7209 if (area < minArea) {
7210 minArea = area;
7211 targetNode = child;
7212 }
7213 }
7214 }
7215
7216 node = targetNode || node.children[0];
7217 }
7218
7219 return node;
7220 };
7221
7222 RBush.prototype._insert = function _insert (item, level, isNode) {
7223 var bbox = isNode ? item : this.toBBox(item);
7224 var insertPath = [];
7225
7226 // find the best node for accommodating the item, saving all nodes along the path too
7227 var node = this._chooseSubtree(bbox, this.data, level, insertPath);
7228
7229 // put the item into the node
7230 node.children.push(item);
7231 extend(node, bbox);
7232
7233 // split on node overflow; propagate upwards if necessary
7234 while (level >= 0) {
7235 if (insertPath[level].children.length > this._maxEntries) {
7236 this._split(insertPath, level);
7237 level--;
7238 } else { break; }
7239 }
7240
7241 // adjust bboxes along the insertion path
7242 this._adjustParentBBoxes(bbox, insertPath, level);
7243 };
7244
7245 // split overflowed node into two
7246 RBush.prototype._split = function _split (insertPath, level) {
7247 var node = insertPath[level];
7248 var M = node.children.length;
7249 var m = this._minEntries;
7250
7251 this._chooseSplitAxis(node, m, M);
7252
7253 var splitIndex = this._chooseSplitIndex(node, m, M);
7254
7255 var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
7256 newNode.height = node.height;
7257 newNode.leaf = node.leaf;
7258
7259 calcBBox(node, this.toBBox);
7260 calcBBox(newNode, this.toBBox);
7261
7262 if (level) { insertPath[level - 1].children.push(newNode); }
7263 else { this._splitRoot(node, newNode); }
7264 };
7265
7266 RBush.prototype._splitRoot = function _splitRoot (node, newNode) {
7267 // split root node
7268 this.data = createNode([node, newNode]);
7269 this.data.height = node.height + 1;
7270 this.data.leaf = false;
7271 calcBBox(this.data, this.toBBox);
7272 };
7273
7274 RBush.prototype._chooseSplitIndex = function _chooseSplitIndex (node, m, M) {
7275 var index;
7276 var minOverlap = Infinity;
7277 var minArea = Infinity;
7278
7279 for (var i = m; i <= M - m; i++) {
7280 var bbox1 = distBBox(node, 0, i, this.toBBox);
7281 var bbox2 = distBBox(node, i, M, this.toBBox);
7282
7283 var overlap = intersectionArea(bbox1, bbox2);
7284 var area = bboxArea(bbox1) + bboxArea(bbox2);
7285
7286 // choose distribution with minimum overlap
7287 if (overlap < minOverlap) {
7288 minOverlap = overlap;
7289 index = i;
7290
7291 minArea = area < minArea ? area : minArea;
7292
7293 } else if (overlap === minOverlap) {
7294 // otherwise choose distribution with minimum area
7295 if (area < minArea) {
7296 minArea = area;
7297 index = i;
7298 }
7299 }
7300 }
7301
7302 return index || M - m;
7303 };
7304
7305 // sorts node children by the best axis for split
7306 RBush.prototype._chooseSplitAxis = function _chooseSplitAxis (node, m, M) {
7307 var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
7308 var compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
7309 var xMargin = this._allDistMargin(node, m, M, compareMinX);
7310 var yMargin = this._allDistMargin(node, m, M, compareMinY);
7311
7312 // if total distributions margin value is minimal for x, sort by minX,
7313 // otherwise it's already sorted by minY
7314 if (xMargin < yMargin) { node.children.sort(compareMinX); }
7315 };
7316
7317 // total margin of all possible split distributions where each node is at least m full
7318 RBush.prototype._allDistMargin = function _allDistMargin (node, m, M, compare) {
7319 node.children.sort(compare);
7320
7321 var toBBox = this.toBBox;
7322 var leftBBox = distBBox(node, 0, m, toBBox);
7323 var rightBBox = distBBox(node, M - m, M, toBBox);
7324 var margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
7325
7326 for (var i = m; i < M - m; i++) {
7327 var child = node.children[i];
7328 extend(leftBBox, node.leaf ? toBBox(child) : child);
7329 margin += bboxMargin(leftBBox);
7330 }
7331
7332 for (var i$1 = M - m - 1; i$1 >= m; i$1--) {
7333 var child$1 = node.children[i$1];
7334 extend(rightBBox, node.leaf ? toBBox(child$1) : child$1);
7335 margin += bboxMargin(rightBBox);
7336 }
7337
7338 return margin;
7339 };
7340
7341 RBush.prototype._adjustParentBBoxes = function _adjustParentBBoxes (bbox, path, level) {
7342 // adjust bboxes along the given tree path
7343 for (var i = level; i >= 0; i--) {
7344 extend(path[i], bbox);
7345 }
7346 };
7347
7348 RBush.prototype._condense = function _condense (path) {
7349 // go through the path, removing empty nodes and updating bboxes
7350 for (var i = path.length - 1, siblings = (void 0); i >= 0; i--) {
7351 if (path[i].children.length === 0) {
7352 if (i > 0) {
7353 siblings = path[i - 1].children;
7354 siblings.splice(siblings.indexOf(path[i]), 1);
7355
7356 } else { this.clear(); }
7357
7358 } else { calcBBox(path[i], this.toBBox); }
7359 }
7360 };
7361
7362 function findItem(item, items, equalsFn) {
7363 if (!equalsFn) { return items.indexOf(item); }
7364
7365 for (var i = 0; i < items.length; i++) {
7366 if (equalsFn(item, items[i])) { return i; }
7367 }
7368 return -1;
7369 }
7370
7371 // calculate node's bbox from bboxes of its children
7372 function calcBBox(node, toBBox) {
7373 distBBox(node, 0, node.children.length, toBBox, node);
7374 }
7375
7376 // min bounding rectangle of node children from k to p-1
7377 function distBBox(node, k, p, toBBox, destNode) {
7378 if (!destNode) { destNode = createNode(null); }
7379 destNode.minX = Infinity;
7380 destNode.minY = Infinity;
7381 destNode.maxX = -Infinity;
7382 destNode.maxY = -Infinity;
7383
7384 for (var i = k; i < p; i++) {
7385 var child = node.children[i];
7386 extend(destNode, node.leaf ? toBBox(child) : child);
7387 }
7388
7389 return destNode;
7390 }
7391
7392 function extend(a, b) {
7393 a.minX = Math.min(a.minX, b.minX);
7394 a.minY = Math.min(a.minY, b.minY);
7395 a.maxX = Math.max(a.maxX, b.maxX);
7396 a.maxY = Math.max(a.maxY, b.maxY);
7397 return a;
7398 }
7399
7400 function compareNodeMinX(a, b) { return a.minX - b.minX; }
7401 function compareNodeMinY(a, b) { return a.minY - b.minY; }
7402
7403 function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
7404 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
7405
7406 function enlargedArea(a, b) {
7407 return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
7408 (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
7409 }
7410
7411 function intersectionArea(a, b) {
7412 var minX = Math.max(a.minX, b.minX);
7413 var minY = Math.max(a.minY, b.minY);
7414 var maxX = Math.min(a.maxX, b.maxX);
7415 var maxY = Math.min(a.maxY, b.maxY);
7416
7417 return Math.max(0, maxX - minX) *
7418 Math.max(0, maxY - minY);
7419 }
7420
7421 function contains(a, b) {
7422 return a.minX <= b.minX &&
7423 a.minY <= b.minY &&
7424 b.maxX <= a.maxX &&
7425 b.maxY <= a.maxY;
7426 }
7427
7428 function intersects(a, b) {
7429 return b.minX <= a.maxX &&
7430 b.minY <= a.maxY &&
7431 b.maxX >= a.minX &&
7432 b.maxY >= a.minY;
7433 }
7434
7435 function createNode(children) {
7436 return {
7437 children: children,
7438 height: 1,
7439 leaf: true,
7440 minX: Infinity,
7441 minY: Infinity,
7442 maxX: -Infinity,
7443 maxY: -Infinity
7444 };
7445 }
7446
7447 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
7448 // combines selection algorithm with binary divide & conquer approach
7449
7450 function multiSelect(arr, left, right, n, compare) {
7451 var stack = [left, right];
7452
7453 while (stack.length) {
7454 right = stack.pop();
7455 left = stack.pop();
7456
7457 if (right - left <= n) { continue; }
7458
7459 var mid = left + Math.ceil((right - left) / n / 2) * n;
7460 quickselect(arr, mid, left, right, compare);
7461
7462 stack.push(left, mid, mid, right);
7463 }
7464 }
7465
7466 return RBush;
7467
7468 }));
7469 }(rbush));
7470
7471 var RBush = rbush.exports;
7472
7473 var Shape;
7474 (function (Shape) {
7475 Shape["GROUP"] = "g";
7476 Shape["CIRCLE"] = "circle";
7477 Shape["ELLIPSE"] = "ellipse";
7478 Shape["IMAGE"] = "image";
7479 Shape["RECT"] = "rect";
7480 Shape["LINE"] = "line";
7481 Shape["POLYLINE"] = "polyline";
7482 Shape["POLYGON"] = "polygon";
7483 Shape["TEXT"] = "text";
7484 Shape["PATH"] = "path";
7485 Shape["HTML"] = "html";
7486 Shape["MESH"] = "mesh";
7487 })(Shape || (Shape = {}));
7488 var ClipSpaceNearZ;
7489 (function (ClipSpaceNearZ) {
7490 ClipSpaceNearZ[ClipSpaceNearZ["ZERO"] = 0] = "ZERO";
7491 ClipSpaceNearZ[ClipSpaceNearZ["NEGATIVE_ONE"] = 1] = "NEGATIVE_ONE";
7492 })(ClipSpaceNearZ || (ClipSpaceNearZ = {}));
7493
7494 var AbstractRendererPlugin = /** @class */ (function () {
7495 function AbstractRendererPlugin() {
7496 this.plugins = [];
7497 }
7498 AbstractRendererPlugin.prototype.addRenderingPlugin = function (plugin) {
7499 this.plugins.push(plugin);
7500 this.context.renderingPlugins.push(plugin);
7501 };
7502 AbstractRendererPlugin.prototype.removeAllRenderingPlugins = function () {
7503 var _this = this;
7504 this.plugins.forEach(function (plugin) {
7505 var index = _this.context.renderingPlugins.indexOf(plugin);
7506 if (index >= 0) {
7507 _this.context.renderingPlugins.splice(index, 1);
7508 }
7509 });
7510 };
7511 return AbstractRendererPlugin;
7512 }());
7513 var AbstractRenderer = /** @class */ (function () {
7514 function AbstractRenderer(config) {
7515 this.clipSpaceNearZ = ClipSpaceNearZ.NEGATIVE_ONE;
7516 this.plugins = [];
7517 this.config = __assign({
7518 /**
7519 * only dirty object will cause re-render
7520 */
7521 enableDirtyCheck: true, enableCulling: false,
7522 /**
7523 * enable auto rendering by default
7524 */
7525 enableAutoRendering: true,
7526 /**
7527 * enable dirty rectangle rendering by default
7528 */
7529 enableDirtyRectangleRendering: true, enableDirtyRectangleRenderingDebug: false }, config);
7530 }
7531 AbstractRenderer.prototype.registerPlugin = function (plugin) {
7532 var index = this.plugins.findIndex(function (p) { return p === plugin; });
7533 if (index === -1) {
7534 this.plugins.push(plugin);
7535 }
7536 };
7537 AbstractRenderer.prototype.unregisterPlugin = function (plugin) {
7538 var index = this.plugins.findIndex(function (p) { return p === plugin; });
7539 if (index > -1) {
7540 this.plugins.splice(index, 1);
7541 }
7542 };
7543 AbstractRenderer.prototype.getPlugins = function () {
7544 return this.plugins;
7545 };
7546 AbstractRenderer.prototype.getPlugin = function (name) {
7547 return this.plugins.find(function (plugin) { return plugin.name === name; });
7548 };
7549 AbstractRenderer.prototype.getConfig = function () {
7550 return this.config;
7551 };
7552 AbstractRenderer.prototype.setConfig = function (config) {
7553 Object.assign(this.config, config);
7554 };
7555 return AbstractRenderer;
7556 }());
7557
7558 function copyVec3(a, b) {
7559 a[0] = b[0];
7560 a[1] = b[1];
7561 a[2] = b[2];
7562 return a;
7563 }
7564 function subVec3(o, a, b) {
7565 o[0] = a[0] - b[0];
7566 o[1] = a[1] - b[1];
7567 o[2] = a[2] - b[2];
7568 return o;
7569 }
7570 function addVec3(o, a, b) {
7571 o[0] = a[0] + b[0];
7572 o[1] = a[1] + b[1];
7573 o[2] = a[2] + b[2];
7574 return o;
7575 }
7576 function scaleVec3(o, a, b) {
7577 o[0] = a[0] * b;
7578 o[1] = a[1] * b;
7579 o[2] = a[2] * b;
7580 return o;
7581 }
7582 function maxVec3(o, a, b) {
7583 o[0] = Math.max(a[0], b[0]);
7584 o[1] = Math.max(a[1], b[1]);
7585 o[2] = Math.max(a[2], b[2]);
7586 return o;
7587 }
7588 function minVec3(o, a, b) {
7589 o[0] = Math.min(a[0], b[0]);
7590 o[1] = Math.min(a[1], b[1]);
7591 o[2] = Math.min(a[2], b[2]);
7592 return o;
7593 }
7594 function getAngle(angle) {
7595 if (angle === undefined) {
7596 return 0;
7597 }
7598 else if (angle > 360 || angle < -360) {
7599 return angle % 360;
7600 }
7601 return angle;
7602 }
7603 function createVec3(x, y, z) {
7604 if (y === void 0) { y = 0; }
7605 if (z === void 0) { z = 0; }
7606 if (Array.isArray(x) && x.length === 3) {
7607 return clone$2(x);
7608 }
7609 if (isNumber(x)) {
7610 return fromValues$2(x, y, z);
7611 }
7612 return fromValues$2(x[0], x[1] || y, x[2] || z);
7613 }
7614 function deg2rad(deg) {
7615 return deg * (Math.PI / 180);
7616 }
7617 function rad2deg(rad) {
7618 return rad * (180 / Math.PI);
7619 }
7620 function turn2deg(turn) {
7621 return 360 * turn;
7622 }
7623 function getEulerFromQuat(out, quat) {
7624 var x = quat[0];
7625 var y = quat[1];
7626 var z = quat[2];
7627 var w = quat[3];
7628 var x2 = x * x;
7629 var y2 = y * y;
7630 var z2 = z * z;
7631 var w2 = w * w;
7632 var unit = x2 + y2 + z2 + w2;
7633 var test = x * w - y * z;
7634 if (test > 0.499995 * unit) {
7635 // TODO: Use glmatrix.EPSILON
7636 // singularity at the north pole
7637 out[0] = Math.PI / 2;
7638 out[1] = 2 * Math.atan2(y, x);
7639 out[2] = 0;
7640 }
7641 else if (test < -0.499995 * unit) {
7642 //TODO: Use glmatrix.EPSILON
7643 // singularity at the south pole
7644 out[0] = -Math.PI / 2;
7645 out[1] = 2 * Math.atan2(y, x);
7646 out[2] = 0;
7647 }
7648 else {
7649 out[0] = Math.asin(2 * (x * z - w * y));
7650 out[1] = Math.atan2(2 * (x * w + y * z), 1 - 2 * (z2 + w2));
7651 out[2] = Math.atan2(2 * (x * y + z * w), 1 - 2 * (y2 + z2));
7652 }
7653 // TODO: Return them as degrees and not as radians
7654 return out;
7655 }
7656 function getEulerFromMat4(out, m) {
7657 var x;
7658 var z;
7659 var halfPi = Math.PI * 0.5;
7660 var _a = __read(getScaling(create$2(), m), 3), sx = _a[0], sy = _a[1], sz = _a[2];
7661 var y = Math.asin(-m[2] / sx);
7662 if (y < halfPi) {
7663 if (y > -halfPi) {
7664 x = Math.atan2(m[6] / sy, m[10] / sz);
7665 z = Math.atan2(m[1] / sx, m[0] / sx);
7666 }
7667 else {
7668 // Not a unique solution
7669 z = 0;
7670 x = -Math.atan2(m[4] / sy, m[5] / sy);
7671 }
7672 }
7673 else {
7674 // Not a unique solution
7675 z = 0;
7676 x = Math.atan2(m[4] / sy, m[5] / sy);
7677 }
7678 out[0] = x;
7679 out[1] = y;
7680 out[2] = z;
7681 return out;
7682 }
7683 /**
7684 * @see https://github.com/toji/gl-matrix/issues/329
7685 * @see https://doc.babylonjs.com/divingDeeper/mesh/transforms/center_origin/rotation_conventions
7686 */
7687 function getEuler(out, quat) {
7688 if (quat.length === 16) {
7689 return getEulerFromMat4(out, quat);
7690 }
7691 else {
7692 return getEulerFromQuat(out, quat);
7693 }
7694 }
7695 function fromRotationTranslationScale$1(rotation, x, y, scaleX, scaleY) {
7696 var cos = Math.cos(rotation);
7697 var sin = Math.sin(rotation);
7698 return fromValues(scaleX * cos, scaleY * sin, 0, -scaleX * sin, scaleY * cos, 0, x, y, 1);
7699 }
7700 function makePerspective(out, left, right, top, bottom, near, far, zero) {
7701 if (zero === void 0) { zero = false; }
7702 var x = (2 * near) / (right - left);
7703 var y = (2 * near) / (top - bottom);
7704 var a = (right + left) / (right - left);
7705 var b = (top + bottom) / (top - bottom);
7706 var c;
7707 var d;
7708 if (zero) {
7709 c = -far / (far - near);
7710 d = (-far * near) / (far - near);
7711 }
7712 else {
7713 c = -(far + near) / (far - near);
7714 d = (-2 * far * near) / (far - near);
7715 }
7716 out[0] = x;
7717 out[1] = 0;
7718 out[2] = 0;
7719 out[3] = 0;
7720 out[4] = 0;
7721 out[5] = y;
7722 out[6] = 0;
7723 out[7] = 0;
7724 out[8] = a;
7725 out[9] = b;
7726 out[10] = c;
7727 out[11] = -1;
7728 out[12] = 0;
7729 out[13] = 0;
7730 out[14] = d;
7731 out[15] = 0;
7732 return out;
7733 }
7734 function decompose(mat) {
7735 var row0x = mat[0];
7736 var row0y = mat[1];
7737 var row1x = mat[3];
7738 var row1y = mat[4];
7739 // decompose 3x3 matrix
7740 // @see https://www.w3.org/TR/css-transforms-1/#decomposing-a-2d-matrix
7741 var scalingX = Math.sqrt(row0x * row0x + row0y * row0y);
7742 var scalingY = Math.sqrt(row1x * row1x + row1y * row1y);
7743 // If determinant is negative, one axis was flipped.
7744 var determinant = row0x * row1y - row0y * row1x;
7745 if (determinant < 0) {
7746 // Flip axis with minimum unit vector dot product.
7747 if (row0x < row1y) {
7748 scalingX = -scalingX;
7749 }
7750 else {
7751 scalingY = -scalingY;
7752 }
7753 }
7754 // Renormalize matrix to remove scale.
7755 if (scalingX) {
7756 row0x *= 1 / scalingX;
7757 row0y *= 1 / scalingX;
7758 }
7759 if (scalingY) {
7760 row1x *= 1 / scalingY;
7761 row1y *= 1 / scalingY;
7762 }
7763 // Compute rotation and renormalize matrix.
7764 var rotation = Math.atan2(row0y, row0x);
7765 var angle = rad2deg(rotation);
7766 return [mat[6], mat[7], scalingX, scalingY, angle];
7767 }
7768 var tmp = create$1();
7769 var perspectiveMatrix = create$1();
7770 var tmpVec4 = create$3();
7771 var row = [create$2(), create$2(), create$2()];
7772 var pdum3 = create$2();
7773 /*
7774 Input: matrix ; a 4x4 matrix
7775 Output: translation ; a 3 component vector
7776 scale ; a 3 component vector
7777 skew ; skew factors XY,XZ,YZ represented as a 3 component vector
7778 perspective ; a 4 component vector
7779 quaternion ; a 4 component vector
7780 Returns false if the matrix cannot be decomposed, true if it can
7781
7782
7783 References:
7784 https://github.com/kamicane/matrix3d/blob/master/lib/Matrix3d.js
7785 https://github.com/ChromiumWebApps/chromium/blob/master/ui/gfx/transform_util.cc
7786 http://www.w3.org/TR/css3-transforms/#decomposing-a-3d-matrix
7787 */
7788 function decomposeMat4(matrix, translation, scale, skew, perspective, quaternion) {
7789 //normalize, if not possible then bail out early
7790 if (!normalize$4(tmp, matrix))
7791 return false;
7792 // perspectiveMatrix is used to solve for perspective, but it also provides
7793 // an easy way to test for singularity of the upper 3x3 component.
7794 copy(perspectiveMatrix, tmp);
7795 perspectiveMatrix[3] = 0;
7796 perspectiveMatrix[7] = 0;
7797 perspectiveMatrix[11] = 0;
7798 perspectiveMatrix[15] = 1;
7799 // If the perspectiveMatrix is not invertible, we are also unable to
7800 // decompose, so we'll bail early. Constant taken from SkMatrix44::invert.
7801 if (Math.abs(determinant(perspectiveMatrix)) < 1e-8)
7802 return false;
7803 var a03 = tmp[3], a13 = tmp[7], a23 = tmp[11], a30 = tmp[12], a31 = tmp[13], a32 = tmp[14], a33 = tmp[15];
7804 // First, isolate perspective.
7805 if (a03 !== 0 || a13 !== 0 || a23 !== 0) {
7806 tmpVec4[0] = a03;
7807 tmpVec4[1] = a13;
7808 tmpVec4[2] = a23;
7809 tmpVec4[3] = a33;
7810 // Solve the equation by inverting perspectiveMatrix and multiplying
7811 // rightHandSide by the inverse.
7812 // resuing the perspectiveMatrix here since it's no longer needed
7813 var ret = invert(perspectiveMatrix, perspectiveMatrix);
7814 if (!ret)
7815 return false;
7816 transpose(perspectiveMatrix, perspectiveMatrix);
7817 //multiply by transposed inverse perspective matrix, into perspective vec4
7818 transformMat4$1(perspective, tmpVec4, perspectiveMatrix);
7819 }
7820 else {
7821 //no perspective
7822 perspective[0] = perspective[1] = perspective[2] = 0;
7823 perspective[3] = 1;
7824 }
7825 // Next take care of translation
7826 translation[0] = a30;
7827 translation[1] = a31;
7828 translation[2] = a32;
7829 // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
7830 mat3from4(row, tmp);
7831 // Compute X scale factor and normalize first row.
7832 scale[0] = length(row[0]);
7833 normalize(row[0], row[0]);
7834 // Compute XY shear factor and make 2nd row orthogonal to 1st.
7835 skew[0] = dot(row[0], row[1]);
7836 combine(row[1], row[1], row[0], 1.0, -skew[0]);
7837 // Now, compute Y scale and normalize 2nd row.
7838 scale[1] = length(row[1]);
7839 normalize(row[1], row[1]);
7840 skew[0] /= scale[1];
7841 // Compute XZ and YZ shears, orthogonalize 3rd row
7842 skew[1] = dot(row[0], row[2]);
7843 combine(row[2], row[2], row[0], 1.0, -skew[1]);
7844 skew[2] = dot(row[1], row[2]);
7845 combine(row[2], row[2], row[1], 1.0, -skew[2]);
7846 // Next, get Z scale and normalize 3rd row.
7847 scale[2] = length(row[2]);
7848 normalize(row[2], row[2]);
7849 skew[1] /= scale[2];
7850 skew[2] /= scale[2];
7851 // At this point, the matrix (in rows) is orthonormal.
7852 // Check for a coordinate system flip. If the determinant
7853 // is -1, then negate the matrix and the scaling factors.
7854 cross(pdum3, row[1], row[2]);
7855 if (dot(row[0], pdum3) < 0) {
7856 for (var i = 0; i < 3; i++) {
7857 scale[i] *= -1;
7858 row[i][0] *= -1;
7859 row[i][1] *= -1;
7860 row[i][2] *= -1;
7861 }
7862 }
7863 // Now, get the rotations out
7864 quaternion[0] =
7865 0.5 * Math.sqrt(Math.max(1 + row[0][0] - row[1][1] - row[2][2], 0));
7866 quaternion[1] =
7867 0.5 * Math.sqrt(Math.max(1 - row[0][0] + row[1][1] - row[2][2], 0));
7868 quaternion[2] =
7869 0.5 * Math.sqrt(Math.max(1 - row[0][0] - row[1][1] + row[2][2], 0));
7870 quaternion[3] =
7871 0.5 * Math.sqrt(Math.max(1 + row[0][0] + row[1][1] + row[2][2], 0));
7872 if (row[2][1] > row[1][2])
7873 quaternion[0] = -quaternion[0];
7874 if (row[0][2] > row[2][0])
7875 quaternion[1] = -quaternion[1];
7876 if (row[1][0] > row[0][1])
7877 quaternion[2] = -quaternion[2];
7878 return true;
7879 }
7880 function normalize$4(out, mat) {
7881 var m44 = mat[15];
7882 // Cannot normalize.
7883 if (m44 === 0)
7884 return false;
7885 var scale = 1 / m44;
7886 for (var i = 0; i < 16; i++)
7887 out[i] = mat[i] * scale;
7888 return true;
7889 }
7890 //gets upper-left of a 4x4 matrix into a 3x3 of vectors
7891 function mat3from4(out, mat4x4) {
7892 out[0][0] = mat4x4[0];
7893 out[0][1] = mat4x4[1];
7894 out[0][2] = mat4x4[2];
7895 out[1][0] = mat4x4[4];
7896 out[1][1] = mat4x4[5];
7897 out[1][2] = mat4x4[6];
7898 out[2][0] = mat4x4[8];
7899 out[2][1] = mat4x4[9];
7900 out[2][2] = mat4x4[10];
7901 }
7902 function combine(out, a, b, scale1, scale2) {
7903 out[0] = a[0] * scale1 + b[0] * scale2;
7904 out[1] = a[1] * scale1 + b[1] * scale2;
7905 out[2] = a[2] * scale1 + b[2] * scale2;
7906 }
7907
7908 /**
7909 * Axis-Aligned Bounding Box
7910 * 为了便于后续 Frustum Culling,通过查找表定义 p-vertex 和 n-vertex
7911 * @see https://github.com/antvis/GWebGPUEngine/issues/3
7912 */
7913 var AABB = /** @class */ (function () {
7914 function AABB() {
7915 this.center = [0, 0, 0];
7916 this.halfExtents = [0, 0, 0];
7917 this.min = [0, 0, 0];
7918 this.max = [0, 0, 0];
7919 }
7920 AABB.isEmpty = function (aabb) {
7921 return (!aabb ||
7922 (aabb.halfExtents[0] === 0 &&
7923 aabb.halfExtents[1] === 0 &&
7924 aabb.halfExtents[2] === 0));
7925 };
7926 // center: vec3 = vec3.create();
7927 // halfExtents: vec3 = vec3.create();
7928 // min: vec3 = vec3.create();
7929 // max: vec3 = vec3.create();
7930 AABB.prototype.update = function (center, halfExtents) {
7931 copyVec3(this.center, center);
7932 copyVec3(this.halfExtents, halfExtents);
7933 subVec3(this.min, this.center, this.halfExtents);
7934 addVec3(this.max, this.center, this.halfExtents);
7935 // vec3.copy(this.center, center);
7936 // vec3.copy(this.halfExtents, halfExtents);
7937 // vec3.sub(this.min, this.center, this.halfExtents);
7938 // vec3.add(this.max, this.center, this.halfExtents);
7939 };
7940 AABB.prototype.setMinMax = function (min, max) {
7941 // vec3.add(this.center, max, min);
7942 // vec3.scale(this.center, this.center, 0.5);
7943 // vec3.sub(this.halfExtents, max, min);
7944 // vec3.scale(this.halfExtents, this.halfExtents, 0.5);
7945 // vec3.copy(this.min, min);
7946 // vec3.copy(this.max, max);
7947 addVec3(this.center, max, min);
7948 scaleVec3(this.center, this.center, 0.5);
7949 subVec3(this.halfExtents, max, min);
7950 scaleVec3(this.halfExtents, this.halfExtents, 0.5);
7951 copyVec3(this.min, min);
7952 copyVec3(this.max, max);
7953 };
7954 AABB.prototype.getMin = function () {
7955 return this.min;
7956 };
7957 AABB.prototype.getMax = function () {
7958 return this.max;
7959 };
7960 AABB.prototype.add = function (aabb) {
7961 if (AABB.isEmpty(aabb)) {
7962 return;
7963 }
7964 if (AABB.isEmpty(this)) {
7965 this.setMinMax(aabb.getMin(), aabb.getMax());
7966 return;
7967 }
7968 var tc = this.center;
7969 var tcx = tc[0];
7970 var tcy = tc[1];
7971 var tcz = tc[2];
7972 var th = this.halfExtents;
7973 var thx = th[0];
7974 var thy = th[1];
7975 var thz = th[2];
7976 var tminx = tcx - thx;
7977 var tmaxx = tcx + thx;
7978 var tminy = tcy - thy;
7979 var tmaxy = tcy + thy;
7980 var tminz = tcz - thz;
7981 var tmaxz = tcz + thz;
7982 var oc = aabb.center;
7983 var ocx = oc[0];
7984 var ocy = oc[1];
7985 var ocz = oc[2];
7986 var oh = aabb.halfExtents;
7987 var ohx = oh[0];
7988 var ohy = oh[1];
7989 var ohz = oh[2];
7990 var ominx = ocx - ohx;
7991 var omaxx = ocx + ohx;
7992 var ominy = ocy - ohy;
7993 var omaxy = ocy + ohy;
7994 var ominz = ocz - ohz;
7995 var omaxz = ocz + ohz;
7996 if (ominx < tminx) {
7997 tminx = ominx;
7998 }
7999 if (omaxx > tmaxx) {
8000 tmaxx = omaxx;
8001 }
8002 if (ominy < tminy) {
8003 tminy = ominy;
8004 }
8005 if (omaxy > tmaxy) {
8006 tmaxy = omaxy;
8007 }
8008 if (ominz < tminz) {
8009 tminz = ominz;
8010 }
8011 if (omaxz > tmaxz) {
8012 tmaxz = omaxz;
8013 }
8014 tc[0] = (tminx + tmaxx) * 0.5;
8015 tc[1] = (tminy + tmaxy) * 0.5;
8016 tc[2] = (tminz + tmaxz) * 0.5;
8017 th[0] = (tmaxx - tminx) * 0.5;
8018 th[1] = (tmaxy - tminy) * 0.5;
8019 th[2] = (tmaxz - tminz) * 0.5;
8020 this.min[0] = tminx;
8021 this.min[1] = tminy;
8022 this.min[2] = tminz;
8023 this.max[0] = tmaxx;
8024 this.max[1] = tmaxy;
8025 this.max[2] = tmaxz;
8026 };
8027 AABB.prototype.setFromTransformedAABB = function (aabb, m) {
8028 var bc = this.center;
8029 var br = this.halfExtents;
8030 var ac = aabb.center;
8031 var ar = aabb.halfExtents;
8032 var mx0 = m[0];
8033 var mx1 = m[4];
8034 var mx2 = m[8];
8035 var my0 = m[1];
8036 var my1 = m[5];
8037 var my2 = m[9];
8038 var mz0 = m[2];
8039 var mz1 = m[6];
8040 var mz2 = m[10];
8041 var mx0a = Math.abs(mx0);
8042 var mx1a = Math.abs(mx1);
8043 var mx2a = Math.abs(mx2);
8044 var my0a = Math.abs(my0);
8045 var my1a = Math.abs(my1);
8046 var my2a = Math.abs(my2);
8047 var mz0a = Math.abs(mz0);
8048 var mz1a = Math.abs(mz1);
8049 var mz2a = Math.abs(mz2);
8050 bc[0] = m[12] + mx0 * ac[0] + mx1 * ac[1] + mx2 * ac[2];
8051 bc[1] = m[13] + my0 * ac[0] + my1 * ac[1] + my2 * ac[2];
8052 bc[2] = m[14] + mz0 * ac[0] + mz1 * ac[1] + mz2 * ac[2];
8053 // vec3.set(
8054 // bc,
8055 // m[12] + mx0 * ac[0] + mx1 * ac[1] + mx2 * ac[2],
8056 // m[13] + my0 * ac[0] + my1 * ac[1] + my2 * ac[2],
8057 // m[14] + mz0 * ac[0] + mz1 * ac[1] + mz2 * ac[2],
8058 // );
8059 br[0] = mx0a * ar[0] + mx1a * ar[1] + mx2a * ar[2];
8060 br[1] = my0a * ar[0] + my1a * ar[1] + my2a * ar[2];
8061 br[2] = mz0a * ar[0] + mz1a * ar[1] + mz2a * ar[2];
8062 // vec3.set(
8063 // br,
8064 // mx0a * ar[0] + mx1a * ar[1] + mx2a * ar[2],
8065 // my0a * ar[0] + my1a * ar[1] + my2a * ar[2],
8066 // mz0a * ar[0] + mz1a * ar[1] + mz2a * ar[2],
8067 // );
8068 // this.min = vec3.sub(this.min, bc, br);
8069 // this.max = vec3.add(this.max, bc, br);
8070 subVec3(this.min, bc, br);
8071 addVec3(this.max, bc, br);
8072 };
8073 AABB.prototype.intersects = function (aabb) {
8074 var aMax = this.getMax();
8075 var aMin = this.getMin();
8076 var bMax = aabb.getMax();
8077 var bMin = aabb.getMin();
8078 return (aMin[0] <= bMax[0] &&
8079 aMax[0] >= bMin[0] &&
8080 aMin[1] <= bMax[1] &&
8081 aMax[1] >= bMin[1] &&
8082 aMin[2] <= bMax[2] &&
8083 aMax[2] >= bMin[2]);
8084 };
8085 AABB.prototype.intersection = function (aabb) {
8086 if (!this.intersects(aabb)) {
8087 return null;
8088 }
8089 var intersection = new AABB();
8090 // const min = vec3.max(vec3.create(), this.getMin(), aabb.getMin());
8091 // const max = vec3.min(vec3.create(), this.getMax(), aabb.getMax());
8092 var min = maxVec3([0, 0, 0], this.getMin(), aabb.getMin());
8093 var max = minVec3([0, 0, 0], this.getMax(), aabb.getMax());
8094 intersection.setMinMax(min, max);
8095 return intersection;
8096 };
8097 // containsPoint(point: vec3) {
8098 // const min = this.getMin();
8099 // const max = this.getMax();
8100 // return !(
8101 // point[0] < min[0] ||
8102 // point[0] > max[0] ||
8103 // point[1] < min[1] ||
8104 // point[1] > max[1] ||
8105 // point[2] < min[2] ||
8106 // point[2] > max[2]
8107 // );
8108 // }
8109 /**
8110 * get n-vertex
8111 * @param plane plane of CullingVolume
8112 */
8113 AABB.prototype.getNegativeFarPoint = function (plane) {
8114 if (plane.pnVertexFlag === 0x111) {
8115 return copyVec3([0, 0, 0], this.min);
8116 // return vec3.copy(vec3.create(), this.min);
8117 }
8118 else if (plane.pnVertexFlag === 0x110) {
8119 return [this.min[0], this.min[1], this.max[2]];
8120 // return vec3.fromValues(this.min[0], this.min[1], this.max[2]);
8121 }
8122 else if (plane.pnVertexFlag === 0x101) {
8123 return [this.min[0], this.max[1], this.min[2]];
8124 // return vec3.fromValues(this.min[0], this.max[1], this.min[2]);
8125 }
8126 else if (plane.pnVertexFlag === 0x100) {
8127 return [this.min[0], this.max[1], this.max[2]];
8128 // return vec3.fromValues(this.min[0], this.max[1], this.max[2]);
8129 }
8130 else if (plane.pnVertexFlag === 0x011) {
8131 return [this.max[0], this.min[1], this.min[2]];
8132 // return vec3.fromValues(this.max[0], this.min[1], this.min[2]);
8133 }
8134 else if (plane.pnVertexFlag === 0x010) {
8135 return [this.max[0], this.min[1], this.max[2]];
8136 // return vec3.fromValues(this.max[0], this.min[1], this.max[2]);
8137 }
8138 else if (plane.pnVertexFlag === 0x001) {
8139 return [this.max[0], this.max[1], this.min[2]];
8140 // return vec3.fromValues(this.max[0], this.max[1], this.min[2]);
8141 }
8142 else {
8143 return [this.max[0], this.max[1], this.max[2]];
8144 // return vec3.fromValues(this.max[0], this.max[1], this.max[2]);
8145 }
8146 };
8147 /**
8148 * get p-vertex
8149 * @param plane plane of CullingVolume
8150 */
8151 AABB.prototype.getPositiveFarPoint = function (plane) {
8152 if (plane.pnVertexFlag === 0x111) {
8153 return copyVec3([0, 0, 0], this.max);
8154 // return vec3.copy(vec3.create(), this.max);
8155 }
8156 else if (plane.pnVertexFlag === 0x110) {
8157 return [this.max[0], this.max[1], this.min[2]];
8158 // return vec3.fromValues(this.max[0], this.max[1], this.min[2]);
8159 }
8160 else if (plane.pnVertexFlag === 0x101) {
8161 return [this.max[0], this.min[1], this.max[2]];
8162 // return vec3.fromValues(this.max[0], this.min[1], this.max[2]);
8163 }
8164 else if (plane.pnVertexFlag === 0x100) {
8165 return [this.max[0], this.min[1], this.min[2]];
8166 // return vec3.fromValues(this.max[0], this.min[1], this.min[2]);
8167 }
8168 else if (plane.pnVertexFlag === 0x011) {
8169 return [this.min[0], this.max[1], this.max[2]];
8170 // return vec3.fromValues(this.min[0], this.max[1], this.max[2]);
8171 }
8172 else if (plane.pnVertexFlag === 0x010) {
8173 return [this.min[0], this.max[1], this.min[2]];
8174 // return vec3.fromValues(this.min[0], this.max[1], this.min[2]);
8175 }
8176 else if (plane.pnVertexFlag === 0x001) {
8177 return [this.min[0], this.min[1], this.max[2]];
8178 // return vec3.fromValues(this.min[0], this.min[1], this.max[2]);
8179 }
8180 else {
8181 return [this.min[0], this.min[1], this.min[2]];
8182 // return vec3.fromValues(this.min[0], this.min[1], this.min[2]);
8183 }
8184 };
8185 return AABB;
8186 }());
8187
8188 var Plane = /** @class */ (function () {
8189 function Plane(distance, normal) {
8190 this.distance = distance || 0;
8191 this.normal = normal || fromValues$2(0, 1, 0);
8192 this.updatePNVertexFlag();
8193 }
8194 Plane.prototype.updatePNVertexFlag = function () {
8195 this.pnVertexFlag =
8196 (Number(this.normal[0] >= 0) << 8) +
8197 (Number(this.normal[1] >= 0) << 4) +
8198 Number(this.normal[2] >= 0);
8199 };
8200 Plane.prototype.distanceToPoint = function (point) {
8201 return dot(point, this.normal) - this.distance;
8202 };
8203 Plane.prototype.normalize = function () {
8204 var invLen = 1 / len(this.normal);
8205 scale$1(this.normal, this.normal, invLen);
8206 this.distance *= invLen;
8207 };
8208 Plane.prototype.intersectsLine = function (start, end, point) {
8209 var d0 = this.distanceToPoint(start);
8210 var d1 = this.distanceToPoint(end);
8211 var t = d0 / (d0 - d1);
8212 var intersects = t >= 0 && t <= 1;
8213 if (intersects && point) {
8214 lerp(point, start, end, t);
8215 }
8216 return intersects;
8217 };
8218 return Plane;
8219 }());
8220
8221 var Mask;
8222 (function (Mask) {
8223 Mask[Mask["OUTSIDE"] = 4294967295] = "OUTSIDE";
8224 Mask[Mask["INSIDE"] = 0] = "INSIDE";
8225 Mask[Mask["INDETERMINATE"] = 2147483647] = "INDETERMINATE";
8226 })(Mask || (Mask = {}));
8227 var Frustum = /** @class */ (function () {
8228 function Frustum(planes) {
8229 this.planes = [];
8230 if (planes) {
8231 this.planes = planes;
8232 }
8233 else {
8234 for (var i = 0; i < 6; i++) {
8235 this.planes.push(new Plane());
8236 }
8237 }
8238 }
8239 /**
8240 * extract 6 planes from projectionMatrix
8241 * @see http://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf
8242 */
8243 Frustum.prototype.extractFromVPMatrix = function (projectionMatrix) {
8244 // @ts-ignore
8245 var _a = __read(projectionMatrix, 16), m0 = _a[0], m1 = _a[1], m2 = _a[2], m3 = _a[3], m4 = _a[4], m5 = _a[5], m6 = _a[6], m7 = _a[7], m8 = _a[8], m9 = _a[9], m10 = _a[10], m11 = _a[11], m12 = _a[12], m13 = _a[13], m14 = _a[14], m15 = _a[15];
8246 // right
8247 set$1(this.planes[0].normal, m3 - m0, m7 - m4, m11 - m8);
8248 this.planes[0].distance = m15 - m12;
8249 // left
8250 set$1(this.planes[1].normal, m3 + m0, m7 + m4, m11 + m8);
8251 this.planes[1].distance = m15 + m12;
8252 // bottom
8253 set$1(this.planes[2].normal, m3 + m1, m7 + m5, m11 + m9);
8254 this.planes[2].distance = m15 + m13;
8255 // top
8256 set$1(this.planes[3].normal, m3 - m1, m7 - m5, m11 - m9);
8257 this.planes[3].distance = m15 - m13;
8258 // far
8259 set$1(this.planes[4].normal, m3 - m2, m7 - m6, m11 - m10);
8260 this.planes[4].distance = m15 - m14;
8261 // near
8262 set$1(this.planes[5].normal, m3 + m2, m7 + m6, m11 + m10);
8263 this.planes[5].distance = m15 + m14;
8264 this.planes.forEach(function (plane) {
8265 plane.normalize();
8266 plane.updatePNVertexFlag();
8267 });
8268 };
8269 return Frustum;
8270 }());
8271
8272 var Point = /** @class */ (function () {
8273 function Point(x, y) {
8274 if (x === void 0) { x = 0; }
8275 if (y === void 0) { y = 0; }
8276 this.x = 0;
8277 this.y = 0;
8278 this.x = x;
8279 this.y = y;
8280 }
8281 Point.prototype.clone = function () {
8282 return new Point(this.x, this.y);
8283 };
8284 Point.prototype.copyFrom = function (p) {
8285 this.x = p.x;
8286 this.y = p.y;
8287 };
8288 return Point;
8289 }());
8290
8291 var Rectangle = /** @class */ (function () {
8292 function Rectangle(x, y, width, height) {
8293 this.x = x;
8294 this.y = y;
8295 this.width = width;
8296 this.height = height;
8297 this.left = x;
8298 this.right = x + width;
8299 this.top = y;
8300 this.bottom = y + height;
8301 }
8302 Rectangle.prototype.toJSON = function () { };
8303 return Rectangle;
8304 }());
8305
8306 var ERROR_MSG_METHOD_NOT_IMPLEMENTED = 'Method not implemented.';
8307 var ERROR_MSG_USE_DOCUMENT_ELEMENT = 'Use document.documentElement instead.';
8308 var ERROR_MSG_APPEND_DESTROYED_ELEMENT = 'Cannot append a destroyed element.';
8309
8310 /**
8311 * Different type of cameras, eg. simple camera used in 2D scene or
8312 * advanced camera which can do actions & switch between landmarks.
8313 */
8314 var CameraType;
8315 (function (CameraType) {
8316 /**
8317 * Performs all the rotational operations with the focal point instead of the camera position.
8318 * This type of camera is useful in applications(like CAD) where 3D objects are being designed or explored.
8319 * Camera cannot orbits over the north & south poles.
8320 * @see http://voxelent.com/tutorial-cameras/
8321 *
8322 * In Three.js it's used in OrbitControls.
8323 * @see https://threejs.org/docs/#examples/zh/controls/OrbitControls
8324 */
8325 CameraType[CameraType["ORBITING"] = 0] = "ORBITING";
8326 /**
8327 * It's similar to the ORBITING camera, but it allows the camera to orbit over the north or south poles.
8328 *
8329 * In Three.js it's used in OrbitControls.
8330 * @see https://threejs.org/docs/#examples/en/controls/TrackballControls
8331 */
8332 CameraType[CameraType["EXPLORING"] = 1] = "EXPLORING";
8333 /**
8334 * Performs all the rotational operations with the camera position.
8335 * It's useful in first person shooting games.
8336 * Camera cannot orbits over the north & south poles.
8337 *
8338 * In Three.js it's used in FirstPersonControls.
8339 * @see https://threejs.org/docs/#examples/en/controls/FirstPersonControls
8340 */
8341 CameraType[CameraType["TRACKING"] = 2] = "TRACKING";
8342 })(CameraType || (CameraType = {}));
8343 /**
8344 * CameraType must be TRACKING
8345 */
8346 var CameraTrackingMode;
8347 (function (CameraTrackingMode) {
8348 CameraTrackingMode[CameraTrackingMode["DEFAULT"] = 0] = "DEFAULT";
8349 CameraTrackingMode[CameraTrackingMode["ROTATIONAL"] = 1] = "ROTATIONAL";
8350 CameraTrackingMode[CameraTrackingMode["TRANSLATIONAL"] = 2] = "TRANSLATIONAL";
8351 CameraTrackingMode[CameraTrackingMode["CINEMATIC"] = 3] = "CINEMATIC";
8352 })(CameraTrackingMode || (CameraTrackingMode = {}));
8353 var CameraProjectionMode;
8354 (function (CameraProjectionMode) {
8355 CameraProjectionMode[CameraProjectionMode["ORTHOGRAPHIC"] = 0] = "ORTHOGRAPHIC";
8356 CameraProjectionMode[CameraProjectionMode["PERSPECTIVE"] = 1] = "PERSPECTIVE";
8357 })(CameraProjectionMode || (CameraProjectionMode = {}));
8358 var CameraEvent = {
8359 UPDATED: 'updated',
8360 };
8361
8362 var MIN_DISTANCE = 0.0002;
8363 /**
8364 * 参考「WebGL Insights - 23.Designing Cameras for WebGL Applications」,基于 Responsible Camera 思路设计
8365 * @see https://github.com/d13g0/nucleo.js/blob/master/source/camera/Camera.js
8366 *
8367 * 保存相机参数,定义相机动作:
8368 * 1. dolly 沿 n 轴移动
8369 * 2. pan 沿 u v 轴移动
8370 * 3. rotate 以方位角旋转
8371 * 4. 移动到 Landmark,具有平滑的动画效果,其间禁止其他用户交互
8372 */
8373 var Camera = /** @class */ (function () {
8374 function Camera() {
8375 /**
8376 * Clip space near Z, default to range `[-1, 1]`
8377 */
8378 this.clipSpaceNearZ = ClipSpaceNearZ.NEGATIVE_ONE;
8379 this.eventEmitter = new eventemitter3();
8380 /**
8381 * Matrix of camera
8382 */
8383 this.matrix = create$1();
8384 /**
8385 * u axis +X is right
8386 * @see http://learnwebgl.brown37.net/07_cameras/camera_introduction.html#a-camera-definition
8387 */
8388 this.right = fromValues$2(1, 0, 0);
8389 /**
8390 * v axis +Y is up
8391 */
8392 this.up = fromValues$2(0, 1, 0);
8393 /**
8394 * n axis +Z is inside
8395 */
8396 this.forward = fromValues$2(0, 0, 1);
8397 /**
8398 * Position of camera.
8399 */
8400 this.position = fromValues$2(0, 0, 1);
8401 /**
8402 * Position of focal point.
8403 */
8404 this.focalPoint = fromValues$2(0, 0, 0);
8405 /**
8406 * vector from focalPoint to position
8407 */
8408 this.distanceVector = fromValues$2(0, 0, -1);
8409 /**
8410 * length(focalPoint - position)
8411 */
8412 this.distance = 1;
8413 /**
8414 * @see https://en.wikipedia.org/wiki/Azimuth
8415 */
8416 this.azimuth = 0;
8417 this.elevation = 0;
8418 this.roll = 0;
8419 this.relAzimuth = 0;
8420 this.relElevation = 0;
8421 this.relRoll = 0;
8422 /**
8423 * 沿 n 轴移动时,保证移动速度从快到慢
8424 */
8425 this.dollyingStep = 0;
8426 this.maxDistance = Infinity;
8427 this.minDistance = -Infinity;
8428 /**
8429 * zoom factor of the camera, default is 1
8430 * eg. https://threejs.org/docs/#api/en/cameras/OrthographicCamera.zoom
8431 */
8432 this.zoom = 1;
8433 /**
8434 * invert the horizontal coordinate system HCS
8435 */
8436 this.rotateWorld = false;
8437 /**
8438 * 投影矩阵参数
8439 */
8440 /**
8441 * field of view [0-360]
8442 * @see http://en.wikipedia.org/wiki/Angle_of_view
8443 */
8444 this.fov = 30;
8445 this.near = 0.1;
8446 this.far = 1000;
8447 this.aspect = 1;
8448 this.projectionMatrix = create$1();
8449 this.projectionMatrixInverse = create$1();
8450 this.jitteredProjectionMatrix = undefined;
8451 this.enableUpdate = true;
8452 // protected following = undefined;
8453 this.type = CameraType.EXPLORING;
8454 this.trackingMode = CameraTrackingMode.DEFAULT;
8455 this.projectionMode = CameraProjectionMode.PERSPECTIVE;
8456 /**
8457 * for culling use
8458 */
8459 this.frustum = new Frustum();
8460 /**
8461 * ortho matrix for Canvas2D & SVG
8462 */
8463 this.orthoMatrix = create$1();
8464 }
8465 // constructor(type = CameraType.EXPLORING, trackingMode = CameraTrackingMode.DEFAULT) {
8466 // this.setType(type, trackingMode);
8467 // }
8468 Camera.prototype.isOrtho = function () {
8469 return this.projectionMode === CameraProjectionMode.ORTHOGRAPHIC;
8470 };
8471 Camera.prototype.getProjectionMode = function () {
8472 return this.projectionMode;
8473 };
8474 Camera.prototype.getPerspective = function () {
8475 // account for TAA
8476 return this.jitteredProjectionMatrix || this.projectionMatrix;
8477 };
8478 Camera.prototype.getPerspectiveInverse = function () {
8479 return this.projectionMatrixInverse;
8480 };
8481 Camera.prototype.getFrustum = function () {
8482 return this.frustum;
8483 };
8484 Camera.prototype.getPosition = function () {
8485 return this.position;
8486 };
8487 Camera.prototype.getFocalPoint = function () {
8488 return this.focalPoint;
8489 };
8490 Camera.prototype.getDollyingStep = function () {
8491 return this.dollyingStep;
8492 };
8493 Camera.prototype.getNear = function () {
8494 return this.near;
8495 };
8496 Camera.prototype.getFar = function () {
8497 return this.far;
8498 };
8499 Camera.prototype.getZoom = function () {
8500 return this.zoom;
8501 };
8502 Camera.prototype.getOrthoMatrix = function () {
8503 return this.orthoMatrix;
8504 };
8505 Camera.prototype.getView = function () {
8506 return this.view;
8507 };
8508 Camera.prototype.setEnableUpdate = function (enabled) {
8509 this.enableUpdate = enabled;
8510 };
8511 Camera.prototype.setType = function (type, trackingMode) {
8512 this.type = type;
8513 if (this.type === CameraType.EXPLORING) {
8514 this.setWorldRotation(true);
8515 }
8516 else {
8517 this.setWorldRotation(false);
8518 }
8519 this._getAngles();
8520 if (this.type === CameraType.TRACKING && trackingMode !== undefined) {
8521 this.setTrackingMode(trackingMode);
8522 }
8523 return this;
8524 };
8525 Camera.prototype.setProjectionMode = function (projectionMode) {
8526 this.projectionMode = projectionMode;
8527 return this;
8528 };
8529 Camera.prototype.setTrackingMode = function (trackingMode) {
8530 if (this.type !== CameraType.TRACKING) {
8531 throw new Error('Impossible to set a tracking mode if the camera is not of tracking type');
8532 }
8533 this.trackingMode = trackingMode;
8534 return this;
8535 };
8536 /**
8537 * If flag is true, it reverses the azimuth and elevation angles.
8538 * Subsequent calls to rotate, setAzimuth, setElevation,
8539 * changeAzimuth or changeElevation will cause the inverted effect.
8540 * setRoll or changeRoll is not affected by this method.
8541 *
8542 * This inversion is useful when one wants to simulate that the world
8543 * is moving, instead of the camera.
8544 *
8545 * By default the camera angles are not reversed.
8546 * @param {Boolean} flag the boolean flag to reverse the angles.
8547 */
8548 Camera.prototype.setWorldRotation = function (flag) {
8549 this.rotateWorld = flag;
8550 this._getAngles();
8551 return this;
8552 };
8553 /**
8554 * 计算 MV 矩阵,为相机矩阵的逆矩阵
8555 */
8556 Camera.prototype.getViewTransform = function () {
8557 return invert(create$1(), this.matrix);
8558 };
8559 Camera.prototype.getWorldTransform = function () {
8560 return this.matrix;
8561 };
8562 Camera.prototype.jitterProjectionMatrix = function (x, y) {
8563 var translation = fromTranslation(create$1(), [x, y, 0]);
8564 this.jitteredProjectionMatrix = multiply(create$1(), translation, this.projectionMatrix);
8565 };
8566 Camera.prototype.clearJitterProjectionMatrix = function () {
8567 this.jitteredProjectionMatrix = undefined;
8568 };
8569 /**
8570 * 设置相机矩阵
8571 */
8572 Camera.prototype.setMatrix = function (matrix) {
8573 this.matrix = matrix;
8574 this._update();
8575 return this;
8576 };
8577 Camera.prototype.setFov = function (fov) {
8578 this.setPerspective(this.near, this.far, fov, this.aspect);
8579 return this;
8580 };
8581 Camera.prototype.setAspect = function (aspect) {
8582 this.setPerspective(this.near, this.far, this.fov, aspect);
8583 return this;
8584 };
8585 Camera.prototype.setNear = function (near) {
8586 if (this.projectionMode === CameraProjectionMode.PERSPECTIVE) {
8587 this.setPerspective(near, this.far, this.fov, this.aspect);
8588 }
8589 else {
8590 this.setOrthographic(this.left, this.rright, this.top, this.bottom, near, this.far);
8591 }
8592 return this;
8593 };
8594 Camera.prototype.setFar = function (far) {
8595 if (this.projectionMode === CameraProjectionMode.PERSPECTIVE) {
8596 this.setPerspective(this.near, far, this.fov, this.aspect);
8597 }
8598 else {
8599 this.setOrthographic(this.left, this.rright, this.top, this.bottom, this.near, far);
8600 }
8601 return this;
8602 };
8603 /**
8604 * Sets an offset in a larger frustum, used in PixelPicking
8605 */
8606 Camera.prototype.setViewOffset = function (fullWidth, fullHeight, x, y, width, height) {
8607 this.aspect = fullWidth / fullHeight;
8608 if (this.view === undefined) {
8609 this.view = {
8610 enabled: true,
8611 fullWidth: 1,
8612 fullHeight: 1,
8613 offsetX: 0,
8614 offsetY: 0,
8615 width: 1,
8616 height: 1,
8617 };
8618 }
8619 this.view.enabled = true;
8620 this.view.fullWidth = fullWidth;
8621 this.view.fullHeight = fullHeight;
8622 this.view.offsetX = x;
8623 this.view.offsetY = y;
8624 this.view.width = width;
8625 this.view.height = height;
8626 if (this.projectionMode === CameraProjectionMode.PERSPECTIVE) {
8627 this.setPerspective(this.near, this.far, this.fov, this.aspect);
8628 }
8629 else {
8630 this.setOrthographic(this.left, this.rright, this.top, this.bottom, this.near, this.far);
8631 }
8632 return this;
8633 };
8634 Camera.prototype.clearViewOffset = function () {
8635 if (this.view !== undefined) {
8636 this.view.enabled = false;
8637 }
8638 if (this.projectionMode === CameraProjectionMode.PERSPECTIVE) {
8639 this.setPerspective(this.near, this.far, this.fov, this.aspect);
8640 }
8641 else {
8642 this.setOrthographic(this.left, this.rright, this.top, this.bottom, this.near, this.far);
8643 }
8644 return this;
8645 };
8646 Camera.prototype.setZoom = function (zoom) {
8647 this.zoom = zoom;
8648 if (this.projectionMode === CameraProjectionMode.ORTHOGRAPHIC) {
8649 this.setOrthographic(this.left, this.rright, this.top, this.bottom, this.near, this.far);
8650 }
8651 else if (this.projectionMode === CameraProjectionMode.PERSPECTIVE) {
8652 this.setPerspective(this.near, this.far, this.fov, this.aspect);
8653 }
8654 return this;
8655 };
8656 /**
8657 * Zoom by specified point in viewport coordinates.
8658 */
8659 Camera.prototype.setZoomByViewportPoint = function (zoom, viewportPoint) {
8660 var _a = this.canvas.viewport2Canvas({
8661 x: viewportPoint[0],
8662 y: viewportPoint[1],
8663 }), ox = _a.x, oy = _a.y;
8664 var roll = this.roll;
8665 this.rotate(0, 0, -roll);
8666 this.setPosition(ox, oy);
8667 this.setFocalPoint(ox, oy);
8668 this.setZoom(zoom);
8669 this.rotate(0, 0, roll);
8670 var _b = this.canvas.viewport2Canvas({
8671 x: viewportPoint[0],
8672 y: viewportPoint[1],
8673 }), cx = _b.x, cy = _b.y;
8674 // project to rotated axis
8675 var dvec = fromValues$2(cx - ox, cy - oy, 0);
8676 var dx = dot(dvec, this.right) / length(this.right);
8677 var dy = dot(dvec, this.up) / length(this.up);
8678 this.pan(-dx, -dy);
8679 return this;
8680 };
8681 Camera.prototype.setPerspective = function (near, far, fov, aspect) {
8682 var _a;
8683 this.projectionMode = CameraProjectionMode.PERSPECTIVE;
8684 this.fov = fov;
8685 this.near = near;
8686 this.far = far;
8687 this.aspect = aspect;
8688 var top = (this.near * Math.tan(deg2rad(0.5 * this.fov))) / this.zoom;
8689 var height = 2 * top;
8690 var width = this.aspect * height;
8691 var left = -0.5 * width;
8692 if ((_a = this.view) === null || _a === void 0 ? void 0 : _a.enabled) {
8693 var fullWidth = this.view.fullWidth;
8694 var fullHeight = this.view.fullHeight;
8695 left += (this.view.offsetX * width) / fullWidth;
8696 top -= (this.view.offsetY * height) / fullHeight;
8697 width *= this.view.width / fullWidth;
8698 height *= this.view.height / fullHeight;
8699 }
8700 makePerspective(this.projectionMatrix, left, left + width, top, top - height, near, this.far, this.clipSpaceNearZ === ClipSpaceNearZ.ZERO);
8701 // flipY since the origin of OpenGL/WebGL is bottom-left compared with top-left in Canvas2D
8702 scale(this.projectionMatrix, this.projectionMatrix, fromValues$2(1, -1, 1));
8703 invert(this.projectionMatrixInverse, this.projectionMatrix);
8704 this.triggerUpdate();
8705 return this;
8706 };
8707 Camera.prototype.setOrthographic = function (l, r, t, b, near, far) {
8708 var _a;
8709 this.projectionMode = CameraProjectionMode.ORTHOGRAPHIC;
8710 this.rright = r;
8711 this.left = l;
8712 this.top = t;
8713 this.bottom = b;
8714 this.near = near;
8715 this.far = far;
8716 var dx = (this.rright - this.left) / (2 * this.zoom);
8717 var dy = (this.top - this.bottom) / (2 * this.zoom);
8718 var cx = (this.rright + this.left) / 2;
8719 var cy = (this.top + this.bottom) / 2;
8720 var left = cx - dx;
8721 var right = cx + dx;
8722 var top = cy + dy;
8723 var bottom = cy - dy;
8724 if ((_a = this.view) === null || _a === void 0 ? void 0 : _a.enabled) {
8725 var scaleW = (this.rright - this.left) / this.view.fullWidth / this.zoom;
8726 var scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom;
8727 left += scaleW * this.view.offsetX;
8728 right = left + scaleW * this.view.width;
8729 top -= scaleH * this.view.offsetY;
8730 bottom = top - scaleH * this.view.height;
8731 }
8732 if (this.clipSpaceNearZ === ClipSpaceNearZ.NEGATIVE_ONE) {
8733 ortho(this.projectionMatrix, left, right, bottom, top, near, far);
8734 }
8735 else {
8736 orthoZO(this.projectionMatrix, left, right, bottom, top, near, far);
8737 }
8738 // flipY since the origin of OpenGL/WebGL is bottom-left compared with top-left in Canvas2D
8739 scale(this.projectionMatrix, this.projectionMatrix, fromValues$2(1, -1, 1));
8740 invert(this.projectionMatrixInverse, this.projectionMatrix);
8741 this._getOrthoMatrix();
8742 this.triggerUpdate();
8743 return this;
8744 };
8745 /**
8746 * Move the camera in world coordinates.
8747 * It will keep looking at the current focal point.
8748 *
8749 * support scalars or vectors.
8750 * @example
8751 * setPosition(1, 2, 3);
8752 * setPosition([1, 2, 3]);
8753 */
8754 Camera.prototype.setPosition = function (x, y, z) {
8755 if (y === void 0) { y = this.position[1]; }
8756 if (z === void 0) { z = this.position[2]; }
8757 var position = createVec3(x, y, z);
8758 this._setPosition(position);
8759 this.setFocalPoint(this.focalPoint);
8760 this.triggerUpdate();
8761 return this;
8762 };
8763 /**
8764 * Sets the focal point of this camera in world coordinates.
8765 *
8766 * support scalars or vectors.
8767 * @example
8768 * setFocalPoint(1, 2, 3);
8769 * setFocalPoint([1, 2, 3]);
8770 */
8771 Camera.prototype.setFocalPoint = function (x, y, z) {
8772 if (y === void 0) { y = this.focalPoint[1]; }
8773 if (z === void 0) { z = this.focalPoint[2]; }
8774 var up = fromValues$2(0, 1, 0);
8775 this.focalPoint = createVec3(x, y, z);
8776 if (this.trackingMode === CameraTrackingMode.CINEMATIC) {
8777 var d = subtract$1(create$2(), this.focalPoint, this.position);
8778 x = d[0];
8779 y = d[1];
8780 z = d[2];
8781 var r = length(d);
8782 var el = rad2deg(Math.asin(y / r));
8783 var az = 90 + rad2deg(Math.atan2(z, x));
8784 var m = create$1();
8785 rotateY(m, m, deg2rad(az));
8786 rotateX(m, m, deg2rad(el));
8787 up = transformMat4(create$2(), [0, 1, 0], m);
8788 }
8789 invert(this.matrix, lookAt(create$1(), this.position, this.focalPoint, up));
8790 this._getAxes();
8791 this._getDistance();
8792 this._getAngles();
8793 this.triggerUpdate();
8794 return this;
8795 };
8796 Camera.prototype.getDistance = function () {
8797 return this.distance;
8798 };
8799 Camera.prototype.getDistanceVector = function () {
8800 return this.distanceVector;
8801 };
8802 /**
8803 * Moves the camera towards/from the focal point.
8804 */
8805 Camera.prototype.setDistance = function (d) {
8806 if (this.distance === d || d < 0) {
8807 return this;
8808 }
8809 this.distance = d;
8810 if (this.distance < MIN_DISTANCE) {
8811 this.distance = MIN_DISTANCE;
8812 }
8813 this.dollyingStep = this.distance / 100;
8814 var pos = create$2();
8815 d = this.distance;
8816 var n = this.forward;
8817 var f = this.focalPoint;
8818 pos[0] = d * n[0] + f[0];
8819 pos[1] = d * n[1] + f[1];
8820 pos[2] = d * n[2] + f[2];
8821 this._setPosition(pos);
8822 this.triggerUpdate();
8823 return this;
8824 };
8825 Camera.prototype.setMaxDistance = function (d) {
8826 this.maxDistance = d;
8827 return this;
8828 };
8829 Camera.prototype.setMinDistance = function (d) {
8830 this.minDistance = d;
8831 return this;
8832 };
8833 /**
8834 * 设置相机方位角,不同相机模式下需要重新计算相机位置或者是视点位置
8835 * the azimuth in degrees
8836 */
8837 Camera.prototype.setAzimuth = function (az) {
8838 this.azimuth = getAngle(az);
8839 this.computeMatrix();
8840 this._getAxes();
8841 if (this.type === CameraType.ORBITING ||
8842 this.type === CameraType.EXPLORING) {
8843 this._getPosition();
8844 }
8845 else if (this.type === CameraType.TRACKING) {
8846 this._getFocalPoint();
8847 }
8848 this.triggerUpdate();
8849 return this;
8850 };
8851 Camera.prototype.getAzimuth = function () {
8852 return this.azimuth;
8853 };
8854 /**
8855 * 设置相机方位角,不同相机模式下需要重新计算相机位置或者是视点位置
8856 */
8857 Camera.prototype.setElevation = function (el) {
8858 this.elevation = getAngle(el);
8859 this.computeMatrix();
8860 this._getAxes();
8861 if (this.type === CameraType.ORBITING ||
8862 this.type === CameraType.EXPLORING) {
8863 this._getPosition();
8864 }
8865 else if (this.type === CameraType.TRACKING) {
8866 this._getFocalPoint();
8867 }
8868 this.triggerUpdate();
8869 return this;
8870 };
8871 Camera.prototype.getElevation = function () {
8872 return this.elevation;
8873 };
8874 /**
8875 * 设置相机方位角,不同相机模式下需要重新计算相机位置或者是视点位置
8876 */
8877 Camera.prototype.setRoll = function (angle) {
8878 this.roll = getAngle(angle);
8879 this.computeMatrix();
8880 this._getAxes();
8881 if (this.type === CameraType.ORBITING ||
8882 this.type === CameraType.EXPLORING) {
8883 this._getPosition();
8884 }
8885 else if (this.type === CameraType.TRACKING) {
8886 this._getFocalPoint();
8887 }
8888 this.triggerUpdate();
8889 return this;
8890 };
8891 Camera.prototype.getRoll = function () {
8892 return this.roll;
8893 };
8894 /**
8895 * 根据相机矩阵重新计算各种相机参数
8896 */
8897 Camera.prototype._update = function () {
8898 this._getAxes();
8899 this._getPosition();
8900 this._getDistance();
8901 this._getAngles();
8902 this._getOrthoMatrix();
8903 this.triggerUpdate();
8904 };
8905 /**
8906 * 计算相机矩阵
8907 */
8908 Camera.prototype.computeMatrix = function () {
8909 // 使用四元数描述 3D 旋转
8910 // @see https://xiaoiver.github.io/coding/2018/12/28/Camera-%E8%AE%BE%E8%AE%A1-%E4%B8%80.html
8911 var rotZ = setAxisAngle(create$4(), [0, 0, 1], deg2rad(this.roll));
8912 identity$1(this.matrix);
8913 // only consider HCS for EXPLORING and ORBITING cameras
8914 var rotX = setAxisAngle(create$4(), [1, 0, 0], deg2rad(((this.rotateWorld && this.type !== CameraType.TRACKING) ||
8915 this.type === CameraType.TRACKING
8916 ? 1
8917 : -1) * this.elevation));
8918 var rotY = setAxisAngle(create$4(), [0, 1, 0], deg2rad(((this.rotateWorld && this.type !== CameraType.TRACKING) ||
8919 this.type === CameraType.TRACKING
8920 ? 1
8921 : -1) * this.azimuth));
8922 var rotQ = multiply$2(create$4(), rotY, rotX);
8923 rotQ = multiply$2(create$4(), rotQ, rotZ);
8924 var rotMatrix = fromQuat(create$1(), rotQ);
8925 if (this.type === CameraType.ORBITING ||
8926 this.type === CameraType.EXPLORING) {
8927 translate(this.matrix, this.matrix, this.focalPoint);
8928 multiply(this.matrix, this.matrix, rotMatrix);
8929 translate(this.matrix, this.matrix, [0, 0, this.distance]);
8930 }
8931 else if (this.type === CameraType.TRACKING) {
8932 translate(this.matrix, this.matrix, this.position);
8933 multiply(this.matrix, this.matrix, rotMatrix);
8934 }
8935 };
8936 /**
8937 * Sets the camera position in the camera matrix
8938 */
8939 Camera.prototype._setPosition = function (x, y, z) {
8940 this.position = createVec3(x, y, z);
8941 var m = this.matrix;
8942 m[12] = this.position[0];
8943 m[13] = this.position[1];
8944 m[14] = this.position[2];
8945 m[15] = 1;
8946 this._getOrthoMatrix();
8947 };
8948 /**
8949 * Recalculates axes based on the current matrix
8950 */
8951 Camera.prototype._getAxes = function () {
8952 copy$1(this.right, createVec3(transformMat4$1(create$3(), [1, 0, 0, 0], this.matrix)));
8953 copy$1(this.up, createVec3(transformMat4$1(create$3(), [0, 1, 0, 0], this.matrix)));
8954 copy$1(this.forward, createVec3(transformMat4$1(create$3(), [0, 0, 1, 0], this.matrix)));
8955 normalize(this.right, this.right);
8956 normalize(this.up, this.up);
8957 normalize(this.forward, this.forward);
8958 };
8959 /**
8960 * Recalculates euler angles based on the current state
8961 */
8962 Camera.prototype._getAngles = function () {
8963 // Recalculates angles
8964 var x = this.distanceVector[0];
8965 var y = this.distanceVector[1];
8966 var z = this.distanceVector[2];
8967 var r = length(this.distanceVector);
8968 // FAST FAIL: If there is no distance we cannot compute angles
8969 if (r === 0) {
8970 this.elevation = 0;
8971 this.azimuth = 0;
8972 return;
8973 }
8974 if (this.type === CameraType.TRACKING) {
8975 this.elevation = rad2deg(Math.asin(y / r));
8976 this.azimuth = rad2deg(Math.atan2(-x, -z));
8977 }
8978 else {
8979 if (this.rotateWorld) {
8980 this.elevation = rad2deg(Math.asin(y / r));
8981 this.azimuth = rad2deg(Math.atan2(-x, -z));
8982 }
8983 else {
8984 this.elevation = -rad2deg(Math.asin(y / r));
8985 this.azimuth = -rad2deg(Math.atan2(-x, -z));
8986 }
8987 }
8988 };
8989 /**
8990 * 重新计算相机位置,只有 ORBITING 模式相机位置才会发生变化
8991 */
8992 Camera.prototype._getPosition = function () {
8993 copy$1(this.position, createVec3(transformMat4$1(create$3(), [0, 0, 0, 1], this.matrix)));
8994 // 相机位置变化,需要重新计算视距
8995 this._getDistance();
8996 };
8997 /**
8998 * 重新计算视点,只有 TRACKING 模式视点才会发生变化
8999 */
9000 Camera.prototype._getFocalPoint = function () {
9001 transformMat3(this.distanceVector, [0, 0, -this.distance], fromMat4(create(), this.matrix));
9002 add$1(this.focalPoint, this.position, this.distanceVector);
9003 // 视点变化,需要重新计算视距
9004 this._getDistance();
9005 };
9006 /**
9007 * 重新计算视距
9008 */
9009 Camera.prototype._getDistance = function () {
9010 this.distanceVector = subtract$1(create$2(), this.focalPoint, this.position);
9011 this.distance = length(this.distanceVector);
9012 this.dollyingStep = this.distance / 100;
9013 };
9014 Camera.prototype._getOrthoMatrix = function () {
9015 if (this.projectionMode !== CameraProjectionMode.ORTHOGRAPHIC) {
9016 return;
9017 }
9018 var position = this.position;
9019 var rotZ = setAxisAngle(create$4(), [0, 0, 1], (-this.roll * Math.PI) / 180);
9020 fromRotationTranslationScaleOrigin(this.orthoMatrix, rotZ, fromValues$2((this.rright - this.left) / 2 - position[0], (this.top - this.bottom) / 2 - position[1], 0), fromValues$2(this.zoom, this.zoom, 1), position);
9021 };
9022 Camera.prototype.triggerUpdate = function () {
9023 if (this.enableUpdate) {
9024 // update frustum
9025 var viewMatrix = this.getViewTransform();
9026 var vpMatrix = multiply(create$1(), this.getPerspective(), viewMatrix);
9027 this.getFrustum().extractFromVPMatrix(vpMatrix);
9028 this.eventEmitter.emit(CameraEvent.UPDATED);
9029 }
9030 };
9031 Camera.prototype.rotate = function (azimuth, elevation, roll) {
9032 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9033 };
9034 Camera.prototype.pan = function (tx, ty) {
9035 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9036 };
9037 Camera.prototype.dolly = function (value) {
9038 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9039 };
9040 Camera.prototype.createLandmark = function (name, params) {
9041 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9042 };
9043 Camera.prototype.gotoLandmark = function (name, options) {
9044 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9045 };
9046 Camera.prototype.cancelLandmarkAnimation = function () {
9047 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
9048 };
9049 return Camera;
9050 }());
9051
9052 function memoize(func, resolver) {
9053 if (typeof func !== 'function' ||
9054 (resolver != null && typeof resolver !== 'function')) {
9055 throw new TypeError('Expected a function');
9056 }
9057 var memoized = function () {
9058 var args = [];
9059 for (var _i = 0; _i < arguments.length; _i++) {
9060 args[_i] = arguments[_i];
9061 }
9062 var key = resolver ? resolver.apply(this, args) : args[0];
9063 var cache = memoized.cache;
9064 if (cache.has(key)) {
9065 return cache.get(key);
9066 }
9067 var result = func.apply(this, args);
9068 memoized.cache = cache.set(key, result) || cache;
9069 return result;
9070 };
9071 memoized.cache = new (memoize.Cache || Map)();
9072 return memoized;
9073 }
9074 memoize.Cache = Map;
9075
9076 // These units are iterated through, so be careful when adding or changing the
9077 // order.
9078 var UnitType;
9079 (function (UnitType) {
9080 UnitType[UnitType["kUnknown"] = 0] = "kUnknown";
9081 UnitType[UnitType["kNumber"] = 1] = "kNumber";
9082 UnitType[UnitType["kPercentage"] = 2] = "kPercentage";
9083 // Length units
9084 UnitType[UnitType["kEms"] = 3] = "kEms";
9085 // kExs,
9086 UnitType[UnitType["kPixels"] = 4] = "kPixels";
9087 // kCentimeters,
9088 // kMillimeters,
9089 // kInches,
9090 // kPoints,
9091 // kPicas,
9092 // kQuarterMillimeters,
9093 // https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
9094 //
9095 // See also IsViewportPercentageLength.
9096 // kViewportWidth,
9097 // kViewportHeight,
9098 // kViewportInlineSize,
9099 // kViewportBlockSize,
9100 // kViewportMin,
9101 // kViewportMax,
9102 // kSmallViewportWidth,
9103 // kSmallViewportHeight,
9104 // kSmallViewportInlineSize,
9105 // kSmallViewportBlockSize,
9106 // kSmallViewportMin,
9107 // kSmallViewportMax,
9108 // kLargeViewportWidth,
9109 // kLargeViewportHeight,
9110 // kLargeViewportInlineSize,
9111 // kLargeViewportBlockSize,
9112 // kLargeViewportMin,
9113 // kLargeViewportMax,
9114 // kDynamicViewportWidth,
9115 // kDynamicViewportHeight,
9116 // kDynamicViewportInlineSize,
9117 // kDynamicViewportBlockSize,
9118 // kDynamicViewportMin,
9119 // kDynamicViewportMax,
9120 // https://drafts.csswg.org/css-contain-3/#container-lengths
9121 //
9122 // See also IsContainerPercentageLength.
9123 // kContainerWidth,
9124 // kContainerHeight,
9125 // kContainerInlineSize,
9126 // kContainerBlockSize,
9127 // kContainerMin,
9128 // kContainerMax,
9129 UnitType[UnitType["kRems"] = 5] = "kRems";
9130 // kChs,
9131 // kUserUnits, // The SVG term for unitless lengths
9132 // Angle units
9133 UnitType[UnitType["kDegrees"] = 6] = "kDegrees";
9134 UnitType[UnitType["kRadians"] = 7] = "kRadians";
9135 UnitType[UnitType["kGradians"] = 8] = "kGradians";
9136 UnitType[UnitType["kTurns"] = 9] = "kTurns";
9137 // Time units
9138 UnitType[UnitType["kMilliseconds"] = 10] = "kMilliseconds";
9139 UnitType[UnitType["kSeconds"] = 11] = "kSeconds";
9140 // kHertz,
9141 // kKilohertz,
9142 // Resolution
9143 // kDotsPerPixel,
9144 // kDotsPerInch,
9145 // kDotsPerCentimeter,
9146 // Other units
9147 // kFraction,
9148 UnitType[UnitType["kInteger"] = 12] = "kInteger";
9149 // This value is used to handle quirky margins in reflow roots (body, td,
9150 // and th) like WinIE. The basic idea is that a stylesheet can use the value
9151 // __qem (for quirky em) instead of em. When the quirky value is used, if
9152 // you're in quirks mode, the margin will collapse away inside a table cell.
9153 // This quirk is specified in the HTML spec but our impl is different.
9154 // TODO: Remove this. crbug.com/443952
9155 // kQuirkyEms,
9156 })(UnitType || (UnitType = {}));
9157 var UnitCategory;
9158 (function (UnitCategory) {
9159 UnitCategory[UnitCategory["kUNumber"] = 0] = "kUNumber";
9160 UnitCategory[UnitCategory["kUPercent"] = 1] = "kUPercent";
9161 UnitCategory[UnitCategory["kULength"] = 2] = "kULength";
9162 UnitCategory[UnitCategory["kUAngle"] = 3] = "kUAngle";
9163 UnitCategory[UnitCategory["kUTime"] = 4] = "kUTime";
9164 // kUFrequency,
9165 // kUResolution,
9166 UnitCategory[UnitCategory["kUOther"] = 5] = "kUOther";
9167 })(UnitCategory || (UnitCategory = {}));
9168 var ValueRange;
9169 (function (ValueRange) {
9170 ValueRange[ValueRange["kAll"] = 0] = "kAll";
9171 ValueRange[ValueRange["kNonNegative"] = 1] = "kNonNegative";
9172 ValueRange[ValueRange["kInteger"] = 2] = "kInteger";
9173 ValueRange[ValueRange["kNonNegativeInteger"] = 3] = "kNonNegativeInteger";
9174 ValueRange[ValueRange["kPositiveInteger"] = 4] = "kPositiveInteger";
9175 })(ValueRange || (ValueRange = {}));
9176 var Nested;
9177 (function (Nested) {
9178 Nested[Nested["kYes"] = 0] = "kYes";
9179 Nested[Nested["kNo"] = 1] = "kNo";
9180 })(Nested || (Nested = {}));
9181 var ParenLess;
9182 (function (ParenLess) {
9183 ParenLess[ParenLess["kYes"] = 0] = "kYes";
9184 ParenLess[ParenLess["kNo"] = 1] = "kNo";
9185 })(ParenLess || (ParenLess = {}));
9186
9187 // This file specifies the unit strings used in CSSPrimitiveValues.
9188 var data = [
9189 {
9190 name: 'em',
9191 unit_type: UnitType.kEms,
9192 },
9193 // {
9194 // name: 'ex',
9195 // unit_type: UnitType.kExs,
9196 // },
9197 {
9198 name: 'px',
9199 unit_type: UnitType.kPixels,
9200 },
9201 // {
9202 // name: "cm",
9203 // unit_type: UnitType.kCentimeters,
9204 // },
9205 // {
9206 // name: "mm",
9207 // unit_type: UnitType.kMillimeters,
9208 // },
9209 // {
9210 // name: "q",
9211 // unit_type: UnitType.kQuarterMillimeters,
9212 // },
9213 // {
9214 // name: "in",
9215 // unit_type: UnitType.kInches,
9216 // },
9217 // {
9218 // name: "pt",
9219 // unit_type: UnitType.kPoints,
9220 // },
9221 // {
9222 // name: "pc",
9223 // unit_type: UnitType.kPicas,
9224 // },
9225 {
9226 name: 'deg',
9227 unit_type: UnitType.kDegrees,
9228 },
9229 {
9230 name: 'rad',
9231 unit_type: UnitType.kRadians,
9232 },
9233 {
9234 name: 'grad',
9235 unit_type: UnitType.kGradians,
9236 },
9237 {
9238 name: 'ms',
9239 unit_type: UnitType.kMilliseconds,
9240 },
9241 {
9242 name: 's',
9243 unit_type: UnitType.kSeconds,
9244 },
9245 // {
9246 // name: "hz",
9247 // unit_type: UnitType.kHertz,
9248 // },
9249 // {
9250 // name: "khz",
9251 // unit_type: UnitType.kKilohertz,
9252 // },
9253 // {
9254 // name: "dpi",
9255 // unit_type: "kDotsPerInch",
9256 // },
9257 // {
9258 // name: "dpcm",
9259 // unit_type: "kDotsPerCentimeter",
9260 // },
9261 // {
9262 // name: "dppx",
9263 // unit_type: "kDotsPerPixel",
9264 // },
9265 // {
9266 // name: "x",
9267 // unit_type: "kDotsPerPixel",
9268 // },
9269 // {
9270 // name: "vw",
9271 // unit_type: "kViewportWidth",
9272 // },
9273 // {
9274 // name: "vh",
9275 // unit_type: "kViewportHeight",
9276 // },
9277 // {
9278 // name: "vi",
9279 // unit_type: "kViewportInlineSize",
9280 // },
9281 // {
9282 // name: "vb",
9283 // unit_type: "kViewportBlockSize",
9284 // },
9285 // {
9286 // name: "vmin",
9287 // unit_type: UnitType.kViewportMin,
9288 // },
9289 // {
9290 // name: "vmax",
9291 // unit_type: UnitType.kViewportMax,
9292 // },
9293 // {
9294 // name: "svw",
9295 // unit_type: "kSmallViewportWidth",
9296 // },
9297 // {
9298 // name: "svh",
9299 // unit_type: "kSmallViewportHeight",
9300 // },
9301 // {
9302 // name: "svi",
9303 // unit_type: "kSmallViewportInlineSize",
9304 // },
9305 // {
9306 // name: "svb",
9307 // unit_type: "kSmallViewportBlockSize",
9308 // },
9309 // {
9310 // name: "svmin",
9311 // unit_type: "kSmallViewportMin",
9312 // },
9313 // {
9314 // name: "svmax",
9315 // unit_type: "kSmallViewportMax",
9316 // },
9317 // {
9318 // name: "lvw",
9319 // unit_type: "kLargeViewportWidth",
9320 // },
9321 // {
9322 // name: "lvh",
9323 // unit_type: "kLargeViewportHeight",
9324 // },
9325 // {
9326 // name: "lvi",
9327 // unit_type: "kLargeViewportInlineSize",
9328 // },
9329 // {
9330 // name: "lvb",
9331 // unit_type: "kLargeViewportBlockSize",
9332 // },
9333 // {
9334 // name: "lvmin",
9335 // unit_type: UnitType.kLargeViewportMin,
9336 // },
9337 // {
9338 // name: "lvmax",
9339 // unit_type: UnitType.kLargeViewportMax,
9340 // },
9341 // {
9342 // name: "dvw",
9343 // unit_type: UnitType.kDynamicViewportWidth,
9344 // },
9345 // {
9346 // name: "dvh",
9347 // unit_type: UnitType.kDynamicViewportHeight,
9348 // },
9349 // {
9350 // name: "dvi",
9351 // unit_type: UnitType.kDynamicViewportInlineSize,
9352 // },
9353 // {
9354 // name: "dvb",
9355 // unit_type: UnitType.kDynamicViewportBlockSize,
9356 // },
9357 // {
9358 // name: "dvmin",
9359 // unit_type: UnitType.kDynamicViewportMin,
9360 // },
9361 // {
9362 // name: "dvmax",
9363 // unit_type: UnitType.kDynamicViewportMax,
9364 // },
9365 // {
9366 // name: "cqw",
9367 // unit_type: UnitType.kContainerWidth,
9368 // },
9369 // {
9370 // name: "cqh",
9371 // unit_type: UnitType.kContainerHeight,
9372 // },
9373 // {
9374 // name: "cqi",
9375 // unit_type: UnitType.kContainerInlineSize,
9376 // },
9377 // {
9378 // name: "cqb",
9379 // unit_type: UnitType.kContainerBlockSize,
9380 // },
9381 // {
9382 // name: "cqmin",
9383 // unit_type: UnitType.kContainerMin,
9384 // },
9385 // {
9386 // name: "cqmax",
9387 // unit_type: UnitType.kContainerMax,
9388 // },
9389 {
9390 name: 'rem',
9391 unit_type: UnitType.kRems,
9392 },
9393 // {
9394 // name: 'fr',
9395 // unit_type: UnitType.kFraction,
9396 // },
9397 {
9398 name: 'turn',
9399 unit_type: UnitType.kTurns,
9400 },
9401 // {
9402 // name: 'ch',
9403 // unit_type: UnitType.kChs,
9404 // },
9405 // {
9406 // name: '__qem',
9407 // unit_type: UnitType.kQuirkyEms,
9408 // },
9409 ];
9410 var CSSStyleValueType;
9411 (function (CSSStyleValueType) {
9412 CSSStyleValueType[CSSStyleValueType["kUnknownType"] = 0] = "kUnknownType";
9413 CSSStyleValueType[CSSStyleValueType["kUnparsedType"] = 1] = "kUnparsedType";
9414 CSSStyleValueType[CSSStyleValueType["kKeywordType"] = 2] = "kKeywordType";
9415 // Start of CSSNumericValue subclasses
9416 CSSStyleValueType[CSSStyleValueType["kUnitType"] = 3] = "kUnitType";
9417 CSSStyleValueType[CSSStyleValueType["kSumType"] = 4] = "kSumType";
9418 CSSStyleValueType[CSSStyleValueType["kProductType"] = 5] = "kProductType";
9419 CSSStyleValueType[CSSStyleValueType["kNegateType"] = 6] = "kNegateType";
9420 CSSStyleValueType[CSSStyleValueType["kInvertType"] = 7] = "kInvertType";
9421 CSSStyleValueType[CSSStyleValueType["kMinType"] = 8] = "kMinType";
9422 CSSStyleValueType[CSSStyleValueType["kMaxType"] = 9] = "kMaxType";
9423 CSSStyleValueType[CSSStyleValueType["kClampType"] = 10] = "kClampType";
9424 // End of CSSNumericValue subclasses
9425 CSSStyleValueType[CSSStyleValueType["kTransformType"] = 11] = "kTransformType";
9426 CSSStyleValueType[CSSStyleValueType["kPositionType"] = 12] = "kPositionType";
9427 CSSStyleValueType[CSSStyleValueType["kURLImageType"] = 13] = "kURLImageType";
9428 CSSStyleValueType[CSSStyleValueType["kColorType"] = 14] = "kColorType";
9429 CSSStyleValueType[CSSStyleValueType["kUnsupportedColorType"] = 15] = "kUnsupportedColorType";
9430 })(CSSStyleValueType || (CSSStyleValueType = {}));
9431 // function parseCSSStyleValue(propertyName: string, value: string): CSSStyleValue[] {
9432 // // const propertyId = cssPropertyID(propertyName);
9433 // // if (propertyId === CSSPropertyID.kInvalid) {
9434 // // return [];
9435 // // }
9436 // // const customPropertyName = propertyId === CSSPropertyID.kVariable ? propertyName : null;
9437 // // return fromString(propertyId, customPropertyName, value);
9438 // return [];
9439 // }
9440 var stringToUnitType = function (name) {
9441 return data.find(function (item) { return item.name === name; }).unit_type;
9442 };
9443 var unitFromName = function (name) {
9444 if (!name) {
9445 return UnitType.kUnknown;
9446 }
9447 if (name === 'number') {
9448 return UnitType.kNumber;
9449 }
9450 if (name === 'percent' || name === '%') {
9451 return UnitType.kPercentage;
9452 }
9453 return stringToUnitType(name);
9454 };
9455 var unitTypeToUnitCategory = function (type) {
9456 switch (type) {
9457 case UnitType.kNumber:
9458 case UnitType.kInteger:
9459 return UnitCategory.kUNumber;
9460 case UnitType.kPercentage:
9461 return UnitCategory.kUPercent;
9462 case UnitType.kPixels:
9463 // case UnitType.kCentimeters:
9464 // case UnitType.kMillimeters:
9465 // case UnitType.kQuarterMillimeters:
9466 // case UnitType.kInches:
9467 // case UnitType.kPoints:
9468 // case UnitType.kPicas:
9469 // case UnitType.kUserUnits:
9470 return UnitCategory.kULength;
9471 case UnitType.kMilliseconds:
9472 case UnitType.kSeconds:
9473 return UnitCategory.kUTime;
9474 case UnitType.kDegrees:
9475 case UnitType.kRadians:
9476 case UnitType.kGradians:
9477 case UnitType.kTurns:
9478 return UnitCategory.kUAngle;
9479 // case UnitType.kHertz:
9480 // case UnitType.kKilohertz:
9481 // return UnitCategory.kUFrequency;
9482 // case UnitType.kDotsPerPixel:
9483 // case UnitType.kDotsPerInch:
9484 // case UnitType.kDotsPerCentimeter:
9485 // return UnitCategory.kUResolution;
9486 default:
9487 return UnitCategory.kUOther;
9488 }
9489 };
9490 var canonicalUnitTypeForCategory = function (category) {
9491 // The canonical unit type is chosen according to the way
9492 // CSSPropertyParser.ValidUnit() chooses the default unit in each category
9493 // (based on unitflags).
9494 switch (category) {
9495 case UnitCategory.kUNumber:
9496 return UnitType.kNumber;
9497 case UnitCategory.kULength:
9498 return UnitType.kPixels;
9499 case UnitCategory.kUPercent:
9500 return UnitType.kPercentage;
9501 // return UnitType.kUnknown; // Cannot convert between numbers and percent.
9502 case UnitCategory.kUTime:
9503 return UnitType.kSeconds;
9504 case UnitCategory.kUAngle:
9505 return UnitType.kDegrees;
9506 // case UnitCategory.kUFrequency:
9507 // return UnitType.kHertz;
9508 // case UnitCategory.kUResolution:
9509 // return UnitType.kDotsPerPixel;
9510 default:
9511 return UnitType.kUnknown;
9512 }
9513 };
9514 /**
9515 * @see https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/core/css/css_primitive_value.cc#353
9516 */
9517 var conversionToCanonicalUnitsScaleFactor = function (unit_type) {
9518 var factor = 1.0;
9519 // FIXME: the switch can be replaced by an array of scale factors.
9520 switch (unit_type) {
9521 // These are "canonical" units in their respective categories.
9522 case UnitType.kPixels:
9523 // case UnitType.kUserUnits:
9524 case UnitType.kDegrees:
9525 case UnitType.kSeconds:
9526 // case UnitType.kHertz:
9527 break;
9528 case UnitType.kMilliseconds:
9529 factor = 0.001;
9530 break;
9531 // case UnitType.kCentimeters:
9532 // // factor = kCssPixelsPerCentimeter;
9533 // break;
9534 // case UnitType.kDotsPerCentimeter:
9535 // // factor = 1 / kCssPixelsPerCentimeter;
9536 // break;
9537 // case UnitType.kMillimeters:
9538 // // factor = kCssPixelsPerMillimeter;
9539 // break;
9540 // case UnitType.kQuarterMillimeters:
9541 // // factor = kCssPixelsPerQuarterMillimeter;
9542 // break;
9543 // case UnitType.kInches:
9544 // // factor = kCssPixelsPerInch;
9545 // break;
9546 // case UnitType.kDotsPerInch:
9547 // // factor = 1 / kCssPixelsPerInch;
9548 // break;
9549 // case UnitType.kPoints:
9550 // // factor = kCssPixelsPerPoint;
9551 // break;
9552 // case UnitType.kPicas:
9553 // // factor = kCssPixelsPerPica;
9554 // break;
9555 case UnitType.kRadians:
9556 factor = 180 / Math.PI;
9557 break;
9558 case UnitType.kGradians:
9559 factor = 0.9;
9560 break;
9561 case UnitType.kTurns:
9562 factor = 360;
9563 break;
9564 }
9565 return factor;
9566 };
9567 var unitTypeToString = function (type) {
9568 switch (type) {
9569 case UnitType.kNumber:
9570 case UnitType.kInteger:
9571 // case UnitType.kUserUnits:
9572 return '';
9573 case UnitType.kPercentage:
9574 return '%';
9575 case UnitType.kEms:
9576 // case UnitType.kQuirkyEms:
9577 return 'em';
9578 // case UnitType.kExs:
9579 // return 'ex';
9580 case UnitType.kRems:
9581 return 'rem';
9582 // case UnitType.kChs:
9583 // return 'ch';
9584 case UnitType.kPixels:
9585 return 'px';
9586 // case UnitType.kCentimeters:
9587 // return 'cm';
9588 // case UnitType.kDotsPerPixel:
9589 // return 'dppx';
9590 // case UnitType.kDotsPerInch:
9591 // return 'dpi';
9592 // case UnitType.kDotsPerCentimeter:
9593 // return 'dpcm';
9594 // case UnitType.kMillimeters:
9595 // return 'mm';
9596 // case UnitType.kQuarterMillimeters:
9597 // return 'q';
9598 // case UnitType.kInches:
9599 // return 'in';
9600 // case UnitType.kPoints:
9601 // return 'pt';
9602 // case UnitType.kPicas:
9603 // return 'pc';
9604 case UnitType.kDegrees:
9605 return 'deg';
9606 case UnitType.kRadians:
9607 return 'rad';
9608 case UnitType.kGradians:
9609 return 'grad';
9610 case UnitType.kMilliseconds:
9611 return 'ms';
9612 case UnitType.kSeconds:
9613 return 's';
9614 // case UnitType.kHertz:
9615 // return 'hz';
9616 // case UnitType.kKilohertz:
9617 // return 'khz';
9618 case UnitType.kTurns:
9619 return 'turn';
9620 }
9621 return '';
9622 };
9623 /**
9624 * CSSStyleValue is the base class for all CSS values accessible from Typed OM.
9625 * Values that are not yet supported as specific types are also returned as base CSSStyleValues.
9626 *
9627 * Spec @see https://drafts.css-houdini.org/css-typed-om/#stylevalue-objects
9628 * Docs @see https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleValue
9629 */
9630 var CSSStyleValue = /** @class */ (function () {
9631 function CSSStyleValue() {
9632 }
9633 // static parse(propertyName: string, value: string): CSSStyleValue {
9634 // return parseCSSStyleValue(propertyName, value)[0];
9635 // }
9636 // static parseAll(propertyName: string, value: string): CSSStyleValue[] {
9637 // return parseCSSStyleValue(propertyName, value);
9638 // }
9639 CSSStyleValue.isAngle = function (unit) {
9640 return (unit === UnitType.kDegrees ||
9641 unit === UnitType.kRadians ||
9642 unit === UnitType.kGradians ||
9643 unit === UnitType.kTurns);
9644 };
9645 // static isViewportPercentageLength(type: UnitType) {
9646 // return type >= UnitType.kViewportWidth && type <= UnitType.kDynamicViewportMax;
9647 // }
9648 // static isContainerPercentageLength(type: UnitType) {
9649 // return type >= UnitType.kContainerWidth && type <= UnitType.kContainerMax;
9650 // }
9651 CSSStyleValue.isLength = function (type) {
9652 // return (type >= UnitType.kEms && type <= UnitType.kUserUnits) || type == UnitType.kQuirkyEms;
9653 return type >= UnitType.kEms && type < UnitType.kDegrees;
9654 };
9655 CSSStyleValue.isRelativeUnit = function (type) {
9656 return (type === UnitType.kPercentage ||
9657 type === UnitType.kEms ||
9658 // type === UnitType.kExs ||
9659 type === UnitType.kRems
9660 // type === UnitType.kChs ||
9661 // this.isViewportPercentageLength(type) ||
9662 // this.isContainerPercentageLength(type)
9663 );
9664 };
9665 CSSStyleValue.isTime = function (unit) {
9666 return unit === UnitType.kSeconds || unit === UnitType.kMilliseconds;
9667 };
9668 // protected abstract toCSSValue(): CSSValue;
9669 CSSStyleValue.prototype.toString = function () {
9670 return this.buildCSSText(Nested.kNo, ParenLess.kNo, '');
9671 };
9672 CSSStyleValue.prototype.isNumericValue = function () {
9673 return (this.getType() >= CSSStyleValueType.kUnitType &&
9674 this.getType() <= CSSStyleValueType.kClampType);
9675 };
9676 return CSSStyleValue;
9677 }());
9678
9679 /**
9680 * CSSColorValue is the base class used for the various CSS color interfaces.
9681 *
9682 * @see https://drafts.css-houdini.org/css-typed-om-1/#colorvalue-objects
9683 */
9684 var CSSColorValue = /** @class */ (function (_super) {
9685 __extends(CSSColorValue, _super);
9686 function CSSColorValue(colorSpace) {
9687 var _this = _super.call(this) || this;
9688 _this.colorSpace = colorSpace;
9689 return _this;
9690 }
9691 CSSColorValue.prototype.getType = function () {
9692 return CSSStyleValueType.kColorType;
9693 };
9694 // buildCSSText(n: Nested, p: ParenLess, result: string): string {
9695 // let text = '';
9696 // if (this.colorSpace === 'rgb') {
9697 // text = `rgba(${this.channels.join(',')},${this.alpha})`;
9698 // }
9699 // return (result += text);
9700 // }
9701 /**
9702 * @see https://drafts.css-houdini.org/css-typed-om-1/#dom-csscolorvalue-to
9703 */
9704 CSSColorValue.prototype.to = function (colorSpace) {
9705 return this;
9706 };
9707 return CSSColorValue;
9708 }(CSSStyleValue));
9709
9710 var GradientType;
9711 (function (GradientType) {
9712 GradientType[GradientType["Constant"] = 0] = "Constant";
9713 GradientType[GradientType["LinearGradient"] = 1] = "LinearGradient";
9714 GradientType[GradientType["RadialGradient"] = 2] = "RadialGradient";
9715 })(GradientType || (GradientType = {}));
9716 var CSSGradientValue = /** @class */ (function (_super) {
9717 __extends(CSSGradientValue, _super);
9718 function CSSGradientValue(type, value) {
9719 var _this = _super.call(this) || this;
9720 _this.type = type;
9721 _this.value = value;
9722 return _this;
9723 }
9724 CSSGradientValue.prototype.clone = function () {
9725 return new CSSGradientValue(this.type, this.value);
9726 };
9727 CSSGradientValue.prototype.buildCSSText = function (n, p, result) {
9728 return result;
9729 };
9730 CSSGradientValue.prototype.getType = function () {
9731 return CSSStyleValueType.kColorType;
9732 };
9733 return CSSGradientValue;
9734 }(CSSStyleValue));
9735
9736 /**
9737 * CSSKeywordValue represents CSS Values that are specified as keywords
9738 * eg. 'initial'
9739 * @see https://developer.mozilla.org/en-US/docs/Web/API/CSSKeywordValue
9740 * @see https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl
9741 */
9742 var CSSKeywordValue = /** @class */ (function (_super) {
9743 __extends(CSSKeywordValue, _super);
9744 function CSSKeywordValue(value) {
9745 var _this = _super.call(this) || this;
9746 _this.value = value;
9747 return _this;
9748 }
9749 CSSKeywordValue.prototype.clone = function () {
9750 return new CSSKeywordValue(this.value);
9751 };
9752 CSSKeywordValue.prototype.getType = function () {
9753 return CSSStyleValueType.kKeywordType;
9754 };
9755 CSSKeywordValue.prototype.buildCSSText = function (n, p, result) {
9756 return result + this.value;
9757 };
9758 return CSSKeywordValue;
9759 }(CSSStyleValue));
9760
9761 var camelCase = memoize(function (str) {
9762 if (str === void 0) { str = ''; }
9763 return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
9764 });
9765 var kebabize = function (str) {
9766 return str
9767 .split('')
9768 .map(function (letter, idx) {
9769 return letter.toUpperCase() === letter
9770 ? "".concat(idx !== 0 ? '-' : '').concat(letter.toLowerCase())
9771 : letter;
9772 })
9773 .join('');
9774 };
9775
9776 function DCHECK(bool) {
9777 if (!bool) {
9778 throw new Error();
9779 }
9780 }
9781 function isFunction$1(func) {
9782 return typeof func === 'function';
9783 }
9784 function isSymbol(value) {
9785 // @see https://github.com/lodash/lodash/blob/master/isSymbol.js
9786 return typeof value === 'symbol';
9787 }
9788 var definedProps = function (obj) {
9789 return Object.fromEntries(Object.entries(obj).filter(function (_a) {
9790 var _b = __read(_a, 2), v = _b[1];
9791 return v !== undefined;
9792 }));
9793 };
9794 var FORMAT_ATTR_MAP = {
9795 d: {
9796 alias: 'path',
9797 },
9798 strokeDasharray: {
9799 alias: 'lineDash',
9800 },
9801 strokeWidth: {
9802 alias: 'lineWidth',
9803 },
9804 textAnchor: {
9805 alias: 'textAlign',
9806 },
9807 src: {
9808 alias: 'img',
9809 },
9810 };
9811 var formatAttributeName = memoize(function (name) {
9812 var attributeName = camelCase(name);
9813 var map = FORMAT_ATTR_MAP[attributeName];
9814 attributeName = (map === null || map === void 0 ? void 0 : map.alias) || attributeName;
9815 return attributeName;
9816 });
9817
9818 // type CSSNumericBaseType =
9819 // | 'length'
9820 // | 'angle'
9821 // | 'time'
9822 // | 'frequency'
9823 // | 'resolution'
9824 // | 'flex'
9825 // | 'percent';
9826 // https://drafts.css-houdini.org/css-typed-om/#dictdef-cssnumerictype
9827 // interface CSSNumericType {
9828 // length: number;
9829 // angle: number;
9830 // time: number;
9831 // frequency: number;
9832 // resolution: number;
9833 // flex: number;
9834 // percent: number;
9835 // percentHint: CSSNumericBaseType;
9836 // }
9837 var formatInfinityOrNaN = function (number, suffix) {
9838 if (suffix === void 0) { suffix = ''; }
9839 var result = '';
9840 if (!Number.isFinite(number)) {
9841 if (number > 0)
9842 result = 'infinity';
9843 else
9844 result = '-infinity';
9845 }
9846 else {
9847 DCHECK(Number.isNaN(number));
9848 result = 'NaN';
9849 }
9850 return (result += suffix);
9851 };
9852 var toCanonicalUnit = function (unit) {
9853 return canonicalUnitTypeForCategory(unitTypeToUnitCategory(unit));
9854 };
9855 /**
9856 * CSSNumericValue is the base class for numeric and length typed CSS Values.
9857 * @see https://drafts.css-houdini.org/css-typed-om/#numeric-objects
9858 * @see https://developer.mozilla.org/en-US/docs/Web/API/CSSNumericValue
9859 * @see https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl
9860 */
9861 /**
9862 * Represents numeric values that can be expressed as a single number plus a
9863 * unit (or a naked number or percentage).
9864 * @see https://drafts.css-houdini.org/css-typed-om/#cssunitvalue
9865 */
9866 var CSSUnitValue = /** @class */ (function (_super) {
9867 __extends(CSSUnitValue, _super);
9868 function CSSUnitValue(value, unitOrName) {
9869 if (unitOrName === void 0) { unitOrName = UnitType.kNumber; }
9870 var _this = _super.call(this) || this;
9871 var unit;
9872 if (typeof unitOrName === 'string') {
9873 unit = unitFromName(unitOrName);
9874 }
9875 else {
9876 unit = unitOrName;
9877 }
9878 _this.unit = unit;
9879 _this.value = value;
9880 return _this;
9881 }
9882 CSSUnitValue.prototype.clone = function () {
9883 return new CSSUnitValue(this.value, this.unit);
9884 };
9885 CSSUnitValue.prototype.equals = function (other) {
9886 var other_unit_value = other;
9887 return (this.value === other_unit_value.value &&
9888 this.unit === other_unit_value.unit);
9889 };
9890 CSSUnitValue.prototype.getType = function () {
9891 return CSSStyleValueType.kUnitType;
9892 };
9893 CSSUnitValue.prototype.convertTo = function (target_unit) {
9894 if (this.unit === target_unit) {
9895 return new CSSUnitValue(this.value, this.unit);
9896 }
9897 // Instead of defining the scale factors for every unit to every other unit,
9898 // we simply convert to the canonical unit and back since we already have
9899 // the scale factors for canonical units.
9900 var canonical_unit = toCanonicalUnit(this.unit);
9901 if (canonical_unit !== toCanonicalUnit(target_unit) ||
9902 canonical_unit === UnitType.kUnknown) {
9903 return null;
9904 }
9905 var scale_factor = conversionToCanonicalUnitsScaleFactor(this.unit) /
9906 conversionToCanonicalUnitsScaleFactor(target_unit);
9907 return new CSSUnitValue(this.value * scale_factor, target_unit);
9908 };
9909 CSSUnitValue.prototype.buildCSSText = function (n, p, result) {
9910 var text;
9911 switch (this.unit) {
9912 case UnitType.kUnknown:
9913 // FIXME
9914 break;
9915 case UnitType.kInteger:
9916 text = Number(this.value).toFixed(0);
9917 break;
9918 case UnitType.kNumber:
9919 case UnitType.kPercentage:
9920 case UnitType.kEms:
9921 // case UnitType.kQuirkyEms:
9922 // case UnitType.kExs:
9923 case UnitType.kRems:
9924 // case UnitType.kChs:
9925 case UnitType.kPixels:
9926 // case UnitType.kCentimeters:
9927 // case UnitType.kDotsPerPixel:
9928 // case UnitType.kDotsPerInch:
9929 // case UnitType.kDotsPerCentimeter:
9930 // case UnitType.kMillimeters:
9931 // case UnitType.kQuarterMillimeters:
9932 // case UnitType.kInches:
9933 // case UnitType.kPoints:
9934 // case UnitType.kPicas:
9935 // case UnitType.kUserUnits:
9936 case UnitType.kDegrees:
9937 case UnitType.kRadians:
9938 case UnitType.kGradians:
9939 case UnitType.kMilliseconds:
9940 case UnitType.kSeconds:
9941 // case UnitType.kHertz:
9942 // case UnitType.kKilohertz:
9943 case UnitType.kTurns: // case UnitType.kContainerMax: { // case UnitType.kContainerMin: // case UnitType.kContainerBlockSize: // case UnitType.kContainerInlineSize: // case UnitType.kContainerHeight: // case UnitType.kContainerWidth: // case UnitType.kDynamicViewportMax: // case UnitType.kDynamicViewportMin: // case UnitType.kDynamicViewportBlockSize: // case UnitType.kDynamicViewportInlineSize: // case UnitType.kDynamicViewportHeight: // case UnitType.kDynamicViewportWidth: // case UnitType.kLargeViewportMax: // case UnitType.kLargeViewportMin: // case UnitType.kLargeViewportBlockSize: // case UnitType.kLargeViewportInlineSize: // case UnitType.kLargeViewportHeight: // case UnitType.kLargeViewportWidth: // case UnitType.kSmallViewportMax: // case UnitType.kSmallViewportMin: // case UnitType.kSmallViewportBlockSize: // case UnitType.kSmallViewportInlineSize: // case UnitType.kSmallViewportHeight: // case UnitType.kSmallViewportWidth: // case UnitType.kViewportMax: // case UnitType.kViewportMin: // case UnitType.kViewportBlockSize: // case UnitType.kViewportInlineSize: // case UnitType.kViewportHeight: // case UnitType.kViewportWidth: // case UnitType.kFraction:
9944 {
9945 var kMinInteger = -999999;
9946 var kMaxInteger = 999999;
9947 var value = this.value;
9948 var unit = unitTypeToString(this.unit);
9949 if (value < kMinInteger || value > kMaxInteger) {
9950 var unit_1 = unitTypeToString(this.unit);
9951 if (!Number.isFinite(value) || Number.isNaN(value)) {
9952 text = formatInfinityOrNaN(value, unit_1);
9953 }
9954 else {
9955 text = value + (unit_1 || '');
9956 }
9957 }
9958 else {
9959 text = "".concat(value).concat(unit);
9960 }
9961 }
9962 }
9963 result += text;
9964 return result;
9965 };
9966 return CSSUnitValue;
9967 }(CSSStyleValue));
9968 var Opx = new CSSUnitValue(0, 'px');
9969 new CSSUnitValue(1, 'px');
9970 var Odeg = new CSSUnitValue(0, 'deg');
9971
9972 /**
9973 * The CSSRGB class represents the CSS rgb()/rgba() functions.
9974 *
9975 * @see https://drafts.css-houdini.org/css-typed-om-1/#cssrgb
9976 */
9977 var CSSRGB = /** @class */ (function (_super) {
9978 __extends(CSSRGB, _super);
9979 function CSSRGB(r, g, b, alpha,
9980 /**
9981 * 'transparent' & 'none' has the same rgba data
9982 */
9983 isNone) {
9984 if (alpha === void 0) { alpha = 1; }
9985 if (isNone === void 0) { isNone = false; }
9986 var _this = _super.call(this, 'rgb') || this;
9987 _this.r = r;
9988 _this.g = g;
9989 _this.b = b;
9990 _this.alpha = alpha;
9991 _this.isNone = isNone;
9992 return _this;
9993 }
9994 CSSRGB.prototype.clone = function () {
9995 return new CSSRGB(this.r, this.g, this.b, this.alpha);
9996 };
9997 CSSRGB.prototype.buildCSSText = function (n, p, result) {
9998 return result + "rgba(".concat(this.r, ",").concat(this.g, ",").concat(this.b, ",").concat(this.alpha, ")");
9999 };
10000 return CSSRGB;
10001 }(CSSColorValue));
10002
10003 /**
10004 * CSSKeywordValue
10005 */
10006 var unsetKeywordValue = new CSSKeywordValue('unset');
10007 var initialKeywordValue = new CSSKeywordValue('initial');
10008 var inheritKeywordValue = new CSSKeywordValue('inherit');
10009 var keywordCache = {
10010 '': unsetKeywordValue,
10011 unset: unsetKeywordValue,
10012 initial: initialKeywordValue,
10013 inherit: inheritKeywordValue,
10014 };
10015 var getOrCreateKeyword = function (name) {
10016 if (!keywordCache[name]) {
10017 keywordCache[name] = new CSSKeywordValue(name);
10018 }
10019 return keywordCache[name];
10020 };
10021 /**
10022 * CSSColor
10023 */
10024 var noneColor = new CSSRGB(0, 0, 0, 0, true);
10025 var transparentColor = new CSSRGB(0, 0, 0, 0);
10026 var getOrCreateRGBA = memoize(function (r, g, b, a) {
10027 return new CSSRGB(r, g, b, a);
10028 }, function (r, g, b, a) {
10029 return "rgba(".concat(r, ",").concat(g, ",").concat(b, ",").concat(a, ")");
10030 });
10031 // export const getOrCreateUnitValue = memoize(
10032 // (value: number, unitOrName: UnitType | string = UnitType.kNumber) => {
10033 // return new CSSUnitValue(value, unitOrName);
10034 // },
10035 // (value: number, unitOrName: UnitType | string = UnitType.kNumber) => {
10036 // return `${value}${unitOrName}`;
10037 // },
10038 // );
10039 var getOrCreateUnitValue = function (value, unitOrName) {
10040 if (unitOrName === void 0) { unitOrName = UnitType.kNumber; }
10041 return new CSSUnitValue(value, unitOrName);
10042 };
10043 var PECENTAGE_50 = new CSSUnitValue(50, '%');
10044
10045 /**
10046 * @see https://doc.babylonjs.com/how_to/optimizing_your_scene#changing-mesh-culling-strategy
10047 */
10048 var Strategy;
10049 (function (Strategy) {
10050 Strategy[Strategy["Standard"] = 0] = "Standard";
10051 })(Strategy || (Strategy = {}));
10052
10053 var SortReason;
10054 (function (SortReason) {
10055 SortReason[SortReason["ADDED"] = 0] = "ADDED";
10056 SortReason[SortReason["REMOVED"] = 1] = "REMOVED";
10057 SortReason[SortReason["Z_INDEX_CHANGED"] = 2] = "Z_INDEX_CHANGED";
10058 })(SortReason || (SortReason = {}));
10059
10060 var EMPTY_PARSED_PATH = {
10061 absolutePath: [],
10062 hasArc: false,
10063 segments: [],
10064 polygons: [],
10065 polylines: [],
10066 curve: null,
10067 totalLength: 0,
10068 rect: new Rectangle(0, 0, 0, 0),
10069 };
10070
10071 /**
10072 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type
10073 */
10074 var PropertySyntax;
10075 (function (PropertySyntax) {
10076 /**
10077 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#coordinate
10078 */
10079 PropertySyntax["COORDINATE"] = "<coordinate>";
10080 /**
10081 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#color
10082 */
10083 PropertySyntax["COLOR"] = "<color>";
10084 /**
10085 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#paint
10086 */
10087 PropertySyntax["PAINT"] = "<paint>";
10088 /**
10089 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#number
10090 */
10091 PropertySyntax["NUMBER"] = "<number>";
10092 /**
10093 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/angle
10094 */
10095 PropertySyntax["ANGLE"] = "<angle>";
10096 /**
10097 * <number> with range 0..1
10098 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#opacity_value
10099 */
10100 PropertySyntax["OPACITY_VALUE"] = "<opacity-value>";
10101 /**
10102 * <number> with range 0..Infinity
10103 */
10104 PropertySyntax["SHADOW_BLUR"] = "<shadow-blur>";
10105 /**
10106 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#length
10107 */
10108 PropertySyntax["LENGTH"] = "<length>";
10109 /**
10110 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#percentage
10111 */
10112 PropertySyntax["PERCENTAGE"] = "<percentage>";
10113 PropertySyntax["LENGTH_PERCENTAGE"] = "<length> | <percentage>";
10114 PropertySyntax["LENGTH_PERCENTAGE_12"] = "[<length> | <percentage>]{1,2}";
10115 /**
10116 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/margin#formal_syntax
10117 */
10118 PropertySyntax["LENGTH_PERCENTAGE_14"] = "[<length> | <percentage>]{1,4}";
10119 /**
10120 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Content_type#list-of-ts
10121 */
10122 PropertySyntax["LIST_OF_POINTS"] = "<list-of-points>";
10123 PropertySyntax["PATH"] = "<path>";
10124 /**
10125 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/filter#formal_syntax
10126 */
10127 PropertySyntax["FILTER"] = "<filter>";
10128 PropertySyntax["Z_INDEX"] = "<z-index>";
10129 PropertySyntax["OFFSET_DISTANCE"] = "<offset-distance>";
10130 PropertySyntax["DEFINED_PATH"] = "<defined-path>";
10131 PropertySyntax["MARKER"] = "<marker>";
10132 PropertySyntax["TRANSFORM"] = "<transform>";
10133 PropertySyntax["TRANSFORM_ORIGIN"] = "<transform-origin>";
10134 PropertySyntax["TEXT"] = "<text>";
10135 PropertySyntax["TEXT_TRANSFORM"] = "<text-transform>";
10136 })(PropertySyntax || (PropertySyntax = {}));
10137
10138 /**
10139 * borrow from gradient-parser, but we delete some browser compatible prefix such as `-webkit-`
10140 * @see https://github.com/rafaelcaricio/gradient-parser
10141 */
10142 function colorStopToString(colorStop) {
10143 var type = colorStop.type, value = colorStop.value;
10144 if (type === 'hex') {
10145 return "#".concat(value);
10146 }
10147 else if (type === 'literal') {
10148 return value;
10149 }
10150 else if (type === 'rgb') {
10151 return "rgb(".concat(value.join(','), ")");
10152 }
10153 else {
10154 return "rgba(".concat(value.join(','), ")");
10155 }
10156 }
10157 var parseGradient$1 = (function () {
10158 var tokens = {
10159 linearGradient: /^(linear\-gradient)/i,
10160 repeatingLinearGradient: /^(repeating\-linear\-gradient)/i,
10161 radialGradient: /^(radial\-gradient)/i,
10162 repeatingRadialGradient: /^(repeating\-radial\-gradient)/i,
10163 /**
10164 * @see https://projects.verou.me/conic-gradient/
10165 */
10166 conicGradient: /^(conic\-gradient)/i,
10167 sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,
10168 extentKeywords: /^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,
10169 positionKeywords: /^(left|center|right|top|bottom)/i,
10170 pixelValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,
10171 percentageValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,
10172 emValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,
10173 angleValue: /^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,
10174 startCall: /^\(/,
10175 endCall: /^\)/,
10176 comma: /^,/,
10177 hexColor: /^\#([0-9a-fA-F]+)/,
10178 literalColor: /^([a-zA-Z]+)/,
10179 rgbColor: /^rgb/i,
10180 rgbaColor: /^rgba/i,
10181 number: /^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,
10182 };
10183 var input = '';
10184 function error(msg) {
10185 throw new Error(input + ': ' + msg);
10186 }
10187 function getAST() {
10188 var ast = matchListDefinitions();
10189 if (input.length > 0) {
10190 error('Invalid input not EOF');
10191 }
10192 return ast;
10193 }
10194 function matchListDefinitions() {
10195 return matchListing(matchDefinition);
10196 }
10197 function matchDefinition() {
10198 return (matchGradient('linear-gradient', tokens.linearGradient, matchLinearOrientation) ||
10199 matchGradient('repeating-linear-gradient', tokens.repeatingLinearGradient, matchLinearOrientation) ||
10200 matchGradient('radial-gradient', tokens.radialGradient, matchListRadialOrientations) ||
10201 matchGradient('repeating-radial-gradient', tokens.repeatingRadialGradient, matchListRadialOrientations) ||
10202 matchGradient('conic-gradient', tokens.conicGradient, matchListRadialOrientations));
10203 }
10204 function matchGradient(gradientType, pattern, orientationMatcher) {
10205 return matchCall(pattern, function (captures) {
10206 var orientation = orientationMatcher();
10207 if (orientation) {
10208 if (!scan(tokens.comma)) {
10209 error('Missing comma before color stops');
10210 }
10211 }
10212 return {
10213 type: gradientType,
10214 orientation: orientation,
10215 colorStops: matchListing(matchColorStop),
10216 };
10217 });
10218 }
10219 function matchCall(pattern, callback) {
10220 var captures = scan(pattern);
10221 if (captures) {
10222 if (!scan(tokens.startCall)) {
10223 error('Missing (');
10224 }
10225 var result = callback(captures);
10226 if (!scan(tokens.endCall)) {
10227 error('Missing )');
10228 }
10229 return result;
10230 }
10231 }
10232 function matchLinearOrientation() {
10233 return matchSideOrCorner() || matchAngle();
10234 }
10235 function matchSideOrCorner() {
10236 return match('directional', tokens.sideOrCorner, 1);
10237 }
10238 function matchAngle() {
10239 return match('angular', tokens.angleValue, 1);
10240 }
10241 function matchListRadialOrientations() {
10242 var radialOrientations, radialOrientation = matchRadialOrientation(), lookaheadCache;
10243 if (radialOrientation) {
10244 radialOrientations = [];
10245 radialOrientations.push(radialOrientation);
10246 lookaheadCache = input;
10247 if (scan(tokens.comma)) {
10248 radialOrientation = matchRadialOrientation();
10249 if (radialOrientation) {
10250 radialOrientations.push(radialOrientation);
10251 }
10252 else {
10253 input = lookaheadCache;
10254 }
10255 }
10256 }
10257 return radialOrientations;
10258 }
10259 function matchRadialOrientation() {
10260 var radialType = matchCircle() || matchEllipse();
10261 if (radialType) {
10262 // @ts-ignore
10263 radialType.at = matchAtPosition();
10264 }
10265 else {
10266 var extent = matchExtentKeyword();
10267 if (extent) {
10268 radialType = extent;
10269 var positionAt = matchAtPosition();
10270 if (positionAt) {
10271 // @ts-ignore
10272 radialType.at = positionAt;
10273 }
10274 }
10275 else {
10276 var defaultPosition = matchPositioning();
10277 if (defaultPosition) {
10278 radialType = {
10279 type: 'default-radial',
10280 // @ts-ignore
10281 at: defaultPosition,
10282 };
10283 }
10284 }
10285 }
10286 return radialType;
10287 }
10288 function matchCircle() {
10289 var circle = match('shape', /^(circle)/i, 0);
10290 if (circle) {
10291 // @ts-ignore
10292 circle.style = matchLength() || matchExtentKeyword();
10293 }
10294 return circle;
10295 }
10296 function matchEllipse() {
10297 var ellipse = match('shape', /^(ellipse)/i, 0);
10298 if (ellipse) {
10299 // @ts-ignore
10300 ellipse.style = matchDistance() || matchExtentKeyword();
10301 }
10302 return ellipse;
10303 }
10304 function matchExtentKeyword() {
10305 return match('extent-keyword', tokens.extentKeywords, 1);
10306 }
10307 function matchAtPosition() {
10308 if (match('position', /^at/, 0)) {
10309 var positioning = matchPositioning();
10310 if (!positioning) {
10311 error('Missing positioning value');
10312 }
10313 return positioning;
10314 }
10315 }
10316 function matchPositioning() {
10317 var location = matchCoordinates();
10318 if (location.x || location.y) {
10319 return {
10320 type: 'position',
10321 value: location,
10322 };
10323 }
10324 }
10325 function matchCoordinates() {
10326 return {
10327 x: matchDistance(),
10328 y: matchDistance(),
10329 };
10330 }
10331 function matchListing(matcher) {
10332 var captures = matcher();
10333 var result = [];
10334 if (captures) {
10335 result.push(captures);
10336 while (scan(tokens.comma)) {
10337 captures = matcher();
10338 if (captures) {
10339 result.push(captures);
10340 }
10341 else {
10342 error('One extra comma');
10343 }
10344 }
10345 }
10346 return result;
10347 }
10348 function matchColorStop() {
10349 var color = matchColor();
10350 if (!color) {
10351 error('Expected color definition');
10352 }
10353 color.length = matchDistance();
10354 return color;
10355 }
10356 function matchColor() {
10357 return (matchHexColor() ||
10358 matchRGBAColor() ||
10359 matchRGBColor() ||
10360 matchLiteralColor());
10361 }
10362 function matchLiteralColor() {
10363 return match('literal', tokens.literalColor, 0);
10364 }
10365 function matchHexColor() {
10366 return match('hex', tokens.hexColor, 1);
10367 }
10368 function matchRGBColor() {
10369 return matchCall(tokens.rgbColor, function () {
10370 return {
10371 type: 'rgb',
10372 value: matchListing(matchNumber),
10373 };
10374 });
10375 }
10376 function matchRGBAColor() {
10377 return matchCall(tokens.rgbaColor, function () {
10378 return {
10379 type: 'rgba',
10380 value: matchListing(matchNumber),
10381 };
10382 });
10383 }
10384 function matchNumber() {
10385 return scan(tokens.number)[1];
10386 }
10387 function matchDistance() {
10388 return (match('%', tokens.percentageValue, 1) ||
10389 matchPositionKeyword() ||
10390 matchLength());
10391 }
10392 function matchPositionKeyword() {
10393 return match('position-keyword', tokens.positionKeywords, 1);
10394 }
10395 function matchLength() {
10396 return match('px', tokens.pixelValue, 1) || match('em', tokens.emValue, 1);
10397 }
10398 function match(type, pattern, captureIndex) {
10399 var captures = scan(pattern);
10400 if (captures) {
10401 return {
10402 type: type,
10403 value: captures[captureIndex],
10404 };
10405 }
10406 }
10407 function scan(regexp) {
10408 var blankCaptures = /^[\n\r\t\s]+/.exec(input);
10409 if (blankCaptures) {
10410 consume(blankCaptures[0].length);
10411 }
10412 var captures = regexp.exec(input);
10413 if (captures) {
10414 consume(captures[0].length);
10415 }
10416 return captures;
10417 }
10418 function consume(size) {
10419 input = input.substring(size);
10420 }
10421 return function (code) {
10422 input = code;
10423 return getAST();
10424 };
10425 })();
10426 function computeLinearGradient(width, height, angle) {
10427 var rad = deg2rad(angle.value);
10428 var rx = 0;
10429 var ry = 0;
10430 var rcx = rx + width / 2;
10431 var rcy = ry + height / 2;
10432 // get the length of gradient line
10433 // @see https://observablehq.com/@danburzo/css-gradient-line
10434 var length = Math.abs(width * Math.cos(rad)) + Math.abs(height * Math.sin(rad));
10435 var x1 = rcx - (Math.cos(rad) * length) / 2;
10436 var y1 = rcy - (Math.sin(rad) * length) / 2;
10437 var x2 = rcx + (Math.cos(rad) * length) / 2;
10438 var y2 = rcy + (Math.sin(rad) * length) / 2;
10439 return { x1: x1, y1: y1, x2: x2, y2: y2 };
10440 }
10441 function computeRadialGradient(width, height, cx, cy, size) {
10442 // 'px'
10443 var x = cx.value;
10444 var y = cy.value;
10445 // TODO: 'em'
10446 // '%'
10447 if (cx.unit === UnitType.kPercentage) {
10448 x = (cx.value / 100) * width;
10449 }
10450 if (cy.unit === UnitType.kPercentage) {
10451 y = (cy.value / 100) * height;
10452 }
10453 // default to farthest-side
10454 var r = Math.max(distanceSquareRoot([0, 0], [x, y]), distanceSquareRoot([0, height], [x, y]), distanceSquareRoot([width, height], [x, y]), distanceSquareRoot([width, 0], [x, y]));
10455 if (size) {
10456 if (size instanceof CSSUnitValue) {
10457 r = size.value;
10458 }
10459 else if (size instanceof CSSKeywordValue) {
10460 // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Images/Using_CSS_gradients#example_closest-side_for_circles
10461 if (size.value === 'closest-side') {
10462 r = Math.min(x, width - x, y, height - y);
10463 }
10464 else if (size.value === 'farthest-side') {
10465 r = Math.max(x, width - x, y, height - y);
10466 }
10467 else if (size.value === 'closest-corner') {
10468 r = Math.min(distanceSquareRoot([0, 0], [x, y]), distanceSquareRoot([0, height], [x, y]), distanceSquareRoot([width, height], [x, y]), distanceSquareRoot([width, 0], [x, y]));
10469 }
10470 }
10471 }
10472 return { x: x, y: y, r: r };
10473 }
10474
10475 var regexLG = /^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i;
10476 var regexRG = /^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i;
10477 var regexPR = /^p\s*\(\s*([axyn])\s*\)\s*(.*)/i;
10478 var regexColorStop = /[\d.]+:(#[^\s]+|[^\)]+\))/gi;
10479 function spaceColorStops(colorStops) {
10480 var _a, _b, _c;
10481 var length = colorStops.length;
10482 colorStops[length - 1].length = (_a = colorStops[length - 1].length) !== null && _a !== void 0 ? _a : {
10483 type: '%',
10484 value: '100',
10485 };
10486 if (length > 1) {
10487 colorStops[0].length = (_b = colorStops[0].length) !== null && _b !== void 0 ? _b : {
10488 type: '%',
10489 value: '0',
10490 };
10491 }
10492 var previousIndex = 0;
10493 var previousOffset = Number(colorStops[0].length.value);
10494 for (var i = 1; i < length; i++) {
10495 // support '%' & 'px'
10496 var offset = (_c = colorStops[i].length) === null || _c === void 0 ? void 0 : _c.value;
10497 if (!isNil(offset) && !isNil(previousOffset)) {
10498 for (var j = 1; j < i - previousIndex; j++)
10499 colorStops[previousIndex + j].length = {
10500 type: '%',
10501 value: "".concat(previousOffset +
10502 ((Number(offset) - previousOffset) * j) / (i - previousIndex)),
10503 };
10504 previousIndex = i;
10505 previousOffset = Number(offset);
10506 }
10507 }
10508 }
10509 // The position of the gradient line's starting point.
10510 // different from CSS side(to top) @see https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient#values
10511 var SideOrCornerToDegMap = {
10512 left: 270 - 90,
10513 top: 0 - 90,
10514 bottom: 180 - 90,
10515 right: 90 - 90,
10516 'left top': 315 - 90,
10517 'top left': 315 - 90,
10518 'left bottom': 225 - 90,
10519 'bottom left': 225 - 90,
10520 'right top': 45 - 90,
10521 'top right': 45 - 90,
10522 'right bottom': 135 - 90,
10523 'bottom right': 135 - 90,
10524 };
10525 var angleToDeg = memoize(function (orientation) {
10526 var angle;
10527 if (orientation.type === 'angular') {
10528 angle = Number(orientation.value);
10529 }
10530 else {
10531 angle = SideOrCornerToDegMap[orientation.value] || 0;
10532 }
10533 return getOrCreateUnitValue(angle, 'deg');
10534 });
10535 var positonToCSSUnitValue = memoize(function (position) {
10536 var cx = 50;
10537 var cy = 50;
10538 var unitX = '%';
10539 var unitY = '%';
10540 if ((position === null || position === void 0 ? void 0 : position.type) === 'position') {
10541 var _a = position.value, x = _a.x, y = _a.y;
10542 if ((x === null || x === void 0 ? void 0 : x.type) === 'position-keyword') {
10543 if (x.value === 'left') {
10544 cx = 0;
10545 }
10546 else if (x.value === 'center') {
10547 cx = 50;
10548 }
10549 else if (x.value === 'right') {
10550 cx = 100;
10551 }
10552 else if (x.value === 'top') {
10553 cy = 0;
10554 }
10555 else if (x.value === 'bottom') {
10556 cy = 100;
10557 }
10558 }
10559 if ((y === null || y === void 0 ? void 0 : y.type) === 'position-keyword') {
10560 if (y.value === 'left') {
10561 cx = 0;
10562 }
10563 else if (y.value === 'center') {
10564 cy = 50;
10565 }
10566 else if (y.value === 'right') {
10567 cx = 100;
10568 }
10569 else if (y.value === 'top') {
10570 cy = 0;
10571 }
10572 else if (y.value === 'bottom') {
10573 cy = 100;
10574 }
10575 }
10576 if ((x === null || x === void 0 ? void 0 : x.type) === 'px' || (x === null || x === void 0 ? void 0 : x.type) === '%' || (x === null || x === void 0 ? void 0 : x.type) === 'em') {
10577 unitX = x === null || x === void 0 ? void 0 : x.type;
10578 cx = Number(x.value);
10579 }
10580 if ((y === null || y === void 0 ? void 0 : y.type) === 'px' || (y === null || y === void 0 ? void 0 : y.type) === '%' || (y === null || y === void 0 ? void 0 : y.type) === 'em') {
10581 unitY = y === null || y === void 0 ? void 0 : y.type;
10582 cy = Number(y.value);
10583 }
10584 }
10585 return {
10586 cx: getOrCreateUnitValue(cx, unitX),
10587 cy: getOrCreateUnitValue(cy, unitY),
10588 };
10589 });
10590 var parseGradient = memoize(function (colorStr) {
10591 var _a;
10592 if (colorStr.indexOf('linear') > -1 || colorStr.indexOf('radial') > -1) {
10593 var ast = parseGradient$1(colorStr);
10594 return ast.map(function (_a) {
10595 var type = _a.type, orientation = _a.orientation, colorStops = _a.colorStops;
10596 spaceColorStops(colorStops);
10597 var steps = colorStops.map(function (colorStop) {
10598 // TODO: only support % for now, should calc percentage of axis length when using px/em
10599 return {
10600 offset: getOrCreateUnitValue(Number(colorStop.length.value), '%'),
10601 color: colorStopToString(colorStop),
10602 };
10603 });
10604 if (type === 'linear-gradient') {
10605 return new CSSGradientValue(GradientType.LinearGradient, {
10606 angle: orientation
10607 ? angleToDeg(orientation)
10608 : Odeg,
10609 steps: steps,
10610 });
10611 }
10612 else if (type === 'radial-gradient') {
10613 if (!orientation) {
10614 orientation = [
10615 {
10616 type: 'shape',
10617 value: 'circle',
10618 },
10619 ];
10620 }
10621 if (orientation[0].type === 'shape' &&
10622 orientation[0].value === 'circle') {
10623 var _b = positonToCSSUnitValue(orientation[0].at), cx = _b.cx, cy = _b.cy;
10624 var size = void 0;
10625 if (orientation[0].style) {
10626 var _c = orientation[0].style, type_1 = _c.type, value = _c.value;
10627 if (type_1 === 'extent-keyword') {
10628 size = getOrCreateKeyword(value);
10629 }
10630 else {
10631 size = getOrCreateUnitValue(value, type_1);
10632 }
10633 }
10634 return new CSSGradientValue(GradientType.RadialGradient, {
10635 cx: cx,
10636 cy: cy,
10637 size: size,
10638 steps: steps,
10639 });
10640 }
10641 // TODO: support ellipse shape
10642 // TODO: repeating-linear-gradient & repeating-radial-gradient
10643 // } else if (type === 'repeating-linear-gradient') {
10644 // } else if (type === 'repeating-radial-gradient') {
10645 }
10646 });
10647 }
10648 // legacy format, should be deprecated later
10649 var type = colorStr[0];
10650 if (colorStr[1] === '(' || colorStr[2] === '(') {
10651 if (type === 'l') {
10652 var arr = regexLG.exec(colorStr);
10653 if (arr) {
10654 var steps = ((_a = arr[2].match(regexColorStop)) === null || _a === void 0 ? void 0 : _a.map(function (stop) { return stop.split(':'); })) || [];
10655 return [
10656 new CSSGradientValue(GradientType.LinearGradient, {
10657 angle: getOrCreateUnitValue(parseFloat(arr[1]), 'deg'),
10658 steps: steps.map(function (_a) {
10659 var _b = __read(_a, 2), offset = _b[0], color = _b[1];
10660 return ({
10661 offset: getOrCreateUnitValue(Number(offset) * 100, '%'),
10662 color: color,
10663 });
10664 }),
10665 }),
10666 ];
10667 }
10668 }
10669 else if (type === 'r') {
10670 var parsedRadialGradient = parseRadialGradient(colorStr);
10671 if (parsedRadialGradient) {
10672 if (isString(parsedRadialGradient)) {
10673 colorStr = parsedRadialGradient;
10674 }
10675 else {
10676 return [
10677 new CSSGradientValue(GradientType.RadialGradient, parsedRadialGradient),
10678 ];
10679 }
10680 }
10681 }
10682 else if (type === 'p') {
10683 return parsePattern(colorStr);
10684 }
10685 }
10686 });
10687 function parseRadialGradient(gradientStr) {
10688 var _a;
10689 var arr = regexRG.exec(gradientStr);
10690 if (arr) {
10691 var steps = ((_a = arr[4].match(regexColorStop)) === null || _a === void 0 ? void 0 : _a.map(function (stop) { return stop.split(':'); })) || [];
10692 return {
10693 cx: getOrCreateUnitValue(50, '%'),
10694 cy: getOrCreateUnitValue(50, '%'),
10695 steps: steps.map(function (_a) {
10696 var _b = __read(_a, 2), offset = _b[0], color = _b[1];
10697 return ({
10698 offset: getOrCreateUnitValue(Number(offset) * 100, '%'),
10699 color: color,
10700 });
10701 }),
10702 };
10703 }
10704 return null;
10705 }
10706 function parsePattern(patternStr) {
10707 var arr = regexPR.exec(patternStr);
10708 if (arr) {
10709 var repetition = arr[1];
10710 var src = arr[2];
10711 switch (repetition) {
10712 case 'a':
10713 repetition = 'repeat';
10714 break;
10715 case 'x':
10716 repetition = 'repeat-x';
10717 break;
10718 case 'y':
10719 repetition = 'repeat-y';
10720 break;
10721 case 'n':
10722 repetition = 'no-repeat';
10723 break;
10724 default:
10725 repetition = 'no-repeat';
10726 }
10727 return {
10728 image: src,
10729 // @ts-ignore
10730 repetition: repetition,
10731 };
10732 }
10733 return null;
10734 }
10735 function isPattern(object) {
10736 return object && !!object.image;
10737 }
10738 function isCSSRGB(object) {
10739 return (object &&
10740 !isNil(object.r) &&
10741 !isNil(object.g) &&
10742 !isNil(object.b));
10743 }
10744 /**
10745 * @see https://github.com/WebKit/WebKit/blob/main/Source/WebCore/css/parser/CSSParser.cpp#L97
10746 */
10747 var parseColor = memoize(function (colorStr) {
10748 if (isPattern(colorStr)) {
10749 return __assign({ repetition: 'repeat' }, colorStr);
10750 }
10751 if (isNil(colorStr)) {
10752 colorStr = '';
10753 }
10754 if (colorStr === 'transparent') {
10755 // transparent black
10756 return transparentColor;
10757 }
10758 else if (colorStr === 'currentColor') {
10759 // @see https://github.com/adobe-webplatform/Snap.svg/issues/526
10760 colorStr = 'black';
10761 }
10762 // support CSS gradient syntax
10763 var g = parseGradient(colorStr);
10764 if (g) {
10765 return g;
10766 }
10767 // constants
10768 var color$1 = color(colorStr);
10769 var rgba = [0, 0, 0, 0];
10770 if (color$1 !== null) {
10771 rgba[0] = color$1.r || 0;
10772 rgba[1] = color$1.g || 0;
10773 rgba[2] = color$1.b || 0;
10774 rgba[3] = color$1.opacity;
10775 }
10776 // return new CSSRGB(...rgba);
10777 return getOrCreateRGBA.apply(void 0, __spreadArray([], __read(rgba), false));
10778 });
10779 function mergeColors(left, right) {
10780 // only support constant value, exclude gradient & pattern
10781 if (!isCSSRGB(left) || !isCSSRGB(right)) {
10782 return;
10783 }
10784 return [
10785 [Number(left.r), Number(left.g), Number(left.b), Number(left.alpha)],
10786 [Number(right.r), Number(right.g), Number(right.b), Number(right.alpha)],
10787 function (color) {
10788 var rgba = color.slice();
10789 if (rgba[3]) {
10790 for (var i = 0; i < 3; i++)
10791 rgba[i] = Math.round(clamp(rgba[i], 0, 255));
10792 }
10793 rgba[3] = clamp(rgba[3], 0, 1);
10794 return "rgba(".concat(rgba.join(','), ")");
10795 },
10796 ];
10797 }
10798
10799 function parseDimension(unitRegExp, string) {
10800 if (isNil(string)) {
10801 return getOrCreateUnitValue(0, 'px');
10802 }
10803 string = "".concat(string).trim().toLowerCase();
10804 if (isFinite(Number(string))) {
10805 if ('px'.search(unitRegExp) >= 0) {
10806 return getOrCreateUnitValue(Number(string), 'px');
10807 }
10808 else if ('deg'.search(unitRegExp) >= 0) {
10809 return getOrCreateUnitValue(Number(string), 'deg');
10810 }
10811 }
10812 var matchedUnits = [];
10813 string = string.replace(unitRegExp, function (match) {
10814 matchedUnits.push(match);
10815 return 'U' + match;
10816 });
10817 var taggedUnitRegExp = 'U(' + unitRegExp.source + ')';
10818 return matchedUnits.map(function (unit) {
10819 return getOrCreateUnitValue(Number(string
10820 .replace(new RegExp('U' + unit, 'g'), '')
10821 .replace(new RegExp(taggedUnitRegExp, 'g'), '*0')), unit);
10822 })[0];
10823 }
10824 /**
10825 * <length>
10826 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/length
10827 * length with only absolute unit, eg. 1px
10828 */
10829 var parseLength = memoize(function (css) {
10830 return parseDimension(new RegExp('px', 'g'), css);
10831 });
10832 /**
10833 * <percentage>
10834 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/percentage
10835 */
10836 memoize(function (css) {
10837 return parseDimension(new RegExp('%', 'g'), css);
10838 });
10839 /**
10840 * length with absolute or relative unit,
10841 * eg. 1px, 0.7em, 50%, calc(100% - 200px);
10842 *
10843 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/length-percentage
10844 */
10845 // export const parseLengthOrPercentage = memoize((css: string): CSSUnitValue => {
10846 // if (isNumber(css) || isFinite(Number(css))) {
10847 // return getOrCreateUnitValue(Number(css), 'px');
10848 // }
10849 // return parseDimension(new RegExp('px|%|em|rem', 'g'), css) as CSSUnitValue;
10850 // });
10851 var parseLengthOrPercentage = function (css) {
10852 if (isNumber(css) || isFinite(Number(css))) {
10853 // Number(css) is NaN
10854 return getOrCreateUnitValue(Number(css) || 0, 'px');
10855 // return Number(css);
10856 }
10857 return parseDimension(new RegExp('px|%|em|rem', 'g'), css);
10858 };
10859 var parseAngle = memoize(function (css) {
10860 return parseDimension(new RegExp('deg|rad|grad|turn', 'g'), css);
10861 });
10862 /**
10863 * merge CSSUnitValue
10864 *
10865 * @example
10866 * 10px + 20px = 30px
10867 * 10deg + 10rad
10868 * 10% + 20% = 30%
10869 */
10870 function mergeDimensions(left, right, target, nonNegative, index) {
10871 if (index === void 0) { index = 0; }
10872 var unit = '';
10873 var leftValue = left.value || 0;
10874 var rightValue = right.value || 0;
10875 var canonicalUnit = toCanonicalUnit(left.unit);
10876 var leftCanonicalUnitValue = left.convertTo(canonicalUnit);
10877 var rightCanonicalUnitValue = right.convertTo(canonicalUnit);
10878 if (leftCanonicalUnitValue && rightCanonicalUnitValue) {
10879 leftValue = leftCanonicalUnitValue.value;
10880 rightValue = rightCanonicalUnitValue.value;
10881 unit = unitTypeToString(left.unit);
10882 }
10883 else {
10884 // format '%' to 'px'
10885 if (CSSUnitValue.isLength(left.unit) || CSSUnitValue.isLength(right.unit)) {
10886 leftValue = convertPercentUnit(left, index, target);
10887 rightValue = convertPercentUnit(right, index, target);
10888 unit = 'px';
10889 }
10890 }
10891 // // format 'rad' 'turn' to 'deg'
10892 // if (CSSUnitValue.isAngle(left.unit) || CSSUnitValue.isAngle(right.unit)) {
10893 // leftValue = convertAngleUnit(left);
10894 // rightValue = convertAngleUnit(right);
10895 // unit = 'deg';
10896 // }
10897 return [
10898 leftValue,
10899 rightValue,
10900 function (value) {
10901 if (nonNegative) {
10902 value = Math.max(value, 0);
10903 }
10904 return value + unit;
10905 },
10906 ];
10907 }
10908 function convertAngleUnit(value) {
10909 var deg = 0;
10910 if (value.unit === UnitType.kDegrees) {
10911 deg = value.value;
10912 }
10913 else if (value.unit === UnitType.kRadians) {
10914 deg = rad2deg(Number(value.value));
10915 }
10916 else if (value.unit === UnitType.kTurns) {
10917 deg = turn2deg(Number(value.value));
10918 }
10919 return deg;
10920 }
10921 function parseDimensionArrayFormat(string, size) {
10922 var parsed;
10923 if (Array.isArray(string)) {
10924 // [1, '2px', 3]
10925 parsed = string.map(function (segment) { return Number(segment); });
10926 }
10927 else if (isString(string)) {
10928 parsed = string.split(' ').map(function (segment) { return Number(segment); });
10929 }
10930 else if (isNumber(string)) {
10931 parsed = [string];
10932 }
10933 if (size === 2) {
10934 if (parsed.length === 1) {
10935 return [parsed[0], parsed[0]];
10936 }
10937 else {
10938 return [parsed[0], parsed[1]];
10939 }
10940 }
10941 else {
10942 if (parsed.length === 1) {
10943 return [parsed[0], parsed[0], parsed[0], parsed[0]];
10944 }
10945 else if (parsed.length === 2) {
10946 return [parsed[0], parsed[1], parsed[0], parsed[1]];
10947 }
10948 else if (parsed.length === 3) {
10949 return [parsed[0], parsed[1], parsed[2], parsed[1]];
10950 }
10951 else {
10952 return [parsed[0], parsed[1], parsed[2], parsed[3]];
10953 }
10954 }
10955 }
10956 function parseDimensionArray(string) {
10957 if (isString(string)) {
10958 // "1px 2px 3px"
10959 return string.split(' ').map(function (segment) { return parseLengthOrPercentage(segment); });
10960 }
10961 else {
10962 // [1, '2px', 3]
10963 return string.map(function (segment) { return parseLengthOrPercentage(segment.toString()); });
10964 }
10965 }
10966 // export function mergeDimensionList(
10967 // left: CSSUnitValue[],
10968 // right: CSSUnitValue[],
10969 // target: IElement | null,
10970 // ): [number[], number[], (list: number[]) => string] | undefined {
10971 // if (left.length !== right.length) {
10972 // return;
10973 // }
10974 // const unit = left[0].unit;
10975 // return [
10976 // left.map((l) => l.value),
10977 // right.map((l) => l.value),
10978 // (values: number[]) => {
10979 // return values.map((n) => new CSSUnitValue(n, unit)).join(' ');
10980 // },
10981 // ];
10982 // }
10983 function convertPercentUnit(valueWithUnit, vec3Index, target) {
10984 if (valueWithUnit.value === 0) {
10985 return 0;
10986 }
10987 if (valueWithUnit.unit === UnitType.kPixels) {
10988 return Number(valueWithUnit.value);
10989 }
10990 else if (valueWithUnit.unit === UnitType.kPercentage && target) {
10991 var bounds = target.nodeName === Shape.GROUP
10992 ? target.getLocalBounds()
10993 : // : target.getGeometryBounds();
10994 target.geometry.contentBounds;
10995 return (valueWithUnit.value / 100) * bounds.halfExtents[vec3Index] * 2;
10996 }
10997 return 0;
10998 }
10999
11000 var parseParam = function (css) {
11001 return parseDimension(/deg|rad|grad|turn|px|%/g, css);
11002 };
11003 var supportedFilters = [
11004 'blur',
11005 'brightness',
11006 'drop-shadow',
11007 'contrast',
11008 'grayscale',
11009 'sepia',
11010 'saturate',
11011 'hue-rotate',
11012 'invert',
11013 ];
11014 function parseFilter(filterStr) {
11015 if (filterStr === void 0) { filterStr = ''; }
11016 filterStr = filterStr.toLowerCase().trim();
11017 if (filterStr === 'none') {
11018 return [];
11019 }
11020 var filterRegExp = /\s*([\w-]+)\(([^)]*)\)/g;
11021 var result = [];
11022 var match;
11023 var prevLastIndex = 0;
11024 while ((match = filterRegExp.exec(filterStr))) {
11025 if (match.index !== prevLastIndex) {
11026 return [];
11027 }
11028 prevLastIndex = match.index + match[0].length;
11029 if (supportedFilters.indexOf(match[1]) > -1) {
11030 result.push({
11031 name: match[1],
11032 params: match[2].split(' ').map(function (p) { return parseParam(p) || parseColor(p); }),
11033 });
11034 }
11035 if (filterRegExp.lastIndex === filterStr.length) {
11036 return result;
11037 }
11038 }
11039 return [];
11040 }
11041
11042 function numberToString(x) {
11043 // scale(0.00000001) -> scale(0)
11044 // return x.toFixed(6).replace(/0+$/, '').replace(/\.$/, '');
11045 return x.toString();
11046 }
11047 /**
11048 * parse string or number to CSSUnitValue(numeric)
11049 *
11050 * eg.
11051 * * 0 -> CSSUnitValue(0)
11052 * * '2' -> CSSUnitValue(2)
11053 */
11054 var parseNumber = memoize(function (string) {
11055 if (typeof string === 'number') {
11056 return getOrCreateUnitValue(string);
11057 }
11058 if (/^\s*[-+]?(\d*\.)?\d+\s*$/.test(string)) {
11059 return getOrCreateUnitValue(Number(string));
11060 }
11061 else {
11062 return getOrCreateUnitValue(0);
11063 }
11064 });
11065 /**
11066 * separate string to array
11067 * eg.
11068 * * [0.5, 0.5] -> [CSSUnitValue, CSSUnitValue]
11069 */
11070 memoize(function (string) {
11071 if (isString(string)) {
11072 return string.split(' ').map(parseNumber);
11073 }
11074 else {
11075 return string.map(parseNumber);
11076 }
11077 });
11078 function mergeNumbers(left, right) {
11079 return [left, right, numberToString];
11080 }
11081 function clampedMergeNumbers(min, max) {
11082 return function (left, right) { return [
11083 left,
11084 right,
11085 function (x) { return numberToString(clamp(x, min, max)); },
11086 ]; };
11087 }
11088 function mergeNumberLists(left, right) {
11089 if (left.length !== right.length) {
11090 return;
11091 }
11092 return [
11093 left,
11094 right,
11095 function (numberList) {
11096 return numberList;
11097 },
11098 ];
11099 }
11100
11101 function getOrCalculatePathTotalLength(path) {
11102 if (path.parsedStyle.path.totalLength === 0) {
11103 path.parsedStyle.path.totalLength = getTotalLength(path.parsedStyle.path.absolutePath);
11104 }
11105 return path.parsedStyle.path.totalLength;
11106 }
11107 function removeRedundantMCommand(path) {
11108 for (var i = 0; i < path.length; i++) {
11109 var prevSegment = path[i - 1];
11110 var segment = path[i];
11111 var cmd = segment[0];
11112 if (cmd === 'M') {
11113 if (prevSegment) {
11114 var prevCmd = prevSegment[0];
11115 var srcPoint = [segment[1], segment[2]];
11116 var destPoint = void 0;
11117 if (prevCmd === 'L' || prevCmd === 'M') {
11118 destPoint = [prevSegment[1], prevSegment[2]];
11119 }
11120 else if (prevCmd === 'C' || prevCmd === 'A' || prevCmd === 'Q') {
11121 destPoint = [
11122 prevSegment[prevSegment.length - 2],
11123 prevSegment[prevSegment.length - 1],
11124 ];
11125 }
11126 if (destPoint && isSamePoint(srcPoint, destPoint)) {
11127 path.splice(i, 1);
11128 i--;
11129 }
11130 }
11131 }
11132 }
11133 }
11134 function hasArcOrBezier(path) {
11135 var hasArc = false;
11136 var count = path.length;
11137 for (var i = 0; i < count; i++) {
11138 var params = path[i];
11139 var cmd = params[0];
11140 if (cmd === 'C' || cmd === 'A' || cmd === 'Q') {
11141 hasArc = true;
11142 break;
11143 }
11144 }
11145 return hasArc;
11146 }
11147 function extractPolygons(pathArray) {
11148 var polygons = [];
11149 var polylines = [];
11150 var points = []; // 防止第一个命令不是 'M'
11151 for (var i = 0; i < pathArray.length; i++) {
11152 var params = pathArray[i];
11153 var cmd = params[0];
11154 if (cmd === 'M') {
11155 // 遇到 'M' 判定是否是新数组,新数组中没有点
11156 if (points.length) {
11157 // 如果存在点,则说明没有遇到 'Z',开始了一个新的多边形
11158 polylines.push(points);
11159 points = []; // 创建新的点
11160 }
11161 points.push([params[1], params[2]]);
11162 }
11163 else if (cmd === 'Z') {
11164 if (points.length) {
11165 // 存在点
11166 polygons.push(points);
11167 points = []; // 开始新的点集合
11168 }
11169 // 如果不存在点,同时 'Z',则说明是错误,不处理
11170 }
11171 else {
11172 points.push([params[1], params[2]]);
11173 }
11174 }
11175 // 说明 points 未放入 polygons 或者 polyline
11176 // 仅当只有一个 M,没有 Z 时会发生这种情况
11177 if (points.length > 0) {
11178 polylines.push(points);
11179 }
11180 return {
11181 polygons: polygons,
11182 polylines: polylines,
11183 };
11184 }
11185 function isSamePoint(point1, point2) {
11186 return point1[0] === point2[0] && point1[1] === point2[1];
11187 }
11188 function getPathBBox(segments, lineWidth) {
11189 var xArr = [];
11190 var yArr = [];
11191 var segmentsWithAngle = [];
11192 for (var i = 0; i < segments.length; i++) {
11193 var segment = segments[i];
11194 var currentPoint = segment.currentPoint, params = segment.params, prePoint = segment.prePoint;
11195 var box$1 = void 0;
11196 switch (segment.command) {
11197 case 'Q':
11198 box$1 = box(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4]);
11199 break;
11200 case 'C':
11201 box$1 = box$3(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4], params[5], params[6]);
11202 break;
11203 case 'A':
11204 var arcParams = segment.arcParams;
11205 box$1 = box$5(arcParams.cx, arcParams.cy, arcParams.rx, arcParams.ry, arcParams.xRotation, arcParams.startAngle, arcParams.endAngle);
11206 break;
11207 default:
11208 xArr.push(currentPoint[0]);
11209 yArr.push(currentPoint[1]);
11210 break;
11211 }
11212 if (box$1) {
11213 segment.box = box$1;
11214 xArr.push(box$1.x, box$1.x + box$1.width);
11215 yArr.push(box$1.y, box$1.y + box$1.height);
11216 }
11217 if (lineWidth &&
11218 (segment.command === 'L' || segment.command === 'M') &&
11219 segment.prePoint &&
11220 segment.nextPoint) {
11221 segmentsWithAngle.push(segment);
11222 }
11223 }
11224 // bbox calculation should ignore NaN for path attribute
11225 // ref: https://github.com/antvis/g/issues/210
11226 // ref: https://github.com/antvis/G2/issues/3109
11227 xArr = xArr.filter(function (item) { return !Number.isNaN(item) && item !== Infinity && item !== -Infinity; });
11228 yArr = yArr.filter(function (item) { return !Number.isNaN(item) && item !== Infinity && item !== -Infinity; });
11229 var minX = min(xArr);
11230 var minY = min(yArr);
11231 var maxX = max(xArr);
11232 var maxY = max(yArr);
11233 if (segmentsWithAngle.length === 0) {
11234 return {
11235 x: minX,
11236 y: minY,
11237 width: maxX - minX,
11238 height: maxY - minY,
11239 };
11240 }
11241 for (var i = 0; i < segmentsWithAngle.length; i++) {
11242 var segment = segmentsWithAngle[i];
11243 var currentPoint = segment.currentPoint;
11244 var extra = void 0;
11245 if (currentPoint[0] === minX) {
11246 extra = getExtraFromSegmentWithAngle(segment, lineWidth);
11247 minX = minX - extra.xExtra;
11248 }
11249 else if (currentPoint[0] === maxX) {
11250 extra = getExtraFromSegmentWithAngle(segment, lineWidth);
11251 maxX = maxX + extra.xExtra;
11252 }
11253 if (currentPoint[1] === minY) {
11254 extra = getExtraFromSegmentWithAngle(segment, lineWidth);
11255 minY = minY - extra.yExtra;
11256 }
11257 else if (currentPoint[1] === maxY) {
11258 extra = getExtraFromSegmentWithAngle(segment, lineWidth);
11259 maxY = maxY + extra.yExtra;
11260 }
11261 }
11262 return {
11263 x: minX,
11264 y: minY,
11265 width: maxX - minX,
11266 height: maxY - minY,
11267 };
11268 }
11269 function getExtraFromSegmentWithAngle(segment, lineWidth) {
11270 var prePoint = segment.prePoint, currentPoint = segment.currentPoint, nextPoint = segment.nextPoint;
11271 var currentAndPre = Math.pow(currentPoint[0] - prePoint[0], 2) +
11272 Math.pow(currentPoint[1] - prePoint[1], 2);
11273 var currentAndNext = Math.pow(currentPoint[0] - nextPoint[0], 2) +
11274 Math.pow(currentPoint[1] - nextPoint[1], 2);
11275 var preAndNext = Math.pow(prePoint[0] - nextPoint[0], 2) +
11276 Math.pow(prePoint[1] - nextPoint[1], 2);
11277 // 以 currentPoint 为顶点的夹角
11278 var currentAngle = Math.acos((currentAndPre + currentAndNext - preAndNext) /
11279 (2 * Math.sqrt(currentAndPre) * Math.sqrt(currentAndNext)));
11280 // 夹角为空、 0 或 PI 时,不需要计算夹角处的额外宽度
11281 // 注意: 由于计算精度问题,夹角为 0 的情况计算出来的角度可能是一个很小的值,还需要判断其与 0 是否近似相等
11282 if (!currentAngle ||
11283 Math.sin(currentAngle) === 0 ||
11284 isNumberEqual(currentAngle, 0)) {
11285 return {
11286 xExtra: 0,
11287 yExtra: 0,
11288 };
11289 }
11290 var xAngle = Math.abs(Math.atan2(nextPoint[1] - currentPoint[1], nextPoint[0] - currentPoint[0]));
11291 var yAngle = Math.abs(Math.atan2(nextPoint[0] - currentPoint[0], nextPoint[1] - currentPoint[1]));
11292 // 将夹角转为锐角
11293 xAngle = xAngle > Math.PI / 2 ? Math.PI - xAngle : xAngle;
11294 yAngle = yAngle > Math.PI / 2 ? Math.PI - yAngle : yAngle;
11295 // 这里不考虑在水平和垂直方向的投影,直接使用最大差值
11296 // 由于上层统一加减了二分之一线宽,这里需要进行弥补
11297 var extra = {
11298 // 水平方向投影
11299 xExtra: Math.cos(currentAngle / 2 - xAngle) *
11300 ((lineWidth / 2) * (1 / Math.sin(currentAngle / 2))) -
11301 lineWidth / 2 || 0,
11302 // 垂直方向投影
11303 yExtra: Math.cos(yAngle - currentAngle / 2) *
11304 ((lineWidth / 2) * (1 / Math.sin(currentAngle / 2))) -
11305 lineWidth / 2 || 0,
11306 };
11307 return extra;
11308 }
11309 // 点对称
11310 function toSymmetry(point, center) {
11311 return [
11312 center[0] + (center[0] - point[0]),
11313 center[1] + (center[1] - point[1]),
11314 ];
11315 }
11316 var angleBetween$1 = function (v0, v1) {
11317 var p = v0.x * v1.x + v0.y * v1.y;
11318 var n = Math.sqrt((Math.pow(v0.x, 2) + Math.pow(v0.y, 2)) *
11319 (Math.pow(v1.x, 2) + Math.pow(v1.y, 2)));
11320 var sign = v0.x * v1.y - v0.y * v1.x < 0 ? -1 : 1;
11321 var angle = sign * Math.acos(p / n);
11322 return angle;
11323 };
11324 /**
11325 * @see https://github.com/rveciana/svg-path-properties/blob/b6bd9a322966f6ef7a311872d80c56e3718de861/src/arc.ts#L121
11326 */
11327 var pointOnEllipticalArc = function (p0, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, p1, t) {
11328 // In accordance to: http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters
11329 rx = Math.abs(rx);
11330 ry = Math.abs(ry);
11331 xAxisRotation = mod(xAxisRotation, 360);
11332 var xAxisRotationRadians = deg2rad(xAxisRotation);
11333 // If the endpoints are identical, then this is equivalent to omitting the elliptical arc segment entirely.
11334 if (p0.x === p1.x && p0.y === p1.y) {
11335 return { x: p0.x, y: p0.y, ellipticalArcAngle: 0 }; // Check if angle is correct
11336 }
11337 // If rx = 0 or ry = 0 then this arc is treated as a straight line segment joining the endpoints.
11338 if (rx === 0 || ry === 0) {
11339 //return this.pointOnLine(p0, p1, t);
11340 return { x: 0, y: 0, ellipticalArcAngle: 0 }; // Check if angle is correct
11341 }
11342 // Following "Conversion from endpoint to center parameterization"
11343 // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
11344 // Step #1: Compute transformedPoint
11345 var dx = (p0.x - p1.x) / 2;
11346 var dy = (p0.y - p1.y) / 2;
11347 var transformedPoint = {
11348 x: Math.cos(xAxisRotationRadians) * dx + Math.sin(xAxisRotationRadians) * dy,
11349 y: -Math.sin(xAxisRotationRadians) * dx +
11350 Math.cos(xAxisRotationRadians) * dy,
11351 };
11352 // Ensure radii are large enough
11353 var radiiCheck = Math.pow(transformedPoint.x, 2) / Math.pow(rx, 2) +
11354 Math.pow(transformedPoint.y, 2) / Math.pow(ry, 2);
11355 if (radiiCheck > 1) {
11356 rx = Math.sqrt(radiiCheck) * rx;
11357 ry = Math.sqrt(radiiCheck) * ry;
11358 }
11359 // Step #2: Compute transformedCenter
11360 var cSquareNumerator = Math.pow(rx, 2) * Math.pow(ry, 2) -
11361 Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) -
11362 Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
11363 var cSquareRootDenom = Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) +
11364 Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
11365 var cRadicand = cSquareNumerator / cSquareRootDenom;
11366 // Make sure this never drops below zero because of precision
11367 cRadicand = cRadicand < 0 ? 0 : cRadicand;
11368 var cCoef = (largeArcFlag !== sweepFlag ? 1 : -1) * Math.sqrt(cRadicand);
11369 var transformedCenter = {
11370 x: cCoef * ((rx * transformedPoint.y) / ry),
11371 y: cCoef * (-(ry * transformedPoint.x) / rx),
11372 };
11373 // Step #3: Compute center
11374 var center = {
11375 x: Math.cos(xAxisRotationRadians) * transformedCenter.x -
11376 Math.sin(xAxisRotationRadians) * transformedCenter.y +
11377 (p0.x + p1.x) / 2,
11378 y: Math.sin(xAxisRotationRadians) * transformedCenter.x +
11379 Math.cos(xAxisRotationRadians) * transformedCenter.y +
11380 (p0.y + p1.y) / 2,
11381 };
11382 // Step #4: Compute start/sweep angles
11383 // Start angle of the elliptical arc prior to the stretch and rotate operations.
11384 // Difference between the start and end angles
11385 var startVector = {
11386 x: (transformedPoint.x - transformedCenter.x) / rx,
11387 y: (transformedPoint.y - transformedCenter.y) / ry,
11388 };
11389 var startAngle = angleBetween$1({
11390 x: 1,
11391 y: 0,
11392 }, startVector);
11393 var endVector = {
11394 x: (-transformedPoint.x - transformedCenter.x) / rx,
11395 y: (-transformedPoint.y - transformedCenter.y) / ry,
11396 };
11397 var sweepAngle = angleBetween$1(startVector, endVector);
11398 if (!sweepFlag && sweepAngle > 0) {
11399 sweepAngle -= 2 * Math.PI;
11400 }
11401 else if (sweepFlag && sweepAngle < 0) {
11402 sweepAngle += 2 * Math.PI;
11403 }
11404 // We use % instead of `mod(..)` because we want it to be -360deg to 360deg(but actually in radians)
11405 sweepAngle %= 2 * Math.PI;
11406 // From http://www.w3.org/TR/SVG/implnote.html#ArcParameterizationAlternatives
11407 var angle = startAngle + sweepAngle * t;
11408 var ellipseComponentX = rx * Math.cos(angle);
11409 var ellipseComponentY = ry * Math.sin(angle);
11410 var point = {
11411 x: Math.cos(xAxisRotationRadians) * ellipseComponentX -
11412 Math.sin(xAxisRotationRadians) * ellipseComponentY +
11413 center.x,
11414 y: Math.sin(xAxisRotationRadians) * ellipseComponentX +
11415 Math.cos(xAxisRotationRadians) * ellipseComponentY +
11416 center.y,
11417 ellipticalArcStartAngle: startAngle,
11418 ellipticalArcEndAngle: startAngle + sweepAngle,
11419 ellipticalArcAngle: angle,
11420 ellipticalArcCenter: center,
11421 resultantRx: rx,
11422 resultantRy: ry,
11423 };
11424 return point;
11425 };
11426 function path2Segments(path) {
11427 var segments = [];
11428 var currentPoint = null; // 当前图形
11429 var nextParams = null; // 下一节点的 path 参数
11430 var startMovePoint = null; // 开始 M 的点,可能会有多个
11431 var lastStartMovePointIndex = 0; // 最近一个开始点 M 的索引
11432 var count = path.length;
11433 for (var i = 0; i < count; i++) {
11434 var params = path[i];
11435 nextParams = path[i + 1];
11436 var command = params[0];
11437 // 数学定义上的参数,便于后面的计算
11438 var segment = {
11439 command: command,
11440 prePoint: currentPoint,
11441 params: params,
11442 startTangent: null,
11443 endTangent: null,
11444 currentPoint: null,
11445 nextPoint: null,
11446 arcParams: null,
11447 box: null,
11448 cubicParams: null,
11449 };
11450 switch (command) {
11451 case 'M':
11452 startMovePoint = [params[1], params[2]];
11453 lastStartMovePointIndex = i;
11454 break;
11455 case 'A':
11456 var arcParams = getArcParams(currentPoint, params);
11457 segment.arcParams = arcParams;
11458 break;
11459 }
11460 if (command === 'Z') {
11461 // 有了 Z 后,当前节点从开始 M 的点开始
11462 currentPoint = startMovePoint;
11463 // 如果当前点的命令为 Z,相当于当前点为最近一个 M 点,则下一个点直接指向最近一个 M 点的下一个点
11464 nextParams = path[lastStartMovePointIndex + 1];
11465 }
11466 else {
11467 var len = params.length;
11468 currentPoint = [params[len - 2], params[len - 1]];
11469 }
11470 if (nextParams && nextParams[0] === 'Z') {
11471 // 如果下一个点的命令为 Z,则下一个点直接指向最近一个 M 点
11472 nextParams = path[lastStartMovePointIndex];
11473 if (segments[lastStartMovePointIndex]) {
11474 // 如果下一个点的命令为 Z,则最近一个 M 点的前一个点为当前点
11475 segments[lastStartMovePointIndex].prePoint = currentPoint;
11476 }
11477 }
11478 segment.currentPoint = currentPoint;
11479 // 如果当前点与最近一个 M 点相同,则最近一个 M 点的前一个点为当前点的前一个点
11480 if (segments[lastStartMovePointIndex] &&
11481 isSamePoint(currentPoint, segments[lastStartMovePointIndex].currentPoint)) {
11482 segments[lastStartMovePointIndex].prePoint = segment.prePoint;
11483 }
11484 var nextPoint = nextParams
11485 ? [nextParams[nextParams.length - 2], nextParams[nextParams.length - 1]]
11486 : null;
11487 segment.nextPoint = nextPoint;
11488 // Add startTangent and endTangent
11489 var prePoint = segment.prePoint;
11490 if (['L', 'H', 'V'].includes(command)) {
11491 segment.startTangent = [
11492 prePoint[0] - currentPoint[0],
11493 prePoint[1] - currentPoint[1],
11494 ];
11495 segment.endTangent = [
11496 currentPoint[0] - prePoint[0],
11497 currentPoint[1] - prePoint[1],
11498 ];
11499 }
11500 else if (command === 'Q') {
11501 // 二次贝塞尔曲线只有一个控制点
11502 var cp = [params[1], params[2]];
11503 // 二次贝塞尔曲线的终点为 currentPoint
11504 segment.startTangent = [prePoint[0] - cp[0], prePoint[1] - cp[1]];
11505 segment.endTangent = [currentPoint[0] - cp[0], currentPoint[1] - cp[1]];
11506 }
11507 else if (command === 'T') {
11508 var preSegment = segments[i - 1];
11509 var cp = toSymmetry(preSegment.currentPoint, prePoint);
11510 if (preSegment.command === 'Q') {
11511 segment.command = 'Q';
11512 segment.startTangent = [prePoint[0] - cp[0], prePoint[1] - cp[1]];
11513 segment.endTangent = [currentPoint[0] - cp[0], currentPoint[1] - cp[1]];
11514 }
11515 else {
11516 // @ts-ignore
11517 segment.command = 'TL';
11518 segment.startTangent = [
11519 prePoint[0] - currentPoint[0],
11520 prePoint[1] - currentPoint[1],
11521 ];
11522 segment.endTangent = [
11523 currentPoint[0] - prePoint[0],
11524 currentPoint[1] - prePoint[1],
11525 ];
11526 }
11527 }
11528 else if (command === 'C') {
11529 // 三次贝塞尔曲线有两个控制点
11530 var cp1 = [params[1], params[2]];
11531 var cp2 = [params[3], params[4]];
11532 segment.startTangent = [prePoint[0] - cp1[0], prePoint[1] - cp1[1]];
11533 segment.endTangent = [currentPoint[0] - cp2[0], currentPoint[1] - cp2[1]];
11534 // horizontal line, eg. ['C', 100, 100, 100, 100, 200, 200]
11535 if (segment.startTangent[0] === 0 && segment.startTangent[1] === 0) {
11536 segment.startTangent = [cp1[0] - cp2[0], cp1[1] - cp2[1]];
11537 }
11538 if (segment.endTangent[0] === 0 && segment.endTangent[1] === 0) {
11539 segment.endTangent = [cp2[0] - cp1[0], cp2[1] - cp1[1]];
11540 }
11541 }
11542 else if (command === 'S') {
11543 var preSegment = segments[i - 1];
11544 var cp1 = toSymmetry(preSegment.currentPoint, prePoint);
11545 var cp2 = [params[1], params[2]];
11546 if (preSegment.command === 'C') {
11547 segment.command = 'C'; // 将 S 命令变换为 C 命令
11548 segment.startTangent = [prePoint[0] - cp1[0], prePoint[1] - cp1[1]];
11549 segment.endTangent = [
11550 currentPoint[0] - cp2[0],
11551 currentPoint[1] - cp2[1],
11552 ];
11553 }
11554 else {
11555 // @ts-ignore
11556 segment.command = 'SQ'; // 将 S 命令变换为 SQ 命令
11557 segment.startTangent = [prePoint[0] - cp2[0], prePoint[1] - cp2[1]];
11558 segment.endTangent = [
11559 currentPoint[0] - cp2[0],
11560 currentPoint[1] - cp2[1],
11561 ];
11562 }
11563 }
11564 else if (command === 'A') {
11565 var _a = getTangentAtRatio(segment, 0), dx1 = _a.x, dy1 = _a.y;
11566 var _b = getTangentAtRatio(segment, 1, false), dx2 = _b.x, dy2 = _b.y;
11567 segment.startTangent = [dx1, dy1];
11568 segment.endTangent = [dx2, dy2];
11569 }
11570 segments.push(segment);
11571 }
11572 return segments;
11573 }
11574 /**
11575 * Use length instead of ratio
11576 */
11577 function getTangentAtRatio(segment, ratio, sign) {
11578 if (sign === void 0) { sign = true; }
11579 var _a = segment.arcParams, _b = _a.rx, rx = _b === void 0 ? 0 : _b, _c = _a.ry, ry = _c === void 0 ? 0 : _c, xRotation = _a.xRotation, arcFlag = _a.arcFlag, sweepFlag = _a.sweepFlag;
11580 var p1 = pointOnEllipticalArc({ x: segment.prePoint[0], y: segment.prePoint[1] }, rx, ry, xRotation, !!arcFlag, !!sweepFlag, { x: segment.currentPoint[0], y: segment.currentPoint[1] }, ratio);
11581 var p2 = pointOnEllipticalArc({ x: segment.prePoint[0], y: segment.prePoint[1] }, rx, ry, xRotation, !!arcFlag, !!sweepFlag, { x: segment.currentPoint[0], y: segment.currentPoint[1] }, sign ? ratio + 0.005 : ratio - 0.005);
11582 var xDist = p2.x - p1.x;
11583 var yDist = p2.y - p1.y;
11584 var dist = Math.sqrt(xDist * xDist + yDist * yDist);
11585 return { x: -xDist / dist, y: -yDist / dist };
11586 }
11587 // 向量长度
11588 function vMag(v) {
11589 return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
11590 }
11591 // u.v/|u||v|,计算夹角的余弦值
11592 function vRatio(u, v) {
11593 // 当存在一个向量的长度为 0 时,夹角也为 0,即夹角的余弦值为 1
11594 return vMag(u) * vMag(v)
11595 ? (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v))
11596 : 1;
11597 }
11598 // 向量角度
11599 function vAngle(u, v) {
11600 return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v));
11601 }
11602 function getArcParams(startPoint, params) {
11603 var rx = params[1];
11604 var ry = params[2];
11605 var xRotation = mod(deg2rad(params[3]), Math.PI * 2);
11606 var arcFlag = params[4];
11607 var sweepFlag = params[5];
11608 // 弧形起点坐标
11609 var x1 = startPoint[0];
11610 var y1 = startPoint[1];
11611 // 弧形终点坐标
11612 var x2 = params[6];
11613 var y2 = params[7];
11614 var xp = (Math.cos(xRotation) * (x1 - x2)) / 2.0 +
11615 (Math.sin(xRotation) * (y1 - y2)) / 2.0;
11616 var yp = (-1 * Math.sin(xRotation) * (x1 - x2)) / 2.0 +
11617 (Math.cos(xRotation) * (y1 - y2)) / 2.0;
11618 var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
11619 if (lambda > 1) {
11620 rx *= Math.sqrt(lambda);
11621 ry *= Math.sqrt(lambda);
11622 }
11623 var diff = rx * rx * (yp * yp) + ry * ry * (xp * xp);
11624 var f = diff ? Math.sqrt((rx * rx * (ry * ry) - diff) / diff) : 1;
11625 if (arcFlag === sweepFlag) {
11626 f *= -1;
11627 }
11628 if (isNaN(f)) {
11629 f = 0;
11630 }
11631 // 旋转前的起点坐标,且当长半轴和短半轴的长度为 0 时,坐标按 (0, 0) 处理
11632 var cxp = ry ? (f * rx * yp) / ry : 0;
11633 var cyp = rx ? (f * -ry * xp) / rx : 0;
11634 // 椭圆圆心坐标
11635 var cx = (x1 + x2) / 2.0 + Math.cos(xRotation) * cxp - Math.sin(xRotation) * cyp;
11636 var cy = (y1 + y2) / 2.0 + Math.sin(xRotation) * cxp + Math.cos(xRotation) * cyp;
11637 // 起始点的单位向量
11638 var u = [(xp - cxp) / rx, (yp - cyp) / ry];
11639 // 终止点的单位向量
11640 var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
11641 // 计算起始点和圆心的连线,与 x 轴正方向的夹角
11642 var theta = vAngle([1, 0], u);
11643 // 计算圆弧起始点和终止点与椭圆圆心连线的夹角
11644 var dTheta = vAngle(u, v);
11645 if (vRatio(u, v) <= -1) {
11646 dTheta = Math.PI;
11647 }
11648 if (vRatio(u, v) >= 1) {
11649 dTheta = 0;
11650 }
11651 if (sweepFlag === 0 && dTheta > 0) {
11652 dTheta = dTheta - 2 * Math.PI;
11653 }
11654 if (sweepFlag === 1 && dTheta < 0) {
11655 dTheta = dTheta + 2 * Math.PI;
11656 }
11657 return {
11658 cx: cx,
11659 cy: cy,
11660 // 弧形的起点和终点相同时,长轴和短轴的长度按 0 处理
11661 rx: isSamePoint(startPoint, [x2, y2]) ? 0 : rx,
11662 ry: isSamePoint(startPoint, [x2, y2]) ? 0 : ry,
11663 startAngle: theta,
11664 endAngle: theta + dTheta,
11665 xRotation: xRotation,
11666 arcFlag: arcFlag,
11667 sweepFlag: sweepFlag,
11668 };
11669 }
11670 function commandsToPathString(commands, object, transform) {
11671 var _a = object.parsedStyle, _b = _a.defX, defX = _b === void 0 ? 0 : _b, _c = _a.defY, defY = _c === void 0 ? 0 : _c;
11672 return commands.reduce(function (prev, cur) {
11673 var path = '';
11674 if (cur[0] === 'M' || cur[0] === 'L') {
11675 var p = fromValues$2(cur[1] - defX, cur[2] - defY, 0);
11676 if (transform) {
11677 transformMat4(p, p, transform);
11678 }
11679 path = "".concat(cur[0]).concat(p[0], ",").concat(p[1]);
11680 }
11681 else if (cur[0] === 'Z') {
11682 path = cur[0];
11683 }
11684 else if (cur[0] === 'C') {
11685 var p1 = fromValues$2(cur[1] - defX, cur[2] - defY, 0);
11686 var p2 = fromValues$2(cur[3] - defX, cur[4] - defY, 0);
11687 var p3 = fromValues$2(cur[5] - defX, cur[6] - defY, 0);
11688 if (transform) {
11689 transformMat4(p1, p1, transform);
11690 transformMat4(p2, p2, transform);
11691 transformMat4(p3, p3, transform);
11692 }
11693 path = "".concat(cur[0]).concat(p1[0], ",").concat(p1[1], ",").concat(p2[0], ",").concat(p2[1], ",").concat(p3[0], ",").concat(p3[1]);
11694 }
11695 else if (cur[0] === 'A') {
11696 var c = fromValues$2(cur[6] - defX, cur[7] - defY, 0);
11697 if (transform) {
11698 transformMat4(c, c, transform);
11699 }
11700 path = "".concat(cur[0]).concat(cur[1], ",").concat(cur[2], ",").concat(cur[3], ",").concat(cur[4], ",").concat(cur[5], ",").concat(c[0], ",").concat(c[1]);
11701 }
11702 else if (cur[0] === 'Q') {
11703 var p1 = fromValues$2(cur[1] - defX, cur[2] - defY, 0);
11704 var p2 = fromValues$2(cur[3] - defX, cur[4] - defY, 0);
11705 if (transform) {
11706 transformMat4(p1, p1, transform);
11707 transformMat4(p2, p2, transform);
11708 }
11709 path = "".concat(cur[0]).concat(cur[1], ",").concat(cur[2], ",").concat(cur[3], ",").concat(cur[4], "}");
11710 }
11711 return (prev += path);
11712 }, '');
11713 }
11714 function lineToCommands(x1, y1, x2, y2) {
11715 return [
11716 ['M', x1, y1],
11717 ['L', x2, y2],
11718 ];
11719 }
11720 function ellipseToCommands(rx, ry, cx, cy) {
11721 var factor = ((-1 + Math.sqrt(2)) / 3) * 4;
11722 var dx = rx * factor;
11723 var dy = ry * factor;
11724 var left = cx - rx;
11725 var right = cx + rx;
11726 var top = cy - ry;
11727 var bottom = cy + ry;
11728 return [
11729 ['M', left, cy],
11730 ['C', left, cy - dy, cx - dx, top, cx, top],
11731 ['C', cx + dx, top, right, cy - dy, right, cy],
11732 ['C', right, cy + dy, cx + dx, bottom, cx, bottom],
11733 ['C', cx - dx, bottom, left, cy + dy, left, cy],
11734 ['Z'],
11735 ];
11736 }
11737 function polygonToCommands(points, closed) {
11738 var result = points.map(function (point, i) {
11739 return [i === 0 ? 'M' : 'L', point[0], point[1]];
11740 });
11741 if (closed) {
11742 result.push(['Z']);
11743 }
11744 return result;
11745 }
11746 function rectToCommands(width, height, x, y, radius) {
11747 // @see https://gist.github.com/danielpquinn/dd966af424030d47e476
11748 if (radius) {
11749 var _a = __read(radius, 4), tlr = _a[0], trr = _a[1], brr = _a[2], blr = _a[3];
11750 var signX = width > 0 ? 1 : -1;
11751 var signY = height > 0 ? 1 : -1;
11752 // sweep-flag @see https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths#arcs
11753 var sweepFlag = signX + signY !== 0 ? 1 : 0;
11754 return [
11755 ['M', signX * tlr + x, y],
11756 ['L', width - signX * trr + x, y],
11757 trr ? ['A', trr, trr, 0, 0, sweepFlag, width + x, signY * trr + y] : null,
11758 ['L', width + x, height - signY * brr + y],
11759 brr
11760 ? ['A', brr, brr, 0, 0, sweepFlag, width + x - signX * brr, height + y]
11761 : null,
11762 ['L', x + signX * blr, height + y],
11763 blr
11764 ? ['A', blr, blr, 0, 0, sweepFlag, x, height + y - signY * blr]
11765 : null,
11766 ['L', x, signY * tlr + y],
11767 tlr ? ['A', tlr, tlr, 0, 0, sweepFlag, signX * tlr + x, y] : null,
11768 ['Z'],
11769 ].filter(function (command) { return command; });
11770 }
11771 return [
11772 ['M', x, y],
11773 ['L', x + width, y],
11774 ['L', x + width, y + height],
11775 ['L', x, y + height],
11776 ['Z'],
11777 ];
11778 }
11779 /**
11780 * convert object to path, should account for:
11781 * * transform & origin
11782 * * anchor
11783 * * lineWidth
11784 */
11785 function convertToPath(object, transform) {
11786 if (transform === void 0) { transform = object.getLocalTransform(); }
11787 var commands = [];
11788 switch (object.nodeName) {
11789 case Shape.LINE:
11790 var _a = object.parsedStyle, _b = _a.x1, x1 = _b === void 0 ? 0 : _b, _c = _a.y1, y1 = _c === void 0 ? 0 : _c, _d = _a.x2, x2 = _d === void 0 ? 0 : _d, _e = _a.y2, y2 = _e === void 0 ? 0 : _e;
11791 commands = lineToCommands(x1, y1, x2, y2);
11792 break;
11793 case Shape.CIRCLE: {
11794 var _f = object.parsedStyle, _g = _f.r, r = _g === void 0 ? 0 : _g, _h = _f.cx, cx = _h === void 0 ? 0 : _h, _j = _f.cy, cy = _j === void 0 ? 0 : _j;
11795 commands = ellipseToCommands(r, r, cx, cy);
11796 break;
11797 }
11798 case Shape.ELLIPSE: {
11799 var _k = object.parsedStyle, _l = _k.rx, rx = _l === void 0 ? 0 : _l, _m = _k.ry, ry = _m === void 0 ? 0 : _m, _o = _k.cx, cx = _o === void 0 ? 0 : _o, _p = _k.cy, cy = _p === void 0 ? 0 : _p;
11800 commands = ellipseToCommands(rx, ry, cx, cy);
11801 break;
11802 }
11803 case Shape.POLYLINE:
11804 case Shape.POLYGON:
11805 var points = object.parsedStyle.points;
11806 commands = polygonToCommands(points.points, object.nodeName === Shape.POLYGON);
11807 break;
11808 case Shape.RECT:
11809 var _q = object.parsedStyle, _r = _q.width, width_1 = _r === void 0 ? 0 : _r, _s = _q.height, height_1 = _s === void 0 ? 0 : _s, _t = _q.x, x = _t === void 0 ? 0 : _t, _u = _q.y, y = _u === void 0 ? 0 : _u, radius = _q.radius;
11810 var hasRadius = radius && radius.some(function (r) { return r !== 0; });
11811 commands = rectToCommands(width_1, height_1, x, y, hasRadius &&
11812 radius.map(function (r) {
11813 return clamp(r, 0, Math.min(Math.abs(width_1) / 2, Math.abs(height_1) / 2));
11814 }));
11815 break;
11816 case Shape.PATH:
11817 var absolutePath = object.parsedStyle.path.absolutePath;
11818 commands = __spreadArray([], __read(absolutePath), false);
11819 break;
11820 }
11821 if (commands.length) {
11822 return commandsToPathString(commands, object, transform);
11823 }
11824 }
11825
11826 var internalParsePath = function (path) {
11827 // empty path
11828 if (path === '' || (Array.isArray(path) && path.length === 0)) {
11829 return {
11830 absolutePath: [],
11831 hasArc: false,
11832 segments: [],
11833 polygons: [],
11834 polylines: [],
11835 curve: null,
11836 totalLength: 0,
11837 rect: {
11838 x: 0,
11839 y: 0,
11840 width: 0,
11841 height: 0,
11842 },
11843 };
11844 }
11845 var absolutePath;
11846 try {
11847 absolutePath = normalizePath(path);
11848 }
11849 catch (e) {
11850 absolutePath = normalizePath('');
11851 console.error("[g]: Invalid SVG Path definition: ".concat(path));
11852 }
11853 removeRedundantMCommand(absolutePath);
11854 var hasArc = hasArcOrBezier(absolutePath);
11855 var _a = extractPolygons(absolutePath), polygons = _a.polygons, polylines = _a.polylines;
11856 // for later use
11857 var segments = path2Segments(absolutePath);
11858 // Only calculate bbox here since we don't need length now.
11859 var _b = getPathBBox(segments, 0), x = _b.x, y = _b.y, width = _b.width, height = _b.height;
11860 return {
11861 absolutePath: absolutePath,
11862 hasArc: hasArc,
11863 segments: segments,
11864 polygons: polygons,
11865 polylines: polylines,
11866 // curve,
11867 // Delay the calculation of length.
11868 totalLength: 0,
11869 rect: {
11870 x: Number.isFinite(x) ? x : 0,
11871 y: Number.isFinite(y) ? y : 0,
11872 width: Number.isFinite(width) ? width : 0,
11873 height: Number.isFinite(height) ? height : 0,
11874 },
11875 };
11876 };
11877 var memoizedParsePath = memoize(internalParsePath);
11878 function parsePath(path) {
11879 return (isString(path) ? memoizedParsePath(path) : internalParsePath(path));
11880 }
11881 function mergePaths(left, right, object) {
11882 var curve1 = left.curve;
11883 var curve2 = right.curve;
11884 if (!curve1 || curve1.length === 0) {
11885 // convert to curves to do morphing & picking later
11886 // @see http://thednp.github.io/kute.js/svgCubicMorph.html
11887 curve1 = path2Curve(left.absolutePath, false);
11888 left.curve = curve1;
11889 }
11890 if (!curve2 || curve2.length === 0) {
11891 curve2 = path2Curve(right.absolutePath, false);
11892 right.curve = curve2;
11893 }
11894 var curves = [curve1, curve2];
11895 if (curve1.length !== curve2.length) {
11896 curves = equalizeSegments(curve1, curve2);
11897 }
11898 var curve0 = getDrawDirection(curves[0]) !== getDrawDirection(curves[1])
11899 ? reverseCurve(curves[0])
11900 : clonePath(curves[0]);
11901 return [
11902 curve0,
11903 getRotatedCurve(curves[1], curve0),
11904 function (pathArray) {
11905 // need converting to path string?
11906 return pathArray;
11907 },
11908 ];
11909 }
11910
11911 /**
11912 * @see https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute/points
11913 *
11914 * @example
11915 * points="100,10 250,150 200,110"
11916 */
11917 function parsePoints(pointsOrStr, object) {
11918 var points;
11919 if (isString(pointsOrStr)) {
11920 points = pointsOrStr.split(' ').map(function (pointStr) {
11921 var _a = __read(pointStr.split(','), 2), x = _a[0], y = _a[1];
11922 return [Number(x), Number(y)];
11923 });
11924 }
11925 else {
11926 points = pointsOrStr;
11927 }
11928 var segments = [];
11929 var tempLength = 0;
11930 var segmentT;
11931 var segmentL;
11932 var totalLength = length$2(points);
11933 points.forEach(function (p, i) {
11934 if (points[i + 1]) {
11935 segmentT = [0, 0];
11936 segmentT[0] = tempLength / totalLength;
11937 segmentL = length$4(p[0], p[1], points[i + 1][0], points[i + 1][1]);
11938 tempLength += segmentL;
11939 segmentT[1] = tempLength / totalLength;
11940 segments.push(segmentT);
11941 }
11942 });
11943 var minX = Math.min.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[0]; })), false));
11944 var minY = Math.min.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[1]; })), false));
11945 if (object) {
11946 object.parsedStyle.defX = minX;
11947 object.parsedStyle.defY = minY;
11948 }
11949 return {
11950 points: points,
11951 totalLength: totalLength,
11952 segments: segments,
11953 };
11954 }
11955 function mergePoints(left, right) {
11956 return [
11957 left.points,
11958 right.points,
11959 function (points) {
11960 return points;
11961 },
11962 ];
11963 }
11964
11965 var _ = null;
11966 function cast(pattern) {
11967 return function (contents) {
11968 var i = 0;
11969 return pattern.map(function (x) {
11970 return x === _ ? contents[i++] : x;
11971 });
11972 };
11973 }
11974 function id(x) {
11975 return x;
11976 }
11977 // type: [argTypes, convertTo3D, convertTo2D]
11978 // In the argument types string, lowercase characters represent optional arguments
11979 var transformFunctions = {
11980 // @ts-ignore
11981 matrix: ['NNNNNN', [_, _, 0, 0, _, _, 0, 0, 0, 0, 1, 0, _, _, 0, 1], id],
11982 matrix3d: ['NNNNNNNNNNNNNNNN', id],
11983 rotate: ['A'],
11984 rotatex: ['A'],
11985 rotatey: ['A'],
11986 rotatez: ['A'],
11987 rotate3d: ['NNNA'],
11988 perspective: ['L'],
11989 scale: ['Nn', cast([_, _, new CSSUnitValue(1)]), id],
11990 scalex: [
11991 'N',
11992 cast([_, new CSSUnitValue(1), new CSSUnitValue(1)]),
11993 cast([_, new CSSUnitValue(1)]),
11994 ],
11995 scaley: [
11996 'N',
11997 cast([new CSSUnitValue(1), _, new CSSUnitValue(1)]),
11998 cast([new CSSUnitValue(1), _]),
11999 ],
12000 scalez: ['N', cast([new CSSUnitValue(1), new CSSUnitValue(1), _])],
12001 scale3d: ['NNN', id],
12002 skew: ['Aa', null, id],
12003 skewx: ['A', null, cast([_, Odeg])],
12004 skewy: ['A', null, cast([Odeg, _])],
12005 translate: ['Tt', cast([_, _, Opx]), id],
12006 translatex: ['T', cast([_, Opx, Opx]), cast([_, Opx])],
12007 translatey: ['T', cast([Opx, _, Opx]), cast([Opx, _])],
12008 translatez: ['L', cast([Opx, Opx, _])],
12009 translate3d: ['TTL', id],
12010 };
12011 /**
12012 * none
12013 * scale(1) scale(1, 2)
12014 * scaleX(1)
12015 */
12016 function parseTransform(string) {
12017 string = (string || 'none').toLowerCase().trim();
12018 if (string === 'none') {
12019 return [];
12020 }
12021 var transformRegExp = /\s*(\w+)\(([^)]*)\)/g;
12022 var result = [];
12023 var match;
12024 var prevLastIndex = 0;
12025 while ((match = transformRegExp.exec(string))) {
12026 if (match.index !== prevLastIndex) {
12027 return [];
12028 }
12029 prevLastIndex = match.index + match[0].length;
12030 var functionName = match[1]; // scale
12031 var functionData = transformFunctions[functionName]; // scale(1, 2)
12032 if (!functionData) {
12033 // invalid, eg. scale()
12034 return [];
12035 }
12036 var args = match[2].split(','); // 1,2
12037 var argTypes = functionData[0]; // Nn
12038 if (argTypes.length < args.length) {
12039 // scale(N, n)
12040 return [];
12041 }
12042 var parsedArgs = [];
12043 for (var i = 0; i < argTypes.length; i++) {
12044 var arg = args[i];
12045 var type = argTypes[i];
12046 var parsedArg = void 0;
12047 if (!arg) {
12048 // @ts-ignore
12049 parsedArg = {
12050 a: Odeg,
12051 n: parsedArgs[0],
12052 t: Opx,
12053 }[type];
12054 }
12055 else {
12056 // @ts-ignore
12057 parsedArg = {
12058 A: function (s) {
12059 return s.trim() === '0' ? Odeg : parseAngle(s);
12060 },
12061 N: parseNumber,
12062 T: parseLengthOrPercentage,
12063 L: parseLength,
12064 }[type.toUpperCase()](arg);
12065 }
12066 if (parsedArg === undefined) {
12067 return [];
12068 }
12069 parsedArgs.push(parsedArg);
12070 }
12071 result.push({ t: functionName, d: parsedArgs }); // { t: scale, d: [1, 2] }
12072 if (transformRegExp.lastIndex === string.length) {
12073 return result;
12074 }
12075 }
12076 return [];
12077 }
12078 function convertItemToMatrix(item) {
12079 var x;
12080 var y;
12081 var z;
12082 var angle;
12083 switch (item.t) {
12084 case 'rotatex':
12085 angle = deg2rad(convertAngleUnit(item.d[0]));
12086 return [
12087 1,
12088 0,
12089 0,
12090 0,
12091 0,
12092 Math.cos(angle),
12093 Math.sin(angle),
12094 0,
12095 0,
12096 -Math.sin(angle),
12097 Math.cos(angle),
12098 0,
12099 0,
12100 0,
12101 0,
12102 1,
12103 ];
12104 case 'rotatey':
12105 angle = deg2rad(convertAngleUnit(item.d[0]));
12106 return [
12107 Math.cos(angle),
12108 0,
12109 -Math.sin(angle),
12110 0,
12111 0,
12112 1,
12113 0,
12114 0,
12115 Math.sin(angle),
12116 0,
12117 Math.cos(angle),
12118 0,
12119 0,
12120 0,
12121 0,
12122 1,
12123 ];
12124 case 'rotate':
12125 case 'rotatez':
12126 angle = deg2rad(convertAngleUnit(item.d[0]));
12127 return [
12128 Math.cos(angle),
12129 Math.sin(angle),
12130 0,
12131 0,
12132 -Math.sin(angle),
12133 Math.cos(angle),
12134 0,
12135 0,
12136 0,
12137 0,
12138 1,
12139 0,
12140 0,
12141 0,
12142 0,
12143 1,
12144 ];
12145 case 'rotate3d':
12146 x = item.d[0].value;
12147 y = item.d[1].value;
12148 z = item.d[2].value;
12149 angle = deg2rad(convertAngleUnit(item.d[3]));
12150 var sqrLength = x * x + y * y + z * z;
12151 if (sqrLength === 0) {
12152 x = 1;
12153 y = 0;
12154 z = 0;
12155 }
12156 else if (sqrLength !== 1) {
12157 var length_1 = Math.sqrt(sqrLength);
12158 x /= length_1;
12159 y /= length_1;
12160 z /= length_1;
12161 }
12162 var s = Math.sin(angle / 2);
12163 var sc = s * Math.cos(angle / 2);
12164 var sq = s * s;
12165 return [
12166 1 - 2 * (y * y + z * z) * sq,
12167 2 * (x * y * sq + z * sc),
12168 2 * (x * z * sq - y * sc),
12169 0,
12170 2 * (x * y * sq - z * sc),
12171 1 - 2 * (x * x + z * z) * sq,
12172 2 * (y * z * sq + x * sc),
12173 0,
12174 2 * (x * z * sq + y * sc),
12175 2 * (y * z * sq - x * sc),
12176 1 - 2 * (x * x + y * y) * sq,
12177 0,
12178 0,
12179 0,
12180 0,
12181 1,
12182 ];
12183 case 'scale':
12184 return [
12185 item.d[0].value,
12186 0,
12187 0,
12188 0,
12189 0,
12190 item.d[1].value,
12191 0,
12192 0,
12193 0,
12194 0,
12195 1,
12196 0,
12197 0,
12198 0,
12199 0,
12200 1,
12201 ];
12202 case 'scalex':
12203 return [item.d[0].value, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
12204 case 'scaley':
12205 return [1, 0, 0, 0, 0, item.d[0].value, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
12206 case 'scalez':
12207 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, item.d[0].value, 0, 0, 0, 0, 1];
12208 case 'scale3d':
12209 return [
12210 item.d[0].value,
12211 0,
12212 0,
12213 0,
12214 0,
12215 item.d[1].value,
12216 0,
12217 0,
12218 0,
12219 0,
12220 item.d[2].value,
12221 0,
12222 0,
12223 0,
12224 0,
12225 1,
12226 ];
12227 case 'skew':
12228 var xAngle = deg2rad(convertAngleUnit(item.d[0]));
12229 var yAngle = deg2rad(convertAngleUnit(item.d[1]));
12230 return [
12231 1,
12232 Math.tan(yAngle),
12233 0,
12234 0,
12235 Math.tan(xAngle),
12236 1,
12237 0,
12238 0,
12239 0,
12240 0,
12241 1,
12242 0,
12243 0,
12244 0,
12245 0,
12246 1,
12247 ];
12248 case 'skewx':
12249 angle = deg2rad(convertAngleUnit(item.d[0]));
12250 return [1, 0, 0, 0, Math.tan(angle), 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
12251 case 'skewy':
12252 angle = deg2rad(convertAngleUnit(item.d[0]));
12253 return [1, Math.tan(angle), 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
12254 case 'translate':
12255 // TODO: pass target
12256 x = convertPercentUnit(item.d[0], 0, null) || 0;
12257 y = convertPercentUnit(item.d[1], 0, null) || 0;
12258 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, 0, 1];
12259 case 'translatex':
12260 x = convertPercentUnit(item.d[0], 0, null) || 0;
12261 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, 0, 0, 1];
12262 case 'translatey':
12263 y = convertPercentUnit(item.d[0], 0, null) || 0;
12264 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, y, 0, 1];
12265 case 'translatez':
12266 z = convertPercentUnit(item.d[0], 0, null) || 0;
12267 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, z, 1];
12268 case 'translate3d':
12269 x = convertPercentUnit(item.d[0], 0, null) || 0;
12270 y = convertPercentUnit(item.d[1], 0, null) || 0;
12271 z = convertPercentUnit(item.d[2], 0, null) || 0;
12272 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
12273 case 'perspective':
12274 var t = convertPercentUnit(item.d[0], 0, null) || 0;
12275 var p = t ? -1 / t : 0;
12276 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, p, 0, 0, 0, 1];
12277 case 'matrix':
12278 return [
12279 item.d[0].value,
12280 item.d[1].value,
12281 0,
12282 0,
12283 item.d[2].value,
12284 item.d[3].value,
12285 0,
12286 0,
12287 0,
12288 0,
12289 1,
12290 0,
12291 item.d[4].value,
12292 item.d[5].value,
12293 0,
12294 1,
12295 ];
12296 case 'matrix3d':
12297 return item.d.map(function (d) { return d.value; });
12298 }
12299 }
12300 function multiplyMatrices(a, b) {
12301 return [
12302 a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3],
12303 a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3],
12304 a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3],
12305 a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3],
12306 a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7],
12307 a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7],
12308 a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7],
12309 a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7],
12310 a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11],
12311 a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11],
12312 a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11],
12313 a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11],
12314 a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15],
12315 a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15],
12316 a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15],
12317 a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15],
12318 ];
12319 }
12320 function convertToMatrix(transformList) {
12321 if (transformList.length === 0) {
12322 return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
12323 }
12324 return transformList.map(convertItemToMatrix).reduce(multiplyMatrices);
12325 }
12326 function makeMatrixDecomposition(transformList) {
12327 var translate = [0, 0, 0];
12328 var scale = [1, 1, 1];
12329 var skew = [0, 0, 0];
12330 var perspective = [0, 0, 0, 1];
12331 var quaternion = [0, 0, 0, 1];
12332 decomposeMat4(
12333 // @ts-ignore
12334 convertToMatrix(transformList), translate, scale, skew, perspective, quaternion);
12335 return [[translate, scale, skew, quaternion, perspective]];
12336 }
12337 var composeMatrix = (function () {
12338 function multiply(a, b) {
12339 var result = [
12340 [0, 0, 0, 0],
12341 [0, 0, 0, 0],
12342 [0, 0, 0, 0],
12343 [0, 0, 0, 0],
12344 ];
12345 for (var i = 0; i < 4; i++) {
12346 for (var j = 0; j < 4; j++) {
12347 for (var k = 0; k < 4; k++) {
12348 result[i][j] += b[i][k] * a[k][j];
12349 }
12350 }
12351 }
12352 return result;
12353 }
12354 function is2D(m) {
12355 return (m[0][2] == 0 &&
12356 m[0][3] == 0 &&
12357 m[1][2] == 0 &&
12358 m[1][3] == 0 &&
12359 m[2][0] == 0 &&
12360 m[2][1] == 0 &&
12361 m[2][2] == 1 &&
12362 m[2][3] == 0 &&
12363 m[3][2] == 0 &&
12364 m[3][3] == 1);
12365 }
12366 function composeMatrix(translate, scale, skew, quat, perspective) {
12367 var matrix = [
12368 [1, 0, 0, 0],
12369 [0, 1, 0, 0],
12370 [0, 0, 1, 0],
12371 [0, 0, 0, 1],
12372 ];
12373 for (var i = 0; i < 4; i++) {
12374 matrix[i][3] = perspective[i];
12375 }
12376 for (var i = 0; i < 3; i++) {
12377 for (var j = 0; j < 3; j++) {
12378 matrix[3][i] += translate[j] * matrix[j][i];
12379 }
12380 }
12381 var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
12382 var rotMatrix = [
12383 [1, 0, 0, 0],
12384 [0, 1, 0, 0],
12385 [0, 0, 1, 0],
12386 [0, 0, 0, 1],
12387 ];
12388 rotMatrix[0][0] = 1 - 2 * (y * y + z * z);
12389 rotMatrix[0][1] = 2 * (x * y - z * w);
12390 rotMatrix[0][2] = 2 * (x * z + y * w);
12391 rotMatrix[1][0] = 2 * (x * y + z * w);
12392 rotMatrix[1][1] = 1 - 2 * (x * x + z * z);
12393 rotMatrix[1][2] = 2 * (y * z - x * w);
12394 rotMatrix[2][0] = 2 * (x * z - y * w);
12395 rotMatrix[2][1] = 2 * (y * z + x * w);
12396 rotMatrix[2][2] = 1 - 2 * (x * x + y * y);
12397 matrix = multiply(matrix, rotMatrix);
12398 var temp = [
12399 [1, 0, 0, 0],
12400 [0, 1, 0, 0],
12401 [0, 0, 1, 0],
12402 [0, 0, 0, 1],
12403 ];
12404 if (skew[2]) {
12405 temp[2][1] = skew[2];
12406 matrix = multiply(matrix, temp);
12407 }
12408 if (skew[1]) {
12409 temp[2][1] = 0;
12410 temp[2][0] = skew[0];
12411 matrix = multiply(matrix, temp);
12412 }
12413 if (skew[0]) {
12414 temp[2][0] = 0;
12415 temp[1][0] = skew[0];
12416 matrix = multiply(matrix, temp);
12417 }
12418 for (var i = 0; i < 3; i++) {
12419 for (var j = 0; j < 3; j++) {
12420 matrix[i][j] *= scale[i];
12421 }
12422 }
12423 if (is2D(matrix)) {
12424 return [
12425 matrix[0][0],
12426 matrix[0][1],
12427 matrix[1][0],
12428 matrix[1][1],
12429 matrix[3][0],
12430 matrix[3][1],
12431 ];
12432 }
12433 return matrix[0].concat(matrix[1], matrix[2], matrix[3]);
12434 }
12435 return composeMatrix;
12436 })();
12437 function numberToLongString(x) {
12438 return x.toFixed(6).replace('.000000', '');
12439 }
12440 function mergeMatrices(left, right) {
12441 var leftArgs;
12442 var rightArgs;
12443 // @ts-ignore
12444 if (left.decompositionPair !== right) {
12445 // @ts-ignore
12446 left.decompositionPair = right;
12447 // @ts-ignore
12448 leftArgs = makeMatrixDecomposition(left);
12449 }
12450 // @ts-ignore
12451 if (right.decompositionPair !== left) {
12452 // @ts-ignore
12453 right.decompositionPair = left;
12454 // @ts-ignore
12455 rightArgs = makeMatrixDecomposition(right);
12456 }
12457 if (leftArgs[0] === null || rightArgs[0] === null)
12458 return [
12459 // @ts-ignore
12460 [false],
12461 // @ts-ignore
12462 [true],
12463 // @ts-ignore
12464 function (x) {
12465 return x ? right[0].d : left[0].d;
12466 },
12467 ];
12468 leftArgs[0].push(0);
12469 rightArgs[0].push(1);
12470 return [
12471 leftArgs,
12472 rightArgs,
12473 // @ts-ignore
12474 function (list) {
12475 // @ts-ignore
12476 var q = quat(leftArgs[0][3], rightArgs[0][3], list[5]);
12477 var mat = composeMatrix(list[0], list[1], list[2], q, list[4]);
12478 var stringifiedArgs = mat.map(numberToLongString).join(',');
12479 return stringifiedArgs;
12480 },
12481 ];
12482 }
12483 function dot$2(v1, v2) {
12484 var result = 0;
12485 for (var i = 0; i < v1.length; i++) {
12486 result += v1[i] * v2[i];
12487 }
12488 return result;
12489 }
12490 function quat(fromQ, toQ, f) {
12491 var product = dot$2(fromQ, toQ);
12492 product = clamp(product, -1.0, 1.0);
12493 var quat = [];
12494 if (product === 1.0) {
12495 quat = fromQ;
12496 }
12497 else {
12498 var theta = Math.acos(product);
12499 var w = (Math.sin(f * theta) * 1) / Math.sqrt(1 - product * product);
12500 for (var i = 0; i < 4; i++) {
12501 quat.push(fromQ[i] * (Math.cos(f * theta) - product * w) + toQ[i] * w);
12502 }
12503 }
12504 return quat;
12505 }
12506 // scalex/y/z -> scale
12507 function typeTo2D(type) {
12508 return type.replace(/[xy]/, '');
12509 }
12510 // scalex/y/z -> scale3d
12511 function typeTo3D(type) {
12512 return type.replace(/(x|y|z|3d)?$/, '3d');
12513 }
12514 var isMatrixOrPerspective = function (lt, rt) {
12515 return ((lt === 'perspective' && rt === 'perspective') ||
12516 ((lt === 'matrix' || lt === 'matrix3d') &&
12517 (rt === 'matrix' || rt === 'matrix3d')));
12518 };
12519 function mergeTransforms(left, right, target) {
12520 var flipResults = false;
12521 // padding empty transform, eg. merge 'scale(10)' with 'none' -> scale(1)
12522 if (!left.length || !right.length) {
12523 if (!left.length) {
12524 flipResults = true;
12525 left = right;
12526 right = [];
12527 }
12528 var _loop_1 = function (i) {
12529 var _a = left[i], type = _a.t, args = _a.d;
12530 // none -> scale(1)/translateX(0)
12531 var defaultValue = type.substring(0, 5) === 'scale' ? 1 : 0;
12532 right.push({
12533 t: type,
12534 d: args.map(function (arg) {
12535 if (typeof arg === 'number') {
12536 return getOrCreateUnitValue(defaultValue);
12537 }
12538 return getOrCreateUnitValue(defaultValue, arg.unit);
12539 // {
12540 // unit: arg.unit,
12541 // value: defaultValue,
12542 // };
12543 }),
12544 });
12545 };
12546 for (var i = 0; i < left.length; i++) {
12547 _loop_1(i);
12548 }
12549 }
12550 var leftResult = [];
12551 var rightResult = [];
12552 var types = [];
12553 // merge matrix() with matrix3d()
12554 if (left.length !== right.length) {
12555 var merged = mergeMatrices(left, right);
12556 // @ts-ignore
12557 leftResult = [merged[0]];
12558 // @ts-ignore
12559 rightResult = [merged[1]];
12560 types = [['matrix', [merged[2]]]];
12561 }
12562 else {
12563 for (var i = 0; i < left.length; i++) {
12564 var leftType = left[i].t;
12565 var rightType = right[i].t;
12566 var leftArgs = left[i].d;
12567 var rightArgs = right[i].d;
12568 var leftFunctionData = transformFunctions[leftType];
12569 var rightFunctionData = transformFunctions[rightType];
12570 var type = void 0;
12571 if (isMatrixOrPerspective(leftType, rightType)) {
12572 var merged = mergeMatrices([left[i]], [right[i]]);
12573 // @ts-ignore
12574 leftResult.push(merged[0]);
12575 // @ts-ignore
12576 rightResult.push(merged[1]);
12577 types.push(['matrix', [merged[2]]]);
12578 continue;
12579 }
12580 else if (leftType === rightType) {
12581 type = leftType;
12582 }
12583 else if (leftFunctionData[2] &&
12584 rightFunctionData[2] &&
12585 typeTo2D(leftType) === typeTo2D(rightType)) {
12586 type = typeTo2D(leftType);
12587 // @ts-ignore
12588 leftArgs = leftFunctionData[2](leftArgs);
12589 // @ts-ignore
12590 rightArgs = rightFunctionData[2](rightArgs);
12591 }
12592 else if (leftFunctionData[1] &&
12593 rightFunctionData[1] &&
12594 typeTo3D(leftType) === typeTo3D(rightType)) {
12595 type = typeTo3D(leftType);
12596 // @ts-ignore
12597 leftArgs = leftFunctionData[1](leftArgs);
12598 // @ts-ignore
12599 rightArgs = rightFunctionData[1](rightArgs);
12600 }
12601 else {
12602 var merged = mergeMatrices(left, right);
12603 // @ts-ignore
12604 leftResult = [merged[0]];
12605 // @ts-ignore
12606 rightResult = [merged[1]];
12607 types = [['matrix', [merged[2]]]];
12608 break;
12609 }
12610 var leftArgsCopy = [];
12611 var rightArgsCopy = [];
12612 var stringConversions = [];
12613 for (var j = 0; j < leftArgs.length; j++) {
12614 // const merge = leftArgs[j].unit === UnitType.kNumber ? mergeDimensions : mergeDimensions;
12615 var merged = mergeDimensions(leftArgs[j], rightArgs[j], target, false, j);
12616 leftArgsCopy[j] = merged[0];
12617 rightArgsCopy[j] = merged[1];
12618 stringConversions.push(merged[2]);
12619 }
12620 leftResult.push(leftArgsCopy);
12621 rightResult.push(rightArgsCopy);
12622 types.push([type, stringConversions]);
12623 }
12624 }
12625 if (flipResults) {
12626 var tmp = leftResult;
12627 leftResult = rightResult;
12628 rightResult = tmp;
12629 }
12630 return [
12631 leftResult,
12632 rightResult,
12633 function (list) {
12634 return list
12635 .map(function (args, i) {
12636 var stringifiedArgs = args
12637 .map(function (arg, j) {
12638 return types[i][1][j](arg);
12639 })
12640 .join(',');
12641 if (types[i][0] === 'matrix' &&
12642 stringifiedArgs.split(',').length === 16) {
12643 types[i][0] = 'matrix3d';
12644 }
12645 if (types[i][0] === 'matrix3d' &&
12646 stringifiedArgs.split(',').length === 6) {
12647 types[i][0] = 'matrix';
12648 }
12649 return types[i][0] + '(' + stringifiedArgs + ')';
12650 })
12651 .join(' ');
12652 },
12653 ];
12654 }
12655
12656 /**
12657 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin
12658 * eg. 'center' 'top left' '50px 50px'
12659 */
12660 var parseTransformOrigin = memoize(function (value) {
12661 if (isString(value)) {
12662 if (value === 'text-anchor') {
12663 return [getOrCreateUnitValue(0, 'px'), getOrCreateUnitValue(0, 'px')];
12664 }
12665 var values = value.split(' ');
12666 if (values.length === 1) {
12667 if (values[0] === 'top' || values[0] === 'bottom') {
12668 // 'top' -> 'center top'
12669 values[1] = values[0];
12670 values[0] = 'center';
12671 }
12672 else {
12673 // '50px' -> '50px center'
12674 values[1] = 'center';
12675 }
12676 }
12677 if (values.length !== 2) {
12678 return null;
12679 }
12680 // eg. center bottom
12681 return [
12682 parseLengthOrPercentage(convertKeyword2Percent(values[0])),
12683 parseLengthOrPercentage(convertKeyword2Percent(values[1])),
12684 ];
12685 }
12686 else {
12687 return [
12688 getOrCreateUnitValue(value[0] || 0, 'px'),
12689 getOrCreateUnitValue(value[1] || 0, 'px'),
12690 ];
12691 }
12692 });
12693 function convertKeyword2Percent(keyword) {
12694 if (keyword === 'center') {
12695 return '50%';
12696 }
12697 else if (keyword === 'left' || keyword === 'top') {
12698 return '0';
12699 }
12700 else if (keyword === 'right' || keyword === 'bottom') {
12701 return '100%';
12702 }
12703 return keyword;
12704 }
12705
12706 /**
12707 * Blink used them in code generation(css_properties.json5)
12708 */
12709 var BUILT_IN_PROPERTIES = [
12710 {
12711 /**
12712 * used in CSS Layout API
12713 * eg. `display: 'flex'`
12714 */
12715 n: 'display',
12716 k: ['none'],
12717 },
12718 {
12719 /**
12720 * range [0.0, 1.0]
12721 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/opacity
12722 */
12723 n: 'opacity',
12724 int: true,
12725 inh: true,
12726 d: '1',
12727 syntax: PropertySyntax.OPACITY_VALUE,
12728 },
12729 {
12730 /**
12731 * inheritable, range [0.0, 1.0]
12732 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity
12733 * @see https://svgwg.org/svg2-draft/painting.html#FillOpacity
12734 */
12735 n: 'fillOpacity',
12736 int: true,
12737 inh: true,
12738 d: '1',
12739 syntax: PropertySyntax.OPACITY_VALUE,
12740 },
12741 {
12742 /**
12743 * inheritable, range [0.0, 1.0]
12744 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity
12745 * @see https://svgwg.org/svg2-draft/painting.html#StrokeOpacity
12746 */
12747 n: 'strokeOpacity',
12748 int: true,
12749 inh: true,
12750 d: '1',
12751 syntax: PropertySyntax.OPACITY_VALUE,
12752 },
12753 {
12754 /**
12755 * background-color is not inheritable
12756 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Fills_and_Strokes
12757 */
12758 n: 'fill',
12759 int: true,
12760 k: ['none'],
12761 d: 'none',
12762 syntax: PropertySyntax.PAINT,
12763 },
12764 {
12765 n: 'fillRule',
12766 k: ['nonzero', 'evenodd'],
12767 d: 'nonzero',
12768 },
12769 /**
12770 * default to none
12771 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke#usage_notes
12772 */
12773 {
12774 n: 'stroke',
12775 int: true,
12776 k: ['none'],
12777 d: 'none',
12778 syntax: PropertySyntax.PAINT,
12779 /**
12780 * Stroke 'none' won't affect geometry but others will.
12781 */
12782 l: true,
12783 },
12784 {
12785 n: 'shadowType',
12786 k: ['inner', 'outer', 'both'],
12787 d: 'outer',
12788 l: true,
12789 },
12790 {
12791 n: 'shadowColor',
12792 int: true,
12793 syntax: PropertySyntax.COLOR,
12794 },
12795 {
12796 n: 'shadowOffsetX',
12797 int: true,
12798 l: true,
12799 d: '0',
12800 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12801 },
12802 {
12803 n: 'shadowOffsetY',
12804 int: true,
12805 l: true,
12806 d: '0',
12807 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12808 },
12809 {
12810 n: 'shadowBlur',
12811 int: true,
12812 l: true,
12813 d: '0',
12814 syntax: PropertySyntax.SHADOW_BLUR,
12815 },
12816 {
12817 /**
12818 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width
12819 */
12820 n: 'lineWidth',
12821 int: true,
12822 inh: true,
12823 d: '1',
12824 l: true,
12825 a: ['strokeWidth'],
12826 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12827 },
12828 {
12829 n: 'increasedLineWidthForHitTesting',
12830 inh: true,
12831 d: '0',
12832 l: true,
12833 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12834 },
12835 {
12836 n: 'lineJoin',
12837 inh: true,
12838 l: true,
12839 a: ['strokeLinejoin'],
12840 k: ['miter', 'bevel', 'round'],
12841 d: 'miter',
12842 },
12843 {
12844 n: 'lineCap',
12845 inh: true,
12846 l: true,
12847 a: ['strokeLinecap'],
12848 k: ['butt', 'round', 'square'],
12849 d: 'butt',
12850 },
12851 {
12852 n: 'lineDash',
12853 int: true,
12854 inh: true,
12855 k: ['none'],
12856 a: ['strokeDasharray'],
12857 syntax: PropertySyntax.LENGTH_PERCENTAGE_12,
12858 },
12859 {
12860 n: 'lineDashOffset',
12861 int: true,
12862 inh: true,
12863 d: '0',
12864 a: ['strokeDashoffset'],
12865 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12866 },
12867 {
12868 n: 'offsetPath',
12869 syntax: PropertySyntax.DEFINED_PATH,
12870 },
12871 {
12872 n: 'offsetDistance',
12873 int: true,
12874 syntax: PropertySyntax.OFFSET_DISTANCE,
12875 },
12876 {
12877 n: 'dx',
12878 int: true,
12879 l: true,
12880 d: '0',
12881 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12882 },
12883 {
12884 n: 'dy',
12885 int: true,
12886 l: true,
12887 d: '0',
12888 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12889 },
12890 {
12891 n: 'zIndex',
12892 ind: true,
12893 int: true,
12894 d: '0',
12895 k: ['auto'],
12896 syntax: PropertySyntax.Z_INDEX,
12897 },
12898 {
12899 n: 'visibility',
12900 k: ['visible', 'hidden'],
12901 ind: true,
12902 inh: true,
12903 /**
12904 * support interpolation
12905 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/visibility#interpolation
12906 */
12907 int: true,
12908 d: 'visible',
12909 },
12910 {
12911 n: 'pointerEvents',
12912 inh: true,
12913 k: [
12914 'none',
12915 'auto',
12916 'stroke',
12917 'fill',
12918 'painted',
12919 'visible',
12920 'visiblestroke',
12921 'visiblefill',
12922 'visiblepainted',
12923 // 'bounding-box',
12924 'all',
12925 ],
12926 d: 'auto',
12927 },
12928 {
12929 n: 'filter',
12930 ind: true,
12931 l: true,
12932 k: ['none'],
12933 d: 'none',
12934 syntax: PropertySyntax.FILTER,
12935 },
12936 {
12937 n: 'clipPath',
12938 syntax: PropertySyntax.DEFINED_PATH,
12939 },
12940 {
12941 n: 'textPath',
12942 syntax: PropertySyntax.DEFINED_PATH,
12943 },
12944 {
12945 n: 'textPathSide',
12946 k: ['left', 'right'],
12947 d: 'left',
12948 },
12949 {
12950 n: 'textPathStartOffset',
12951 l: true,
12952 d: '0',
12953 syntax: PropertySyntax.LENGTH_PERCENTAGE,
12954 },
12955 {
12956 n: 'transform',
12957 p: 100,
12958 int: true,
12959 k: ['none'],
12960 d: 'none',
12961 syntax: PropertySyntax.TRANSFORM,
12962 },
12963 {
12964 n: 'transformOrigin',
12965 p: 100,
12966 // int: true,
12967 d: function (nodeName) {
12968 if (nodeName === Shape.CIRCLE || nodeName === Shape.ELLIPSE) {
12969 return 'center';
12970 }
12971 if (nodeName === Shape.TEXT) {
12972 return 'text-anchor';
12973 }
12974 return 'left top';
12975 },
12976 l: true,
12977 syntax: PropertySyntax.TRANSFORM_ORIGIN,
12978 },
12979 {
12980 n: 'anchor',
12981 p: 99,
12982 d: function (nodeName) {
12983 if (nodeName === Shape.CIRCLE || nodeName === Shape.ELLIPSE) {
12984 return '0.5 0.5';
12985 }
12986 return '0 0';
12987 },
12988 l: true,
12989 syntax: PropertySyntax.LENGTH_PERCENTAGE_12,
12990 },
12991 // <circle> & <ellipse>
12992 {
12993 n: 'cx',
12994 int: true,
12995 d: '0',
12996 syntax: PropertySyntax.COORDINATE,
12997 },
12998 {
12999 n: 'cy',
13000 int: true,
13001 d: '0',
13002 syntax: PropertySyntax.COORDINATE,
13003 },
13004 {
13005 n: 'cz',
13006 int: true,
13007 d: '0',
13008 syntax: PropertySyntax.COORDINATE,
13009 },
13010 {
13011 n: 'r',
13012 int: true,
13013 l: true,
13014 d: '0',
13015 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13016 },
13017 {
13018 n: 'rx',
13019 int: true,
13020 l: true,
13021 d: '0',
13022 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13023 },
13024 {
13025 n: 'ry',
13026 int: true,
13027 l: true,
13028 d: '0',
13029 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13030 },
13031 // Rect Image Group
13032 {
13033 // x in local space
13034 n: 'x',
13035 int: true,
13036 d: '0',
13037 syntax: PropertySyntax.COORDINATE,
13038 },
13039 {
13040 // y in local space
13041 n: 'y',
13042 int: true,
13043 d: '0',
13044 syntax: PropertySyntax.COORDINATE,
13045 },
13046 {
13047 // z in local space
13048 n: 'z',
13049 int: true,
13050 d: '0',
13051 syntax: PropertySyntax.COORDINATE,
13052 },
13053 {
13054 n: 'width',
13055 int: true,
13056 l: true,
13057 /**
13058 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/width
13059 */
13060 k: ['auto', 'fit-content', 'min-content', 'max-content'],
13061 d: '0',
13062 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13063 },
13064 {
13065 n: 'height',
13066 int: true,
13067 l: true,
13068 /**
13069 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/height
13070 */
13071 k: ['auto', 'fit-content', 'min-content', 'max-content'],
13072 d: '0',
13073 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13074 },
13075 {
13076 n: 'radius',
13077 int: true,
13078 l: true,
13079 d: '0',
13080 syntax: PropertySyntax.LENGTH_PERCENTAGE_14,
13081 },
13082 // Line
13083 {
13084 n: 'x1',
13085 int: true,
13086 l: true,
13087 syntax: PropertySyntax.COORDINATE,
13088 },
13089 {
13090 n: 'y1',
13091 int: true,
13092 l: true,
13093 syntax: PropertySyntax.COORDINATE,
13094 },
13095 {
13096 n: 'z1',
13097 int: true,
13098 l: true,
13099 syntax: PropertySyntax.COORDINATE,
13100 },
13101 {
13102 n: 'x2',
13103 int: true,
13104 l: true,
13105 syntax: PropertySyntax.COORDINATE,
13106 },
13107 {
13108 n: 'y2',
13109 int: true,
13110 l: true,
13111 syntax: PropertySyntax.COORDINATE,
13112 },
13113 {
13114 n: 'z2',
13115 int: true,
13116 l: true,
13117 syntax: PropertySyntax.COORDINATE,
13118 },
13119 // Path
13120 {
13121 n: 'path',
13122 int: true,
13123 l: true,
13124 d: '',
13125 a: ['d'],
13126 syntax: PropertySyntax.PATH,
13127 p: 50,
13128 },
13129 // Polyline & Polygon
13130 {
13131 n: 'points',
13132 /**
13133 * support interpolation
13134 */
13135 int: true,
13136 l: true,
13137 syntax: PropertySyntax.LIST_OF_POINTS,
13138 p: 50,
13139 },
13140 // Text
13141 {
13142 n: 'text',
13143 l: true,
13144 d: '',
13145 syntax: PropertySyntax.TEXT,
13146 p: 50,
13147 },
13148 {
13149 n: 'textTransform',
13150 l: true,
13151 inh: true,
13152 k: ['capitalize', 'uppercase', 'lowercase', 'none'],
13153 d: 'none',
13154 syntax: PropertySyntax.TEXT_TRANSFORM,
13155 p: 51, // it must get parsed after text
13156 },
13157 {
13158 n: 'font',
13159 l: true,
13160 },
13161 {
13162 n: 'fontSize',
13163 int: true,
13164 inh: true,
13165 /**
13166 * @see https://www.w3schools.com/css/css_font_size.asp
13167 */
13168 d: '16px',
13169 l: true,
13170 syntax: PropertySyntax.LENGTH_PERCENTAGE,
13171 },
13172 {
13173 n: 'fontFamily',
13174 l: true,
13175 inh: true,
13176 d: 'sans-serif',
13177 },
13178 {
13179 n: 'fontStyle',
13180 l: true,
13181 inh: true,
13182 k: ['normal', 'italic', 'oblique'],
13183 d: 'normal',
13184 },
13185 {
13186 n: 'fontWeight',
13187 l: true,
13188 inh: true,
13189 k: ['normal', 'bold', 'bolder', 'lighter'],
13190 d: 'normal',
13191 },
13192 {
13193 n: 'fontVariant',
13194 l: true,
13195 inh: true,
13196 k: ['normal', 'small-caps'],
13197 d: 'normal',
13198 },
13199 {
13200 n: 'lineHeight',
13201 l: true,
13202 syntax: PropertySyntax.LENGTH,
13203 int: true,
13204 d: '0',
13205 },
13206 {
13207 n: 'letterSpacing',
13208 l: true,
13209 syntax: PropertySyntax.LENGTH,
13210 int: true,
13211 d: '0',
13212 },
13213 {
13214 n: 'miterLimit',
13215 l: true,
13216 syntax: PropertySyntax.NUMBER,
13217 d: function (nodeName) {
13218 if (nodeName === Shape.PATH ||
13219 nodeName === Shape.POLYGON ||
13220 nodeName === Shape.POLYLINE) {
13221 return '4';
13222 }
13223 return '10';
13224 },
13225 },
13226 {
13227 n: 'wordWrap',
13228 l: true,
13229 },
13230 {
13231 n: 'wordWrapWidth',
13232 l: true,
13233 },
13234 {
13235 n: 'maxLines',
13236 l: true,
13237 },
13238 {
13239 n: 'textOverflow',
13240 l: true,
13241 d: 'clip',
13242 },
13243 {
13244 n: 'leading',
13245 l: true,
13246 },
13247 {
13248 n: 'textBaseline',
13249 l: true,
13250 inh: true,
13251 k: ['top', 'hanging', 'middle', 'alphabetic', 'ideographic', 'bottom'],
13252 d: 'alphabetic',
13253 },
13254 {
13255 n: 'textAlign',
13256 l: true,
13257 inh: true,
13258 k: ['start', 'center', 'middle', 'end', 'left', 'right'],
13259 d: 'start',
13260 },
13261 // {
13262 // n: 'whiteSpace',
13263 // l: true,
13264 // },
13265 {
13266 n: 'markerStart',
13267 syntax: PropertySyntax.MARKER,
13268 },
13269 {
13270 n: 'markerEnd',
13271 syntax: PropertySyntax.MARKER,
13272 },
13273 {
13274 n: 'markerMid',
13275 syntax: PropertySyntax.MARKER,
13276 },
13277 {
13278 n: 'markerStartOffset',
13279 syntax: PropertySyntax.LENGTH,
13280 l: true,
13281 int: true,
13282 d: '0',
13283 },
13284 {
13285 n: 'markerEndOffset',
13286 syntax: PropertySyntax.LENGTH,
13287 l: true,
13288 int: true,
13289 d: '0',
13290 },
13291 ];
13292 var GEOMETRY_ATTRIBUTE_NAMES = BUILT_IN_PROPERTIES.filter(function (n) { return !!n.l; }).map(function (n) { return n.n; });
13293 var propertyMetadataCache = {};
13294 var unresolvedProperties = new WeakMap();
13295 // const uniqueAttributeSet = new Set<string>();
13296 // const tmpVec3a = vec3.create();
13297 // const tmpVec3b = vec3.create();
13298 // const tmpVec3c = vec3.create();
13299 var isPropertyResolved = function (object, name) {
13300 var properties = unresolvedProperties.get(object);
13301 if (!properties || properties.length === 0) {
13302 return true;
13303 }
13304 return properties.includes(name);
13305 };
13306 var DefaultStyleValueRegistry = /** @class */ (function () {
13307 /**
13308 * need recalc later
13309 */
13310 // dirty = false;
13311 function DefaultStyleValueRegistry(runtime) {
13312 var _this = this;
13313 this.runtime = runtime;
13314 BUILT_IN_PROPERTIES.forEach(function (property) {
13315 _this.registerMetadata(property);
13316 });
13317 }
13318 DefaultStyleValueRegistry.prototype.registerMetadata = function (metadata) {
13319 __spreadArray([metadata.n], __read((metadata.a || [])), false).forEach(function (name) {
13320 propertyMetadataCache[name] = metadata;
13321 });
13322 };
13323 DefaultStyleValueRegistry.prototype.unregisterMetadata = function (name) {
13324 delete propertyMetadataCache[name];
13325 };
13326 DefaultStyleValueRegistry.prototype.getPropertySyntax = function (syntax) {
13327 return this.runtime.CSSPropertySyntaxFactory[syntax];
13328 };
13329 /**
13330 * * parse value, eg.
13331 * fill: 'red' => CSSRGB
13332 * translateX: '10px' => CSSUnitValue { unit: 'px', value: 10 }
13333 * fontSize: '2em' => { unit: 'px', value: 32 }
13334 *
13335 * * calculate used value
13336 * * post process
13337 */
13338 DefaultStyleValueRegistry.prototype.processProperties = function (object, attributes, options) {
13339 var _this = this;
13340 if (options === void 0) { options = {
13341 skipUpdateAttribute: false,
13342 skipParse: false,
13343 forceUpdateGeometry: false,
13344 usedAttributes: [],
13345 }; }
13346 if (!this.runtime.enableCSSParsing) {
13347 Object.assign(object.attributes, attributes);
13348 var attributeNames_1 = Object.keys(attributes);
13349 // clipPath
13350 var oldClipPath = object.parsedStyle.clipPath;
13351 var oldOffsetPath = object.parsedStyle.offsetPath;
13352 object.parsedStyle = Object.assign(object.parsedStyle, attributes);
13353 var needUpdateGeometry_1 = !!options.forceUpdateGeometry;
13354 if (!needUpdateGeometry_1) {
13355 for (var i = 0; i < GEOMETRY_ATTRIBUTE_NAMES.length; i++) {
13356 if (GEOMETRY_ATTRIBUTE_NAMES[i] in attributes) {
13357 needUpdateGeometry_1 = true;
13358 break;
13359 }
13360 }
13361 }
13362 if (attributes.fill) {
13363 object.parsedStyle.fill = parseColor(attributes.fill);
13364 }
13365 if (attributes.stroke) {
13366 object.parsedStyle.stroke = parseColor(attributes.stroke);
13367 }
13368 if (attributes.shadowColor) {
13369 object.parsedStyle.shadowColor = parseColor(attributes.shadowColor);
13370 }
13371 if (attributes.filter) {
13372 object.parsedStyle.filter = parseFilter(attributes.filter);
13373 }
13374 // Rect
13375 // @ts-ignore
13376 if (!isNil(attributes.radius)) {
13377 // @ts-ignore
13378 object.parsedStyle.radius = parseDimensionArrayFormat(
13379 // @ts-ignore
13380 attributes.radius, 4);
13381 }
13382 // Polyline
13383 if (!isNil(attributes.lineDash)) {
13384 object.parsedStyle.lineDash = parseDimensionArrayFormat(attributes.lineDash, 2);
13385 }
13386 // @ts-ignore
13387 if (attributes.points) {
13388 // @ts-ignore
13389 object.parsedStyle.points = parsePoints(attributes.points, object);
13390 }
13391 // Path
13392 // @ts-ignore
13393 if (attributes.path === '') {
13394 object.parsedStyle.path = __assign({}, EMPTY_PARSED_PATH);
13395 }
13396 // @ts-ignore
13397 if (attributes.path) {
13398 object.parsedStyle.path = parsePath(
13399 // @ts-ignore
13400 attributes.path);
13401 object.parsedStyle.defX = object.parsedStyle.path.rect.x;
13402 object.parsedStyle.defY = object.parsedStyle.path.rect.y;
13403 }
13404 // Text
13405 if (attributes.textTransform) {
13406 this.runtime.CSSPropertySyntaxFactory['<text-transform>'].calculator(null, null, { value: attributes.textTransform }, object, null);
13407 }
13408 if (attributes.clipPath) {
13409 this.runtime.CSSPropertySyntaxFactory['<defined-path>'].calculator('clipPath', oldClipPath, attributes.clipPath, object, this.runtime);
13410 }
13411 if (attributes.offsetPath) {
13412 this.runtime.CSSPropertySyntaxFactory['<defined-path>'].calculator('offsetPath', oldOffsetPath, attributes.offsetPath, object, this.runtime);
13413 }
13414 if (attributes.anchor) {
13415 object.parsedStyle.anchor = parseDimensionArrayFormat(
13416 // @ts-ignorex
13417 attributes.anchor, 2);
13418 }
13419 if (attributes.transform) {
13420 object.parsedStyle.transform = parseTransform(attributes.transform);
13421 }
13422 if (attributes.transformOrigin) {
13423 object.parsedStyle.transformOrigin = parseTransformOrigin(attributes.transformOrigin);
13424 }
13425 // Marker
13426 // @ts-ignore
13427 if (attributes.markerStart) {
13428 object.parsedStyle.markerStart = this.runtime.CSSPropertySyntaxFactory['<marker>'].calculator(null,
13429 // @ts-ignore
13430 attributes.markerStart,
13431 // @ts-ignore
13432 attributes.markerStart, null, null);
13433 }
13434 // @ts-ignore
13435 if (attributes.markerEnd) {
13436 object.parsedStyle.markerEnd = this.runtime.CSSPropertySyntaxFactory['<marker>'].calculator(null,
13437 // @ts-ignore
13438 attributes.markerEnd,
13439 // @ts-ignore
13440 attributes.markerEnd, null, null);
13441 }
13442 // @ts-ignore
13443 if (attributes.markerMid) {
13444 object.parsedStyle.markerMid = this.runtime.CSSPropertySyntaxFactory['<marker>'].calculator('',
13445 // @ts-ignore
13446 attributes.markerMid,
13447 // @ts-ignore
13448 attributes.markerMid, null, null);
13449 }
13450 if (
13451 // Circle & Ellipse
13452 ((object.nodeName === Shape.CIRCLE ||
13453 object.nodeName === Shape.ELLIPSE) &&
13454 // @ts-ignore
13455 (!isNil(attributes.cx) ||
13456 // @ts-ignore
13457 !isNil(attributes.cy))) ||
13458 ((object.nodeName === Shape.RECT ||
13459 object.nodeName === Shape.IMAGE ||
13460 object.nodeName === Shape.GROUP ||
13461 object.nodeName === Shape.HTML ||
13462 object.nodeName === Shape.TEXT ||
13463 object.nodeName === Shape.MESH) &&
13464 // @ts-ignore
13465 (!isNil(attributes.x) ||
13466 // @ts-ignore
13467 !isNil(attributes.y) ||
13468 // @ts-ignore
13469 !isNil(attributes.z))) ||
13470 // Line
13471 (object.nodeName === Shape.LINE &&
13472 // @ts-ignore
13473 (!isNil(attributes.x1) ||
13474 // @ts-ignore
13475 !isNil(attributes.y1) ||
13476 // @ts-ignore
13477 !isNil(attributes.z1) ||
13478 // @ts-ignore
13479 !isNil(attributes.x2) ||
13480 // @ts-ignore
13481 !isNil(attributes.y2) ||
13482 // @ts-ignore
13483 !isNil(attributes.z2)))) {
13484 this.runtime.CSSPropertySyntaxFactory['<coordinate>'].postProcessor(object, attributeNames_1);
13485 }
13486 if (!isNil(attributes.zIndex)) {
13487 this.runtime.CSSPropertySyntaxFactory['<z-index>'].postProcessor(object, attributeNames_1);
13488 }
13489 // @ts-ignore
13490 if (attributes.path) {
13491 this.runtime.CSSPropertySyntaxFactory['<path>'].postProcessor(object, attributeNames_1);
13492 }
13493 // @ts-ignore
13494 if (attributes.points) {
13495 this.runtime.CSSPropertySyntaxFactory['<list-of-points>'].postProcessor(object, attributeNames_1);
13496 }
13497 if (!isNil(attributes.offsetDistance)) {
13498 this.runtime.CSSPropertySyntaxFactory['<offset-distance>'].postProcessor(object, attributeNames_1);
13499 }
13500 if (attributes.transform) {
13501 this.runtime.CSSPropertySyntaxFactory['<transform>'].postProcessor(object, attributeNames_1);
13502 }
13503 if (needUpdateGeometry_1) {
13504 this.updateGeometry(object);
13505 }
13506 return;
13507 }
13508 var skipUpdateAttribute = options.skipUpdateAttribute, skipParse = options.skipParse, forceUpdateGeometry = options.forceUpdateGeometry, usedAttributes = options.usedAttributes;
13509 var needUpdateGeometry = forceUpdateGeometry;
13510 var attributeNames = Object.keys(attributes);
13511 attributeNames.forEach(function (attributeName) {
13512 var _a;
13513 if (!skipUpdateAttribute) {
13514 object.attributes[attributeName] = attributes[attributeName];
13515 }
13516 if (!needUpdateGeometry && ((_a = propertyMetadataCache[attributeName]) === null || _a === void 0 ? void 0 : _a.l)) {
13517 needUpdateGeometry = true;
13518 }
13519 });
13520 if (!skipParse) {
13521 attributeNames.forEach(function (name) {
13522 object.computedStyle[name] = _this.parseProperty(name, object.attributes[name], object);
13523 });
13524 }
13525 // let hasUnresolvedProperties = false;
13526 // parse according to priority
13527 // path 50
13528 // points 50
13529 // text 50
13530 // textTransform 51
13531 // anchor 99
13532 // transform 100
13533 // transformOrigin 100
13534 if (usedAttributes === null || usedAttributes === void 0 ? void 0 : usedAttributes.length) {
13535 // uniqueAttributeSet.clear();
13536 attributeNames = Array.from(new Set(attributeNames.concat(usedAttributes)));
13537 }
13538 // [
13539 // 'path',
13540 // 'points',
13541 // 'text',
13542 // 'textTransform',
13543 // 'anchor',
13544 // 'transform',
13545 // 'transformOrigin',
13546 // ].forEach((name) => {
13547 // const index = attributeNames.indexOf(name);
13548 // if (index > -1) {
13549 // attributeNames.splice(index, 1);
13550 // attributeNames.push(name);
13551 // }
13552 // });
13553 attributeNames.forEach(function (name) {
13554 // some style props maybe deleted after parsing such as `anchor` in Text
13555 if (name in object.computedStyle) {
13556 object.parsedStyle[name] = _this.computeProperty(name, object.computedStyle[name], object);
13557 }
13558 });
13559 // if (hasUnresolvedProperties) {
13560 // this.dirty = true;
13561 // return;
13562 // }
13563 // update geometry
13564 if (needUpdateGeometry) {
13565 // object.geometry.dirty = true;
13566 // runtime.sceneGraphService.dirtifyToRoot(object);
13567 this.updateGeometry(object);
13568 }
13569 attributeNames.forEach(function (name) {
13570 if (name in object.parsedStyle) {
13571 _this.postProcessProperty(name, object, attributeNames);
13572 }
13573 });
13574 if (this.runtime.enableCSSParsing && object.children.length) {
13575 attributeNames.forEach(function (name) {
13576 if (name in object.parsedStyle && _this.isPropertyInheritable(name)) {
13577 // update children's inheritable
13578 object.children.forEach(function (child) {
13579 child.internalSetAttribute(name, null, {
13580 skipUpdateAttribute: true,
13581 skipParse: true,
13582 });
13583 });
13584 }
13585 });
13586 }
13587 };
13588 /**
13589 * string -> parsed value
13590 */
13591 DefaultStyleValueRegistry.prototype.parseProperty = function (name, value, object) {
13592 var metadata = propertyMetadataCache[name];
13593 var computed = value;
13594 if (value === '' || isNil(value)) {
13595 value = 'unset';
13596 }
13597 if (value === 'unset' || value === 'initial' || value === 'inherit') {
13598 // computed = new CSSKeywordValue(value);
13599 computed = getOrCreateKeyword(value);
13600 }
13601 else {
13602 if (metadata) {
13603 var keywords = metadata.k, syntax = metadata.syntax;
13604 var handler = syntax && this.getPropertySyntax(syntax);
13605 // use keywords
13606 if (keywords && keywords.indexOf(value) > -1) {
13607 // computed = new CSSKeywordValue(value);
13608 computed = getOrCreateKeyword(value);
13609 }
13610 else if (handler && handler.parser) {
13611 // try to parse it to CSSStyleValue, eg. '10px' -> CSS.px(10)
13612 computed = handler.parser(value, object);
13613 }
13614 }
13615 }
13616 return computed;
13617 };
13618 /**
13619 * computed value -> used value
13620 */
13621 DefaultStyleValueRegistry.prototype.computeProperty = function (name, computed, object) {
13622 var metadata = propertyMetadataCache[name];
13623 var isDocumentElement = object.id === 'g-root';
13624 // let used: CSSStyleValue = computed instanceof CSSStyleValue ? computed.clone() : computed;
13625 var used = computed;
13626 if (metadata) {
13627 var syntax = metadata.syntax, inherited = metadata.inh, defaultValue = metadata.d;
13628 if (computed instanceof CSSKeywordValue) {
13629 var value = computed.value;
13630 /**
13631 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/unset
13632 */
13633 if (value === 'unset') {
13634 if (inherited && !isDocumentElement) {
13635 value = 'inherit';
13636 }
13637 else {
13638 value = 'initial';
13639 }
13640 }
13641 if (value === 'initial') {
13642 // @see https://developer.mozilla.org/en-US/docs/Web/CSS/initial
13643 if (!isNil(defaultValue)) {
13644 computed = this.parseProperty(name, isFunction$1(defaultValue)
13645 ? defaultValue(object.nodeName)
13646 : defaultValue, object);
13647 }
13648 }
13649 else if (value === 'inherit') {
13650 // @see https://developer.mozilla.org/en-US/docs/Web/CSS/inherit
13651 // behave like `inherit`
13652 var resolved = this.tryToResolveProperty(object, name, {
13653 inherited: true,
13654 });
13655 if (!isNil(resolved)) {
13656 // object.parsedStyle[name] = resolved;
13657 // return false;
13658 return resolved;
13659 }
13660 else {
13661 this.addUnresolveProperty(object, name);
13662 return;
13663 }
13664 }
13665 }
13666 var handler = syntax && this.getPropertySyntax(syntax);
13667 if (handler && handler.calculator) {
13668 // convert computed value to used value
13669 var oldParsedValue = object.parsedStyle[name];
13670 used = handler.calculator(name, oldParsedValue, computed, object, this.runtime);
13671 }
13672 else if (computed instanceof CSSKeywordValue) {
13673 used = computed.value;
13674 }
13675 else {
13676 used = computed;
13677 }
13678 }
13679 // object.parsedStyle[name] = used;
13680 // return false;
13681 return used;
13682 };
13683 DefaultStyleValueRegistry.prototype.postProcessProperty = function (name, object, attributes) {
13684 var metadata = propertyMetadataCache[name];
13685 if (metadata && metadata.syntax) {
13686 var handler = metadata.syntax && this.getPropertySyntax(metadata.syntax);
13687 var propertyHandler = handler;
13688 if (propertyHandler && propertyHandler.postProcessor) {
13689 propertyHandler.postProcessor(object, attributes);
13690 }
13691 }
13692 };
13693 /**
13694 * resolve later
13695 */
13696 DefaultStyleValueRegistry.prototype.addUnresolveProperty = function (object, name) {
13697 var properties = unresolvedProperties.get(object);
13698 if (!properties) {
13699 unresolvedProperties.set(object, []);
13700 properties = unresolvedProperties.get(object);
13701 }
13702 if (properties.indexOf(name) === -1) {
13703 properties.push(name);
13704 }
13705 };
13706 DefaultStyleValueRegistry.prototype.tryToResolveProperty = function (object, name, options) {
13707 if (options === void 0) { options = {}; }
13708 var inherited = options.inherited;
13709 if (inherited) {
13710 if (object.parentElement &&
13711 isPropertyResolved(object.parentElement, name)) {
13712 // const computedValue = object.parentElement.computedStyle[name];
13713 var usedValue = object.parentElement.parsedStyle[name];
13714 if (
13715 // usedValue instanceof CSSKeywordValue &&
13716 usedValue === 'unset' ||
13717 usedValue === 'initial' ||
13718 usedValue === 'inherit') {
13719 return;
13720 }
13721 // else if (
13722 // usedValue instanceof CSSUnitValue &&
13723 // CSSUnitValue.isRelativeUnit(usedValue.unit)
13724 // ) {
13725 // return false;
13726 // }
13727 return usedValue;
13728 }
13729 }
13730 return;
13731 };
13732 DefaultStyleValueRegistry.prototype.recalc = function (object) {
13733 var properties = unresolvedProperties.get(object);
13734 if (properties && properties.length) {
13735 var attributes_1 = {};
13736 properties.forEach(function (property) {
13737 attributes_1[property] = object.attributes[property];
13738 });
13739 this.processProperties(object, attributes_1);
13740 unresolvedProperties.delete(object);
13741 }
13742 };
13743 /**
13744 * update geometry when relative props changed,
13745 * eg. r of Circle, width/height of Rect
13746 */
13747 DefaultStyleValueRegistry.prototype.updateGeometry = function (object) {
13748 var nodeName = object.nodeName;
13749 var geometryUpdater = this.runtime.geometryUpdaterFactory[nodeName];
13750 if (geometryUpdater) {
13751 var geometry_1 = object.geometry;
13752 if (!geometry_1.contentBounds) {
13753 geometry_1.contentBounds = new AABB();
13754 }
13755 if (!geometry_1.renderBounds) {
13756 geometry_1.renderBounds = new AABB();
13757 }
13758 var parsedStyle = object.parsedStyle;
13759 var _a = geometryUpdater.update(parsedStyle, object), width = _a.width, height = _a.height, _b = _a.depth, depth = _b === void 0 ? 0 : _b, _c = _a.offsetX, offsetX = _c === void 0 ? 0 : _c, _d = _a.offsetY, offsetY = _d === void 0 ? 0 : _d, _e = _a.offsetZ, offsetZ = _e === void 0 ? 0 : _e;
13760 // init with content box
13761 var halfExtents = [
13762 Math.abs(width) / 2,
13763 Math.abs(height) / 2,
13764 depth / 2,
13765 ];
13766 // const halfExtents = vec3.set(
13767 // tmpVec3a,
13768 // Math.abs(width) / 2,
13769 // Math.abs(height) / 2,
13770 // depth / 2,
13771 // );
13772 // anchor is center by default, don't account for lineWidth here
13773 var _f = parsedStyle, stroke = _f.stroke, lineWidth = _f.lineWidth,
13774 // lineCap,
13775 // lineJoin,
13776 // miterLimit,
13777 increasedLineWidthForHitTesting = _f.increasedLineWidthForHitTesting, shadowType = _f.shadowType, shadowColor = _f.shadowColor, _g = _f.filter, filter = _g === void 0 ? [] : _g, transformOrigin = _f.transformOrigin;
13778 var anchor = parsedStyle.anchor;
13779 // <Text> use textAlign & textBaseline instead of anchor
13780 if (nodeName === Shape.TEXT) {
13781 delete parsedStyle.anchor;
13782 }
13783 else if (nodeName === Shape.MESH) {
13784 parsedStyle.anchor[2] = 0.5;
13785 }
13786 var center = [
13787 ((1 - ((anchor && anchor[0]) || 0) * 2) * width) / 2 + offsetX,
13788 ((1 - ((anchor && anchor[1]) || 0) * 2) * height) / 2 + offsetY,
13789 (1 - ((anchor && anchor[2]) || 0) * 2) * halfExtents[2] + offsetZ,
13790 ];
13791 // const center = vec3.set(
13792 // tmpVec3b,
13793 // ((1 - ((anchor && anchor[0]) || 0) * 2) * width) / 2 + offsetX,
13794 // ((1 - ((anchor && anchor[1]) || 0) * 2) * height) / 2 + offsetY,
13795 // (1 - ((anchor && anchor[2]) || 0) * 2) * halfExtents[2] + offsetZ,
13796 // );
13797 // update geometry's AABB
13798 geometry_1.contentBounds.update(center, halfExtents);
13799 // @see https://github.molgen.mpg.de/git-mirror/cairo/blob/master/src/cairo-stroke-style.c#L97..L128
13800 var expansion = nodeName === Shape.POLYLINE ||
13801 nodeName === Shape.POLYGON ||
13802 nodeName === Shape.PATH
13803 ? Math.SQRT2
13804 : 0.5;
13805 // if (lineCap?.value === 'square') {
13806 // expansion = Math.SQRT1_2;
13807 // }
13808 // if (lineJoin?.value === 'miter' && expansion < Math.SQRT2 * miterLimit) {
13809 // expansion = Math.SQRT1_2 * miterLimit;
13810 // }
13811 // append border only if stroke existed
13812 var hasStroke = stroke && !stroke.isNone;
13813 if (hasStroke) {
13814 var halfLineWidth = ((lineWidth || 0) + (increasedLineWidthForHitTesting || 0)) *
13815 expansion;
13816 // halfExtents[0] += halfLineWidth[0];
13817 // halfExtents[1] += halfLineWidth[1];
13818 halfExtents[0] += halfLineWidth;
13819 halfExtents[1] += halfLineWidth;
13820 // vec3.add(
13821 // halfExtents,
13822 // halfExtents,
13823 // vec3.set(tmpVec3c, halfLineWidth, halfLineWidth, 0),
13824 // );
13825 }
13826 geometry_1.renderBounds.update(center, halfExtents);
13827 // account for shadow, only support constant value now
13828 if (shadowColor && shadowType && shadowType !== 'inner') {
13829 var _h = geometry_1.renderBounds, min = _h.min, max = _h.max;
13830 var _j = parsedStyle, shadowBlur = _j.shadowBlur, shadowOffsetX = _j.shadowOffsetX, shadowOffsetY = _j.shadowOffsetY;
13831 var shadowBlurInPixels = shadowBlur || 0;
13832 var shadowOffsetXInPixels = shadowOffsetX || 0;
13833 var shadowOffsetYInPixels = shadowOffsetY || 0;
13834 var shadowLeft = min[0] - shadowBlurInPixels + shadowOffsetXInPixels;
13835 var shadowRight = max[0] + shadowBlurInPixels + shadowOffsetXInPixels;
13836 var shadowTop = min[1] - shadowBlurInPixels + shadowOffsetYInPixels;
13837 var shadowBottom = max[1] + shadowBlurInPixels + shadowOffsetYInPixels;
13838 min[0] = Math.min(min[0], shadowLeft);
13839 max[0] = Math.max(max[0], shadowRight);
13840 min[1] = Math.min(min[1], shadowTop);
13841 max[1] = Math.max(max[1], shadowBottom);
13842 geometry_1.renderBounds.setMinMax(min, max);
13843 }
13844 // account for filter, eg. blur(5px), drop-shadow()
13845 filter.forEach(function (_a) {
13846 var name = _a.name, params = _a.params;
13847 if (name === 'blur') {
13848 var blurRadius = params[0].value;
13849 geometry_1.renderBounds.update(geometry_1.renderBounds.center, addVec3(geometry_1.renderBounds.halfExtents, geometry_1.renderBounds.halfExtents, [blurRadius, blurRadius, 0]));
13850 }
13851 else if (name === 'drop-shadow') {
13852 var shadowOffsetX = params[0].value;
13853 var shadowOffsetY = params[1].value;
13854 var shadowBlur = params[2].value;
13855 var _b = geometry_1.renderBounds, min = _b.min, max = _b.max;
13856 var shadowLeft = min[0] - shadowBlur + shadowOffsetX;
13857 var shadowRight = max[0] + shadowBlur + shadowOffsetX;
13858 var shadowTop = min[1] - shadowBlur + shadowOffsetY;
13859 var shadowBottom = max[1] + shadowBlur + shadowOffsetY;
13860 min[0] = Math.min(min[0], shadowLeft);
13861 max[0] = Math.max(max[0], shadowRight);
13862 min[1] = Math.min(min[1], shadowTop);
13863 max[1] = Math.max(max[1], shadowBottom);
13864 geometry_1.renderBounds.setMinMax(min, max);
13865 }
13866 });
13867 anchor = parsedStyle.anchor;
13868 // if (nodeName === Shape.RECT) {
13869 // account for negative width / height of Rect
13870 // @see https://github.com/antvis/g/issues/957
13871 var flipY = width < 0;
13872 var flipX = height < 0;
13873 // } else {
13874 // }
13875 // set transform origin
13876 var usedOriginXValue = (flipY ? -1 : 1) *
13877 (transformOrigin
13878 ? convertPercentUnit(transformOrigin[0], 0, object)
13879 : 0);
13880 var usedOriginYValue = (flipX ? -1 : 1) *
13881 (transformOrigin
13882 ? convertPercentUnit(transformOrigin[1], 1, object)
13883 : 0);
13884 usedOriginXValue =
13885 usedOriginXValue -
13886 (flipY ? -1 : 1) *
13887 ((anchor && anchor[0]) || 0) *
13888 geometry_1.contentBounds.halfExtents[0] *
13889 2;
13890 usedOriginYValue =
13891 usedOriginYValue -
13892 (flipX ? -1 : 1) *
13893 ((anchor && anchor[1]) || 0) *
13894 geometry_1.contentBounds.halfExtents[1] *
13895 2;
13896 object.setOrigin(usedOriginXValue, usedOriginYValue);
13897 // FIXME setOrigin may have already dirtified to root.
13898 this.runtime.sceneGraphService.dirtifyToRoot(object);
13899 }
13900 };
13901 DefaultStyleValueRegistry.prototype.isPropertyInheritable = function (name) {
13902 var metadata = propertyMetadataCache[name];
13903 if (!metadata) {
13904 return false;
13905 }
13906 return metadata.inh;
13907 };
13908 return DefaultStyleValueRegistry;
13909 }());
13910
13911 var CSSPropertyAngle = /** @class */ (function () {
13912 function CSSPropertyAngle() {
13913 this.parser = parseAngle;
13914 this.parserWithCSSDisabled = null;
13915 this.mixer = mergeNumbers;
13916 }
13917 CSSPropertyAngle.prototype.calculator = function (name, oldParsed, parsed, object) {
13918 return convertAngleUnit(parsed);
13919 };
13920 return CSSPropertyAngle;
13921 }());
13922
13923 /**
13924 * clipPath / textPath / offsetPath
13925 */
13926 var CSSPropertyClipPath = /** @class */ (function () {
13927 function CSSPropertyClipPath() {
13928 }
13929 CSSPropertyClipPath.prototype.calculator = function (name, oldPath, newPath, object, runtime) {
13930 // unset
13931 if (newPath instanceof CSSKeywordValue) {
13932 newPath = null;
13933 }
13934 runtime.sceneGraphService.updateDisplayObjectDependency(name, oldPath, newPath, object);
13935 if (name === 'clipPath') {
13936 // should affect children
13937 object.forEach(function (leaf) {
13938 if (leaf.childNodes.length === 0) {
13939 runtime.sceneGraphService.dirtifyToRoot(leaf);
13940 }
13941 });
13942 }
13943 return newPath;
13944 };
13945 return CSSPropertyClipPath;
13946 }());
13947
13948 var CSSPropertyColor = /** @class */ (function () {
13949 function CSSPropertyColor() {
13950 this.parser = parseColor;
13951 this.parserWithCSSDisabled = parseColor;
13952 this.mixer = mergeColors;
13953 }
13954 CSSPropertyColor.prototype.calculator = function (name, oldParsed, parsed, object) {
13955 if (parsed instanceof CSSKeywordValue) {
13956 // 'unset' 'none'
13957 return parsed.value === 'none' ? noneColor : transparentColor;
13958 }
13959 return parsed;
13960 };
13961 return CSSPropertyColor;
13962 }());
13963
13964 var CSSPropertyFilter = /** @class */ (function () {
13965 function CSSPropertyFilter() {
13966 this.parser = parseFilter;
13967 }
13968 CSSPropertyFilter.prototype.calculator = function (name, oldParsed, parsed) {
13969 // unset or none
13970 if (parsed instanceof CSSKeywordValue) {
13971 return [];
13972 }
13973 return parsed;
13974 };
13975 return CSSPropertyFilter;
13976 }());
13977
13978 function getFontSize(object) {
13979 var fontSize = object.parsedStyle.fontSize;
13980 return isNil(fontSize) ? null : fontSize;
13981 }
13982 /**
13983 * <length> & <percentage>
13984 */
13985 var CSSPropertyLengthOrPercentage = /** @class */ (function () {
13986 function CSSPropertyLengthOrPercentage() {
13987 this.parser = parseLengthOrPercentage;
13988 this.parserWithCSSDisabled = null;
13989 this.mixer = mergeNumbers;
13990 }
13991 /**
13992 * according to parent's bounds
13993 *
13994 * @example
13995 * CSS.percent(50) -> CSS.px(0.5 * parent.width)
13996 */
13997 CSSPropertyLengthOrPercentage.prototype.calculator = function (name, oldParsed, computed, object, runtime) {
13998 var _a;
13999 if (isNumber(computed)) {
14000 return computed;
14001 }
14002 if (CSSUnitValue.isRelativeUnit(computed.unit)) {
14003 var registry = runtime.styleValueRegistry;
14004 if (computed.unit === UnitType.kPercentage) {
14005 // TODO: merge dimensions
14006 return 0;
14007 }
14008 else if (computed.unit === UnitType.kEms) {
14009 if (object.parentNode) {
14010 var fontSize = getFontSize(object.parentNode);
14011 if (fontSize) {
14012 fontSize *= computed.value;
14013 return fontSize;
14014 }
14015 else {
14016 registry.addUnresolveProperty(object, name);
14017 }
14018 }
14019 else {
14020 registry.addUnresolveProperty(object, name);
14021 }
14022 return 0;
14023 }
14024 else if (computed.unit === UnitType.kRems) {
14025 if ((_a = object === null || object === void 0 ? void 0 : object.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) {
14026 var fontSize = getFontSize(object.ownerDocument.documentElement);
14027 if (fontSize) {
14028 fontSize *= computed.value;
14029 return fontSize;
14030 }
14031 else {
14032 registry.addUnresolveProperty(object, name);
14033 }
14034 }
14035 else {
14036 registry.addUnresolveProperty(object, name);
14037 }
14038 return 0;
14039 }
14040 }
14041 else {
14042 // remove listener if exists
14043 // registry.unregisterParentGeometryBoundsChangedHandler(object, name);
14044 // return absolute value
14045 return computed.value;
14046 }
14047 };
14048 return CSSPropertyLengthOrPercentage;
14049 }());
14050
14051 /**
14052 * format to Tuple2<CSSUnitValue>
14053 *
14054 * @example
14055 * rect.style.lineDash = 10;
14056 * rect.style.lineDash = [10, 10];
14057 * rect.style.lineDash = '10 10';
14058 */
14059 var CSSPropertyLengthOrPercentage12 = /** @class */ (function () {
14060 function CSSPropertyLengthOrPercentage12() {
14061 this.mixer = mergeNumberLists;
14062 }
14063 CSSPropertyLengthOrPercentage12.prototype.parser = function (radius) {
14064 var parsed = parseDimensionArray(isNumber(radius) ? [radius] : radius);
14065 var formatted;
14066 if (parsed.length === 1) {
14067 formatted = [parsed[0], parsed[0]];
14068 }
14069 else {
14070 formatted = [parsed[0], parsed[1]];
14071 }
14072 return formatted;
14073 };
14074 CSSPropertyLengthOrPercentage12.prototype.calculator = function (name, oldParsed, computed) {
14075 return computed.map(function (c) { return c.value; });
14076 };
14077 return CSSPropertyLengthOrPercentage12;
14078 }());
14079
14080 /**
14081 * used in rounded rect
14082 *
14083 * @example
14084 * rect.style.radius = 10;
14085 * rect.style.radius = '10 10';
14086 * rect.style.radius = '10 10 10 10';
14087 */
14088 var CSSPropertyLengthOrPercentage14 = /** @class */ (function () {
14089 function CSSPropertyLengthOrPercentage14() {
14090 this.mixer = mergeNumberLists;
14091 }
14092 CSSPropertyLengthOrPercentage14.prototype.parser = function (radius) {
14093 var parsed = parseDimensionArray(isNumber(radius) ? [radius] : radius);
14094 var formatted;
14095 // format to Tuple<CSSUnitValue>
14096 if (parsed.length === 1) {
14097 formatted = [parsed[0], parsed[0], parsed[0], parsed[0]];
14098 }
14099 else if (parsed.length === 2) {
14100 formatted = [parsed[0], parsed[1], parsed[0], parsed[1]];
14101 }
14102 else if (parsed.length === 3) {
14103 formatted = [parsed[0], parsed[1], parsed[2], parsed[1]];
14104 }
14105 else {
14106 formatted = [parsed[0], parsed[1], parsed[2], parsed[3]];
14107 }
14108 return formatted;
14109 };
14110 CSSPropertyLengthOrPercentage14.prototype.calculator = function (name, oldParsed, computed) {
14111 return computed.map(function (c) { return c.value; });
14112 };
14113 return CSSPropertyLengthOrPercentage14;
14114 }());
14115
14116 var tmpMat4 = create$1();
14117 function parsedTransformToMat4(transform, object) {
14118 var defX = object.parsedStyle.defX || 0;
14119 var defY = object.parsedStyle.defY || 0;
14120 // reset transform
14121 object.resetLocalTransform();
14122 object.setLocalPosition(defX, defY);
14123 transform.forEach(function (parsed) {
14124 var t = parsed.t, d = parsed.d;
14125 if (t === 'scale') {
14126 // scale(1) scale(1, 1)
14127 var newScale = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [1, 1];
14128 object.scaleLocal(newScale[0], newScale[1], 1);
14129 }
14130 else if (t === 'scalex') {
14131 var newScale = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [1];
14132 object.scaleLocal(newScale[0], 1, 1);
14133 }
14134 else if (t === 'scaley') {
14135 var newScale = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [1];
14136 object.scaleLocal(1, newScale[0], 1);
14137 }
14138 else if (t === 'scalez') {
14139 var newScale = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [1];
14140 object.scaleLocal(1, 1, newScale[0]);
14141 }
14142 else if (t === 'scale3d') {
14143 var newScale = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [1, 1, 1];
14144 object.scaleLocal(newScale[0], newScale[1], newScale[2]);
14145 }
14146 else if (t === 'translate') {
14147 var newTranslation = d || [Opx, Opx];
14148 object.translateLocal(newTranslation[0].value, newTranslation[1].value, 0);
14149 }
14150 else if (t === 'translatex') {
14151 var newTranslation = d || [Opx];
14152 object.translateLocal(newTranslation[0].value, 0, 0);
14153 }
14154 else if (t === 'translatey') {
14155 var newTranslation = d || [Opx];
14156 object.translateLocal(0, newTranslation[0].value, 0);
14157 }
14158 else if (t === 'translatez') {
14159 var newTranslation = d || [Opx];
14160 object.translateLocal(0, 0, newTranslation[0].value);
14161 }
14162 else if (t === 'translate3d') {
14163 var newTranslation = d || [Opx, Opx, Opx];
14164 object.translateLocal(newTranslation[0].value, newTranslation[1].value, newTranslation[2].value);
14165 }
14166 else if (t === 'rotate') {
14167 var newAngles = d || [Odeg];
14168 object.rotateLocal(0, 0, convertAngleUnit(newAngles[0]));
14169 }
14170 else if (t === 'rotatex') {
14171 var newAngles = d || [Odeg];
14172 object.rotateLocal(convertAngleUnit(newAngles[0]), 0, 0);
14173 }
14174 else if (t === 'rotatey') {
14175 var newAngles = d || [Odeg];
14176 object.rotateLocal(0, convertAngleUnit(newAngles[0]), 0);
14177 }
14178 else if (t === 'rotatez') {
14179 var newAngles = d || [Odeg];
14180 object.rotateLocal(0, 0, convertAngleUnit(newAngles[0]));
14181 }
14182 else if (t === 'rotate3d') ;
14183 else if (t === 'skew') {
14184 var newSkew = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [0, 0];
14185 object.setLocalSkew(deg2rad(newSkew[0]), deg2rad(newSkew[1]));
14186 }
14187 else if (t === 'skewx') {
14188 var newSkew = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [0];
14189 object.setLocalSkew(deg2rad(newSkew[0]), object.getLocalSkew()[1]);
14190 }
14191 else if (t === 'skewy') {
14192 var newSkew = (d === null || d === void 0 ? void 0 : d.map(function (s) { return s.value; })) || [0];
14193 object.setLocalSkew(object.getLocalSkew()[0], deg2rad(newSkew[0]));
14194 }
14195 else if (t === 'matrix') {
14196 var _a = __read(d.map(function (s) { return s.value; }), 6), a = _a[0], b = _a[1], c = _a[2], dd = _a[3], tx = _a[4], ty = _a[5];
14197 object.setLocalTransform(set(tmpMat4, a, b, 0, 0, c, dd, 0, 0, 0, 0, 1, 0, tx + defX, ty + defY, 0, 1));
14198 }
14199 else if (t === 'matrix3d') {
14200 // @ts-ignore
14201 set.apply(mat4, __spreadArray([tmpMat4], __read(d.map(function (s) { return s.value; })), false));
14202 tmpMat4[12] += defX;
14203 tmpMat4[13] += defY;
14204 object.setLocalTransform(tmpMat4);
14205 }
14206 });
14207 return object.getLocalTransform();
14208 }
14209
14210 /**
14211 * local position
14212 */
14213 var CSSPropertyLocalPosition = /** @class */ (function (_super) {
14214 __extends(CSSPropertyLocalPosition, _super);
14215 function CSSPropertyLocalPosition() {
14216 return _super !== null && _super.apply(this, arguments) || this;
14217 }
14218 /**
14219 * update local position
14220 */
14221 CSSPropertyLocalPosition.prototype.postProcessor = function (object, attributes) {
14222 var x;
14223 var y;
14224 var z;
14225 switch (object.nodeName) {
14226 case Shape.CIRCLE:
14227 case Shape.ELLIPSE:
14228 var _a = object.parsedStyle, cx = _a.cx, cy = _a.cy, cz = _a.cz;
14229 if (!isNil(cx)) {
14230 x = cx;
14231 }
14232 if (!isNil(cy)) {
14233 y = cy;
14234 }
14235 if (!isNil(cz)) {
14236 z = cz;
14237 }
14238 break;
14239 case Shape.LINE:
14240 var _b = object.parsedStyle, x1 = _b.x1, x2 = _b.x2, y1 = _b.y1, y2 = _b.y2;
14241 var minX = Math.min(x1, x2);
14242 var minY = Math.min(y1, y2);
14243 x = minX;
14244 y = minY;
14245 z = 0;
14246 break;
14247 case Shape.RECT:
14248 case Shape.IMAGE:
14249 case Shape.GROUP:
14250 case Shape.HTML:
14251 case Shape.TEXT:
14252 case Shape.MESH:
14253 if (!isNil(object.parsedStyle.x)) {
14254 x = object.parsedStyle.x;
14255 }
14256 if (!isNil(object.parsedStyle.y)) {
14257 y = object.parsedStyle.y;
14258 }
14259 if (!isNil(object.parsedStyle.z)) {
14260 z = object.parsedStyle.z;
14261 }
14262 break;
14263 }
14264 if (object.nodeName !== Shape.PATH &&
14265 object.nodeName !== Shape.POLYLINE &&
14266 object.nodeName !== Shape.POLYGON) {
14267 object.parsedStyle.defX = x || 0;
14268 object.parsedStyle.defY = y || 0;
14269 }
14270 var needResetLocalPosition = !isNil(x) || !isNil(y) || !isNil(z);
14271 // only if `transform` won't be processed later
14272 if (needResetLocalPosition && attributes.indexOf('transform') === -1) {
14273 // account for current transform if needed
14274 var transform = object.parsedStyle.transform;
14275 if (transform && transform.length) {
14276 parsedTransformToMat4(transform, object);
14277 }
14278 else {
14279 var _c = __read(object.getLocalPosition(), 3), ox = _c[0], oy = _c[1], oz = _c[2];
14280 object.setLocalPosition(isNil(x) ? ox : x, isNil(y) ? oy : y, isNil(z) ? oz : z);
14281 }
14282 }
14283 };
14284 return CSSPropertyLocalPosition;
14285 }(CSSPropertyLengthOrPercentage));
14286
14287 var CSSPropertyMarker = /** @class */ (function () {
14288 function CSSPropertyMarker() {
14289 }
14290 CSSPropertyMarker.prototype.calculator = function (name, oldMarker, newMarker, object) {
14291 // unset
14292 if (newMarker instanceof CSSKeywordValue) {
14293 newMarker = null;
14294 }
14295 var cloned = newMarker === null || newMarker === void 0 ? void 0 : newMarker.cloneNode(true);
14296 if (cloned) {
14297 // FIXME: SVG should not inherit parent's style, add a flag here
14298 cloned.style.isMarker = true;
14299 }
14300 return cloned;
14301 };
14302 return CSSPropertyMarker;
14303 }());
14304
14305 var CSSPropertyNumber = /** @class */ (function () {
14306 function CSSPropertyNumber() {
14307 this.mixer = mergeNumbers;
14308 this.parser = parseNumber;
14309 this.parserWithCSSDisabled = null;
14310 }
14311 CSSPropertyNumber.prototype.calculator = function (name, oldParsed, computed) {
14312 return computed.value;
14313 };
14314 return CSSPropertyNumber;
14315 }());
14316
14317 var CSSPropertyOffsetDistance = /** @class */ (function () {
14318 function CSSPropertyOffsetDistance() {
14319 this.parser = parseNumber;
14320 this.parserWithCSSDisabled = null;
14321 this.mixer = clampedMergeNumbers(0, 1);
14322 }
14323 CSSPropertyOffsetDistance.prototype.calculator = function (name, oldParsed, computed) {
14324 return computed.value;
14325 };
14326 CSSPropertyOffsetDistance.prototype.postProcessor = function (object) {
14327 var _a = object.parsedStyle, offsetPath = _a.offsetPath, offsetDistance = _a.offsetDistance;
14328 if (!offsetPath) {
14329 return;
14330 }
14331 var nodeName = offsetPath.nodeName;
14332 if (nodeName === Shape.LINE ||
14333 nodeName === Shape.PATH ||
14334 nodeName === Shape.POLYLINE) {
14335 // set position in world space
14336 var point = offsetPath.getPoint(offsetDistance);
14337 if (point) {
14338 object.parsedStyle.defX = point.x;
14339 object.parsedStyle.defY = point.y;
14340 object.setLocalPosition(point.x, point.y);
14341 }
14342 }
14343 };
14344 return CSSPropertyOffsetDistance;
14345 }());
14346
14347 /**
14348 * opacity
14349 */
14350 var CSSPropertyOpacity = /** @class */ (function () {
14351 function CSSPropertyOpacity() {
14352 this.parser = parseNumber;
14353 this.parserWithCSSDisabled = null;
14354 this.mixer = clampedMergeNumbers(0, 1);
14355 }
14356 CSSPropertyOpacity.prototype.calculator = function (name, oldParsed, computed) {
14357 return computed.value;
14358 };
14359 return CSSPropertyOpacity;
14360 }());
14361
14362 var CSSPropertyPath = /** @class */ (function () {
14363 function CSSPropertyPath() {
14364 /**
14365 * path2Curve
14366 */
14367 this.parser = parsePath;
14368 this.parserWithCSSDisabled = parsePath;
14369 this.mixer = mergePaths;
14370 }
14371 CSSPropertyPath.prototype.calculator = function (name, oldParsed, parsed) {
14372 // unset
14373 if (parsed instanceof CSSKeywordValue && parsed.value === 'unset') {
14374 return {
14375 absolutePath: [],
14376 hasArc: false,
14377 segments: [],
14378 polygons: [],
14379 polylines: [],
14380 curve: null,
14381 totalLength: 0,
14382 rect: new Rectangle(0, 0, 0, 0),
14383 };
14384 }
14385 return parsed;
14386 };
14387 /**
14388 * update local position
14389 */
14390 CSSPropertyPath.prototype.postProcessor = function (object, attributes) {
14391 object.parsedStyle.defX = object.parsedStyle.path.rect.x;
14392 object.parsedStyle.defY = object.parsedStyle.path.rect.y;
14393 if (object.nodeName === Shape.PATH &&
14394 attributes.indexOf('transform') === -1) {
14395 var _a = object.parsedStyle, _b = _a.defX, defX = _b === void 0 ? 0 : _b, _c = _a.defY, defY = _c === void 0 ? 0 : _c;
14396 object.setLocalPosition(defX, defY);
14397 }
14398 };
14399 return CSSPropertyPath;
14400 }());
14401
14402 var CSSPropertyPoints = /** @class */ (function () {
14403 function CSSPropertyPoints() {
14404 this.parser = parsePoints;
14405 this.mixer = mergePoints;
14406 }
14407 /**
14408 * update local position
14409 */
14410 CSSPropertyPoints.prototype.postProcessor = function (object, attributes) {
14411 if ((object.nodeName === Shape.POLYGON ||
14412 object.nodeName === Shape.POLYLINE) &&
14413 attributes.indexOf('transform') === -1) {
14414 var _a = object.parsedStyle, defX = _a.defX, defY = _a.defY;
14415 object.setLocalPosition(defX, defY);
14416 }
14417 };
14418 return CSSPropertyPoints;
14419 }());
14420
14421 var CSSPropertyShadowBlur = /** @class */ (function (_super) {
14422 __extends(CSSPropertyShadowBlur, _super);
14423 function CSSPropertyShadowBlur() {
14424 var _this = _super !== null && _super.apply(this, arguments) || this;
14425 _this.mixer = clampedMergeNumbers(0, Infinity);
14426 return _this;
14427 }
14428 return CSSPropertyShadowBlur;
14429 }(CSSPropertyLengthOrPercentage));
14430
14431 var CSSPropertyText = /** @class */ (function () {
14432 function CSSPropertyText() {
14433 }
14434 CSSPropertyText.prototype.calculator = function (name, oldParsed, parsed, object) {
14435 if (parsed instanceof CSSKeywordValue) {
14436 if (parsed.value === 'unset') {
14437 return '';
14438 }
14439 else {
14440 return parsed.value;
14441 }
14442 }
14443 // allow number as valid text content
14444 return "".concat(parsed);
14445 };
14446 CSSPropertyText.prototype.postProcessor = function (object) {
14447 object.nodeValue = "".concat(object.parsedStyle.text) || '';
14448 };
14449 return CSSPropertyText;
14450 }());
14451
14452 /**
14453 * it must transform after text get parsed
14454 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-transform
14455 */
14456 var CSSPropertyTextTransform = /** @class */ (function () {
14457 function CSSPropertyTextTransform() {
14458 }
14459 CSSPropertyTextTransform.prototype.calculator = function (name, oldParsed, parsed, object) {
14460 var rawText = object.getAttribute('text');
14461 if (rawText) {
14462 var transformedText = rawText;
14463 if (parsed.value === 'capitalize') {
14464 transformedText = rawText.charAt(0).toUpperCase() + rawText.slice(1);
14465 }
14466 else if (parsed.value === 'lowercase') {
14467 transformedText = rawText.toLowerCase();
14468 }
14469 else if (parsed.value === 'uppercase') {
14470 transformedText = rawText.toUpperCase();
14471 }
14472 object.parsedStyle.text = transformedText;
14473 }
14474 return parsed.value;
14475 };
14476 return CSSPropertyTextTransform;
14477 }());
14478
14479 var canvasMap = {};
14480 var defaultCanvasIdCounter = 0;
14481 /**
14482 * destroy existed canvas with the same id
14483 */
14484 function cleanExistedCanvas(container, canvas) {
14485 if (container) {
14486 var id = typeof container === 'string'
14487 ? container
14488 : container.id || defaultCanvasIdCounter++;
14489 if (canvasMap[id]) {
14490 canvasMap[id].destroy();
14491 }
14492 canvasMap[id] = canvas;
14493 }
14494 }
14495 var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
14496
14497 function isElement(target) {
14498 return !!target.getAttribute;
14499 }
14500 function sortedIndex(array, value) {
14501 var low = 0;
14502 var high = array.length;
14503 while (low < high) {
14504 var mid = (low + high) >>> 1;
14505 if (sortByZIndex(array[mid], value) < 0) {
14506 low = mid + 1;
14507 }
14508 else {
14509 high = mid;
14510 }
14511 }
14512 return low;
14513 }
14514 function sortByZIndex(o1, o2) {
14515 var zIndex1 = Number(o1.parsedStyle.zIndex);
14516 var zIndex2 = Number(o2.parsedStyle.zIndex);
14517 if (zIndex1 === zIndex2) {
14518 var parent_1 = o1.parentNode;
14519 if (parent_1) {
14520 var children = parent_1.childNodes || [];
14521 return children.indexOf(o1) - children.indexOf(o2);
14522 }
14523 }
14524 return zIndex1 - zIndex2;
14525 }
14526 function findClosestClipPathTarget(object) {
14527 var _a;
14528 var el = object;
14529 do {
14530 var clipPath = (_a = el.parsedStyle) === null || _a === void 0 ? void 0 : _a.clipPath;
14531 if (clipPath)
14532 return el;
14533 el = el.parentElement;
14534 } while (el !== null);
14535 return null;
14536 }
14537 function getStyle($el, property) {
14538 if (isBrowser) {
14539 return document.defaultView
14540 .getComputedStyle($el, null)
14541 .getPropertyValue(property);
14542 }
14543 }
14544 function getWidth($el) {
14545 var width = getStyle($el, 'width');
14546 if (width === 'auto') {
14547 return $el.offsetWidth;
14548 }
14549 return parseFloat(width);
14550 }
14551 function getHeight($el) {
14552 var height = getStyle($el, 'height');
14553 if (height === 'auto') {
14554 return $el.offsetHeight;
14555 }
14556 return parseFloat(height);
14557 }
14558
14559 // borrow from hammer.js
14560 var MOUSE_POINTER_ID = 1;
14561 var TOUCH_TO_POINTER = {
14562 touchstart: 'pointerdown',
14563 touchend: 'pointerup',
14564 touchendoutside: 'pointerupoutside',
14565 touchmove: 'pointermove',
14566 touchcancel: 'pointercancel',
14567 };
14568 var clock = typeof performance === 'object' && performance.now ? performance : Date;
14569
14570 function isFillOrStrokeAffected(pointerEvents, fill, stroke) {
14571 // account for pointerEvents
14572 // @see https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
14573 var hasFill = false;
14574 var hasStroke = false;
14575 var isFillOtherThanNone = !!fill && !fill.isNone;
14576 var isStrokeOtherThanNone = !!stroke && !stroke.isNone;
14577 if (pointerEvents === 'visiblepainted' ||
14578 pointerEvents === 'painted' ||
14579 pointerEvents === 'auto') {
14580 hasFill = isFillOtherThanNone;
14581 hasStroke = isStrokeOtherThanNone;
14582 }
14583 else if (pointerEvents === 'visiblefill' || pointerEvents === 'fill') {
14584 hasFill = true;
14585 }
14586 else if (pointerEvents === 'visiblestroke' || pointerEvents === 'stroke') {
14587 hasStroke = true;
14588 }
14589 else if (pointerEvents === 'visible' || pointerEvents === 'all') {
14590 // The values of the fill and stroke do not affect event processing.
14591 hasFill = true;
14592 hasStroke = true;
14593 }
14594 return [hasFill, hasStroke];
14595 }
14596
14597 /**
14598 * Thanks for following contributor of codes
14599 * https://gist.github.com/1866474
14600 * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
14601 * http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
14602 * https://github.com/Financial-Times/polyfill-library/blob/master/polyfills/requestAnimationFrame/polyfill.js
14603 **/
14604 var uId = 1;
14605 var uniqueId = function () { return uId++; };
14606 // We use `self` instead of `window` for `WebWorker` support.
14607 var root = typeof self === 'object' && self.self == self
14608 ? self
14609 : // @ts-ignore
14610 typeof global === 'object' && global.global == global
14611 ? // @ts-ignore
14612 global
14613 : {};
14614 var nowOffset = Date.now();
14615 // use performance api if exist, otherwise use Date.now.
14616 // Date.now polyfill required.
14617 var pnow = function () {
14618 if (root.performance && typeof root.performance.now === 'function') {
14619 return root.performance.now();
14620 }
14621 // fallback
14622 return Date.now() - nowOffset;
14623 };
14624 var reservedCBs = {};
14625 var lastTime = Date.now();
14626 var polyfillRaf = function (callback) {
14627 if (typeof callback !== 'function') {
14628 throw new TypeError(callback + ' is not a function');
14629 }
14630 var currentTime = Date.now();
14631 var gap = currentTime - lastTime;
14632 var delay = gap > 16 ? 0 : 16 - gap;
14633 var id = uniqueId();
14634 reservedCBs[id] = callback;
14635 // keys(reservedCBs).length > 1 의미는 이미 setTimeout 이 걸려있는 경우.
14636 // 함께 callback 이 실행될 수 있게 reservedCBs 에만 추가해주고 return
14637 if (Object.keys(reservedCBs).length > 1)
14638 return id;
14639 setTimeout(function () {
14640 lastTime = currentTime;
14641 var copied = reservedCBs;
14642 reservedCBs = {};
14643 Object.keys(copied).forEach(function (key) { return copied[key](pnow()); });
14644 }, delay);
14645 return id;
14646 };
14647 var polyfillCaf = function (id) {
14648 delete reservedCBs[id];
14649 };
14650 var vendorPrefixes = ['', 'webkit', 'moz', 'ms', 'o'];
14651 var getRequestAnimationFrame = function (vp) {
14652 if (typeof vp !== 'string')
14653 return polyfillRaf;
14654 if (vp === '')
14655 return root['requestAnimationFrame'];
14656 return root[vp + 'RequestAnimationFrame'];
14657 };
14658 var getCancelAnimationFrame = function (vp) {
14659 if (typeof vp !== 'string')
14660 return polyfillCaf;
14661 if (vp === '')
14662 return root['cancelAnimationFrame'];
14663 return (root[vp + 'CancelAnimationFrame'] ||
14664 root[vp + 'CancelRequestAnimationFrame']);
14665 };
14666 var find$1 = function (arr, predicate) {
14667 var i = 0;
14668 while (arr[i] !== void 0) {
14669 if (predicate(arr[i]))
14670 return arr[i];
14671 i = i + 1;
14672 }
14673 };
14674 var vp = find$1(vendorPrefixes, function (vp) { return !!getRequestAnimationFrame(vp); });
14675 var raf = getRequestAnimationFrame(vp);
14676 var caf = getCancelAnimationFrame(vp);
14677 root.requestAnimationFrame = raf;
14678 root.cancelAnimationFrame = caf;
14679
14680 var AsyncParallelHook = /** @class */ (function () {
14681 function AsyncParallelHook() {
14682 this.callbacks = [];
14683 }
14684 AsyncParallelHook.prototype.getCallbacksNum = function () {
14685 return this.callbacks.length;
14686 };
14687 AsyncParallelHook.prototype.tapPromise = function (options, fn) {
14688 this.callbacks.push(fn);
14689 };
14690 AsyncParallelHook.prototype.promise = function () {
14691 var args = [];
14692 for (var _i = 0; _i < arguments.length; _i++) {
14693 args[_i] = arguments[_i];
14694 }
14695 return Promise.all(this.callbacks.map(function (callback) {
14696 return callback.apply(void 0, __spreadArray([], __read(args), false));
14697 }));
14698 };
14699 return AsyncParallelHook;
14700 }());
14701
14702 var AsyncSeriesWaterfallHook = /** @class */ (function () {
14703 function AsyncSeriesWaterfallHook() {
14704 this.callbacks = [];
14705 }
14706 AsyncSeriesWaterfallHook.prototype.tapPromise = function (options, fn) {
14707 this.callbacks.push(fn);
14708 };
14709 AsyncSeriesWaterfallHook.prototype.promise = function () {
14710 var args = [];
14711 for (var _i = 0; _i < arguments.length; _i++) {
14712 args[_i] = arguments[_i];
14713 }
14714 return __awaiter(this, void 0, void 0, function () {
14715 var result, i, callback;
14716 var _a;
14717 return __generator(this, function (_b) {
14718 switch (_b.label) {
14719 case 0:
14720 if (!this.callbacks.length) return [3 /*break*/, 6];
14721 return [4 /*yield*/, (_a = this.callbacks)[0].apply(_a, __spreadArray([], __read(args), false))];
14722 case 1:
14723 result = _b.sent();
14724 i = 0;
14725 _b.label = 2;
14726 case 2:
14727 if (!(i < this.callbacks.length - 1)) return [3 /*break*/, 5];
14728 callback = this.callbacks[i];
14729 return [4 /*yield*/, callback(result)];
14730 case 3:
14731 // @ts-ignore
14732 result = _b.sent();
14733 _b.label = 4;
14734 case 4:
14735 i++;
14736 return [3 /*break*/, 2];
14737 case 5: return [2 /*return*/, result];
14738 case 6: return [2 /*return*/, null];
14739 }
14740 });
14741 });
14742 };
14743 return AsyncSeriesWaterfallHook;
14744 }());
14745
14746 var SyncHook = /** @class */ (function () {
14747 function SyncHook() {
14748 this.callbacks = [];
14749 }
14750 SyncHook.prototype.tap = function (options, fn) {
14751 this.callbacks.push(fn);
14752 };
14753 SyncHook.prototype.call = function () {
14754 /* eslint-disable-next-line prefer-rest-params */
14755 var argsArr = arguments;
14756 this.callbacks.forEach(function (callback) {
14757 /* eslint-disable-next-line prefer-spread */
14758 callback.apply(void 0, argsArr);
14759 });
14760 };
14761 return SyncHook;
14762 }());
14763
14764 var SyncWaterfallHook = /** @class */ (function () {
14765 function SyncWaterfallHook() {
14766 this.callbacks = [];
14767 }
14768 SyncWaterfallHook.prototype.tap = function (options, fn) {
14769 this.callbacks.push(fn);
14770 };
14771 SyncWaterfallHook.prototype.call = function () {
14772 if (this.callbacks.length) {
14773 /* eslint-disable-next-line prefer-rest-params */
14774 var argsArr = arguments;
14775 /* eslint-disable-next-line prefer-spread */
14776 var result = this.callbacks[0].apply(void 0, argsArr);
14777 for (var i = 0; i < this.callbacks.length - 1; i++) {
14778 var callback = this.callbacks[i];
14779 // @ts-ignore
14780 result = callback(result);
14781 }
14782 return result;
14783 }
14784 return null;
14785 };
14786 return SyncWaterfallHook;
14787 }());
14788
14789 var genericFontFamilies = [
14790 'serif',
14791 'sans-serif',
14792 'monospace',
14793 'cursive',
14794 'fantasy',
14795 'system-ui',
14796 ];
14797 var stringRegExp = /([\"\'])[^\'\"]+\1/;
14798 function toFontString(attributes) {
14799 var fontSize = attributes.fontSize, fontFamily = attributes.fontFamily, fontStyle = attributes.fontStyle, fontVariant = attributes.fontVariant, fontWeight = attributes.fontWeight;
14800 // build canvas api font setting from individual components. Convert a numeric this.fontSize to px
14801 // const fontSizeString: string = isNumber(fontSize) ? `${fontSize}px` : fontSize.toString();
14802 var fontSizeString = (isNumber(fontSize) && "".concat(fontSize, "px")) || '16px';
14803 // Clean-up fontFamily property by quoting each font name
14804 // this will support font names with spaces
14805 var fontFamilies = fontFamily.split(',');
14806 for (var i = fontFamilies.length - 1; i >= 0; i--) {
14807 // Trim any extra white-space
14808 var fontFamily_1 = fontFamilies[i].trim();
14809 // Check if font already contains strings
14810 if (!stringRegExp.test(fontFamily_1) &&
14811 genericFontFamilies.indexOf(fontFamily_1) < 0) {
14812 fontFamily_1 = "\"".concat(fontFamily_1, "\"");
14813 }
14814 fontFamilies[i] = fontFamily_1;
14815 }
14816 return "".concat(fontStyle, " ").concat(fontVariant, " ").concat(fontWeight, " ").concat(fontSizeString, " ").concat(fontFamilies.join(','));
14817 }
14818
14819 /**
14820 * @see /zh/docs/api/animation#支持变换的属性
14821 *
14822 * support the following formats like CSS Transform:
14823 *
14824 * scale
14825 * * scale(x, y)
14826 * * scaleX(x)
14827 * * scaleY(x)
14828 * * scaleZ(z)
14829 * * scale3d(x, y, z)
14830 *
14831 * translate (unit: none, px, %(relative to its bounds))
14832 * * translate(x, y) eg. translate(0, 0) translate(0, 30px) translate(100%, 100%)
14833 * * translateX(0)
14834 * * translateY(0)
14835 * * translateZ(0)
14836 * * translate3d(0, 0, 0)
14837 *
14838 * rotate (unit: deg rad turn)
14839 * * rotate(0.5turn) rotate(30deg) rotate(1rad)
14840 *
14841 * none
14842 *
14843 * unsupported for now:
14844 * * calc() eg. translate(calc(100% + 10px))
14845 * * matrix/matrix3d()
14846 * * skew/skewX/skewY
14847 * * perspective
14848 */
14849 var CSSPropertyTransform = /** @class */ (function () {
14850 function CSSPropertyTransform() {
14851 this.parser = parseTransform;
14852 this.parserWithCSSDisabled = parseTransform;
14853 this.mixer = mergeTransforms;
14854 }
14855 CSSPropertyTransform.prototype.calculator = function (name, oldParsed, parsed, object) {
14856 // 'none'
14857 if (parsed instanceof CSSKeywordValue) {
14858 return [];
14859 }
14860 return parsed;
14861 };
14862 CSSPropertyTransform.prototype.postProcessor = function (object) {
14863 var transform = object.parsedStyle.transform;
14864 parsedTransformToMat4(transform, object);
14865 };
14866 return CSSPropertyTransform;
14867 }());
14868
14869 /**
14870 * @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin
14871 * @example
14872 * [10px, 10px] [10%, 10%]
14873 */
14874 var CSSPropertyTransformOrigin = /** @class */ (function () {
14875 function CSSPropertyTransformOrigin() {
14876 this.parser = parseTransformOrigin;
14877 // calculator(
14878 // name: string,
14879 // oldParsed: [CSSUnitValue, CSSUnitValue],
14880 // parsed: [CSSUnitValue, CSSUnitValue],
14881 // object: DisplayObject,
14882 // ): [number, number] {
14883 // console.log(object, parsed);
14884 // return [parsed[0].value, parsed[1].value];
14885 // // return [convertPercentUnit(parsed[0], 0, object), convertPercentUnit(parsed[1], 1, object)];
14886 // }
14887 }
14888 return CSSPropertyTransformOrigin;
14889 }());
14890
14891 var CSSPropertyZIndex = /** @class */ (function () {
14892 function CSSPropertyZIndex() {
14893 this.parser = parseNumber;
14894 }
14895 CSSPropertyZIndex.prototype.calculator = function (name, oldParsed, computed, object) {
14896 return computed.value;
14897 };
14898 CSSPropertyZIndex.prototype.postProcessor = function (object) {
14899 if (object.parentNode) {
14900 var parentEntity = object.parentNode;
14901 var parentRenderable = parentEntity.renderable;
14902 var parentSortable = parentEntity.sortable;
14903 if (parentRenderable) {
14904 parentRenderable.dirty = true;
14905 }
14906 // need re-sort on parent
14907 if (parentSortable) {
14908 parentSortable.dirty = true;
14909 parentSortable.dirtyReason = SortReason.Z_INDEX_CHANGED;
14910 }
14911 }
14912 };
14913 return CSSPropertyZIndex;
14914 }());
14915
14916 var CircleUpdater = /** @class */ (function () {
14917 function CircleUpdater() {
14918 }
14919 CircleUpdater.prototype.update = function (parsedStyle, object) {
14920 var r = parsedStyle.r;
14921 var width = r * 2;
14922 var height = r * 2;
14923 return {
14924 width: width,
14925 height: height,
14926 };
14927 };
14928 return CircleUpdater;
14929 }());
14930
14931 var EllipseUpdater = /** @class */ (function () {
14932 function EllipseUpdater() {
14933 }
14934 EllipseUpdater.prototype.update = function (parsedStyle, object) {
14935 var rx = parsedStyle.rx, ry = parsedStyle.ry;
14936 var width = rx * 2;
14937 var height = ry * 2;
14938 return {
14939 width: width,
14940 height: height,
14941 };
14942 };
14943 return EllipseUpdater;
14944 }());
14945
14946 var LineUpdater = /** @class */ (function () {
14947 function LineUpdater() {
14948 }
14949 LineUpdater.prototype.update = function (parsedStyle) {
14950 var x1 = parsedStyle.x1, y1 = parsedStyle.y1, x2 = parsedStyle.x2, y2 = parsedStyle.y2;
14951 var minX = Math.min(x1, x2);
14952 var maxX = Math.max(x1, x2);
14953 var minY = Math.min(y1, y2);
14954 var maxY = Math.max(y1, y2);
14955 var width = maxX - minX;
14956 var height = maxY - minY;
14957 return {
14958 width: width,
14959 height: height,
14960 };
14961 };
14962 return LineUpdater;
14963 }());
14964
14965 var PathUpdater = /** @class */ (function () {
14966 function PathUpdater() {
14967 }
14968 PathUpdater.prototype.update = function (parsedStyle) {
14969 var path = parsedStyle.path;
14970 var _a = path.rect, width = _a.width, height = _a.height;
14971 return {
14972 width: width,
14973 height: height,
14974 };
14975 };
14976 return PathUpdater;
14977 }());
14978
14979 var PolylineUpdater = /** @class */ (function () {
14980 function PolylineUpdater() {
14981 }
14982 PolylineUpdater.prototype.update = function (parsedStyle) {
14983 if (parsedStyle.points && isArray(parsedStyle.points.points)) {
14984 var points = parsedStyle.points.points;
14985 // FIXME: account for miter lineJoin
14986 var minX = Math.min.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[0]; })), false));
14987 var maxX = Math.max.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[0]; })), false));
14988 var minY = Math.min.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[1]; })), false));
14989 var maxY = Math.max.apply(Math, __spreadArray([], __read(points.map(function (point) { return point[1]; })), false));
14990 var width = maxX - minX;
14991 var height = maxY - minY;
14992 return {
14993 width: width,
14994 height: height,
14995 };
14996 }
14997 return {
14998 width: 0,
14999 height: 0,
15000 };
15001 };
15002 return PolylineUpdater;
15003 }());
15004
15005 var RectUpdater = /** @class */ (function () {
15006 function RectUpdater() {
15007 }
15008 RectUpdater.prototype.update = function (parsedStyle, object) {
15009 var img = parsedStyle.img, _a = parsedStyle.width, width = _a === void 0 ? 0 : _a, _b = parsedStyle.height, height = _b === void 0 ? 0 : _b;
15010 var contentWidth = width;
15011 var contentHeight = height;
15012 // resize with HTMLImageElement's size
15013 if (img && !isString(img)) {
15014 if (!contentWidth) {
15015 contentWidth = img.width;
15016 parsedStyle.width = contentWidth;
15017 }
15018 if (!contentHeight) {
15019 contentHeight = img.height;
15020 parsedStyle.height = contentHeight;
15021 }
15022 }
15023 return {
15024 width: contentWidth,
15025 height: contentHeight,
15026 };
15027 };
15028 return RectUpdater;
15029 }());
15030
15031 var TextUpdater = /** @class */ (function () {
15032 function TextUpdater(globalRuntime) {
15033 this.globalRuntime = globalRuntime;
15034 }
15035 TextUpdater.prototype.isReadyToMeasure = function (parsedStyle, object) {
15036 var text = parsedStyle.text, textAlign = parsedStyle.textAlign, textBaseline = parsedStyle.textBaseline, fontSize = parsedStyle.fontSize, fontStyle = parsedStyle.fontStyle, fontWeight = parsedStyle.fontWeight, fontVariant = parsedStyle.fontVariant, lineWidth = parsedStyle.lineWidth;
15037 return (text &&
15038 fontSize &&
15039 fontStyle &&
15040 fontWeight &&
15041 fontVariant &&
15042 textAlign &&
15043 textBaseline &&
15044 !isNil(lineWidth));
15045 };
15046 TextUpdater.prototype.update = function (parsedStyle, object) {
15047 var _a, _b;
15048 var text = parsedStyle.text, textAlign = parsedStyle.textAlign, lineWidth = parsedStyle.lineWidth, textBaseline = parsedStyle.textBaseline, dx = parsedStyle.dx, dy = parsedStyle.dy;
15049 if (!this.isReadyToMeasure(parsedStyle, object)) {
15050 parsedStyle.metrics = {
15051 font: '',
15052 width: 0,
15053 height: 0,
15054 lines: [],
15055 lineWidths: [],
15056 lineHeight: 0,
15057 maxLineWidth: 0,
15058 fontProperties: {
15059 ascent: 0,
15060 descent: 0,
15061 fontSize: 0,
15062 },
15063 lineMetrics: [],
15064 };
15065 return {
15066 width: 0,
15067 height: 0,
15068 x: 0,
15069 y: 0,
15070 offsetX: 0,
15071 offsetY: 0,
15072 };
15073 }
15074 var offscreenCanvas = (((_b = (_a = object === null || object === void 0 ? void 0 : object.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.getConfig()) || {}).offscreenCanvas;
15075 var metrics = this.globalRuntime.textService.measureText(text, parsedStyle, offscreenCanvas);
15076 parsedStyle.metrics = metrics;
15077 var width = metrics.width, height = metrics.height, lineHeight = metrics.lineHeight, fontProperties = metrics.fontProperties;
15078 // anchor is left-top by default
15079 var halfExtents = [width / 2, height / 2, 0];
15080 // default 'left'
15081 var anchor = [0, 1];
15082 var lineXOffset = 0;
15083 if (textAlign === 'center' || textAlign === 'middle') {
15084 lineXOffset = lineWidth / 2;
15085 anchor = [0.5, 1];
15086 }
15087 else if (textAlign === 'right' || textAlign === 'end') {
15088 lineXOffset = lineWidth;
15089 anchor = [1, 1];
15090 }
15091 var lineYOffset = 0;
15092 if (textBaseline === 'middle') {
15093 // eslint-disable-next-line prefer-destructuring
15094 lineYOffset = halfExtents[1];
15095 }
15096 else if (textBaseline === 'top' || textBaseline === 'hanging') {
15097 lineYOffset = halfExtents[1] * 2;
15098 }
15099 else if (textBaseline === 'alphabetic') {
15100 // prevent calling getImageData for ascent metrics
15101 lineYOffset = this.globalRuntime.enableCSSParsing
15102 ? lineHeight - fontProperties.ascent
15103 : 0;
15104 }
15105 else if (textBaseline === 'bottom' || textBaseline === 'ideographic') {
15106 lineYOffset = 0;
15107 }
15108 // TODO: ideographic & bottom
15109 if (dx) {
15110 lineXOffset += dx;
15111 }
15112 if (dy) {
15113 lineYOffset += dy;
15114 }
15115 // update anchor
15116 parsedStyle.anchor = [anchor[0], anchor[1], 0];
15117 return {
15118 width: halfExtents[0] * 2,
15119 height: halfExtents[1] * 2,
15120 offsetX: lineXOffset,
15121 offsetY: lineYOffset,
15122 };
15123 };
15124 return TextUpdater;
15125 }());
15126
15127 function isFederatedEvent(value) {
15128 return !!value.type;
15129 }
15130 /**
15131 * An DOM-compatible synthetic event implementation that is "forwarded" on behalf of an original
15132 * FederatedEvent or native Event.
15133 */
15134 var FederatedEvent = /** @class */ (function () {
15135 /**
15136 * The event boundary which manages this event. Propagation can only occur
15137 * within the boundary's jurisdiction.
15138 */
15139 function FederatedEvent(manager) {
15140 /**
15141 * The propagation phase.
15142 * @see https://developer.mozilla.org/en-US/docs/Web/API/Event/eventPhase
15143 */
15144 this.eventPhase = FederatedEvent.prototype.NONE;
15145 /**
15146 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/bubbles
15147 */
15148 this.bubbles = true;
15149 /**
15150 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/cancelBubble
15151 */
15152 this.cancelBubble = true;
15153 /**
15154 * @see https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable
15155 */
15156 this.cancelable = false;
15157 /** Flags whether the default response of the user agent was prevent through this event. */
15158 this.defaultPrevented = false;
15159 /** Flags whether propagation was stopped. */
15160 this.propagationStopped = false;
15161 /** Flags whether propagation was immediately stopped. */
15162 this.propagationImmediatelyStopped = false;
15163 /**
15164 * The coordinates of the evnet relative to the nearest DOM layer.
15165 * This is a non-standard property.
15166 */
15167 this.layer = new Point();
15168 /**
15169 * The coordinates of the event relative to the DOM document.
15170 * This is a non-standard property.
15171 * relative to the DOM document.
15172 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent/pageX
15173 */
15174 this.page = new Point();
15175 /**
15176 * relative to Canvas, origin is left-top
15177 */
15178 this.canvas = new Point();
15179 /**
15180 * relative to Viewport, account for Camera
15181 */
15182 this.viewport = new Point();
15183 this.composed = false;
15184 this.NONE = 0;
15185 this.CAPTURING_PHASE = 1;
15186 this.AT_TARGET = 2;
15187 this.BUBBLING_PHASE = 3;
15188 this.manager = manager;
15189 }
15190 Object.defineProperty(FederatedEvent.prototype, "name", {
15191 /**
15192 * @deprecated
15193 */
15194 get: function () {
15195 return this.type;
15196 },
15197 enumerable: false,
15198 configurable: true
15199 });
15200 Object.defineProperty(FederatedEvent.prototype, "layerX", {
15201 get: function () {
15202 return this.layer.x;
15203 },
15204 enumerable: false,
15205 configurable: true
15206 });
15207 Object.defineProperty(FederatedEvent.prototype, "layerY", {
15208 get: function () {
15209 return this.layer.y;
15210 },
15211 enumerable: false,
15212 configurable: true
15213 });
15214 Object.defineProperty(FederatedEvent.prototype, "pageX", {
15215 get: function () {
15216 return this.page.x;
15217 },
15218 enumerable: false,
15219 configurable: true
15220 });
15221 Object.defineProperty(FederatedEvent.prototype, "pageY", {
15222 get: function () {
15223 return this.page.y;
15224 },
15225 enumerable: false,
15226 configurable: true
15227 });
15228 Object.defineProperty(FederatedEvent.prototype, "x", {
15229 get: function () {
15230 return this.canvas.x;
15231 },
15232 enumerable: false,
15233 configurable: true
15234 });
15235 Object.defineProperty(FederatedEvent.prototype, "y", {
15236 get: function () {
15237 return this.canvas.y;
15238 },
15239 enumerable: false,
15240 configurable: true
15241 });
15242 Object.defineProperty(FederatedEvent.prototype, "canvasX", {
15243 get: function () {
15244 return this.canvas.x;
15245 },
15246 enumerable: false,
15247 configurable: true
15248 });
15249 Object.defineProperty(FederatedEvent.prototype, "canvasY", {
15250 get: function () {
15251 return this.canvas.y;
15252 },
15253 enumerable: false,
15254 configurable: true
15255 });
15256 Object.defineProperty(FederatedEvent.prototype, "viewportX", {
15257 get: function () {
15258 return this.viewport.x;
15259 },
15260 enumerable: false,
15261 configurable: true
15262 });
15263 Object.defineProperty(FederatedEvent.prototype, "viewportY", {
15264 get: function () {
15265 return this.viewport.y;
15266 },
15267 enumerable: false,
15268 configurable: true
15269 });
15270 /**
15271 * The propagation path for this event
15272 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/composedPath
15273 *
15274 * So composedPath()[0] represents the original target.
15275 * @see https://polymer-library.polymer-project.org/3.0/docs/devguide/events#retargeting
15276 */
15277 FederatedEvent.prototype.composedPath = function () {
15278 if (this.manager && (!this.path || this.path[0] !== this.target)) {
15279 this.path = this.target ? this.manager.propagationPath(this.target) : [];
15280 }
15281 return this.path;
15282 };
15283 Object.defineProperty(FederatedEvent.prototype, "propagationPath", {
15284 /**
15285 * @deprecated
15286 */
15287 get: function () {
15288 return this.composedPath();
15289 },
15290 enumerable: false,
15291 configurable: true
15292 });
15293 /**
15294 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/preventDefault
15295 */
15296 FederatedEvent.prototype.preventDefault = function () {
15297 if (this.nativeEvent instanceof Event && this.nativeEvent.cancelable) {
15298 this.nativeEvent.preventDefault();
15299 }
15300 this.defaultPrevented = true;
15301 };
15302 /**
15303 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopImmediatePropagation
15304 */
15305 FederatedEvent.prototype.stopImmediatePropagation = function () {
15306 this.propagationImmediatelyStopped = true;
15307 };
15308 /**
15309 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopPropagation
15310 */
15311 FederatedEvent.prototype.stopPropagation = function () {
15312 this.propagationStopped = true;
15313 };
15314 /**
15315 * added for compatibility with DOM Event,
15316 * deprecated props and methods
15317 */
15318 FederatedEvent.prototype.initEvent = function () { };
15319 FederatedEvent.prototype.initUIEvent = function () { };
15320 FederatedEvent.prototype.clone = function () {
15321 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15322 };
15323 return FederatedEvent;
15324 }());
15325
15326 var FederatedMouseEvent = /** @class */ (function (_super) {
15327 __extends(FederatedMouseEvent, _super);
15328 function FederatedMouseEvent() {
15329 var _this = _super !== null && _super.apply(this, arguments) || this;
15330 /**
15331 * The coordinates of the mouse event relative to the canvas.
15332 */
15333 _this.client = new Point();
15334 /**
15335 * The movement in this pointer relative to the last `mousemove` event.
15336 */
15337 _this.movement = new Point();
15338 /**
15339 * The offset of the pointer coordinates w.r.t. target DisplayObject in world space. This is
15340 * not supported at the moment.
15341 */
15342 _this.offset = new Point();
15343 /**
15344 * The pointer coordinates in world space.
15345 */
15346 _this.global = new Point();
15347 /**
15348 * The pointer coordinates in sceen space.
15349 */
15350 _this.screen = new Point();
15351 return _this;
15352 }
15353 Object.defineProperty(FederatedMouseEvent.prototype, "clientX", {
15354 get: function () {
15355 return this.client.x;
15356 },
15357 enumerable: false,
15358 configurable: true
15359 });
15360 Object.defineProperty(FederatedMouseEvent.prototype, "clientY", {
15361 get: function () {
15362 return this.client.y;
15363 },
15364 enumerable: false,
15365 configurable: true
15366 });
15367 Object.defineProperty(FederatedMouseEvent.prototype, "movementX", {
15368 get: function () {
15369 return this.movement.x;
15370 },
15371 enumerable: false,
15372 configurable: true
15373 });
15374 Object.defineProperty(FederatedMouseEvent.prototype, "movementY", {
15375 get: function () {
15376 return this.movement.y;
15377 },
15378 enumerable: false,
15379 configurable: true
15380 });
15381 Object.defineProperty(FederatedMouseEvent.prototype, "offsetX", {
15382 get: function () {
15383 return this.offset.x;
15384 },
15385 enumerable: false,
15386 configurable: true
15387 });
15388 Object.defineProperty(FederatedMouseEvent.prototype, "offsetY", {
15389 get: function () {
15390 return this.offset.y;
15391 },
15392 enumerable: false,
15393 configurable: true
15394 });
15395 Object.defineProperty(FederatedMouseEvent.prototype, "globalX", {
15396 get: function () {
15397 return this.global.x;
15398 },
15399 enumerable: false,
15400 configurable: true
15401 });
15402 Object.defineProperty(FederatedMouseEvent.prototype, "globalY", {
15403 get: function () {
15404 return this.global.y;
15405 },
15406 enumerable: false,
15407 configurable: true
15408 });
15409 Object.defineProperty(FederatedMouseEvent.prototype, "screenX", {
15410 get: function () {
15411 return this.screen.x;
15412 },
15413 enumerable: false,
15414 configurable: true
15415 });
15416 Object.defineProperty(FederatedMouseEvent.prototype, "screenY", {
15417 get: function () {
15418 return this.screen.y;
15419 },
15420 enumerable: false,
15421 configurable: true
15422 });
15423 FederatedMouseEvent.prototype.getModifierState = function (key) {
15424 return ('getModifierState' in this.nativeEvent &&
15425 this.nativeEvent.getModifierState(key));
15426 };
15427 FederatedMouseEvent.prototype.initMouseEvent = function () {
15428 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15429 };
15430 return FederatedMouseEvent;
15431 }(FederatedEvent));
15432
15433 // @ts-ignore
15434 var FederatedPointerEvent = /** @class */ (function (_super) {
15435 __extends(FederatedPointerEvent, _super);
15436 function FederatedPointerEvent() {
15437 var _this = _super !== null && _super.apply(this, arguments) || this;
15438 /**
15439 * The width of the pointer's contact along the x-axis, measured in CSS pixels.
15440 * radiusX of TouchEvents will be represented by this value.
15441 *
15442 * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width
15443 */
15444 _this.width = 0;
15445 /**
15446 * The height of the pointer's contact along the y-axis, measured in CSS pixels.
15447 * radiusY of TouchEvents will be represented by this value.
15448 *
15449 * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height
15450 */
15451 _this.height = 0;
15452 /**
15453 * Indicates whether or not the pointer device that created the event is the primary pointer.
15454 *
15455 * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary
15456 */
15457 _this.isPrimary = false;
15458 return _this;
15459 }
15460 /**
15461 * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/getCoalescedEvents
15462 */
15463 FederatedPointerEvent.prototype.getCoalescedEvents = function () {
15464 if (this.type === 'pointermove' ||
15465 this.type === 'mousemove' ||
15466 this.type === 'touchmove') {
15467 // @ts-ignore
15468 return [this];
15469 }
15470 return [];
15471 };
15472 /**
15473 * @see https://chromestatus.com/feature/5765569655603200
15474 */
15475 FederatedPointerEvent.prototype.getPredictedEvents = function () {
15476 throw new Error('getPredictedEvents is not supported!');
15477 };
15478 /**
15479 * @see https://github.com/antvis/G/issues/1115
15480 * We currently reuses event objects in the event system,
15481 * avoiding the creation of a large number of event objects.
15482 * Reused objects are only used to carry different data,
15483 * such as coordinate information, native event objects,
15484 * and therefore the lifecycle is limited to the event handler,
15485 * which can lead to unintended consequences if an attempt is made to cache the entire event object.
15486 *
15487 * Therefore, while keeping the above performance considerations in mind, it is possible to provide a clone method that creates a new object when the user really wants to cache it, e.g.
15488 */
15489 FederatedPointerEvent.prototype.clone = function () {
15490 return this.manager.clonePointerEvent(this);
15491 };
15492 return FederatedPointerEvent;
15493 }(FederatedMouseEvent));
15494
15495 // @ts-ignore
15496 var FederatedWheelEvent = /** @class */ (function (_super) {
15497 __extends(FederatedWheelEvent, _super);
15498 function FederatedWheelEvent() {
15499 return _super !== null && _super.apply(this, arguments) || this;
15500 }
15501 FederatedWheelEvent.prototype.clone = function () {
15502 return this.manager.cloneWheelEvent(this);
15503 };
15504 return FederatedWheelEvent;
15505 }(FederatedMouseEvent));
15506
15507 /**
15508 * @see https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events
15509 *
15510 * @example
15511 const event = new CustomEvent('build', { detail: { prop1: 'xx' } });
15512 circle.addEventListener('build', (e) => {
15513 e.target; // circle
15514 e.detail; // { prop1: 'xx' }
15515 });
15516
15517 circle.dispatchEvent(event);
15518 */
15519 var CustomEvent = /** @class */ (function (_super) {
15520 __extends(CustomEvent, _super);
15521 // eslint-disable-next-line @typescript-eslint/ban-types
15522 function CustomEvent(eventName, object) {
15523 var _this = _super.call(this, null) || this;
15524 _this.type = eventName;
15525 _this.detail = object;
15526 // compatible with G 3.0
15527 Object.assign(_this, object);
15528 return _this;
15529 }
15530 return CustomEvent;
15531 }(FederatedEvent));
15532
15533 var DELEGATION_SPLITTER = ':';
15534 /**
15535 * Objects that can receive events and may have listeners for them.
15536 * eg. Element, Canvas, DisplayObject
15537 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
15538 */
15539 var EventTarget = /** @class */ (function () {
15540 function EventTarget() {
15541 /**
15542 * event emitter
15543 */
15544 this.emitter = new eventemitter3();
15545 }
15546 /**
15547 * @deprecated
15548 * @alias addEventListener
15549 */
15550 EventTarget.prototype.on = function (type, listener, options) {
15551 this.addEventListener(type, listener, options);
15552 return this;
15553 };
15554 /**
15555 * support `capture` & `once` in options
15556 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener
15557 */
15558 EventTarget.prototype.addEventListener = function (type, listener, options) {
15559 var capture = (isBoolean(options) && options) || (isObject(options) && options.capture);
15560 var once = isObject(options) && options.once;
15561 var context = isFunction$1(listener) ? undefined : listener;
15562 // compatible with G 3.0
15563 // support using delegate name in event type, eg. 'node:click'
15564 var useDelegatedName = false;
15565 var delegatedName = '';
15566 if (type.indexOf(DELEGATION_SPLITTER) > -1) {
15567 var _a = __read(type.split(DELEGATION_SPLITTER), 2), name_1 = _a[0], eventType = _a[1];
15568 type = eventType;
15569 delegatedName = name_1;
15570 useDelegatedName = true;
15571 }
15572 type = capture ? "".concat(type, "capture") : type;
15573 listener = isFunction$1(listener) ? listener : listener.handleEvent;
15574 // compatible with G 3.0
15575 if (useDelegatedName) {
15576 var originListener_1 = listener;
15577 listener = function () {
15578 var _a;
15579 var args = [];
15580 for (var _i = 0; _i < arguments.length; _i++) {
15581 args[_i] = arguments[_i];
15582 }
15583 if (((_a = args[0].target) === null || _a === void 0 ? void 0 : _a.name) !== delegatedName) {
15584 return;
15585 }
15586 // @ts-ignore
15587 originListener_1.apply(void 0, __spreadArray([], __read(args), false));
15588 };
15589 }
15590 if (once) {
15591 this.emitter.once(type, listener, context);
15592 }
15593 else {
15594 this.emitter.on(type, listener, context);
15595 }
15596 return this;
15597 };
15598 /**
15599 * @deprecated
15600 * @alias removeEventListener
15601 */
15602 EventTarget.prototype.off = function (type, listener, options) {
15603 if (type) {
15604 this.removeEventListener(type, listener, options);
15605 }
15606 else {
15607 // remove all listeners
15608 this.removeAllEventListeners();
15609 }
15610 return this;
15611 };
15612 EventTarget.prototype.removeAllEventListeners = function () {
15613 this.emitter.removeAllListeners();
15614 };
15615 EventTarget.prototype.removeEventListener = function (type, listener, options) {
15616 var capture = (isBoolean(options) && options) || (isObject(options) && options.capture);
15617 var context = isFunction$1(listener) ? undefined : listener;
15618 type = capture ? "".concat(type, "capture") : type;
15619 listener = isFunction$1(listener) ? listener : listener === null || listener === void 0 ? void 0 : listener.handleEvent;
15620 this.emitter.off(type, listener, context);
15621 return this;
15622 };
15623 /**
15624 * @deprecated
15625 * @alias dispatchEvent
15626 */
15627 // eslint-disable-next-line @typescript-eslint/ban-types
15628 EventTarget.prototype.emit = function (eventName, object) {
15629 this.dispatchEvent(new CustomEvent(eventName, object));
15630 };
15631 /**
15632 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
15633 */
15634 EventTarget.prototype.dispatchEvent = function (e, skipPropagate) {
15635 var _a, _b;
15636 if (skipPropagate === void 0) { skipPropagate = false; }
15637 if (!isFederatedEvent(e)) {
15638 throw new Error('DisplayObject cannot propagate events outside of the Federated Events API');
15639 }
15640 // should account for Element / Document / Canvas
15641 var canvas;
15642 // @ts-ignore
15643 if (this.document) {
15644 canvas = this;
15645 // @ts-ignore
15646 }
15647 else if (this.defaultView) {
15648 canvas = this.defaultView;
15649 }
15650 else {
15651 canvas = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView;
15652 }
15653 // assign event manager
15654 if (canvas) {
15655 e.manager = canvas.getEventService() || null;
15656 if (!e.manager) {
15657 return false;
15658 }
15659 e.defaultPrevented = false;
15660 e.path = [];
15661 if (!skipPropagate) {
15662 e.target = this;
15663 }
15664 (_b = e.manager) === null || _b === void 0 ? void 0 : _b.dispatchEvent(e, e.type, skipPropagate);
15665 }
15666 return !e.defaultPrevented;
15667 };
15668 return EventTarget;
15669 }());
15670
15671 /**
15672 * @see https://developer.mozilla.org/en-US/docs/Web/API/Node
15673 */
15674 var Node = /** @class */ (function (_super) {
15675 __extends(Node, _super);
15676 function Node() {
15677 var _this = _super !== null && _super.apply(this, arguments) || this;
15678 _this.shadow = false;
15679 /**
15680 * points to canvas.document
15681 * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument
15682 */
15683 _this.ownerDocument = null;
15684 /**
15685 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/isConnected
15686 * @example
15687 circle.isConnected; // false
15688 canvas.appendChild(circle);
15689 circle.isConnected; // true
15690 */
15691 _this.isConnected = false;
15692 /**
15693 * Returns node's node document's document base URL.
15694 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node
15695 */
15696 _this.baseURI = '';
15697 /**
15698 * Returns the children.
15699 * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes
15700 */
15701 _this.childNodes = [];
15702 /**
15703 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType
15704 */
15705 _this.nodeType = 0;
15706 /**
15707 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeName
15708 */
15709 _this.nodeName = '';
15710 /**
15711 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeValue
15712 */
15713 _this.nodeValue = null;
15714 /**
15715 * @see https://developer.mozilla.org/en-US/docs/Web/API/ParentNode
15716 */
15717 _this.parentNode = null;
15718 return _this;
15719 }
15720 Node.isNode = function (target) {
15721 return !!target.childNodes;
15722 };
15723 Object.defineProperty(Node.prototype, "textContent", {
15724 /**
15725 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/textContent
15726 */
15727 get: function () {
15728 var e_1, _a;
15729 var out = '';
15730 if (this.nodeName === Shape.TEXT) {
15731 // @ts-ignore
15732 out += this.style.text;
15733 }
15734 try {
15735 for (var _b = __values(this.childNodes), _c = _b.next(); !_c.done; _c = _b.next()) {
15736 var child = _c.value;
15737 if (child.nodeName === Shape.TEXT) {
15738 out += child.nodeValue;
15739 }
15740 else {
15741 out += child.textContent;
15742 }
15743 }
15744 }
15745 catch (e_1_1) { e_1 = { error: e_1_1 }; }
15746 finally {
15747 try {
15748 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
15749 }
15750 finally { if (e_1) throw e_1.error; }
15751 }
15752 return out;
15753 },
15754 set: function (content) {
15755 var _this = this;
15756 // remove all children
15757 this.childNodes.slice().forEach(function (child) {
15758 _this.removeChild(child);
15759 });
15760 if (this.nodeName === Shape.TEXT) {
15761 // @ts-ignore
15762 this.style.text = "".concat(content);
15763 }
15764 },
15765 enumerable: false,
15766 configurable: true
15767 });
15768 /**
15769 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/getRootNode
15770 */
15771 Node.prototype.getRootNode = function (opts) {
15772 if (opts === void 0) { opts = {}; }
15773 if (this.parentNode) {
15774 return this.parentNode.getRootNode(opts);
15775 }
15776 if (opts.composed && this.host) {
15777 return this.host.getRootNode(opts);
15778 }
15779 return this;
15780 };
15781 Node.prototype.hasChildNodes = function () {
15782 return this.childNodes.length > 0;
15783 };
15784 Node.prototype.isDefaultNamespace = function (namespace) {
15785 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15786 };
15787 Node.prototype.lookupNamespaceURI = function (prefix) {
15788 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15789 };
15790 Node.prototype.lookupPrefix = function (namespace) {
15791 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15792 };
15793 Node.prototype.normalize = function () {
15794 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
15795 };
15796 /**
15797 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Node/isEqualNode
15798 */
15799 Node.prototype.isEqualNode = function (otherNode) {
15800 // TODO: compare 2 nodes, not sameness
15801 return this === otherNode;
15802 };
15803 Node.prototype.isSameNode = function (otherNode) {
15804 return this.isEqualNode(otherNode);
15805 };
15806 Object.defineProperty(Node.prototype, "parent", {
15807 /**
15808 * @deprecated
15809 * @alias parentNode
15810 */
15811 get: function () {
15812 return this.parentNode;
15813 },
15814 enumerable: false,
15815 configurable: true
15816 });
15817 Object.defineProperty(Node.prototype, "parentElement", {
15818 get: function () {
15819 return null;
15820 },
15821 enumerable: false,
15822 configurable: true
15823 });
15824 Object.defineProperty(Node.prototype, "nextSibling", {
15825 get: function () {
15826 return null;
15827 },
15828 enumerable: false,
15829 configurable: true
15830 });
15831 Object.defineProperty(Node.prototype, "previousSibling", {
15832 get: function () {
15833 return null;
15834 },
15835 enumerable: false,
15836 configurable: true
15837 });
15838 Object.defineProperty(Node.prototype, "firstChild", {
15839 get: function () {
15840 return this.childNodes.length > 0 ? this.childNodes[0] : null;
15841 },
15842 enumerable: false,
15843 configurable: true
15844 });
15845 Object.defineProperty(Node.prototype, "lastChild", {
15846 get: function () {
15847 return this.childNodes.length > 0
15848 ? this.childNodes[this.childNodes.length - 1]
15849 : null;
15850 },
15851 enumerable: false,
15852 configurable: true
15853 });
15854 /**
15855 * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
15856 * @see https://github.com/b-fuze/deno-dom/blob/master/src/dom/node.ts#L338
15857 */
15858 Node.prototype.compareDocumentPosition = function (other) {
15859 var _a;
15860 if (other === this) {
15861 // same node
15862 return 0;
15863 }
15864 // if (!(other instanceof Node)) {
15865 // throw new TypeError(
15866 // 'Node.compareDocumentPosition: Argument 1 does not implement interface Node.',
15867 // );
15868 // }
15869 var node1Root = other;
15870 // eslint-disable-next-line @typescript-eslint/no-this-alias
15871 var node2Root = this;
15872 var node1Hierarchy = [node1Root];
15873 var node2Hierarchy = [node2Root];
15874 while ((_a = node1Root.parentNode) !== null && _a !== void 0 ? _a : node2Root.parentNode) {
15875 node1Root = node1Root.parentNode
15876 ? (node1Hierarchy.push(node1Root.parentNode), node1Root.parentNode)
15877 : node1Root;
15878 node2Root = node2Root.parentNode
15879 ? (node2Hierarchy.push(node2Root.parentNode), node2Root.parentNode)
15880 : node2Root;
15881 }
15882 // Check if they don't share the same root node
15883 if (node1Root !== node2Root) {
15884 return (Node.DOCUMENT_POSITION_DISCONNECTED |
15885 Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
15886 Node.DOCUMENT_POSITION_PRECEDING);
15887 }
15888 var longerHierarchy = node1Hierarchy.length > node2Hierarchy.length
15889 ? node1Hierarchy
15890 : node2Hierarchy;
15891 var shorterHierarchy = longerHierarchy === node1Hierarchy ? node2Hierarchy : node1Hierarchy;
15892 // Check if either is a container of the other
15893 if (longerHierarchy[longerHierarchy.length - shorterHierarchy.length] ===
15894 shorterHierarchy[0]) {
15895 return longerHierarchy === node1Hierarchy
15896 ? // other is a child of this
15897 Node.DOCUMENT_POSITION_CONTAINED_BY | Node.DOCUMENT_POSITION_FOLLOWING
15898 : // this is a child of other
15899 Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING;
15900 }
15901 // Find their first common ancestor and see whether they
15902 // are preceding or following
15903 var longerStart = longerHierarchy.length - shorterHierarchy.length;
15904 for (var i = shorterHierarchy.length - 1; i >= 0; i--) {
15905 var shorterHierarchyNode = shorterHierarchy[i];
15906 var longerHierarchyNode = longerHierarchy[longerStart + i];
15907 // We found the first common ancestor
15908 if (longerHierarchyNode !== shorterHierarchyNode) {
15909 var siblings = shorterHierarchyNode.parentNode.childNodes;
15910 if (siblings.indexOf(shorterHierarchyNode) <
15911 siblings.indexOf(longerHierarchyNode)) {
15912 // Shorter is before longer
15913 if (shorterHierarchy === node1Hierarchy) {
15914 // Other is before this
15915 return Node.DOCUMENT_POSITION_PRECEDING;
15916 }
15917 else {
15918 // This is before other
15919 return Node.DOCUMENT_POSITION_FOLLOWING;
15920 }
15921 }
15922 else {
15923 // Longer is before shorter
15924 if (longerHierarchy === node1Hierarchy) {
15925 // Other is before this
15926 return Node.DOCUMENT_POSITION_PRECEDING;
15927 }
15928 else {
15929 // Other is after this
15930 return Node.DOCUMENT_POSITION_FOLLOWING;
15931 }
15932 }
15933 }
15934 }
15935 return Node.DOCUMENT_POSITION_FOLLOWING;
15936 };
15937 /**
15938 * @deprecated
15939 * @alias contains
15940 */
15941 Node.prototype.contain = function (other) {
15942 return this.contains(other);
15943 };
15944 Node.prototype.contains = function (other) {
15945 // the node itself, one of its direct children
15946 var tmp = other;
15947 // @see https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
15948 while (tmp && this !== tmp) {
15949 tmp = tmp.parentNode;
15950 }
15951 return !!tmp;
15952 };
15953 Node.prototype.getAncestor = function (n) {
15954 // eslint-disable-next-line @typescript-eslint/no-this-alias
15955 var temp = this;
15956 while (n > 0 && temp) {
15957 temp = temp.parentNode;
15958 n--;
15959 }
15960 return temp;
15961 };
15962 Node.prototype.forEach = function (callback, assigned) {
15963 if (assigned === void 0) { assigned = false; }
15964 if (!callback(this)) {
15965 (assigned ? this.childNodes.slice() : this.childNodes).forEach(function (child) {
15966 child.forEach(callback);
15967 });
15968 }
15969 };
15970 /**
15971 * Both nodes are in different documents or different trees in the same document.
15972 */
15973 Node.DOCUMENT_POSITION_DISCONNECTED = 1;
15974 /**
15975 * otherNode precedes the node in either a pre-order depth-first traversal
15976 * of a tree containing both (e.g., as an ancestor or previous sibling or a descendant of a previous sibling or previous sibling of an ancestor) or (if they are disconnected) in an arbitrary but consistent ordering.
15977 */
15978 Node.DOCUMENT_POSITION_PRECEDING = 2;
15979 /**
15980 * otherNode follows the node in either a pre-order depth-first traversal of a tree containing both (e.g., as a descendant or following sibling or a descendant of a following sibling or following sibling of an ancestor) or (if they are disconnected) in an arbitrary but consistent ordering.
15981 */
15982 Node.DOCUMENT_POSITION_FOLLOWING = 4;
15983 /**
15984 * otherNode is an ancestor of the node.
15985 */
15986 Node.DOCUMENT_POSITION_CONTAINS = 8;
15987 /**
15988 * otherNode is a descendant of the node.
15989 */
15990 Node.DOCUMENT_POSITION_CONTAINED_BY = 16;
15991 /**
15992 * The result relies upon arbitrary and/or implementation-specific behavior and is not guaranteed to be portable.
15993 */
15994 Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 32;
15995 return Node;
15996 }(EventTarget));
15997
15998 var PROPAGATION_LIMIT = 2048;
15999 var EventService = /** @class */ (function () {
16000 function EventService(globalRuntime, context) {
16001 var _this = this;
16002 this.globalRuntime = globalRuntime;
16003 this.context = context;
16004 this.emitter = new eventemitter3();
16005 this.cursor = 'default';
16006 this.mappingTable = {};
16007 this.mappingState = {
16008 trackingData: {},
16009 };
16010 this.eventPool = new Map();
16011 this.tmpMatrix = create$1();
16012 this.tmpVec3 = create$2();
16013 this.onPointerDown = function (from) {
16014 var e = _this.createPointerEvent(from);
16015 _this.dispatchEvent(e, 'pointerdown');
16016 if (e.pointerType === 'touch') {
16017 _this.dispatchEvent(e, 'touchstart');
16018 }
16019 else if (e.pointerType === 'mouse' || e.pointerType === 'pen') {
16020 var isRightButton = e.button === 2;
16021 _this.dispatchEvent(e, isRightButton ? 'rightdown' : 'mousedown');
16022 }
16023 var trackingData = _this.trackingData(from.pointerId);
16024 trackingData.pressTargetsByButton[from.button] = e.composedPath();
16025 _this.freeEvent(e);
16026 };
16027 this.onPointerUp = function (from) {
16028 var _a;
16029 var now = clock.now();
16030 var e = _this.createPointerEvent(from, undefined, undefined, _this.context.config.alwaysTriggerPointerEventOnCanvas
16031 ? _this.rootTarget
16032 : undefined);
16033 _this.dispatchEvent(e, 'pointerup');
16034 if (e.pointerType === 'touch') {
16035 _this.dispatchEvent(e, 'touchend');
16036 }
16037 else if (e.pointerType === 'mouse' || e.pointerType === 'pen') {
16038 var isRightButton = e.button === 2;
16039 _this.dispatchEvent(e, isRightButton ? 'rightup' : 'mouseup');
16040 }
16041 var trackingData = _this.trackingData(from.pointerId);
16042 var pressTarget = _this.findMountedTarget(trackingData.pressTargetsByButton[from.button]);
16043 var clickTarget = pressTarget;
16044 // pointerupoutside only bubbles. It only bubbles upto the parent that doesn't contain
16045 // the pointerup location.
16046 if (pressTarget && !e.composedPath().includes(pressTarget)) {
16047 var currentTarget = pressTarget;
16048 while (currentTarget && !e.composedPath().includes(currentTarget)) {
16049 e.currentTarget = currentTarget;
16050 _this.notifyTarget(e, 'pointerupoutside');
16051 if (e.pointerType === 'touch') {
16052 _this.notifyTarget(e, 'touchendoutside');
16053 }
16054 else if (e.pointerType === 'mouse' || e.pointerType === 'pen') {
16055 var isRightButton = e.button === 2;
16056 _this.notifyTarget(e, isRightButton ? 'rightupoutside' : 'mouseupoutside');
16057 }
16058 if (Node.isNode(currentTarget)) {
16059 currentTarget = currentTarget.parentNode;
16060 }
16061 }
16062 delete trackingData.pressTargetsByButton[from.button];
16063 // currentTarget is the most specific ancestor holding both the pointerdown and pointerup
16064 // targets. That is - it's our click target!
16065 clickTarget = currentTarget;
16066 }
16067 if (clickTarget) {
16068 var clickEvent = _this.clonePointerEvent(e, 'click');
16069 clickEvent.target = clickTarget;
16070 clickEvent.path = [];
16071 if (!trackingData.clicksByButton[from.button]) {
16072 trackingData.clicksByButton[from.button] = {
16073 clickCount: 0,
16074 target: clickEvent.target,
16075 timeStamp: now,
16076 };
16077 }
16078 var clickHistory = trackingData.clicksByButton[from.button];
16079 if (clickHistory.target === clickEvent.target &&
16080 now - clickHistory.timeStamp < 200) {
16081 ++clickHistory.clickCount;
16082 }
16083 else {
16084 clickHistory.clickCount = 1;
16085 }
16086 clickHistory.target = clickEvent.target;
16087 clickHistory.timeStamp = now;
16088 clickEvent.detail = clickHistory.clickCount;
16089 // @see https://github.com/antvis/G/issues/1091
16090 if (!((_a = e.detail) === null || _a === void 0 ? void 0 : _a.preventClick)) {
16091 if (!_this.context.config.useNativeClickEvent &&
16092 (clickEvent.pointerType === 'mouse' ||
16093 clickEvent.pointerType === 'touch')) {
16094 _this.dispatchEvent(clickEvent, 'click');
16095 }
16096 _this.dispatchEvent(clickEvent, 'pointertap');
16097 }
16098 _this.freeEvent(clickEvent);
16099 }
16100 _this.freeEvent(e);
16101 };
16102 this.onPointerMove = function (from) {
16103 var e = _this.createPointerEvent(from, undefined, undefined, _this.context.config.alwaysTriggerPointerEventOnCanvas
16104 ? _this.rootTarget
16105 : undefined);
16106 var isMouse = e.pointerType === 'mouse' || e.pointerType === 'pen';
16107 var trackingData = _this.trackingData(from.pointerId);
16108 var outTarget = _this.findMountedTarget(trackingData.overTargets);
16109 // First pointerout/pointerleave
16110 if (trackingData.overTargets && outTarget !== e.target) {
16111 // pointerout always occurs on the overTarget when the pointer hovers over another element.
16112 var outType = from.type === 'mousemove' ? 'mouseout' : 'pointerout';
16113 var outEvent = _this.createPointerEvent(from, outType, outTarget || undefined);
16114 _this.dispatchEvent(outEvent, 'pointerout');
16115 if (isMouse)
16116 _this.dispatchEvent(outEvent, 'mouseout');
16117 // If the pointer exits overTarget and its descendants, then a pointerleave event is also fired. This event
16118 // is dispatched to all ancestors that no longer capture the pointer.
16119 if (!e.composedPath().includes(outTarget)) {
16120 var leaveEvent = _this.createPointerEvent(from, 'pointerleave', outTarget || undefined);
16121 leaveEvent.eventPhase = leaveEvent.AT_TARGET;
16122 while (leaveEvent.target &&
16123 !e.composedPath().includes(leaveEvent.target)) {
16124 leaveEvent.currentTarget = leaveEvent.target;
16125 _this.notifyTarget(leaveEvent);
16126 if (isMouse) {
16127 _this.notifyTarget(leaveEvent, 'mouseleave');
16128 }
16129 if (Node.isNode(leaveEvent.target)) {
16130 leaveEvent.target = leaveEvent.target.parentNode;
16131 }
16132 }
16133 _this.freeEvent(leaveEvent);
16134 }
16135 _this.freeEvent(outEvent);
16136 }
16137 // Then pointerover
16138 if (outTarget !== e.target) {
16139 // pointerover always occurs on the new overTarget
16140 var overType = from.type === 'mousemove' ? 'mouseover' : 'pointerover';
16141 var overEvent = _this.clonePointerEvent(e, overType); // clone faster
16142 _this.dispatchEvent(overEvent, 'pointerover');
16143 if (isMouse)
16144 _this.dispatchEvent(overEvent, 'mouseover');
16145 // Probe whether the newly hovered Node is an ancestor of the original overTarget.
16146 var overTargetAncestor = outTarget && Node.isNode(outTarget) && outTarget.parentNode;
16147 while (overTargetAncestor &&
16148 overTargetAncestor !==
16149 (Node.isNode(_this.rootTarget) && _this.rootTarget.parentNode)) {
16150 if (overTargetAncestor === e.target)
16151 break;
16152 overTargetAncestor = overTargetAncestor.parentNode;
16153 }
16154 // The pointer has entered a non-ancestor of the original overTarget. This means we need a pointerentered
16155 // event.
16156 var didPointerEnter = !overTargetAncestor ||
16157 overTargetAncestor ===
16158 (Node.isNode(_this.rootTarget) && _this.rootTarget.parentNode);
16159 if (didPointerEnter) {
16160 var enterEvent = _this.clonePointerEvent(e, 'pointerenter');
16161 enterEvent.eventPhase = enterEvent.AT_TARGET;
16162 while (enterEvent.target &&
16163 enterEvent.target !== outTarget &&
16164 enterEvent.target !==
16165 (Node.isNode(_this.rootTarget) && _this.rootTarget.parentNode)) {
16166 enterEvent.currentTarget = enterEvent.target;
16167 _this.notifyTarget(enterEvent);
16168 if (isMouse)
16169 _this.notifyTarget(enterEvent, 'mouseenter');
16170 if (Node.isNode(enterEvent.target)) {
16171 enterEvent.target = enterEvent.target.parentNode;
16172 }
16173 }
16174 _this.freeEvent(enterEvent);
16175 }
16176 _this.freeEvent(overEvent);
16177 }
16178 // Then pointermove
16179 _this.dispatchEvent(e, 'pointermove');
16180 if (e.pointerType === 'touch')
16181 _this.dispatchEvent(e, 'touchmove');
16182 if (isMouse) {
16183 _this.dispatchEvent(e, 'mousemove');
16184 _this.cursor = _this.getCursor(e.target);
16185 }
16186 trackingData.overTargets = e.composedPath();
16187 _this.freeEvent(e);
16188 };
16189 this.onPointerOut = function (from) {
16190 var trackingData = _this.trackingData(from.pointerId);
16191 if (trackingData.overTargets) {
16192 var isMouse = from.pointerType === 'mouse' || from.pointerType === 'pen';
16193 var outTarget = _this.findMountedTarget(trackingData.overTargets);
16194 // pointerout first
16195 var outEvent = _this.createPointerEvent(from, 'pointerout', outTarget || undefined);
16196 _this.dispatchEvent(outEvent);
16197 if (isMouse)
16198 _this.dispatchEvent(outEvent, 'mouseout');
16199 // pointerleave(s) are also dispatched b/c the pointer must've left rootTarget and its descendants to
16200 // get an upstream pointerout event (upstream events do not know rootTarget has descendants).
16201 var leaveEvent = _this.createPointerEvent(from, 'pointerleave', outTarget || undefined);
16202 leaveEvent.eventPhase = leaveEvent.AT_TARGET;
16203 while (leaveEvent.target &&
16204 leaveEvent.target !==
16205 (Node.isNode(_this.rootTarget) && _this.rootTarget.parentNode)) {
16206 leaveEvent.currentTarget = leaveEvent.target;
16207 _this.notifyTarget(leaveEvent);
16208 if (isMouse) {
16209 _this.notifyTarget(leaveEvent, 'mouseleave');
16210 }
16211 if (Node.isNode(leaveEvent.target)) {
16212 leaveEvent.target = leaveEvent.target.parentNode;
16213 }
16214 }
16215 trackingData.overTargets = null;
16216 _this.freeEvent(outEvent);
16217 _this.freeEvent(leaveEvent);
16218 }
16219 _this.cursor = null;
16220 };
16221 this.onPointerOver = function (from) {
16222 var trackingData = _this.trackingData(from.pointerId);
16223 var e = _this.createPointerEvent(from);
16224 var isMouse = e.pointerType === 'mouse' || e.pointerType === 'pen';
16225 _this.dispatchEvent(e, 'pointerover');
16226 if (isMouse)
16227 _this.dispatchEvent(e, 'mouseover');
16228 if (e.pointerType === 'mouse')
16229 _this.cursor = _this.getCursor(e.target);
16230 // pointerenter events must be fired since the pointer entered from upstream.
16231 var enterEvent = _this.clonePointerEvent(e, 'pointerenter');
16232 enterEvent.eventPhase = enterEvent.AT_TARGET;
16233 while (enterEvent.target &&
16234 enterEvent.target !==
16235 (Node.isNode(_this.rootTarget) && _this.rootTarget.parentNode)) {
16236 enterEvent.currentTarget = enterEvent.target;
16237 _this.notifyTarget(enterEvent);
16238 if (isMouse) {
16239 // mouseenter should not bubble
16240 // @see https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseenter_event#usage_notes
16241 _this.notifyTarget(enterEvent, 'mouseenter');
16242 }
16243 if (Node.isNode(enterEvent.target)) {
16244 enterEvent.target = enterEvent.target.parentNode;
16245 }
16246 }
16247 trackingData.overTargets = e.composedPath();
16248 _this.freeEvent(e);
16249 _this.freeEvent(enterEvent);
16250 };
16251 this.onPointerUpOutside = function (from) {
16252 var trackingData = _this.trackingData(from.pointerId);
16253 var pressTarget = _this.findMountedTarget(trackingData.pressTargetsByButton[from.button]);
16254 var e = _this.createPointerEvent(from);
16255 if (pressTarget) {
16256 var currentTarget = pressTarget;
16257 while (currentTarget) {
16258 e.currentTarget = currentTarget;
16259 _this.notifyTarget(e, 'pointerupoutside');
16260 if (e.pointerType === 'touch') ;
16261 else if (e.pointerType === 'mouse' || e.pointerType === 'pen') {
16262 _this.notifyTarget(e, e.button === 2 ? 'rightupoutside' : 'mouseupoutside');
16263 }
16264 if (Node.isNode(currentTarget)) {
16265 currentTarget = currentTarget.parentNode;
16266 }
16267 }
16268 delete trackingData.pressTargetsByButton[from.button];
16269 }
16270 _this.freeEvent(e);
16271 };
16272 this.onWheel = function (from) {
16273 var wheelEvent = _this.createWheelEvent(from);
16274 _this.dispatchEvent(wheelEvent);
16275 _this.freeEvent(wheelEvent);
16276 };
16277 this.onClick = function (from) {
16278 if (_this.context.config.useNativeClickEvent) {
16279 var e = _this.createPointerEvent(from);
16280 _this.dispatchEvent(e);
16281 _this.freeEvent(e);
16282 }
16283 };
16284 this.onPointerCancel = function (from) {
16285 var e = _this.createPointerEvent(from, undefined, undefined, _this.context.config.alwaysTriggerPointerEventOnCanvas
16286 ? _this.rootTarget
16287 : undefined);
16288 _this.dispatchEvent(e);
16289 _this.freeEvent(e);
16290 };
16291 }
16292 EventService.prototype.init = function () {
16293 this.rootTarget = this.context.renderingContext.root.parentNode; // document
16294 this.addEventMapping('pointerdown', this.onPointerDown);
16295 this.addEventMapping('pointerup', this.onPointerUp);
16296 this.addEventMapping('pointermove', this.onPointerMove);
16297 this.addEventMapping('pointerout', this.onPointerOut);
16298 this.addEventMapping('pointerleave', this.onPointerOut);
16299 this.addEventMapping('pointercancel', this.onPointerCancel);
16300 this.addEventMapping('pointerover', this.onPointerOver);
16301 this.addEventMapping('pointerupoutside', this.onPointerUpOutside);
16302 this.addEventMapping('wheel', this.onWheel);
16303 this.addEventMapping('click', this.onClick);
16304 };
16305 EventService.prototype.destroy = function () {
16306 this.emitter.removeAllListeners();
16307 this.mappingTable = {};
16308 this.mappingState = {};
16309 this.eventPool.clear();
16310 };
16311 EventService.prototype.client2Viewport = function (client) {
16312 var bbox = this.context.contextService.getBoundingClientRect();
16313 return new Point(client.x - ((bbox === null || bbox === void 0 ? void 0 : bbox.left) || 0), client.y - ((bbox === null || bbox === void 0 ? void 0 : bbox.top) || 0));
16314 };
16315 EventService.prototype.viewport2Client = function (canvas) {
16316 var bbox = this.context.contextService.getBoundingClientRect();
16317 return new Point(canvas.x + ((bbox === null || bbox === void 0 ? void 0 : bbox.left) || 0), canvas.y + ((bbox === null || bbox === void 0 ? void 0 : bbox.top) || 0));
16318 };
16319 EventService.prototype.viewport2Canvas = function (_a) {
16320 var x = _a.x, y = _a.y;
16321 var canvas = this.rootTarget.defaultView;
16322 var camera = canvas.getCamera();
16323 var _b = this.context.config, width = _b.width, height = _b.height;
16324 var projectionMatrixInverse = camera.getPerspectiveInverse();
16325 var worldMatrix = camera.getWorldTransform();
16326 var vpMatrix = multiply(this.tmpMatrix, worldMatrix, projectionMatrixInverse);
16327 var viewport = set$1(this.tmpVec3, (x / width) * 2 - 1, (1 - y / height) * 2 - 1, 0);
16328 transformMat4(viewport, viewport, vpMatrix);
16329 return new Point(viewport[0], viewport[1]);
16330 };
16331 EventService.prototype.canvas2Viewport = function (canvasP) {
16332 var canvas = this.rootTarget.defaultView;
16333 var camera = canvas.getCamera();
16334 // World -> Clip
16335 var projectionMatrix = camera.getPerspective();
16336 var viewMatrix = camera.getViewTransform();
16337 var vpMatrix = multiply(this.tmpMatrix, projectionMatrix, viewMatrix);
16338 var clip = set$1(this.tmpVec3, canvasP.x, canvasP.y, 0);
16339 transformMat4(this.tmpVec3, this.tmpVec3, vpMatrix);
16340 // Clip -> NDC -> Viewport, flip Y
16341 var _a = this.context.config, width = _a.width, height = _a.height;
16342 return new Point(((clip[0] + 1) / 2) * width, (1 - (clip[1] + 1) / 2) * height);
16343 };
16344 EventService.prototype.setPickHandler = function (pickHandler) {
16345 this.pickHandler = pickHandler;
16346 };
16347 EventService.prototype.addEventMapping = function (type, fn) {
16348 if (!this.mappingTable[type]) {
16349 this.mappingTable[type] = [];
16350 }
16351 this.mappingTable[type].push({
16352 fn: fn,
16353 priority: 0,
16354 });
16355 this.mappingTable[type].sort(function (a, b) { return a.priority - b.priority; });
16356 };
16357 EventService.prototype.mapEvent = function (e) {
16358 if (!this.rootTarget) {
16359 return;
16360 }
16361 var mappers = this.mappingTable[e.type];
16362 if (mappers) {
16363 for (var i = 0, j = mappers.length; i < j; i++) {
16364 mappers[i].fn(e);
16365 }
16366 }
16367 else {
16368 console.warn("[EventService]: Event mapping not defined for ".concat(e.type));
16369 }
16370 };
16371 EventService.prototype.dispatchEvent = function (e, type, skipPropagate) {
16372 // Canvas should skip
16373 if (!skipPropagate) {
16374 e.propagationStopped = false;
16375 e.propagationImmediatelyStopped = false;
16376 this.propagate(e, type);
16377 }
16378 else {
16379 // target phase
16380 e.eventPhase = e.AT_TARGET;
16381 var canvas = this.rootTarget.defaultView || null;
16382 e.currentTarget = canvas;
16383 this.notifyListeners(e, type);
16384 }
16385 this.emitter.emit(type || e.type, e);
16386 };
16387 EventService.prototype.propagate = function (e, type) {
16388 if (!e.target) {
16389 return;
16390 }
16391 // [target, parent, root, Canvas]
16392 var composedPath = e.composedPath();
16393 // event flow: capture -> target -> bubbling
16394 // capture phase
16395 e.eventPhase = e.CAPTURING_PHASE;
16396 for (var i = composedPath.length - 1; i >= 1; i--) {
16397 e.currentTarget = composedPath[i];
16398 this.notifyTarget(e, type);
16399 if (e.propagationStopped || e.propagationImmediatelyStopped)
16400 return;
16401 }
16402 // target phase
16403 e.eventPhase = e.AT_TARGET;
16404 e.currentTarget = e.target;
16405 this.notifyTarget(e, type);
16406 if (e.propagationStopped || e.propagationImmediatelyStopped)
16407 return;
16408 // find current target in composed path
16409 var index = composedPath.indexOf(e.currentTarget);
16410 // bubbling phase
16411 e.eventPhase = e.BUBBLING_PHASE;
16412 for (var i = index + 1; i < composedPath.length; i++) {
16413 e.currentTarget = composedPath[i];
16414 this.notifyTarget(e, type);
16415 if (e.propagationStopped || e.propagationImmediatelyStopped)
16416 return;
16417 }
16418 };
16419 EventService.prototype.propagationPath = function (target) {
16420 var propagationPath = [target];
16421 var canvas = this.rootTarget.defaultView || null;
16422 if (canvas && canvas === target) {
16423 propagationPath.unshift(canvas.document);
16424 return propagationPath;
16425 }
16426 for (var i = 0; i < PROPAGATION_LIMIT && target !== this.rootTarget; i++) {
16427 // if (Node.isNode(target) && !target.parentNode) {
16428 // throw new Error('Cannot find propagation path to disconnected target');
16429 // }
16430 if (Node.isNode(target) && target.parentNode) {
16431 // [target, parent, parent, root]
16432 propagationPath.push(target.parentNode);
16433 target = target.parentNode;
16434 }
16435 }
16436 if (canvas) {
16437 // @ts-ignore
16438 propagationPath.push(canvas);
16439 }
16440 return propagationPath;
16441 };
16442 EventService.prototype.hitTest = function (position) {
16443 var viewportX = position.viewportX, viewportY = position.viewportY;
16444 var _a = this.context.config, width = _a.width, height = _a.height, disableHitTesting = _a.disableHitTesting;
16445 // outside canvas
16446 if (viewportX < 0 ||
16447 viewportY < 0 ||
16448 viewportX > width ||
16449 viewportY > height) {
16450 return null;
16451 }
16452 return ((!disableHitTesting && this.pickHandler(position)) ||
16453 this.rootTarget || // return Document
16454 null);
16455 };
16456 /**
16457 * whether the native event trigger came from Canvas,
16458 * should account for HTML shape
16459 */
16460 EventService.prototype.isNativeEventFromCanvas = function (event) {
16461 var _a;
16462 var $el = this.context.contextService.getDomElement();
16463 var target = (_a = event.nativeEvent) === null || _a === void 0 ? void 0 : _a.target;
16464 if (target) {
16465 // from <canvas>
16466 if (target === $el) {
16467 return true;
16468 }
16469 // from <svg>
16470 if ($el && $el.contains) {
16471 return $el.contains(target);
16472 }
16473 }
16474 if (event.nativeEvent.composedPath) {
16475 return event.nativeEvent.composedPath().indexOf($el) > -1;
16476 }
16477 // account for Touch
16478 return false;
16479 };
16480 /**
16481 * Find HTML from composed path in native UI event.
16482 */
16483 EventService.prototype.getExistedHTML = function (event) {
16484 var e_1, _a;
16485 if (event.nativeEvent.composedPath) {
16486 try {
16487 for (var _b = __values(event.nativeEvent.composedPath()), _c = _b.next(); !_c.done; _c = _b.next()) {
16488 var eventTarget = _c.value;
16489 var existed = this.globalRuntime.nativeHTMLMap.get(eventTarget);
16490 if (existed) {
16491 return existed;
16492 }
16493 }
16494 }
16495 catch (e_1_1) { e_1 = { error: e_1_1 }; }
16496 finally {
16497 try {
16498 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
16499 }
16500 finally { if (e_1) throw e_1.error; }
16501 }
16502 }
16503 return null;
16504 };
16505 EventService.prototype.pickTarget = function (event) {
16506 return this.hitTest({
16507 clientX: event.clientX,
16508 clientY: event.clientY,
16509 viewportX: event.viewportX,
16510 viewportY: event.viewportY,
16511 x: event.canvasX,
16512 y: event.canvasY,
16513 });
16514 };
16515 EventService.prototype.createPointerEvent = function (from, type, target, fallbackTarget) {
16516 var event = this.allocateEvent(FederatedPointerEvent);
16517 this.copyPointerData(from, event);
16518 this.copyMouseData(from, event);
16519 this.copyData(from, event);
16520 event.nativeEvent = from.nativeEvent;
16521 event.originalEvent = from;
16522 var existedHTML = this.getExistedHTML(event);
16523 event.target =
16524 target !== null && target !== void 0 ? target : (existedHTML ||
16525 (this.isNativeEventFromCanvas(event) && this.pickTarget(event)) ||
16526 fallbackTarget);
16527 if (typeof type === 'string') {
16528 event.type = type;
16529 }
16530 return event;
16531 };
16532 EventService.prototype.createWheelEvent = function (from) {
16533 var event = this.allocateEvent(FederatedWheelEvent);
16534 this.copyWheelData(from, event);
16535 this.copyMouseData(from, event);
16536 this.copyData(from, event);
16537 event.nativeEvent = from.nativeEvent;
16538 event.originalEvent = from;
16539 var existedHTML = this.getExistedHTML(event);
16540 event.target =
16541 existedHTML ||
16542 (this.isNativeEventFromCanvas(event) && this.pickTarget(event));
16543 return event;
16544 };
16545 EventService.prototype.trackingData = function (id) {
16546 if (!this.mappingState.trackingData[id]) {
16547 this.mappingState.trackingData[id] = {
16548 pressTargetsByButton: {},
16549 clicksByButton: {},
16550 overTarget: null,
16551 };
16552 }
16553 return this.mappingState.trackingData[id];
16554 };
16555 EventService.prototype.cloneWheelEvent = function (from) {
16556 var event = this.allocateEvent(FederatedWheelEvent);
16557 event.nativeEvent = from.nativeEvent;
16558 event.originalEvent = from.originalEvent;
16559 this.copyWheelData(from, event);
16560 this.copyMouseData(from, event);
16561 this.copyData(from, event);
16562 event.target = from.target;
16563 event.path = from.composedPath().slice();
16564 event.type = from.type;
16565 return event;
16566 };
16567 EventService.prototype.clonePointerEvent = function (from, type) {
16568 var event = this.allocateEvent(FederatedPointerEvent);
16569 event.nativeEvent = from.nativeEvent;
16570 event.originalEvent = from.originalEvent;
16571 this.copyPointerData(from, event);
16572 this.copyMouseData(from, event);
16573 this.copyData(from, event);
16574 event.target = from.target;
16575 event.path = from.composedPath().slice();
16576 event.type = type !== null && type !== void 0 ? type : event.type;
16577 return event;
16578 };
16579 EventService.prototype.copyPointerData = function (from, to) {
16580 // if (
16581 // !(
16582 // from instanceof FederatedPointerEvent &&
16583 // to instanceof FederatedPointerEvent
16584 // )
16585 // )
16586 // return;
16587 to.pointerId = from.pointerId;
16588 to.width = from.width;
16589 to.height = from.height;
16590 to.isPrimary = from.isPrimary;
16591 to.pointerType = from.pointerType;
16592 to.pressure = from.pressure;
16593 to.tangentialPressure = from.tangentialPressure;
16594 to.tiltX = from.tiltX;
16595 to.tiltY = from.tiltY;
16596 to.twist = from.twist;
16597 };
16598 EventService.prototype.copyMouseData = function (from, to) {
16599 // if (
16600 // !(
16601 // from instanceof FederatedMouseEvent && to instanceof FederatedMouseEvent
16602 // )
16603 // )
16604 // return;
16605 to.altKey = from.altKey;
16606 to.button = from.button;
16607 to.buttons = from.buttons;
16608 to.ctrlKey = from.ctrlKey;
16609 to.metaKey = from.metaKey;
16610 to.shiftKey = from.shiftKey;
16611 to.client.copyFrom(from.client);
16612 to.movement.copyFrom(from.movement);
16613 to.canvas.copyFrom(from.canvas);
16614 to.screen.copyFrom(from.screen);
16615 to.global.copyFrom(from.global);
16616 to.offset.copyFrom(from.offset);
16617 };
16618 EventService.prototype.copyWheelData = function (from, to) {
16619 to.deltaMode = from.deltaMode;
16620 to.deltaX = from.deltaX;
16621 to.deltaY = from.deltaY;
16622 to.deltaZ = from.deltaZ;
16623 };
16624 EventService.prototype.copyData = function (from, to) {
16625 to.isTrusted = from.isTrusted;
16626 to.timeStamp = clock.now();
16627 to.type = from.type;
16628 to.detail = from.detail;
16629 to.view = from.view;
16630 to.page.copyFrom(from.page);
16631 to.viewport.copyFrom(from.viewport);
16632 };
16633 EventService.prototype.allocateEvent = function (constructor) {
16634 if (!this.eventPool.has(constructor)) {
16635 this.eventPool.set(constructor, []);
16636 }
16637 // @ts-ignore
16638 var event = this.eventPool.get(constructor).pop() ||
16639 new constructor(this);
16640 event.eventPhase = event.NONE;
16641 event.currentTarget = null;
16642 event.path = [];
16643 event.target = null;
16644 return event;
16645 };
16646 EventService.prototype.freeEvent = function (event) {
16647 if (event.manager !== this)
16648 throw new Error('It is illegal to free an event not managed by this EventBoundary!');
16649 var constructor = event.constructor;
16650 if (!this.eventPool.has(constructor)) {
16651 this.eventPool.set(constructor, []);
16652 }
16653 // @ts-ignore
16654 this.eventPool.get(constructor).push(event);
16655 };
16656 EventService.prototype.notifyTarget = function (e, type) {
16657 type = type !== null && type !== void 0 ? type : e.type;
16658 var key = e.eventPhase === e.CAPTURING_PHASE || e.eventPhase === e.AT_TARGET
16659 ? "".concat(type, "capture")
16660 : type;
16661 this.notifyListeners(e, key);
16662 if (e.eventPhase === e.AT_TARGET) {
16663 this.notifyListeners(e, type);
16664 }
16665 };
16666 EventService.prototype.notifyListeners = function (e, type) {
16667 // hack EventEmitter, stops if the `propagationImmediatelyStopped` flag is set
16668 // @ts-ignore
16669 var emitter = e.currentTarget.emitter;
16670 // @ts-ignore
16671 var listeners = emitter._events[type];
16672 if (!listeners)
16673 return;
16674 if ('fn' in listeners) {
16675 if (listeners.once) {
16676 emitter.removeListener(type, listeners.fn, undefined, true);
16677 }
16678 listeners.fn.call(e.currentTarget || listeners.context, e);
16679 // listeners.fn.call(listeners.context, e);
16680 }
16681 else {
16682 for (var i = 0; i < listeners.length && !e.propagationImmediatelyStopped; i++) {
16683 if (listeners[i].once) {
16684 emitter.removeListener(type, listeners[i].fn, undefined, true);
16685 }
16686 listeners[i].fn.call(e.currentTarget || listeners[i].context, e);
16687 // listeners[i].fn.call(listeners[i].context, e);
16688 }
16689 }
16690 };
16691 /**
16692 * some detached nodes may exist in propagation path, need to skip them
16693 */
16694 EventService.prototype.findMountedTarget = function (propagationPath) {
16695 if (!propagationPath) {
16696 return null;
16697 }
16698 var currentTarget = propagationPath[propagationPath.length - 1];
16699 for (var i = propagationPath.length - 2; i >= 0; i--) {
16700 var target = propagationPath[i];
16701 if (target === this.rootTarget ||
16702 (Node.isNode(target) && target.parentNode === currentTarget)) {
16703 currentTarget = propagationPath[i];
16704 }
16705 else {
16706 break;
16707 }
16708 }
16709 return currentTarget;
16710 };
16711 EventService.prototype.getCursor = function (target) {
16712 var tmp = target;
16713 while (tmp) {
16714 var cursor = isElement(tmp) && tmp.getAttribute('cursor');
16715 if (cursor) {
16716 return cursor;
16717 }
16718 tmp = Node.isNode(tmp) && tmp.parentNode;
16719 }
16720 };
16721 return EventService;
16722 }());
16723
16724 /**
16725 * used in following scenes:
16726 * - g `ctx.measureText`
16727 * - g-plugin-canvas-picker `ctx.isPointInPath`
16728 * - g-plugin-device-renderer `ctx.createLinearGradient` and generate texture
16729 *
16730 * @see https://blog.scottlogic.com/2020/03/19/offscreen-canvas.html
16731 */
16732 var OffscreenCanvasCreator = /** @class */ (function () {
16733 function OffscreenCanvasCreator() {
16734 }
16735 OffscreenCanvasCreator.prototype.getOrCreateCanvas = function (offscreenCanvas, contextAttributes) {
16736 if (this.canvas) {
16737 return this.canvas;
16738 }
16739 // user-defined offscreen canvas
16740 if (offscreenCanvas || runtime.offscreenCanvas) {
16741 this.canvas = offscreenCanvas || runtime.offscreenCanvas;
16742 this.context = this.canvas.getContext('2d', __assign({ willReadFrequently: true }, contextAttributes));
16743 }
16744 else {
16745 try {
16746 // OffscreenCanvas2D measureText can be up to 40% faster.
16747 this.canvas = new window.OffscreenCanvas(0, 0);
16748 this.context = this.canvas.getContext('2d', __assign({ willReadFrequently: true }, contextAttributes));
16749 if (!this.context || !this.context.measureText) {
16750 this.canvas = document.createElement('canvas');
16751 this.context = this.canvas.getContext('2d');
16752 }
16753 }
16754 catch (ex) {
16755 this.canvas = document.createElement('canvas');
16756 this.context = this.canvas.getContext('2d', __assign({ willReadFrequently: true }, contextAttributes));
16757 }
16758 }
16759 this.canvas.width = 10;
16760 this.canvas.height = 10;
16761 return this.canvas;
16762 };
16763 OffscreenCanvasCreator.prototype.getOrCreateContext = function (offscreenCanvas, contextAttributes) {
16764 if (this.context) {
16765 return this.context;
16766 }
16767 this.getOrCreateCanvas(offscreenCanvas, contextAttributes);
16768 return this.context;
16769 };
16770 return OffscreenCanvasCreator;
16771 }());
16772
16773 /**
16774 * why we need re-render
16775 */
16776 var RenderReason;
16777 (function (RenderReason) {
16778 RenderReason[RenderReason["CAMERA_CHANGED"] = 0] = "CAMERA_CHANGED";
16779 RenderReason[RenderReason["DISPLAY_OBJECT_CHANGED"] = 1] = "DISPLAY_OBJECT_CHANGED";
16780 RenderReason[RenderReason["NONE"] = 2] = "NONE";
16781 })(RenderReason || (RenderReason = {}));
16782
16783 /**
16784 * Use frame renderer implemented by `g-canvas/svg/webgl`, in every frame we do followings:
16785 * * update & merge dirty rectangles
16786 * * begin frame
16787 * * filter by visible
16788 * * sort by z-index in scene graph
16789 * * culling with strategies registered in `g-canvas/webgl`
16790 * * end frame
16791 */
16792 var RenderingService = /** @class */ (function () {
16793 function RenderingService(globalRuntime, context) {
16794 this.globalRuntime = globalRuntime;
16795 this.context = context;
16796 this.inited = false;
16797 this.stats = {
16798 /**
16799 * total display objects in scenegraph
16800 */
16801 total: 0,
16802 /**
16803 * number of display objects need to render in current frame
16804 */
16805 rendered: 0,
16806 };
16807 this.zIndexCounter = 0;
16808 this.hooks = {
16809 /**
16810 * called before any frame rendered
16811 */
16812 init: new SyncHook(),
16813 initAsync: new AsyncParallelHook(),
16814 /**
16815 * only dirty object which has sth changed will be rendered
16816 */
16817 dirtycheck: new SyncWaterfallHook(),
16818 /**
16819 * do culling
16820 */
16821 cull: new SyncWaterfallHook(),
16822 /**
16823 * called at beginning of each frame, won't get called if nothing to re-render
16824 */
16825 beginFrame: new SyncHook(),
16826 /**
16827 * called before every dirty object get rendered
16828 */
16829 beforeRender: new SyncHook(),
16830 /**
16831 * called when every dirty object rendering even it's culled
16832 */
16833 render: new SyncHook(),
16834 /**
16835 * called after every dirty object get rendered
16836 */
16837 afterRender: new SyncHook(),
16838 endFrame: new SyncHook(),
16839 destroy: new SyncHook(),
16840 /**
16841 * use async but faster method such as GPU-based picking in `g-plugin-device-renderer`
16842 */
16843 pick: new AsyncSeriesWaterfallHook(),
16844 /**
16845 * Unsafe but sync version of pick.
16846 */
16847 pickSync: new SyncWaterfallHook(),
16848 /**
16849 * used in event system
16850 */
16851 pointerDown: new SyncHook(),
16852 pointerUp: new SyncHook(),
16853 pointerMove: new SyncHook(),
16854 pointerOut: new SyncHook(),
16855 pointerOver: new SyncHook(),
16856 pointerWheel: new SyncHook(),
16857 pointerCancel: new SyncHook(),
16858 click: new SyncHook(),
16859 };
16860 }
16861 RenderingService.prototype.init = function (callback) {
16862 var _this = this;
16863 var context = __assign(__assign({}, this.globalRuntime), this.context);
16864 // register rendering plugins
16865 this.context.renderingPlugins.forEach(function (plugin) {
16866 plugin.apply(context, _this.globalRuntime);
16867 });
16868 this.hooks.init.call();
16869 if (this.hooks.initAsync.getCallbacksNum() === 0) {
16870 this.inited = true;
16871 callback();
16872 }
16873 else {
16874 this.hooks.initAsync.promise().then(function () {
16875 _this.inited = true;
16876 callback();
16877 });
16878 }
16879 };
16880 RenderingService.prototype.getStats = function () {
16881 return this.stats;
16882 };
16883 /**
16884 * Meet the following conditions:
16885 * * disable DirtyRectangleRendering
16886 * * camera changed
16887 */
16888 RenderingService.prototype.disableDirtyRectangleRendering = function () {
16889 var renderer = this.context.config.renderer;
16890 var enableDirtyRectangleRendering = renderer.getConfig().enableDirtyRectangleRendering;
16891 return (!enableDirtyRectangleRendering ||
16892 this.context.renderingContext.renderReasons.has(RenderReason.CAMERA_CHANGED));
16893 };
16894 RenderingService.prototype.render = function (canvasConfig, rerenderCallback) {
16895 var _this = this;
16896 this.stats.total = 0;
16897 this.stats.rendered = 0;
16898 this.zIndexCounter = 0;
16899 var renderingContext = this.context.renderingContext;
16900 this.globalRuntime.sceneGraphService.syncHierarchy(renderingContext.root);
16901 this.globalRuntime.sceneGraphService.triggerPendingEvents();
16902 if (renderingContext.renderReasons.size && this.inited) {
16903 // @ts-ignore
16904 renderingContext.dirtyRectangleRenderingDisabled =
16905 this.disableDirtyRectangleRendering();
16906 var onlyCameraChanged = renderingContext.renderReasons.size === 1 &&
16907 renderingContext.renderReasons.has(RenderReason.CAMERA_CHANGED);
16908 var shouldTriggerRenderHooks = !canvasConfig.disableRenderHooks ||
16909 !(canvasConfig.disableRenderHooks && onlyCameraChanged);
16910 if (shouldTriggerRenderHooks) {
16911 this.renderDisplayObject(renderingContext.root, canvasConfig, renderingContext);
16912 }
16913 this.hooks.beginFrame.call();
16914 if (shouldTriggerRenderHooks) {
16915 renderingContext.renderListCurrentFrame.forEach(function (object) {
16916 _this.hooks.beforeRender.call(object);
16917 _this.hooks.render.call(object);
16918 _this.hooks.afterRender.call(object);
16919 });
16920 }
16921 this.hooks.endFrame.call();
16922 renderingContext.renderListCurrentFrame = [];
16923 renderingContext.renderReasons.clear();
16924 rerenderCallback();
16925 }
16926 // console.log('stats', this.stats);
16927 };
16928 RenderingService.prototype.renderDisplayObject = function (displayObject, canvasConfig, renderingContext) {
16929 var _this = this;
16930 var _a = canvasConfig.renderer.getConfig(), enableDirtyCheck = _a.enableDirtyCheck, enableCulling = _a.enableCulling;
16931 // recalc style values
16932 if (this.globalRuntime.enableCSSParsing) {
16933 this.globalRuntime.styleValueRegistry.recalc(displayObject);
16934 }
16935 // TODO: relayout
16936 // dirtycheck first
16937 var renderable = displayObject.renderable;
16938 var objectChanged = enableDirtyCheck
16939 ? // @ts-ignore
16940 renderable.dirty || renderingContext.dirtyRectangleRenderingDisabled
16941 ? displayObject
16942 : null
16943 : displayObject;
16944 if (objectChanged) {
16945 var objectToRender = enableCulling
16946 ? this.hooks.cull.call(objectChanged, this.context.camera)
16947 : objectChanged;
16948 if (objectToRender) {
16949 this.stats.rendered++;
16950 renderingContext.renderListCurrentFrame.push(objectToRender);
16951 }
16952 }
16953 displayObject.renderable.dirty = false;
16954 displayObject.sortable.renderOrder = this.zIndexCounter++;
16955 this.stats.total++;
16956 // sort is very expensive, use cached result if possible
16957 var sortable = displayObject.sortable;
16958 if (sortable.dirty) {
16959 this.sort(displayObject, sortable);
16960 sortable.dirty = false;
16961 sortable.dirtyChildren = [];
16962 sortable.dirtyReason = undefined;
16963 }
16964 // recursive rendering its children
16965 (sortable.sorted || displayObject.childNodes).forEach(function (child) {
16966 _this.renderDisplayObject(child, canvasConfig, renderingContext);
16967 });
16968 };
16969 RenderingService.prototype.sort = function (displayObject, sortable) {
16970 if (sortable.sorted &&
16971 sortable.dirtyReason !== SortReason.Z_INDEX_CHANGED) {
16972 // avoid re-sorting the whole children list
16973 sortable.dirtyChildren.forEach(function (child) {
16974 var index = displayObject.childNodes.indexOf(child);
16975 if (index === -1) {
16976 // remove from sorted list
16977 var index_1 = sortable.sorted.indexOf(child);
16978 if (index_1 >= 0) {
16979 sortable.sorted.splice(index_1, 1);
16980 }
16981 }
16982 else {
16983 if (sortable.sorted.length === 0) {
16984 sortable.sorted.push(child);
16985 }
16986 else {
16987 var index_2 = sortedIndex(sortable.sorted, child);
16988 sortable.sorted.splice(index_2, 0, child);
16989 }
16990 }
16991 });
16992 }
16993 else {
16994 sortable.sorted = displayObject.childNodes.slice().sort(sortByZIndex);
16995 }
16996 };
16997 RenderingService.prototype.destroy = function () {
16998 this.inited = false;
16999 this.hooks.destroy.call();
17000 this.globalRuntime.sceneGraphService.clearPendingEvents();
17001 };
17002 RenderingService.prototype.dirtify = function () {
17003 // need re-render
17004 this.context.renderingContext.renderReasons.add(RenderReason.DISPLAY_OBJECT_CHANGED);
17005 };
17006 return RenderingService;
17007 }());
17008
17009 var ATTRIBUTE_REGEXP = /\[\s*(.*)=(.*)\s*\]/;
17010 /**
17011 * support the following DOM API:
17012 * * getElementById
17013 * * getElementsByClassName
17014 * * getElementsByName
17015 * * getElementsByTag
17016 * * querySelector
17017 * * querySelectorAll
17018 */
17019 var DefaultSceneGraphSelector = /** @class */ (function () {
17020 function DefaultSceneGraphSelector() {
17021 }
17022 DefaultSceneGraphSelector.prototype.selectOne = function (query, root) {
17023 var _this = this;
17024 if (query.startsWith('.')) {
17025 return root.find(function (node) {
17026 // return !node.shadow && node.id === query.substring(1);
17027 return (((node === null || node === void 0 ? void 0 : node.classList) || []).indexOf(_this.getIdOrClassname(query)) > -1);
17028 });
17029 }
17030 else if (query.startsWith('#')) {
17031 // getElementById('id')
17032 return root.find(function (node) {
17033 // return !node.shadow && node.id === query.substring(1);
17034 return node.id === _this.getIdOrClassname(query);
17035 });
17036 }
17037 else if (query.startsWith('[')) {
17038 var _a = this.getAttribute(query), name_1 = _a.name, value_1 = _a.value;
17039 if (name_1) {
17040 // getElementByName();
17041 return root.find(function (node) {
17042 return root !== node &&
17043 (name_1 === 'name'
17044 ? node.name === value_1
17045 : _this.attributeToString(node, name_1) === value_1);
17046 });
17047 }
17048 else {
17049 return null;
17050 }
17051 }
17052 else {
17053 // getElementsByTag('circle');
17054 return root.find(function (node) { return root !== node && node.nodeName === query; });
17055 }
17056 };
17057 DefaultSceneGraphSelector.prototype.selectAll = function (query, root) {
17058 var _this = this;
17059 // only support `[name="${name}"]` `.className` `#id`
17060 if (query.startsWith('.')) {
17061 // getElementsByClassName('className');
17062 // should not include itself
17063 return root.findAll(function (node) {
17064 return root !== node &&
17065 ((node === null || node === void 0 ? void 0 : node.classList) || []).indexOf(_this.getIdOrClassname(query)) > -1;
17066 });
17067 }
17068 else if (query.startsWith('#')) {
17069 return root.findAll(function (node) {
17070 return root !== node &&
17071 node.id === _this.getIdOrClassname(query);
17072 });
17073 }
17074 else if (query.startsWith('[')) {
17075 var _a = this.getAttribute(query), name_2 = _a.name, value_2 = _a.value;
17076 if (name_2) {
17077 // getElementsByName();
17078 return root.findAll(function (node) {
17079 return root !== node &&
17080 (name_2 === 'name'
17081 ? node.name === value_2
17082 : _this.attributeToString(node, name_2) === value_2);
17083 });
17084 }
17085 else {
17086 return [];
17087 }
17088 }
17089 else {
17090 // getElementsByTag('circle');
17091 return root.findAll(function (node) { return root !== node && node.nodeName === query; });
17092 }
17093 };
17094 DefaultSceneGraphSelector.prototype.is = function (query, node) {
17095 // a simple `matches` implementation
17096 if (query.startsWith('.')) {
17097 return node.className === this.getIdOrClassname(query);
17098 }
17099 else if (query.startsWith('#')) {
17100 return node.id === this.getIdOrClassname(query);
17101 }
17102 else if (query.startsWith('[')) {
17103 var _a = this.getAttribute(query), name_3 = _a.name, value = _a.value;
17104 return name_3 === 'name'
17105 ? node.name === value
17106 : this.attributeToString(node, name_3) === value;
17107 }
17108 else {
17109 return node.nodeName === query;
17110 }
17111 };
17112 DefaultSceneGraphSelector.prototype.getIdOrClassname = function (query) {
17113 return query.substring(1);
17114 };
17115 DefaultSceneGraphSelector.prototype.getAttribute = function (query) {
17116 var matches = query.match(ATTRIBUTE_REGEXP);
17117 var name = '';
17118 var value = '';
17119 if (matches && matches.length > 2) {
17120 name = matches[1].replace(/"/g, '');
17121 value = matches[2].replace(/"/g, '');
17122 }
17123 return { name: name, value: value };
17124 };
17125 DefaultSceneGraphSelector.prototype.attributeToString = function (node, name) {
17126 if (!node.getAttribute) {
17127 return '';
17128 }
17129 var value = node.getAttribute(name);
17130 if (isNil(value)) {
17131 return '';
17132 }
17133 if (value.toString) {
17134 return value.toString();
17135 }
17136 return '';
17137 };
17138 return DefaultSceneGraphSelector;
17139 }());
17140
17141 var MutationEvent = /** @class */ (function (_super) {
17142 __extends(MutationEvent, _super);
17143 function MutationEvent(typeArg, relatedNode, prevValue, newValue, attrName, attrChange, prevParsedValue, newParsedValue) {
17144 var _this = _super.call(this, null) || this;
17145 _this.relatedNode = relatedNode;
17146 _this.prevValue = prevValue;
17147 _this.newValue = newValue;
17148 _this.attrName = attrName;
17149 _this.attrChange = attrChange;
17150 _this.prevParsedValue = prevParsedValue;
17151 _this.newParsedValue = newParsedValue;
17152 _this.type = typeArg;
17153 return _this;
17154 }
17155 MutationEvent.ADDITION = 2;
17156 MutationEvent.MODIFICATION = 1;
17157 MutationEvent.REMOVAL = 3;
17158 return MutationEvent;
17159 }(FederatedEvent));
17160
17161 /**
17162 * built-in events for element
17163 * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent
17164 *
17165 * TODO: use MutationObserver instead
17166 * @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
17167 */
17168 var ElementEvent;
17169 (function (ElementEvent) {
17170 ElementEvent["REPARENT"] = "reparent";
17171 ElementEvent["DESTROY"] = "destroy";
17172 /**
17173 * @see https://www.w3.org/TR/DOM-Level-3-Events/#event-type-DOMAttrModified
17174 */
17175 ElementEvent["ATTR_MODIFIED"] = "DOMAttrModified";
17176 /**
17177 * it has been inserted
17178 * @see https://www.w3.org/TR/DOM-Level-3-Events/#event-type-DOMNodeInserted
17179 */
17180 ElementEvent["INSERTED"] = "DOMNodeInserted";
17181 /**
17182 * it is being removed
17183 * @see https://www.w3.org/TR/DOM-Level-3-Events/#event-type-DOMNodeRemoved
17184 */
17185 ElementEvent["REMOVED"] = "removed";
17186 /**
17187 * @see https://www.w3.org/TR/DOM-Level-3-Events/#domnodeinsertedintodocument
17188 */
17189 ElementEvent["MOUNTED"] = "DOMNodeInsertedIntoDocument";
17190 /**
17191 * @see https://www.w3.org/TR/DOM-Level-3-Events/#domnoderemovedfromdocument
17192 */
17193 ElementEvent["UNMOUNTED"] = "DOMNodeRemovedFromDocument";
17194 ElementEvent["BOUNDS_CHANGED"] = "bounds-changed";
17195 ElementEvent["CULLED"] = "culled";
17196 })(ElementEvent || (ElementEvent = {}));
17197
17198 function markRenderableDirty(e) {
17199 var renderable = e.renderable;
17200 if (renderable) {
17201 renderable.renderBoundsDirty = true;
17202 renderable.boundsDirty = true;
17203 }
17204 }
17205 var reparentEvent = new MutationEvent(ElementEvent.REPARENT, null, '', '', '', 0, '', '');
17206 /**
17207 * update transform in scene graph
17208 *
17209 * @see https://community.khronos.org/t/scene-graphs/50542/7
17210 */
17211 var DefaultSceneGraphService = /** @class */ (function () {
17212 function DefaultSceneGraphService(runtime) {
17213 var _this = this;
17214 this.runtime = runtime;
17215 this.pendingEvents = [];
17216 this.boundsChangedEvent = new CustomEvent(ElementEvent.BOUNDS_CHANGED);
17217 /**
17218 * rotate in world space
17219 */
17220 this.rotate = (function () {
17221 var parentInvertRotation = create$4();
17222 return function (element, degrees, y, z) {
17223 if (y === void 0) { y = 0; }
17224 if (z === void 0) { z = 0; }
17225 if (typeof degrees === 'number') {
17226 degrees = fromValues$2(degrees, y, z);
17227 }
17228 var transform = element.transformable;
17229 if (element.parentNode === null ||
17230 !element.parentNode.transformable) {
17231 _this.rotateLocal(element, degrees);
17232 }
17233 else {
17234 var rotation = create$4();
17235 fromEuler(rotation, degrees[0], degrees[1], degrees[2]);
17236 var rot = _this.getRotation(element);
17237 var parentRot = _this.getRotation(element.parentNode);
17238 copy$3(parentInvertRotation, parentRot);
17239 invert$1(parentInvertRotation, parentInvertRotation);
17240 multiply$2(rotation, parentInvertRotation, rotation);
17241 multiply$2(transform.localRotation, rotation, rot);
17242 normalize$2(transform.localRotation, transform.localRotation);
17243 _this.dirtifyLocal(element, transform);
17244 }
17245 };
17246 })();
17247 /**
17248 * rotate in local space
17249 * @see @see https://docs.microsoft.com/en-us/windows/win32/api/directxmath/nf-directxmath-xmquaternionrotationrollpitchyaw
17250 */
17251 this.rotateLocal = (function () {
17252 var rotation = create$4();
17253 return function (element, degrees, y, z) {
17254 if (y === void 0) { y = 0; }
17255 if (z === void 0) { z = 0; }
17256 if (typeof degrees === 'number') {
17257 degrees = fromValues$2(degrees, y, z);
17258 }
17259 var transform = element.transformable;
17260 fromEuler(rotation, degrees[0], degrees[1], degrees[2]);
17261 mul$1(transform.localRotation, transform.localRotation, rotation);
17262 _this.dirtifyLocal(element, transform);
17263 };
17264 })();
17265 /**
17266 * set euler angles(degrees) in world space
17267 */
17268 this.setEulerAngles = (function () {
17269 var invParentRot = create$4();
17270 return function (element, degrees, y, z) {
17271 if (y === void 0) { y = 0; }
17272 if (z === void 0) { z = 0; }
17273 if (typeof degrees === 'number') {
17274 degrees = fromValues$2(degrees, y, z);
17275 }
17276 var transform = element.transformable;
17277 if (element.parentNode === null ||
17278 !element.parentNode.transformable) {
17279 _this.setLocalEulerAngles(element, degrees);
17280 }
17281 else {
17282 fromEuler(transform.localRotation, degrees[0], degrees[1], degrees[2]);
17283 var parentRotation = _this.getRotation(element.parentNode);
17284 copy$3(invParentRot, invert$1(create$4(), parentRotation));
17285 mul$1(transform.localRotation, transform.localRotation, invParentRot);
17286 _this.dirtifyLocal(element, transform);
17287 }
17288 };
17289 })();
17290 /**
17291 * translate in local space
17292 *
17293 * @example
17294 * ```
17295 * translateLocal(x, y, z)
17296 * translateLocal(vec3(x, y, z))
17297 * ```
17298 */
17299 this.translateLocal = (function () {
17300 return function (element, translation, y, z) {
17301 if (y === void 0) { y = 0; }
17302 if (z === void 0) { z = 0; }
17303 if (typeof translation === 'number') {
17304 translation = fromValues$2(translation, y, z);
17305 }
17306 var transform = element.transformable;
17307 if (equals$1(translation, create$2())) {
17308 return;
17309 }
17310 transformQuat(translation, translation, transform.localRotation);
17311 add$1(transform.localPosition, transform.localPosition, translation);
17312 _this.dirtifyLocal(element, transform);
17313 };
17314 })();
17315 /**
17316 * move to position in world space
17317 *
17318 * 对应 g 原版的 move/moveTo
17319 * @see https://github.com/antvis/g/blob/master/packages/g-base/src/abstract/element.ts#L684-L689
17320 */
17321 this.setPosition = (function () {
17322 var parentInvertMatrix = create$1();
17323 var tmpPosition = create$2();
17324 return function (element, position) {
17325 var transform = element.transformable;
17326 tmpPosition[0] = position[0];
17327 tmpPosition[1] = position[1];
17328 tmpPosition[2] = position[2] || 0;
17329 if (equals$1(_this.getPosition(element), tmpPosition)) {
17330 return;
17331 }
17332 copy$1(transform.position, tmpPosition);
17333 if (element.parentNode === null ||
17334 !element.parentNode.transformable) {
17335 copy$1(transform.localPosition, tmpPosition);
17336 }
17337 else {
17338 var parentTransform = element.parentNode.transformable;
17339 copy(parentInvertMatrix, parentTransform.worldTransform);
17340 invert(parentInvertMatrix, parentInvertMatrix);
17341 transformMat4(transform.localPosition, tmpPosition, parentInvertMatrix);
17342 }
17343 _this.dirtifyLocal(element, transform);
17344 };
17345 })();
17346 /**
17347 * move to position in local space
17348 */
17349 this.setLocalPosition = (function () {
17350 var tmpPosition = create$2();
17351 return function (element, position) {
17352 var transform = element.transformable;
17353 tmpPosition[0] = position[0];
17354 tmpPosition[1] = position[1];
17355 tmpPosition[2] = position[2] || 0;
17356 if (equals$1(transform.localPosition, tmpPosition)) {
17357 return;
17358 }
17359 copy$1(transform.localPosition, tmpPosition);
17360 _this.dirtifyLocal(element, transform);
17361 };
17362 })();
17363 /**
17364 * translate in world space
17365 *
17366 * @example
17367 * ```
17368 * translate(x, y, z)
17369 * translate(vec3(x, y, z))
17370 * ```
17371 *
17372 * 对应 g 原版的 translate 2D
17373 * @see https://github.com/antvis/g/blob/master/packages/g-base/src/abstract/element.ts#L665-L676
17374 */
17375 this.translate = (function () {
17376 var zeroVec3 = create$2();
17377 var tmpVec3 = create$2();
17378 var tr = create$2();
17379 return function (element, translation, y, z) {
17380 if (y === void 0) { y = 0; }
17381 if (z === void 0) { z = 0; }
17382 if (typeof translation === 'number') {
17383 translation = set$1(tmpVec3, translation, y, z);
17384 }
17385 if (equals$1(translation, zeroVec3)) {
17386 return;
17387 }
17388 add$1(tr, _this.getPosition(element), translation);
17389 _this.setPosition(element, tr);
17390 };
17391 })();
17392 this.setRotation = function () {
17393 var parentInvertRotation = create$4();
17394 return function (element, rotation, y, z, w) {
17395 var transform = element.transformable;
17396 if (typeof rotation === 'number') {
17397 rotation = fromValues$4(rotation, y, z, w);
17398 }
17399 if (element.parentNode === null ||
17400 !element.parentNode.transformable) {
17401 _this.setLocalRotation(element, rotation);
17402 }
17403 else {
17404 var parentRot = _this.getRotation(element.parentNode);
17405 copy$3(parentInvertRotation, parentRot);
17406 invert$1(parentInvertRotation, parentInvertRotation);
17407 multiply$2(transform.localRotation, parentInvertRotation, rotation);
17408 normalize$2(transform.localRotation, transform.localRotation);
17409 _this.dirtifyLocal(element, transform);
17410 }
17411 };
17412 };
17413 this.displayObjectDependencyMap = new WeakMap();
17414 this.calcLocalTransform = (function () {
17415 var tmpMat = create$1();
17416 var tmpPosition = create$2();
17417 var tmpQuat = fromValues$4(0, 0, 0, 1);
17418 return function (transform) {
17419 var hasSkew = transform.localSkew[0] !== 0 || transform.localSkew[1] !== 0;
17420 if (hasSkew) {
17421 fromRotationTranslationScaleOrigin(transform.localTransform, transform.localRotation, transform.localPosition, fromValues$2(1, 1, 1), transform.origin);
17422 // apply skew2D
17423 if (transform.localSkew[0] !== 0 || transform.localSkew[1] !== 0) {
17424 var tmpMat4 = identity$1(tmpMat);
17425 tmpMat4[4] = Math.tan(transform.localSkew[0]);
17426 tmpMat4[1] = Math.tan(transform.localSkew[1]);
17427 multiply(transform.localTransform, transform.localTransform, tmpMat4);
17428 }
17429 var scaling = fromRotationTranslationScaleOrigin(tmpMat, tmpQuat, tmpPosition, transform.localScale, transform.origin);
17430 multiply(transform.localTransform, transform.localTransform, scaling);
17431 }
17432 else {
17433 // @see https://github.com/mattdesl/css-mat4/blob/master/index.js
17434 fromRotationTranslationScaleOrigin(transform.localTransform, transform.localRotation, transform.localPosition, transform.localScale, transform.origin);
17435 }
17436 };
17437 })();
17438 }
17439 DefaultSceneGraphService.prototype.matches = function (query, root) {
17440 return this.runtime.sceneGraphSelector.is(query, root);
17441 };
17442 DefaultSceneGraphService.prototype.querySelector = function (query, root) {
17443 return this.runtime.sceneGraphSelector.selectOne(query, root);
17444 };
17445 DefaultSceneGraphService.prototype.querySelectorAll = function (query, root) {
17446 return this.runtime.sceneGraphSelector.selectAll(query, root);
17447 // .filter((node) => !node.shadow);
17448 };
17449 DefaultSceneGraphService.prototype.attach = function (child, parent, index) {
17450 var _a, _b;
17451 var detached = false;
17452 if (child.parentNode) {
17453 detached = child.parentNode !== parent;
17454 this.detach(child);
17455 }
17456 child.parentNode = parent;
17457 if (!isNil(index)) {
17458 child.parentNode.childNodes.splice(index, 0, child);
17459 }
17460 else {
17461 child.parentNode.childNodes.push(child);
17462 }
17463 // parent needs re-sort
17464 var sortable = parent.sortable;
17465 if (((_a = sortable === null || sortable === void 0 ? void 0 : sortable.sorted) === null || _a === void 0 ? void 0 : _a.length) ||
17466 ((_b = child.style) === null || _b === void 0 ? void 0 : _b.zIndex)) {
17467 if (sortable.dirtyChildren.indexOf(child) === -1) {
17468 sortable.dirtyChildren.push(child);
17469 }
17470 // if (sortable) {
17471 // only child has z-Index
17472 sortable.dirty = true;
17473 sortable.dirtyReason = SortReason.ADDED;
17474 }
17475 // this.updateGraphDepth(child);
17476 var transform = child.transformable;
17477 if (transform) {
17478 this.dirtifyWorld(child, transform);
17479 }
17480 if (transform.frozen) {
17481 this.unfreezeParentToRoot(child);
17482 }
17483 if (detached) {
17484 child.dispatchEvent(reparentEvent);
17485 }
17486 };
17487 DefaultSceneGraphService.prototype.detach = function (child) {
17488 var _a, _b;
17489 if (child.parentNode) {
17490 var transform = child.transformable;
17491 // if (transform) {
17492 // const worldTransform = this.getWorldTransform(child, transform);
17493 // mat4.getScaling(transform.localScale, worldTransform);
17494 // mat4.getTranslation(transform.localPosition, worldTransform);
17495 // mat4.getRotation(transform.localRotation, worldTransform);
17496 // transform.localDirtyFlag = true;
17497 // }
17498 // parent needs re-sort
17499 var sortable = child.parentNode.sortable;
17500 // if (sortable) {
17501 if (((_a = sortable === null || sortable === void 0 ? void 0 : sortable.sorted) === null || _a === void 0 ? void 0 : _a.length) ||
17502 ((_b = child.style) === null || _b === void 0 ? void 0 : _b.zIndex)) {
17503 if (sortable.dirtyChildren.indexOf(child) === -1) {
17504 sortable.dirtyChildren.push(child);
17505 }
17506 sortable.dirty = true;
17507 sortable.dirtyReason = SortReason.REMOVED;
17508 }
17509 var index = child.parentNode.childNodes.indexOf(child);
17510 if (index > -1) {
17511 child.parentNode.childNodes.splice(index, 1);
17512 }
17513 if (transform) {
17514 this.dirtifyWorld(child, transform);
17515 }
17516 child.parentNode = null;
17517 }
17518 };
17519 DefaultSceneGraphService.prototype.getOrigin = function (element) {
17520 return element.transformable.origin;
17521 };
17522 /**
17523 * same as pivot in Pixi.js
17524 *
17525 * @see https://stackoverflow.com/questions/40748452/how-to-change-css-transform-origin-but-preserve-transformation
17526 */
17527 DefaultSceneGraphService.prototype.setOrigin = function (element, origin, y, z) {
17528 if (y === void 0) { y = 0; }
17529 if (z === void 0) { z = 0; }
17530 if (typeof origin === 'number') {
17531 origin = [origin, y, z];
17532 }
17533 var transform = element.transformable;
17534 if (origin[0] === transform.origin[0] &&
17535 origin[1] === transform.origin[1] &&
17536 origin[2] === transform.origin[2]) {
17537 return;
17538 }
17539 var originVec = transform.origin;
17540 // const delta = vec3.subtract(vec3.create(), origin, originVec);
17541 // vec3.add(transform.localPosition, transform.localPosition, delta);
17542 // update origin
17543 originVec[0] = origin[0];
17544 originVec[1] = origin[1];
17545 originVec[2] = origin[2] || 0;
17546 this.dirtifyLocal(element, transform);
17547 };
17548 /**
17549 * set euler angles(degrees) in local space
17550 */
17551 DefaultSceneGraphService.prototype.setLocalEulerAngles = function (element, degrees, y, z) {
17552 if (y === void 0) { y = 0; }
17553 if (z === void 0) { z = 0; }
17554 if (typeof degrees === 'number') {
17555 degrees = fromValues$2(degrees, y, z);
17556 }
17557 var transform = element.transformable;
17558 fromEuler(transform.localRotation, degrees[0], degrees[1], degrees[2]);
17559 this.dirtifyLocal(element, transform);
17560 };
17561 /**
17562 * scale in local space
17563 */
17564 DefaultSceneGraphService.prototype.scaleLocal = function (element, scaling) {
17565 var transform = element.transformable;
17566 multiply$1(transform.localScale, transform.localScale, fromValues$2(scaling[0], scaling[1], scaling[2] || 1));
17567 this.dirtifyLocal(element, transform);
17568 };
17569 DefaultSceneGraphService.prototype.setLocalScale = function (element, scaling) {
17570 var transform = element.transformable;
17571 var updatedScaling = fromValues$2(scaling[0], scaling[1], scaling[2] || transform.localScale[2]);
17572 if (equals$1(updatedScaling, transform.localScale)) {
17573 return;
17574 }
17575 copy$1(transform.localScale, updatedScaling);
17576 this.dirtifyLocal(element, transform);
17577 };
17578 DefaultSceneGraphService.prototype.setLocalRotation = function (element, rotation, y, z, w) {
17579 if (typeof rotation === 'number') {
17580 rotation = fromValues$4(rotation, y, z, w);
17581 }
17582 var transform = element.transformable;
17583 copy$3(transform.localRotation, rotation);
17584 this.dirtifyLocal(element, transform);
17585 };
17586 DefaultSceneGraphService.prototype.setLocalSkew = function (element, skew, y) {
17587 if (typeof skew === 'number') {
17588 skew = fromValues$5(skew, y);
17589 }
17590 var transform = element.transformable;
17591 copy$4(transform.localSkew, skew);
17592 this.dirtifyLocal(element, transform);
17593 };
17594 DefaultSceneGraphService.prototype.dirtifyLocal = function (element, transform) {
17595 if (!transform.localDirtyFlag) {
17596 transform.localDirtyFlag = true;
17597 if (!transform.dirtyFlag) {
17598 this.dirtifyWorld(element, transform);
17599 }
17600 }
17601 };
17602 DefaultSceneGraphService.prototype.dirtifyWorld = function (element, transform) {
17603 if (!transform.dirtyFlag) {
17604 this.unfreezeParentToRoot(element);
17605 }
17606 this.dirtifyWorldInternal(element, transform);
17607 this.dirtifyToRoot(element, true);
17608 };
17609 DefaultSceneGraphService.prototype.triggerPendingEvents = function () {
17610 var _this = this;
17611 var set = new Set();
17612 var trigger = function (element, detail) {
17613 if (element.isConnected && !set.has(element.entity)) {
17614 _this.boundsChangedEvent.detail = detail;
17615 _this.boundsChangedEvent.target = element;
17616 if (element.isMutationObserved) {
17617 element.dispatchEvent(_this.boundsChangedEvent);
17618 }
17619 else {
17620 element.ownerDocument.defaultView.dispatchEvent(_this.boundsChangedEvent, true);
17621 }
17622 set.add(element.entity);
17623 }
17624 };
17625 this.pendingEvents.forEach(function (_a) {
17626 var _b = __read(_a, 2), element = _b[0], detail = _b[1];
17627 if (detail.affectChildren) {
17628 element.forEach(function (e) {
17629 trigger(e, detail);
17630 });
17631 }
17632 else {
17633 trigger(element, detail);
17634 }
17635 });
17636 this.clearPendingEvents();
17637 set.clear();
17638 };
17639 DefaultSceneGraphService.prototype.clearPendingEvents = function () {
17640 this.pendingEvents = [];
17641 };
17642 DefaultSceneGraphService.prototype.dirtifyToRoot = function (element, affectChildren) {
17643 if (affectChildren === void 0) { affectChildren = false; }
17644 var p = element;
17645 // only need to re-render itself
17646 if (p.renderable) {
17647 p.renderable.dirty = true;
17648 }
17649 while (p) {
17650 markRenderableDirty(p);
17651 p = p.parentNode;
17652 }
17653 if (affectChildren) {
17654 element.forEach(function (e) {
17655 markRenderableDirty(e);
17656 });
17657 }
17658 // inform dependencies
17659 this.informDependentDisplayObjects(element);
17660 // reuse the same custom event
17661 this.pendingEvents.push([element, { affectChildren: affectChildren }]);
17662 };
17663 DefaultSceneGraphService.prototype.updateDisplayObjectDependency = function (name, oldPath, newPath, object) {
17664 // clear ref to old clip path
17665 if (oldPath && oldPath !== newPath) {
17666 var oldDependencyMap = this.displayObjectDependencyMap.get(oldPath);
17667 if (oldDependencyMap && oldDependencyMap[name]) {
17668 var index = oldDependencyMap[name].indexOf(object);
17669 oldDependencyMap[name].splice(index, 1);
17670 }
17671 }
17672 if (newPath) {
17673 var newDependencyMap = this.displayObjectDependencyMap.get(newPath);
17674 if (!newDependencyMap) {
17675 this.displayObjectDependencyMap.set(newPath, {});
17676 newDependencyMap = this.displayObjectDependencyMap.get(newPath);
17677 }
17678 if (!newDependencyMap[name]) {
17679 newDependencyMap[name] = [];
17680 }
17681 newDependencyMap[name].push(object);
17682 }
17683 };
17684 DefaultSceneGraphService.prototype.informDependentDisplayObjects = function (object) {
17685 var _this = this;
17686 var dependencyMap = this.displayObjectDependencyMap.get(object);
17687 if (dependencyMap) {
17688 Object.keys(dependencyMap).forEach(function (name) {
17689 dependencyMap[name].forEach(function (target) {
17690 _this.dirtifyToRoot(target, true);
17691 target.dispatchEvent(new MutationEvent(ElementEvent.ATTR_MODIFIED, target, _this, _this, name, MutationEvent.MODIFICATION, _this, _this));
17692 if (target.isCustomElement && target.isConnected) {
17693 if (target.attributeChangedCallback) {
17694 target.attributeChangedCallback(name, _this, _this);
17695 }
17696 }
17697 });
17698 });
17699 }
17700 };
17701 DefaultSceneGraphService.prototype.getPosition = function (element) {
17702 var transform = element.transformable;
17703 return getTranslation(transform.position, this.getWorldTransform(element, transform));
17704 };
17705 DefaultSceneGraphService.prototype.getRotation = function (element) {
17706 var transform = element.transformable;
17707 return getRotation(transform.rotation, this.getWorldTransform(element, transform));
17708 };
17709 DefaultSceneGraphService.prototype.getScale = function (element) {
17710 var transform = element.transformable;
17711 return getScaling(transform.scaling, this.getWorldTransform(element, transform));
17712 };
17713 DefaultSceneGraphService.prototype.getWorldTransform = function (element, transform) {
17714 if (transform === void 0) { transform = element.transformable; }
17715 if (!transform.localDirtyFlag && !transform.dirtyFlag) {
17716 return transform.worldTransform;
17717 }
17718 if (element.parentNode && element.parentNode.transformable) {
17719 this.getWorldTransform(element.parentNode);
17720 }
17721 this.sync(element, transform);
17722 return transform.worldTransform;
17723 };
17724 DefaultSceneGraphService.prototype.getLocalPosition = function (element) {
17725 return element.transformable.localPosition;
17726 };
17727 DefaultSceneGraphService.prototype.getLocalRotation = function (element) {
17728 return element.transformable.localRotation;
17729 };
17730 DefaultSceneGraphService.prototype.getLocalScale = function (element) {
17731 return element.transformable.localScale;
17732 };
17733 DefaultSceneGraphService.prototype.getLocalSkew = function (element) {
17734 return element.transformable.localSkew;
17735 };
17736 DefaultSceneGraphService.prototype.getLocalTransform = function (element) {
17737 var transform = element.transformable;
17738 if (transform.localDirtyFlag) {
17739 this.calcLocalTransform(transform);
17740 transform.localDirtyFlag = false;
17741 }
17742 return transform.localTransform;
17743 };
17744 DefaultSceneGraphService.prototype.setLocalTransform = function (element, transform) {
17745 var t = getTranslation(create$2(), transform);
17746 var r = getRotation(create$4(), transform);
17747 var s = getScaling(create$2(), transform);
17748 this.setLocalScale(element, s);
17749 this.setLocalPosition(element, t);
17750 this.setLocalRotation(element, r);
17751 };
17752 DefaultSceneGraphService.prototype.resetLocalTransform = function (element) {
17753 this.setLocalScale(element, [1, 1, 1]);
17754 this.setLocalPosition(element, [0, 0, 0]);
17755 this.setLocalEulerAngles(element, [0, 0, 0]);
17756 this.setLocalSkew(element, [0, 0]);
17757 };
17758 DefaultSceneGraphService.prototype.getTransformedGeometryBounds = function (element, render, existedAABB) {
17759 if (render === void 0) { render = false; }
17760 var bounds = this.getGeometryBounds(element, render);
17761 if (!AABB.isEmpty(bounds)) {
17762 var aabb = existedAABB || new AABB();
17763 aabb.setFromTransformedAABB(bounds, this.getWorldTransform(element));
17764 return aabb;
17765 }
17766 else {
17767 return null;
17768 }
17769 };
17770 /**
17771 * won't account for children
17772 */
17773 DefaultSceneGraphService.prototype.getGeometryBounds = function (element, render) {
17774 if (render === void 0) { render = false; }
17775 var geometry = element.geometry;
17776 var bounds = render
17777 ? geometry.renderBounds
17778 : geometry.contentBounds || null;
17779 // return (bounds && new AABB(bounds.center, bounds.halfExtents)) || new AABB();
17780 return bounds || new AABB();
17781 };
17782 /**
17783 * account for children in world space
17784 */
17785 DefaultSceneGraphService.prototype.getBounds = function (element, render) {
17786 var _this = this;
17787 if (render === void 0) { render = false; }
17788 var renderable = element.renderable;
17789 if (!renderable.boundsDirty && !render && renderable.bounds) {
17790 return renderable.bounds;
17791 }
17792 if (!renderable.renderBoundsDirty && render && renderable.renderBounds) {
17793 return renderable.renderBounds;
17794 }
17795 // reuse existed if possible
17796 var existedAABB = render ? renderable.renderBounds : renderable.bounds;
17797 // reset with geometry's aabb
17798 var aabb = this.getTransformedGeometryBounds(element, render, existedAABB);
17799 // merge children's aabbs
17800 var children = element.childNodes;
17801 children.forEach(function (child) {
17802 var childBounds = _this.getBounds(child, render);
17803 if (childBounds) {
17804 if (!aabb) {
17805 aabb = existedAABB || new AABB();
17806 aabb.update(childBounds.center, childBounds.halfExtents);
17807 }
17808 else {
17809 aabb.add(childBounds);
17810 }
17811 }
17812 });
17813 if (render) {
17814 // FIXME: account for clip path
17815 var clipped = findClosestClipPathTarget(element);
17816 if (clipped) {
17817 // use bounds under world space
17818 var clipPathBounds = clipped.parsedStyle.clipPath.getBounds(render);
17819 if (!aabb) {
17820 aabb = clipPathBounds;
17821 }
17822 else if (clipPathBounds) {
17823 aabb = clipPathBounds.intersection(aabb);
17824 }
17825 }
17826 }
17827 if (!aabb) {
17828 aabb = new AABB();
17829 }
17830 if (aabb) {
17831 if (render) {
17832 renderable.renderBounds = aabb;
17833 }
17834 else {
17835 renderable.bounds = aabb;
17836 }
17837 }
17838 if (render) {
17839 renderable.renderBoundsDirty = false;
17840 }
17841 else {
17842 renderable.boundsDirty = false;
17843 }
17844 return aabb;
17845 };
17846 /**
17847 * account for children in local space
17848 */
17849 DefaultSceneGraphService.prototype.getLocalBounds = function (element) {
17850 if (element.parentNode) {
17851 var parentInvert = create$1();
17852 if (element.parentNode.transformable) {
17853 parentInvert = invert(create$1(), this.getWorldTransform(element.parentNode));
17854 }
17855 var bounds = this.getBounds(element);
17856 if (!AABB.isEmpty(bounds)) {
17857 var localBounds = new AABB();
17858 localBounds.setFromTransformedAABB(bounds, parentInvert);
17859 return localBounds;
17860 }
17861 }
17862 return this.getBounds(element);
17863 };
17864 DefaultSceneGraphService.prototype.getBoundingClientRect = function (element) {
17865 var _a, _b;
17866 var aabb;
17867 var bounds = this.getGeometryBounds(element);
17868 if (!AABB.isEmpty(bounds)) {
17869 aabb = new AABB();
17870 // apply transformation to aabb
17871 aabb.setFromTransformedAABB(bounds, this.getWorldTransform(element));
17872 }
17873 // calc context's offset
17874 var bbox = (_b = (_a = element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.getContextService().getBoundingClientRect();
17875 if (aabb) {
17876 var _c = __read(aabb.getMin(), 2), left = _c[0], top_1 = _c[1];
17877 var _d = __read(aabb.getMax(), 2), right = _d[0], bottom = _d[1];
17878 return new Rectangle(left + ((bbox === null || bbox === void 0 ? void 0 : bbox.left) || 0), top_1 + ((bbox === null || bbox === void 0 ? void 0 : bbox.top) || 0), right - left, bottom - top_1);
17879 }
17880 return new Rectangle((bbox === null || bbox === void 0 ? void 0 : bbox.left) || 0, (bbox === null || bbox === void 0 ? void 0 : bbox.top) || 0, 0, 0);
17881 };
17882 DefaultSceneGraphService.prototype.dirtifyWorldInternal = function (element, transform) {
17883 var _this = this;
17884 if (!transform.dirtyFlag) {
17885 transform.dirtyFlag = true;
17886 transform.frozen = false;
17887 element.childNodes.forEach(function (child) {
17888 var childTransform = child.transformable;
17889 if (!childTransform.dirtyFlag) {
17890 _this.dirtifyWorldInternal(child, childTransform);
17891 }
17892 });
17893 var renderable = element.renderable;
17894 if (renderable) {
17895 renderable.renderBoundsDirty = true;
17896 renderable.boundsDirty = true;
17897 renderable.dirty = true;
17898 }
17899 }
17900 };
17901 DefaultSceneGraphService.prototype.syncHierarchy = function (element) {
17902 var transform = element.transformable;
17903 if (transform.frozen) {
17904 return;
17905 }
17906 transform.frozen = true;
17907 if (transform.localDirtyFlag || transform.dirtyFlag) {
17908 this.sync(element, transform);
17909 }
17910 var children = element.childNodes;
17911 for (var i = 0; i < children.length; i++) {
17912 this.syncHierarchy(children[i]);
17913 }
17914 };
17915 DefaultSceneGraphService.prototype.sync = function (element, transform) {
17916 if (transform.localDirtyFlag) {
17917 this.calcLocalTransform(transform);
17918 transform.localDirtyFlag = false;
17919 }
17920 if (transform.dirtyFlag) {
17921 var parent_1 = element.parentNode;
17922 var parentTransform = parent_1 && parent_1.transformable;
17923 if (parent_1 === null || !parentTransform) {
17924 copy(transform.worldTransform, transform.localTransform);
17925 }
17926 else {
17927 // TODO: should we support scale compensation?
17928 // @see https://github.com/playcanvas/engine/issues/1077#issuecomment-359765557
17929 multiply(transform.worldTransform, parentTransform.worldTransform, transform.localTransform);
17930 }
17931 transform.dirtyFlag = false;
17932 }
17933 };
17934 DefaultSceneGraphService.prototype.unfreezeParentToRoot = function (child) {
17935 var p = child.parentNode;
17936 while (p) {
17937 var transform = p.transformable;
17938 if (transform) {
17939 transform.frozen = false;
17940 }
17941 p = p.parentNode;
17942 }
17943 };
17944 return DefaultSceneGraphService;
17945 }());
17946
17947 var TEXT_METRICS = {
17948 MetricsString: '|ÉqÅ',
17949 BaselineSymbol: 'M',
17950 BaselineMultiplier: 1.4,
17951 HeightMultiplier: 2,
17952 Newlines: [
17953 0x000a,
17954 0x000d, // carriage return
17955 ],
17956 BreakingSpaces: [
17957 0x0009,
17958 0x0020,
17959 0x2000,
17960 0x2001,
17961 0x2002,
17962 0x2003,
17963 0x2004,
17964 0x2005,
17965 0x2006,
17966 0x2008,
17967 0x2009,
17968 0x200a,
17969 0x205f,
17970 0x3000, // ideographic space
17971 ],
17972 };
17973 var LATIN_REGEX = /[a-zA-Z0-9\u00C0-\u00D6\u00D8-\u00f6\u00f8-\u00ff!"#$%&'()*+,-./:;]/;
17974 // Line breaking rules in CJK (Kinsoku Shori)
17975 // Refer from https://en.wikipedia.org/wiki/Line_breaking_rules_in_East_Asian_languages
17976 var regexCannotStartZhCn = /[!%),.:;?\]}¢°·'""†‡›℃∶、。〃〆〕〗〞﹚﹜!"%'),.:;?!]}~]/;
17977 var regexCannotEndZhCn = /[$(£¥·'"〈《「『【〔〖〝﹙﹛$(.[{£¥]/;
17978 var regexCannotStartZhTw = /[!),.:;?\]}¢·–—'"•"、。〆〞〕〉》」︰︱︲︳﹐﹑﹒﹓﹔﹕﹖﹘﹚﹜!),.:;?︶︸︺︼︾﹀﹂﹗]|}、]/;
17979 var regexCannotEndZhTw = /[([{£¥'"‵〈《「『〔〝︴﹙﹛({︵︷︹︻︽︿﹁﹃﹏]/;
17980 var regexCannotStartJaJp = /[)\]}〕〉》」』】〙〗〟'"⦆»ヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻‐゠–〜?!‼⁇⁈⁉・、:;,。.]/;
17981 var regexCannotEndJaJp = /[([{〔〈《「『【〘〖〝'"⦅«—...‥〳〴〵]/;
17982 var regexCannotStartKoKr = /[!%),.:;?\]}¢°'"†‡℃〆〈《「『〕!%),.:;?]}]/;
17983 var regexCannotEndKoKr = /[$([{£¥'"々〇〉》」〔$([{⦆¥₩#]/;
17984 var regexCannotStart = new RegExp("".concat(regexCannotStartZhCn.source, "|").concat(regexCannotStartZhTw.source, "|").concat(regexCannotStartJaJp.source, "|").concat(regexCannotStartKoKr.source));
17985 var regexCannotEnd = new RegExp("".concat(regexCannotEndZhCn.source, "|").concat(regexCannotEndZhTw.source, "|").concat(regexCannotEndJaJp.source, "|").concat(regexCannotEndKoKr.source));
17986 /**
17987 * Borrow from pixi/packages/text/src/TextMetrics.ts
17988 */
17989 var TextService = /** @class */ (function () {
17990 function TextService(runtime) {
17991 var _this = this;
17992 this.runtime = runtime;
17993 /**
17994 * font metrics cache
17995 */
17996 this.fontMetricsCache = {};
17997 this.shouldBreakByKinsokuShorui = function (char, nextChar) {
17998 if (_this.isBreakingSpace(nextChar))
17999 return false;
18000 if (char) {
18001 // Line breaking rules in CJK (Kinsoku Shori)
18002 if (regexCannotEnd.exec(nextChar) || regexCannotStart.exec(char)) {
18003 return true;
18004 }
18005 }
18006 return false;
18007 };
18008 this.trimByKinsokuShorui = function (prev) {
18009 var next = __spreadArray([], __read(prev), false);
18010 var prevLine = next[next.length - 2];
18011 if (!prevLine) {
18012 return prev;
18013 }
18014 var lastChar = prevLine[prevLine.length - 1];
18015 next[next.length - 2] = prevLine.slice(0, -1);
18016 next[next.length - 1] = lastChar + next[next.length - 1];
18017 return next;
18018 };
18019 }
18020 /**
18021 * Calculates the ascent, descent and fontSize of a given font-style.
18022 */
18023 TextService.prototype.measureFont = function (font, offscreenCanvas) {
18024 // as this method is used for preparing assets, don't recalculate things if we don't need to
18025 if (this.fontMetricsCache[font]) {
18026 return this.fontMetricsCache[font];
18027 }
18028 var properties = {
18029 ascent: 0,
18030 descent: 0,
18031 fontSize: 0,
18032 };
18033 var canvas = this.runtime.offscreenCanvasCreator.getOrCreateCanvas(offscreenCanvas);
18034 var context = this.runtime.offscreenCanvasCreator.getOrCreateContext(offscreenCanvas, {
18035 willReadFrequently: true,
18036 });
18037 context.font = font;
18038 var metricsString = TEXT_METRICS.MetricsString + TEXT_METRICS.BaselineSymbol;
18039 var width = Math.ceil(context.measureText(metricsString).width);
18040 var baseline = Math.ceil(context.measureText(TEXT_METRICS.BaselineSymbol).width);
18041 var height = TEXT_METRICS.HeightMultiplier * baseline;
18042 baseline = (baseline * TEXT_METRICS.BaselineMultiplier) | 0;
18043 // @ts-ignore
18044 canvas.width = width;
18045 // @ts-ignore
18046 canvas.height = height;
18047 context.fillStyle = '#f00';
18048 context.fillRect(0, 0, width, height);
18049 context.font = font;
18050 context.textBaseline = 'alphabetic';
18051 context.fillStyle = '#000';
18052 context.fillText(metricsString, 0, baseline);
18053 var imagedata = context.getImageData(0, 0, width || 1, height || 1).data;
18054 var pixels = imagedata.length;
18055 var line = width * 4;
18056 var i = 0;
18057 var idx = 0;
18058 var stop = false;
18059 // ascent. scan from top to bottom until we find a non red pixel
18060 for (i = 0; i < baseline; ++i) {
18061 for (var j = 0; j < line; j += 4) {
18062 if (imagedata[idx + j] !== 255) {
18063 stop = true;
18064 break;
18065 }
18066 }
18067 if (!stop) {
18068 idx += line;
18069 }
18070 else {
18071 break;
18072 }
18073 }
18074 properties.ascent = baseline - i;
18075 idx = pixels - line;
18076 stop = false;
18077 // descent. scan from bottom to top until we find a non red pixel
18078 for (i = height; i > baseline; --i) {
18079 for (var j = 0; j < line; j += 4) {
18080 if (imagedata[idx + j] !== 255) {
18081 stop = true;
18082 break;
18083 }
18084 }
18085 if (!stop) {
18086 idx -= line;
18087 }
18088 else {
18089 break;
18090 }
18091 }
18092 properties.descent = i - baseline;
18093 properties.fontSize = properties.ascent + properties.descent;
18094 this.fontMetricsCache[font] = properties;
18095 return properties;
18096 };
18097 TextService.prototype.measureText = function (text, parsedStyle, offscreenCanvas) {
18098 var fontSize = parsedStyle.fontSize, wordWrap = parsedStyle.wordWrap, strokeHeight = parsedStyle.lineHeight, lineWidth = parsedStyle.lineWidth, textBaseline = parsedStyle.textBaseline, textAlign = parsedStyle.textAlign, letterSpacing = parsedStyle.letterSpacing, textPath = parsedStyle.textPath; parsedStyle.textPathSide; parsedStyle.textPathStartOffset;
18099 var // dropShadow = 0,
18100 // dropShadowDistance = 0,
18101 _a = parsedStyle.leading,
18102 // dropShadow = 0,
18103 // dropShadowDistance = 0,
18104 leading = _a === void 0 ? 0 : _a;
18105 var font = toFontString(parsedStyle);
18106 // if (runtime.enableCSSParsing) {
18107 var fontProperties = this.measureFont(font, offscreenCanvas);
18108 // fallback in case UA disallow canvas data extraction
18109 // (toDataURI, getImageData functions)
18110 if (fontProperties.fontSize === 0) {
18111 fontProperties.fontSize = fontSize;
18112 fontProperties.ascent = fontSize;
18113 }
18114 // } else {
18115 // fontProperties = {
18116 // fontSize,
18117 // };
18118 // }
18119 var context = this.runtime.offscreenCanvasCreator.getOrCreateContext(offscreenCanvas);
18120 context.font = font;
18121 // no overflowing by default
18122 parsedStyle.isOverflowing = false;
18123 var outputText = wordWrap
18124 ? this.wordWrap(text, parsedStyle, offscreenCanvas)
18125 : text;
18126 var lines = outputText.split(/(?:\r\n|\r|\n)/);
18127 var lineWidths = new Array(lines.length);
18128 var maxLineWidth = 0;
18129 // account for textPath
18130 if (textPath) {
18131 textPath.getTotalLength();
18132 // const startingPoint = textPath.getPoint(0);
18133 for (var i = 0; i < lines.length; i++) {
18134 var width = context.measureText(lines[i]).width +
18135 (lines[i].length - 1) * letterSpacing;
18136 // for (
18137 // let i = reverse ? lines[0].length - 1 : 0;
18138 // reverse ? i >= 0 : i < lines[0].length;
18139 // reverse ? i-- : i++
18140 // ) {
18141 // graphemeInfo = lineBounds[i];
18142 // if (positionInPath > totalPathLength) {
18143 // positionInPath %= totalPathLength;
18144 // } else if (positionInPath < 0) {
18145 // positionInPath += totalPathLength;
18146 // }
18147 // // it would probably much faster to send all the grapheme position for a line
18148 // // and calculate path position/angle at once.
18149 // this.setGraphemeOnPath(
18150 // positionInPath,
18151 // graphemeInfo,
18152 // startingPoint
18153 // );
18154 // positionInPath += graphemeInfo.kernedWidth;
18155 // }
18156 }
18157 }
18158 else {
18159 for (var i = 0; i < lines.length; i++) {
18160 // char width + letterSpacing
18161 var lineWidth_1 = context.measureText(lines[i]).width +
18162 (lines[i].length - 1) * letterSpacing;
18163 lineWidths[i] = lineWidth_1;
18164 maxLineWidth = Math.max(maxLineWidth, lineWidth_1);
18165 }
18166 var width = maxLineWidth + lineWidth;
18167 // if (dropShadow) {
18168 // width += dropShadowDistance;
18169 // }
18170 var lineHeight_1 = strokeHeight || fontProperties.fontSize + lineWidth;
18171 var height = Math.max(lineHeight_1, fontProperties.fontSize + lineWidth) +
18172 (lines.length - 1) * (lineHeight_1 + leading);
18173 // if (dropShadow) {
18174 // height += dropShadowDistance;
18175 // }
18176 lineHeight_1 += leading;
18177 // handle vertical text baseline
18178 var offsetY_1 = 0;
18179 if (textBaseline === 'middle') {
18180 offsetY_1 = -height / 2;
18181 }
18182 else if (textBaseline === 'bottom' ||
18183 textBaseline === 'alphabetic' ||
18184 textBaseline === 'ideographic') {
18185 offsetY_1 = -height;
18186 }
18187 else if (textBaseline === 'top' || textBaseline === 'hanging') {
18188 offsetY_1 = 0;
18189 }
18190 return {
18191 font: font,
18192 width: width,
18193 height: height,
18194 lines: lines,
18195 lineWidths: lineWidths,
18196 lineHeight: lineHeight_1,
18197 maxLineWidth: maxLineWidth,
18198 fontProperties: fontProperties,
18199 lineMetrics: lineWidths.map(function (width, i) {
18200 var offsetX = 0;
18201 // handle horizontal text align
18202 if (textAlign === 'center' || textAlign === 'middle') {
18203 offsetX -= width / 2;
18204 }
18205 else if (textAlign === 'right' || textAlign === 'end') {
18206 offsetX -= width;
18207 }
18208 return new Rectangle(offsetX - lineWidth / 2, offsetY_1 + i * lineHeight_1, width + lineWidth, lineHeight_1);
18209 }),
18210 };
18211 }
18212 };
18213 TextService.prototype.setGraphemeOnPath = function () { };
18214 TextService.prototype.wordWrap = function (text, parsedStyle, offscreenCanvas) {
18215 var _this = this;
18216 var _a = parsedStyle.wordWrapWidth, wordWrapWidth = _a === void 0 ? 0 : _a, letterSpacing = parsedStyle.letterSpacing, _b = parsedStyle.maxLines, maxLines = _b === void 0 ? Infinity : _b, textOverflow = parsedStyle.textOverflow;
18217 var context = this.runtime.offscreenCanvasCreator.getOrCreateContext(offscreenCanvas);
18218 var maxWidth = wordWrapWidth + letterSpacing;
18219 var ellipsis = '';
18220 if (textOverflow === 'ellipsis') {
18221 ellipsis = '...';
18222 }
18223 else if (textOverflow && textOverflow !== 'clip') {
18224 ellipsis = textOverflow;
18225 }
18226 var lines = [];
18227 var currentIndex = 0;
18228 var currentWidth = 0;
18229 var cache = {};
18230 var calcWidth = function (char) {
18231 return _this.getFromCache(char, letterSpacing, cache, context);
18232 };
18233 var ellipsisWidth = Array.from(ellipsis).reduce(function (prev, cur) {
18234 return prev + calcWidth(cur);
18235 }, 0);
18236 var chars = Array.from(text);
18237 for (var i = 0; i < chars.length; i++) {
18238 var char = chars[i];
18239 var prevChar = text[i - 1];
18240 var nextChar = text[i + 1];
18241 var charWidth = calcWidth(char);
18242 if (this.isNewline(char)) {
18243 currentIndex++;
18244 // exceed maxLines, break immediately
18245 if (currentIndex >= maxLines) {
18246 parsedStyle.isOverflowing = true;
18247 break;
18248 }
18249 currentWidth = 0;
18250 lines[currentIndex] = '';
18251 continue;
18252 }
18253 if (currentWidth > 0 && currentWidth + charWidth > maxWidth) {
18254 if (currentIndex + 1 >= maxLines) {
18255 parsedStyle.isOverflowing = true;
18256 // If there is not enough space to display the string itself, it is clipped.
18257 // @see https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow#values
18258 if (ellipsisWidth > 0 && ellipsisWidth <= maxWidth) {
18259 // Backspace from line's end.
18260 var currentLineLength = lines[currentIndex].length;
18261 var lastLineWidth = 0;
18262 var lastLineIndex = currentLineLength;
18263 for (var i_1 = 0; i_1 < currentLineLength; i_1++) {
18264 var width = calcWidth(lines[currentIndex][i_1]);
18265 if (lastLineWidth + width + ellipsisWidth > maxWidth) {
18266 lastLineIndex = i_1;
18267 break;
18268 }
18269 lastLineWidth += width;
18270 }
18271 lines[currentIndex] =
18272 (lines[currentIndex] || '').slice(0, lastLineIndex) + ellipsis;
18273 }
18274 break;
18275 }
18276 currentIndex++;
18277 currentWidth = 0;
18278 lines[currentIndex] = '';
18279 if (this.isBreakingSpace(char)) {
18280 continue;
18281 }
18282 if (!this.canBreakInLastChar(char)) {
18283 lines = this.trimToBreakable(lines);
18284 currentWidth = this.sumTextWidthByCache(lines[currentIndex] || '', cache);
18285 }
18286 if (this.shouldBreakByKinsokuShorui(char, nextChar)) {
18287 lines = this.trimByKinsokuShorui(lines);
18288 currentWidth += calcWidth(prevChar || '');
18289 }
18290 }
18291 currentWidth += charWidth;
18292 lines[currentIndex] = (lines[currentIndex] || '') + char;
18293 }
18294 return lines.join('\n');
18295 };
18296 TextService.prototype.isBreakingSpace = function (char) {
18297 if (typeof char !== 'string') {
18298 return false;
18299 }
18300 return TEXT_METRICS.BreakingSpaces.indexOf(char.charCodeAt(0)) >= 0;
18301 };
18302 TextService.prototype.isNewline = function (char) {
18303 if (typeof char !== 'string') {
18304 return false;
18305 }
18306 return TEXT_METRICS.Newlines.indexOf(char.charCodeAt(0)) >= 0;
18307 };
18308 TextService.prototype.trimToBreakable = function (prev) {
18309 var next = __spreadArray([], __read(prev), false);
18310 var prevLine = next[next.length - 2];
18311 var index = this.findBreakableIndex(prevLine);
18312 if (index === -1 || !prevLine)
18313 return next;
18314 var trimmedChar = prevLine.slice(index, index + 1);
18315 var isTrimmedWithSpace = this.isBreakingSpace(trimmedChar);
18316 var trimFrom = index + 1;
18317 var trimTo = index + (isTrimmedWithSpace ? 0 : 1);
18318 next[next.length - 1] += prevLine.slice(trimFrom, prevLine.length);
18319 next[next.length - 2] = prevLine.slice(0, trimTo);
18320 return next;
18321 };
18322 TextService.prototype.canBreakInLastChar = function (char) {
18323 if (char && LATIN_REGEX.test(char))
18324 return false;
18325 return true;
18326 };
18327 TextService.prototype.sumTextWidthByCache = function (text, cache) {
18328 return text.split('').reduce(function (sum, c) {
18329 if (!cache[c])
18330 throw Error('cannot count the word without cache');
18331 return sum + cache[c];
18332 }, 0);
18333 };
18334 TextService.prototype.findBreakableIndex = function (line) {
18335 for (var i = line.length - 1; i >= 0; i--) {
18336 if (!LATIN_REGEX.test(line[i]))
18337 return i;
18338 }
18339 return -1;
18340 };
18341 TextService.prototype.getFromCache = function (key, letterSpacing, cache, context) {
18342 var width = cache[key];
18343 if (typeof width !== 'number') {
18344 var spacing = key.length * letterSpacing;
18345 width = context.measureText(key).width + spacing;
18346 cache[key] = width;
18347 }
18348 return width;
18349 };
18350 return TextService;
18351 }());
18352
18353 var runtime = {};
18354 /**
18355 * Replace with IoC container
18356 */
18357 var geometryUpdaterFactory = (function () {
18358 var _a;
18359 var rectUpdater = new RectUpdater();
18360 var polylineUpdater = new PolylineUpdater();
18361 return _a = {},
18362 _a[Shape.CIRCLE] = new CircleUpdater(),
18363 _a[Shape.ELLIPSE] = new EllipseUpdater(),
18364 _a[Shape.RECT] = rectUpdater,
18365 _a[Shape.IMAGE] = rectUpdater,
18366 _a[Shape.GROUP] = rectUpdater,
18367 _a[Shape.LINE] = new LineUpdater(),
18368 _a[Shape.TEXT] = new TextUpdater(runtime),
18369 _a[Shape.POLYLINE] = polylineUpdater,
18370 _a[Shape.POLYGON] = polylineUpdater,
18371 _a[Shape.PATH] = new PathUpdater(),
18372 _a[Shape.HTML] = null,
18373 _a[Shape.MESH] = null,
18374 _a;
18375 })();
18376 var CSSPropertySyntaxFactory = (function () {
18377 var _a;
18378 var color = new CSSPropertyColor();
18379 var length = new CSSPropertyLengthOrPercentage();
18380 return _a = {},
18381 _a[PropertySyntax.PERCENTAGE] = null,
18382 _a[PropertySyntax.NUMBER] = new CSSPropertyNumber(),
18383 _a[PropertySyntax.ANGLE] = new CSSPropertyAngle(),
18384 _a[PropertySyntax.DEFINED_PATH] = new CSSPropertyClipPath(),
18385 _a[PropertySyntax.PAINT] = color,
18386 _a[PropertySyntax.COLOR] = color,
18387 _a[PropertySyntax.FILTER] = new CSSPropertyFilter(),
18388 _a[PropertySyntax.LENGTH] = length,
18389 _a[PropertySyntax.LENGTH_PERCENTAGE] = length,
18390 _a[PropertySyntax.LENGTH_PERCENTAGE_12] = new CSSPropertyLengthOrPercentage12(),
18391 _a[PropertySyntax.LENGTH_PERCENTAGE_14] = new CSSPropertyLengthOrPercentage14(),
18392 _a[PropertySyntax.COORDINATE] = new CSSPropertyLocalPosition(),
18393 _a[PropertySyntax.OFFSET_DISTANCE] = new CSSPropertyOffsetDistance(),
18394 _a[PropertySyntax.OPACITY_VALUE] = new CSSPropertyOpacity(),
18395 _a[PropertySyntax.PATH] = new CSSPropertyPath(),
18396 _a[PropertySyntax.LIST_OF_POINTS] = new CSSPropertyPoints(),
18397 _a[PropertySyntax.SHADOW_BLUR] = new CSSPropertyShadowBlur(),
18398 _a[PropertySyntax.TEXT] = new CSSPropertyText(),
18399 _a[PropertySyntax.TEXT_TRANSFORM] = new CSSPropertyTextTransform(),
18400 _a[PropertySyntax.TRANSFORM] = new CSSPropertyTransform(),
18401 _a[PropertySyntax.TRANSFORM_ORIGIN] = new CSSPropertyTransformOrigin(),
18402 _a[PropertySyntax.Z_INDEX] = new CSSPropertyZIndex(),
18403 _a[PropertySyntax.MARKER] = new CSSPropertyMarker(),
18404 _a;
18405 })();
18406 var getGlobalThis = function () {
18407 if (typeof globalThis !== 'undefined')
18408 return globalThis;
18409 if (typeof self !== 'undefined')
18410 return self;
18411 if (typeof window !== 'undefined')
18412 return window;
18413 // @ts-ignore
18414 if (typeof global !== 'undefined')
18415 return global;
18416 return {};
18417 // [!] Error: The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten
18418 // @see https://rollupjs.org/troubleshooting/#error-this-is-undefined
18419 // if (typeof this !== 'undefined') return this;
18420 };
18421 /**
18422 * Camera
18423 * `g-camera-api` will provide an advanced implementation
18424 */
18425 runtime.CameraContribution = Camera;
18426 /**
18427 * `g-web-animations-api` will provide an AnimationTimeline
18428 */
18429 runtime.AnimationTimeline = null;
18430 runtime.EasingFunction = null;
18431 runtime.offscreenCanvasCreator = new OffscreenCanvasCreator();
18432 runtime.nativeHTMLMap = new WeakMap();
18433 runtime.sceneGraphSelector = new DefaultSceneGraphSelector();
18434 runtime.sceneGraphService = new DefaultSceneGraphService(runtime);
18435 runtime.textService = new TextService(runtime);
18436 runtime.geometryUpdaterFactory = geometryUpdaterFactory;
18437 runtime.CSSPropertySyntaxFactory = CSSPropertySyntaxFactory;
18438 runtime.styleValueRegistry = new DefaultStyleValueRegistry(runtime);
18439 runtime.layoutRegistry = null;
18440 runtime.globalThis = getGlobalThis();
18441 runtime.enableCSSParsing = true;
18442 runtime.enableDataset = false;
18443 runtime.enableStyleSyntax = true;
18444
18445 var entityCounter = 0;
18446 var insertedEvent = new MutationEvent(ElementEvent.INSERTED, null, '', '', '', 0, '', '');
18447 var removedEvent = new MutationEvent(ElementEvent.REMOVED, null, '', '', '', 0, '', '');
18448 var destroyEvent = new CustomEvent(ElementEvent.DESTROY);
18449 /**
18450 * Has following capabilities:
18451 * * Node insert/remove, eg. appendChild, removeChild, remove...
18452 * * Query eg. querySelector getElementById...
18453 * * Animation
18454 */
18455 var Element = /** @class */ (function (_super) {
18456 __extends(Element, _super);
18457 function Element() {
18458 var _this = _super !== null && _super.apply(this, arguments) || this;
18459 /**
18460 * Unique id.
18461 */
18462 _this.entity = entityCounter++;
18463 _this.renderable = {
18464 bounds: undefined,
18465 boundsDirty: true,
18466 renderBounds: undefined,
18467 renderBoundsDirty: true,
18468 dirtyRenderBounds: undefined,
18469 dirty: false,
18470 };
18471 _this.cullable = {
18472 strategy: Strategy.Standard,
18473 visibilityPlaneMask: -1,
18474 visible: true,
18475 enable: true,
18476 };
18477 _this.transformable = {
18478 dirtyFlag: false,
18479 localDirtyFlag: false,
18480 frozen: false,
18481 localPosition: [0, 0, 0],
18482 localRotation: [0, 0, 0, 1],
18483 localScale: [1, 1, 1],
18484 localTransform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
18485 localSkew: [0, 0],
18486 position: [0, 0, 0],
18487 rotation: [0, 0, 0, 1],
18488 scaling: [1, 1, 1],
18489 worldTransform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
18490 origin: [0, 0, 0],
18491 };
18492 _this.sortable = {
18493 dirty: false,
18494 sorted: undefined,
18495 renderOrder: 0,
18496 dirtyChildren: [],
18497 dirtyReason: undefined,
18498 };
18499 _this.geometry = {
18500 contentBounds: undefined,
18501 renderBounds: undefined,
18502 };
18503 _this.rBushNode = {
18504 aabb: undefined,
18505 };
18506 /**
18507 * https://developer.mozilla.org/zh-CN/docs/Web/API/Element/namespaceURI
18508 */
18509 _this.namespaceURI = 'g';
18510 _this.scrollLeft = 0;
18511 _this.scrollTop = 0;
18512 /**
18513 * We don't support border now
18514 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/clientTop
18515 */
18516 _this.clientTop = 0;
18517 _this.clientLeft = 0;
18518 /**
18519 * is destroyed or not
18520 */
18521 _this.destroyed = false;
18522 /**
18523 * compatible with `style`
18524 * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style
18525 */
18526 _this.style = {};
18527 _this.computedStyle = runtime.enableCSSParsing
18528 ? {
18529 anchor: unsetKeywordValue,
18530 opacity: unsetKeywordValue,
18531 fillOpacity: unsetKeywordValue,
18532 strokeOpacity: unsetKeywordValue,
18533 fill: unsetKeywordValue,
18534 stroke: unsetKeywordValue,
18535 transform: unsetKeywordValue,
18536 transformOrigin: unsetKeywordValue,
18537 visibility: unsetKeywordValue,
18538 pointerEvents: unsetKeywordValue,
18539 lineWidth: unsetKeywordValue,
18540 lineCap: unsetKeywordValue,
18541 lineJoin: unsetKeywordValue,
18542 increasedLineWidthForHitTesting: unsetKeywordValue,
18543 fontSize: unsetKeywordValue,
18544 fontFamily: unsetKeywordValue,
18545 fontStyle: unsetKeywordValue,
18546 fontWeight: unsetKeywordValue,
18547 fontVariant: unsetKeywordValue,
18548 textAlign: unsetKeywordValue,
18549 textBaseline: unsetKeywordValue,
18550 textTransform: unsetKeywordValue,
18551 zIndex: unsetKeywordValue,
18552 filter: unsetKeywordValue,
18553 shadowType: unsetKeywordValue,
18554 }
18555 : null;
18556 /**
18557 * Renderers will use these used values.
18558 */
18559 _this.parsedStyle = {
18560 // opacity: '',
18561 // fillOpacity: '',
18562 // strokeOpacity: '',
18563 // transformOrigin: '',
18564 // visibility: '',
18565 // pointerEvents: '',
18566 // lineWidth: '',
18567 // lineCap: '',
18568 // lineJoin: '',
18569 // increasedLineWidthForHitTesting: '',
18570 // fontSize: '',
18571 // fontFamily: '',
18572 // fontStyle: '',
18573 // fontWeight: '',
18574 // fontVariant: '',
18575 // textAlign: '',
18576 // textBaseline: '',
18577 // textTransform: '',
18578 };
18579 /**
18580 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/attributes
18581 */
18582 _this.attributes = {};
18583 return _this;
18584 }
18585 Object.defineProperty(Element.prototype, "className", {
18586 /**
18587 * used in `getElementsByClassName`
18588 * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
18589 */
18590 get: function () {
18591 // @ts-ignore
18592 return this.getAttribute('class') || '';
18593 },
18594 set: function (className) {
18595 this.setAttribute('class', className);
18596 },
18597 enumerable: false,
18598 configurable: true
18599 });
18600 Object.defineProperty(Element.prototype, "classList", {
18601 /**
18602 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
18603 */
18604 get: function () {
18605 return this.className.split(' ').filter(function (c) { return c !== ''; });
18606 },
18607 enumerable: false,
18608 configurable: true
18609 });
18610 Object.defineProperty(Element.prototype, "tagName", {
18611 get: function () {
18612 return this.nodeName;
18613 },
18614 enumerable: false,
18615 configurable: true
18616 });
18617 Object.defineProperty(Element.prototype, "children", {
18618 get: function () {
18619 return this.childNodes;
18620 },
18621 enumerable: false,
18622 configurable: true
18623 });
18624 Object.defineProperty(Element.prototype, "childElementCount", {
18625 get: function () {
18626 return this.childNodes.length;
18627 },
18628 enumerable: false,
18629 configurable: true
18630 });
18631 Object.defineProperty(Element.prototype, "firstElementChild", {
18632 get: function () {
18633 return this.firstChild;
18634 },
18635 enumerable: false,
18636 configurable: true
18637 });
18638 Object.defineProperty(Element.prototype, "lastElementChild", {
18639 get: function () {
18640 return this.lastChild;
18641 },
18642 enumerable: false,
18643 configurable: true
18644 });
18645 Object.defineProperty(Element.prototype, "parentElement", {
18646 get: function () {
18647 return this.parentNode;
18648 },
18649 enumerable: false,
18650 configurable: true
18651 });
18652 Object.defineProperty(Element.prototype, "nextSibling", {
18653 get: function () {
18654 if (this.parentNode) {
18655 var index = this.parentNode.childNodes.indexOf(this);
18656 return this.parentNode.childNodes[index + 1] || null;
18657 }
18658 return null;
18659 },
18660 enumerable: false,
18661 configurable: true
18662 });
18663 Object.defineProperty(Element.prototype, "previousSibling", {
18664 get: function () {
18665 if (this.parentNode) {
18666 var index = this.parentNode.childNodes.indexOf(this);
18667 return this.parentNode.childNodes[index - 1] || null;
18668 }
18669 return null;
18670 },
18671 enumerable: false,
18672 configurable: true
18673 });
18674 Element.prototype.cloneNode = function (deep) {
18675 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
18676 };
18677 Element.prototype.appendChild = function (child, index) {
18678 var _a;
18679 if (child.destroyed) {
18680 throw new Error(ERROR_MSG_APPEND_DESTROYED_ELEMENT);
18681 }
18682 runtime.sceneGraphService.attach(child, this, index);
18683 if ((_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) {
18684 this.ownerDocument.defaultView.mountChildren(child);
18685 }
18686 insertedEvent.relatedNode = this;
18687 child.dispatchEvent(insertedEvent);
18688 return child;
18689 };
18690 Element.prototype.insertBefore = function (newChild, refChild) {
18691 if (!refChild) {
18692 this.appendChild(newChild);
18693 }
18694 else {
18695 if (newChild.parentElement) {
18696 newChild.parentElement.removeChild(newChild);
18697 }
18698 var index = this.childNodes.indexOf(refChild);
18699 if (index === -1) {
18700 this.appendChild(newChild);
18701 }
18702 else {
18703 this.appendChild(newChild, index);
18704 }
18705 }
18706 return newChild;
18707 };
18708 Element.prototype.replaceChild = function (newChild, oldChild) {
18709 var index = this.childNodes.indexOf(oldChild);
18710 this.removeChild(oldChild);
18711 this.appendChild(newChild, index);
18712 return oldChild;
18713 };
18714 Element.prototype.removeChild = function (child) {
18715 var _a;
18716 // should emit on itself before detach
18717 removedEvent.relatedNode = this;
18718 child.dispatchEvent(removedEvent);
18719 if ((_a = child.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) {
18720 child.ownerDocument.defaultView.unmountChildren(child);
18721 }
18722 // remove from scene graph
18723 runtime.sceneGraphService.detach(child);
18724 return child;
18725 };
18726 /**
18727 * Remove all children which can be appended to its original parent later again.
18728 */
18729 Element.prototype.removeChildren = function () {
18730 for (var i = this.childNodes.length - 1; i >= 0; i--) {
18731 var child = this.childNodes[i];
18732 this.removeChild(child);
18733 }
18734 };
18735 /**
18736 * Recursively destroy all children which can not be appended to its original parent later again.
18737 */
18738 Element.prototype.destroyChildren = function () {
18739 for (var i = this.childNodes.length - 1; i >= 0; i--) {
18740 var child = this.childNodes[i];
18741 if (child.childNodes.length) {
18742 child.destroyChildren();
18743 }
18744 child.destroy();
18745 }
18746 };
18747 /**
18748 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
18749 */
18750 Element.prototype.matches = function (selector) {
18751 return runtime.sceneGraphService.matches(selector, this);
18752 };
18753 Element.prototype.getElementById = function (id) {
18754 return runtime.sceneGraphService.querySelector("#".concat(id), this);
18755 };
18756 Element.prototype.getElementsByName = function (name) {
18757 return runtime.sceneGraphService.querySelectorAll("[name=\"".concat(name, "\"]"), this);
18758 };
18759 Element.prototype.getElementsByClassName = function (className) {
18760 return runtime.sceneGraphService.querySelectorAll(".".concat(className), this);
18761 };
18762 Element.prototype.getElementsByTagName = function (tagName) {
18763 return runtime.sceneGraphService.querySelectorAll(tagName, this);
18764 };
18765 Element.prototype.querySelector = function (selectors) {
18766 return runtime.sceneGraphService.querySelector(selectors, this);
18767 };
18768 Element.prototype.querySelectorAll = function (selectors) {
18769 return runtime.sceneGraphService.querySelectorAll(selectors, this);
18770 };
18771 /**
18772 * should traverses the element and its parents (heading toward the document root)
18773 * until it finds a node that matches the specified CSS selector.
18774 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/closest
18775 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#polyfill
18776 */
18777 Element.prototype.closest = function (selectors) {
18778 var el = this;
18779 do {
18780 if (runtime.sceneGraphService.matches(selectors, el))
18781 return el;
18782 el = el.parentElement;
18783 } while (el !== null);
18784 return null;
18785 };
18786 /**
18787 * search in scene group, but should not include itself
18788 */
18789 Element.prototype.find = function (filter) {
18790 var _this = this;
18791 var target = null;
18792 this.forEach(function (object) {
18793 if (object !== _this && filter(object)) {
18794 target = object;
18795 return true;
18796 }
18797 return false;
18798 });
18799 return target;
18800 };
18801 Element.prototype.findAll = function (filter) {
18802 var _this = this;
18803 var objects = [];
18804 this.forEach(function (object) {
18805 if (object !== _this && filter(object)) {
18806 objects.push(object);
18807 }
18808 });
18809 return objects;
18810 };
18811 /**
18812 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/after
18813 */
18814 Element.prototype.after = function () {
18815 var _this = this;
18816 var nodes = [];
18817 for (var _i = 0; _i < arguments.length; _i++) {
18818 nodes[_i] = arguments[_i];
18819 }
18820 if (this.parentNode) {
18821 var index_1 = this.parentNode.childNodes.indexOf(this);
18822 nodes.forEach(function (node, i) { var _a; return (_a = _this.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(node, index_1 + i + 1); });
18823 }
18824 };
18825 /**
18826 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/before
18827 */
18828 Element.prototype.before = function () {
18829 var _a;
18830 var nodes = [];
18831 for (var _i = 0; _i < arguments.length; _i++) {
18832 nodes[_i] = arguments[_i];
18833 }
18834 if (this.parentNode) {
18835 var index = this.parentNode.childNodes.indexOf(this);
18836 var _b = __read(nodes), first = _b[0], rest = _b.slice(1);
18837 this.parentNode.appendChild(first, index);
18838 (_a = first).after.apply(_a, __spreadArray([], __read(rest), false));
18839 }
18840 };
18841 /**
18842 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/replaceWith
18843 */
18844 Element.prototype.replaceWith = function () {
18845 var nodes = [];
18846 for (var _i = 0; _i < arguments.length; _i++) {
18847 nodes[_i] = arguments[_i];
18848 }
18849 this.after.apply(this, __spreadArray([], __read(nodes), false));
18850 this.remove();
18851 };
18852 /**
18853 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/append
18854 */
18855 Element.prototype.append = function () {
18856 var _this = this;
18857 var nodes = [];
18858 for (var _i = 0; _i < arguments.length; _i++) {
18859 nodes[_i] = arguments[_i];
18860 }
18861 nodes.forEach(function (node) { return _this.appendChild(node); });
18862 };
18863 /**
18864 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/prepend
18865 */
18866 Element.prototype.prepend = function () {
18867 var _this = this;
18868 var nodes = [];
18869 for (var _i = 0; _i < arguments.length; _i++) {
18870 nodes[_i] = arguments[_i];
18871 }
18872 nodes.forEach(function (node, i) { return _this.appendChild(node, i); });
18873 };
18874 /**
18875 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/replaceChildren
18876 */
18877 Element.prototype.replaceChildren = function () {
18878 var nodes = [];
18879 for (var _i = 0; _i < arguments.length; _i++) {
18880 nodes[_i] = arguments[_i];
18881 }
18882 while (this.childNodes.length && this.firstChild) {
18883 this.removeChild(this.firstChild);
18884 }
18885 this.append.apply(this, __spreadArray([], __read(nodes), false));
18886 };
18887 /**
18888 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/remove
18889 */
18890 Element.prototype.remove = function () {
18891 if (this.parentNode) {
18892 return this.parentNode.removeChild(this);
18893 }
18894 return this;
18895 };
18896 Element.prototype.destroy = function () {
18897 // destroy itself before remove
18898 this.dispatchEvent(destroyEvent);
18899 // remove from scenegraph first
18900 this.remove();
18901 // remove event listeners
18902 this.emitter.removeAllListeners();
18903 this.destroyed = true;
18904 };
18905 Element.prototype.getGeometryBounds = function () {
18906 return runtime.sceneGraphService.getGeometryBounds(this);
18907 };
18908 Element.prototype.getRenderBounds = function () {
18909 return runtime.sceneGraphService.getBounds(this, true);
18910 };
18911 /**
18912 * get bounds in world space, account for children
18913 */
18914 Element.prototype.getBounds = function () {
18915 return runtime.sceneGraphService.getBounds(this);
18916 };
18917 /**
18918 * get bounds in local space, account for children
18919 */
18920 Element.prototype.getLocalBounds = function () {
18921 return runtime.sceneGraphService.getLocalBounds(this);
18922 };
18923 /**
18924 * account for context's bounds in client space,
18925 * but not accounting for children
18926 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
18927 */
18928 Element.prototype.getBoundingClientRect = function () {
18929 return runtime.sceneGraphService.getBoundingClientRect(this);
18930 };
18931 /**
18932 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getClientRects
18933 */
18934 Element.prototype.getClientRects = function () {
18935 return [this.getBoundingClientRect()];
18936 };
18937 /**
18938 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/computedStyleMap
18939 * eg. circle.computedStyleMap().get('fill');
18940 */
18941 Element.prototype.computedStyleMap = function () {
18942 return new Map(Object.entries(this.computedStyle));
18943 };
18944 /**
18945 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames
18946 */
18947 Element.prototype.getAttributeNames = function () {
18948 return Object.keys(this.attributes);
18949 };
18950 /**
18951 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
18952 */
18953 Element.prototype.getAttribute = function (name) {
18954 // @see https://github.com/antvis/G/issues/1267
18955 if (isSymbol(name)) {
18956 return runtime.enableCSSParsing ? null : undefined;
18957 }
18958 var value = this.attributes[name];
18959 if (value === undefined) {
18960 var attributeName = formatAttributeName(name);
18961 value = this.attributes[attributeName];
18962 // if the given attribute does not exist, the value returned will either be null or ""
18963 return runtime.enableCSSParsing ? (isNil(value) ? null : value) : value;
18964 }
18965 else {
18966 return value;
18967 }
18968 };
18969 /**
18970 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute
18971 */
18972 Element.prototype.hasAttribute = function (qualifiedName) {
18973 return this.getAttributeNames().includes(qualifiedName);
18974 };
18975 /**
18976 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttributes
18977 */
18978 Element.prototype.hasAttributes = function () {
18979 return !!this.getAttributeNames().length;
18980 };
18981 /**
18982 * should use removeAttribute() instead of setting the attribute value to null either directly or using setAttribute(). Many attributes will not behave as expected if you set them to null.
18983 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute
18984 */
18985 Element.prototype.removeAttribute = function (attributeName) {
18986 this.setAttribute(attributeName, null);
18987 delete this.attributes[attributeName];
18988 };
18989 /**
18990 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
18991 */
18992 Element.prototype.setAttribute = function (attributeName, value, force) {
18993 this.attributes[attributeName] = value;
18994 };
18995 Element.prototype.getAttributeNS = function (namespace, localName) {
18996 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
18997 };
18998 Element.prototype.getAttributeNode = function (qualifiedName) {
18999 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19000 };
19001 Element.prototype.getAttributeNodeNS = function (namespace, localName) {
19002 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19003 };
19004 Element.prototype.hasAttributeNS = function (namespace, localName) {
19005 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19006 };
19007 Element.prototype.removeAttributeNS = function (namespace, localName) {
19008 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19009 };
19010 Element.prototype.removeAttributeNode = function (attr) {
19011 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19012 };
19013 Element.prototype.setAttributeNS = function (namespace, qualifiedName, value) {
19014 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19015 };
19016 Element.prototype.setAttributeNode = function (attr) {
19017 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19018 };
19019 Element.prototype.setAttributeNodeNS = function (attr) {
19020 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19021 };
19022 Element.prototype.toggleAttribute = function (qualifiedName, force) {
19023 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
19024 };
19025 return Element;
19026 }(Node));
19027
19028 function isDisplayObject(value) {
19029 return !!(value === null || value === void 0 ? void 0 : value.nodeName);
19030 }
19031 var mutationEvent = new MutationEvent(ElementEvent.ATTR_MODIFIED, null, null, null, null, MutationEvent.MODIFICATION, null, null);
19032 var DEFAULT_STYLE_PROPS = {
19033 anchor: '',
19034 opacity: '',
19035 fillOpacity: '',
19036 strokeOpacity: '',
19037 fill: '',
19038 stroke: '',
19039 transform: '',
19040 transformOrigin: '',
19041 visibility: '',
19042 pointerEvents: '',
19043 lineWidth: '',
19044 lineCap: '',
19045 lineJoin: '',
19046 increasedLineWidthForHitTesting: '',
19047 fontSize: '',
19048 fontFamily: '',
19049 fontStyle: '',
19050 fontWeight: '',
19051 fontVariant: '',
19052 textAlign: '',
19053 textBaseline: '',
19054 textTransform: '',
19055 zIndex: '',
19056 filter: '',
19057 shadowType: '',
19058 };
19059 var DEFAULT_PARSED_STYLE_PROPS = {
19060 anchor: [0, 0],
19061 fill: noneColor,
19062 stroke: noneColor,
19063 transform: [],
19064 zIndex: 0,
19065 filter: [],
19066 shadowType: 'outer',
19067 miterLimit: 10,
19068 };
19069 var DEFAULT_PARSED_STYLE_PROPS_CSS_DISABLED = __assign(__assign({}, DEFAULT_PARSED_STYLE_PROPS), { opacity: 1, fillOpacity: 1, strokeOpacity: 1, visibility: 'visible', pointerEvents: 'auto', lineWidth: 1, lineCap: 'butt', lineJoin: 'miter', increasedLineWidthForHitTesting: 0, fillRule: 'nonzero' });
19070 var INHERITABLE_BASE_STYLE_PROPS = [
19071 'opacity',
19072 'fillOpacity',
19073 'strokeOpacity',
19074 'transformOrigin',
19075 'visibility',
19076 'pointerEvents',
19077 'lineWidth',
19078 'lineCap',
19079 'lineJoin',
19080 'increasedLineWidthForHitTesting',
19081 ];
19082 var INHERITABLE_STYLE_PROPS = __spreadArray(__spreadArray([], __read(INHERITABLE_BASE_STYLE_PROPS), false), [
19083 'fontSize',
19084 'fontFamily',
19085 'fontStyle',
19086 'fontWeight',
19087 'fontVariant',
19088 'textAlign',
19089 'textBaseline',
19090 'textTransform',
19091 ], false);
19092 var DATASET_PREFIX = 'data-';
19093 /**
19094 * prototype chains: DisplayObject -> Element -> Node -> EventTarget
19095 *
19096 * mixins: Animatable, Transformable, Visible
19097 * @see https://github.com/tannerntannern/ts-mixer/blob/master/README.md#mixing-generic-classes
19098 *
19099 * Provide abilities in scene graph, such as:
19100 * * transform `translate/rotate/scale`
19101 * * add/remove child
19102 * * visibility and z-index
19103 *
19104 * Those abilities are implemented with those components: `Transform/Sortable/Visible`.
19105 *
19106 * Emit following events:
19107 * * init
19108 * * destroy
19109 * * attributeChanged
19110 */
19111 var DisplayObject = /** @class */ (function (_super) {
19112 __extends(DisplayObject, _super);
19113 function DisplayObject(config) {
19114 var _a;
19115 var _this = _super.call(this) || this;
19116 _this.isCustomElement = false;
19117 _this.isMutationObserved = false;
19118 /**
19119 * push to active animations after calling `animate()`
19120 */
19121 _this.activeAnimations = [];
19122 /**
19123 * Use `this.style.clipPath` instead.
19124 * @deprecated
19125 */
19126 _this.getClip = function () {
19127 return this.style.clipPath || null;
19128 };
19129 // assign name, id to config
19130 // eg. group.get('name')
19131 _this.config = config;
19132 // compatible with G 3.0
19133 _this.config.interactive = (_a = _this.config.capture) !== null && _a !== void 0 ? _a : _this.config.interactive;
19134 // init scene graph node
19135 _this.id = _this.config.id || '';
19136 _this.name = _this.config.name || '';
19137 if (_this.config.className || _this.config.class) {
19138 _this.className = _this.config.className || _this.config.class;
19139 }
19140 _this.nodeName = _this.config.type || Shape.GROUP;
19141 // compatible with G 3.0
19142 _this.config.style =
19143 _this.config.style || _this.config.attrs || {};
19144 Object.assign(_this.config.style, _this.config.attrs);
19145 // this.config.style = {
19146 // // ...DEFAULT_STYLE_PROPS,
19147 // ...this.config.style,
19148 // ...this.config.attrs,
19149 // };
19150 if (_this.config.visible != null) {
19151 _this.config.style.visibility =
19152 _this.config.visible === false ? 'hidden' : 'visible';
19153 }
19154 if (_this.config.interactive != null) {
19155 _this.config.style.pointerEvents =
19156 _this.config.interactive === false ? 'none' : 'auto';
19157 }
19158 // merge parsed value
19159 Object.assign(_this.parsedStyle, runtime.enableCSSParsing
19160 ? DEFAULT_PARSED_STYLE_PROPS
19161 : DEFAULT_PARSED_STYLE_PROPS_CSS_DISABLED, _this.config.initialParsedStyle);
19162 if (runtime.enableCSSParsing) {
19163 Object.assign(_this.attributes, DEFAULT_STYLE_PROPS);
19164 }
19165 // start to process attributes
19166 _this.initAttributes(_this.config.style);
19167 var Proxy = runtime.globalThis.Proxy
19168 ? runtime.globalThis.Proxy
19169 : function () { };
19170 if (runtime.enableDataset) {
19171 _this.dataset = new Proxy({}, {
19172 get: function (target, name) {
19173 var formattedName = "".concat(DATASET_PREFIX).concat(kebabize(name));
19174 if (target[formattedName] !== undefined) {
19175 return target[formattedName];
19176 }
19177 return _this.getAttribute(formattedName);
19178 },
19179 set: function (_, prop, value) {
19180 _this.setAttribute("".concat(DATASET_PREFIX).concat(kebabize(prop)), value);
19181 return true;
19182 },
19183 });
19184 }
19185 if (runtime.enableStyleSyntax) {
19186 _this.style = new Proxy(
19187 // @ts-ignore
19188 {
19189 // ...this.attributes,
19190 setProperty: function (propertyName, value) {
19191 _this.setAttribute(propertyName, value);
19192 },
19193 getPropertyValue: function (propertyName) {
19194 return _this.getAttribute(propertyName);
19195 },
19196 removeProperty: function (propertyName) {
19197 _this.removeAttribute(propertyName);
19198 },
19199 item: function () {
19200 return '';
19201 },
19202 }, {
19203 get: function (target, name) {
19204 if (target[name] !== undefined) {
19205 // if (name in target) {
19206 return target[name];
19207 }
19208 return _this.getAttribute(name);
19209 },
19210 set: function (_, prop, value) {
19211 _this.setAttribute(prop, value);
19212 return true;
19213 },
19214 });
19215 }
19216 return _this;
19217 }
19218 DisplayObject.prototype.destroy = function () {
19219 _super.prototype.destroy.call(this);
19220 // stop all active animations
19221 this.getAnimations().forEach(function (animation) {
19222 animation.cancel();
19223 });
19224 // FIXME
19225 // this.renderable = null;
19226 // this.cullable = null;
19227 // this.transformable = null;
19228 // this.rBushNode = null;
19229 // this.geometry = null;
19230 // this.sortable = null;
19231 };
19232 DisplayObject.prototype.cloneNode = function (deep, customCloneFunc) {
19233 var clonedStyle = __assign({}, this.attributes);
19234 for (var attributeName in clonedStyle) {
19235 var attribute = clonedStyle[attributeName];
19236 // @see https://github.com/antvis/G/issues/1095
19237 if (isDisplayObject(attribute) &&
19238 // share the same clipPath if possible
19239 attributeName !== 'clipPath' &&
19240 attributeName !== 'offsetPath' &&
19241 attributeName !== 'textPath') {
19242 clonedStyle[attributeName] = attribute.cloneNode(deep);
19243 }
19244 // TODO: clone other type
19245 if (customCloneFunc) {
19246 clonedStyle[attributeName] = customCloneFunc(attributeName, attribute);
19247 }
19248 }
19249 var cloned = new this.constructor({
19250 // copy id & name
19251 // @see https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode#notes
19252 id: this.id,
19253 name: this.name,
19254 className: this.name,
19255 interactive: this.interactive,
19256 style: clonedStyle,
19257 });
19258 // apply transform
19259 cloned.setLocalTransform(this.getLocalTransform());
19260 if (deep) {
19261 this.children.forEach(function (child) {
19262 // skip marker
19263 if (!child.style.isMarker) {
19264 var clonedChild = child.cloneNode(deep);
19265 cloned.appendChild(clonedChild);
19266 }
19267 });
19268 }
19269 return cloned;
19270 };
19271 DisplayObject.prototype.initAttributes = function (attributes) {
19272 if (attributes === void 0) { attributes = {}; }
19273 var renderable = this.renderable;
19274 var options = {
19275 forceUpdateGeometry: true,
19276 // usedAttributes:
19277 // // only Group / Text should account for text relative props
19278 // this.tagName === Shape.GROUP || this.tagName === Shape.TEXT
19279 // ? INHERITABLE_STYLE_PROPS
19280 // : INHERITABLE_BASE_STYLE_PROPS,
19281 };
19282 if (runtime.enableCSSParsing) {
19283 // @ts-ignore
19284 options.usedAttributes = INHERITABLE_STYLE_PROPS;
19285 }
19286 // account for FCP, process properties as less as possible
19287 var formattedAttributes = {};
19288 for (var name_1 in attributes) {
19289 var attributeName = formatAttributeName(name_1);
19290 formattedAttributes[attributeName] = attributes[name_1];
19291 }
19292 runtime.styleValueRegistry.processProperties(this, formattedAttributes, options);
19293 // redraw at next frame
19294 renderable.dirty = true;
19295 };
19296 DisplayObject.prototype.setAttribute = function (name, value, force) {
19297 if (force === void 0) { force = false; }
19298 var attributeName = formatAttributeName(name);
19299 // ignore undefined value
19300 if (isUndefined(value)) {
19301 return;
19302 }
19303 if (force || value !== this.attributes[attributeName]) {
19304 this.internalSetAttribute(attributeName, value);
19305 _super.prototype.setAttribute.call(this, attributeName, value);
19306 }
19307 };
19308 /**
19309 * called when attributes get changed or initialized
19310 */
19311 DisplayObject.prototype.internalSetAttribute = function (name, value, parseOptions) {
19312 var _a;
19313 if (parseOptions === void 0) { parseOptions = {}; }
19314 var renderable = this.renderable;
19315 var oldValue = this.attributes[name];
19316 var oldParsedValue = this.parsedStyle[name];
19317 runtime.styleValueRegistry.processProperties(this, (_a = {},
19318 _a[name] = value,
19319 _a), parseOptions);
19320 // redraw at next frame
19321 renderable.dirty = true;
19322 var newParsedValue = this.parsedStyle[name];
19323 if (this.isConnected) {
19324 mutationEvent.relatedNode = this;
19325 mutationEvent.prevValue = oldValue;
19326 mutationEvent.newValue = value;
19327 mutationEvent.attrName = name;
19328 mutationEvent.prevParsedValue = oldParsedValue;
19329 mutationEvent.newParsedValue = newParsedValue;
19330 if (this.isMutationObserved) {
19331 this.dispatchEvent(mutationEvent);
19332 }
19333 else {
19334 mutationEvent.target = this;
19335 this.ownerDocument.defaultView.dispatchEvent(mutationEvent, true);
19336 }
19337 }
19338 if (((this.isCustomElement && this.isConnected) || !this.isCustomElement) &&
19339 this.attributeChangedCallback) {
19340 this.attributeChangedCallback(name, oldValue, value, oldParsedValue, newParsedValue);
19341 }
19342 };
19343 // #region transformable
19344 /**
19345 * returns different values than getBoundingClientRect(), as the latter returns value relative to the viewport
19346 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement/getBBox
19347 *
19348 * FIXME: It is worth noting that getBBox responds to original untransformed values of a drawn object.
19349 * @see https://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#getBBox
19350 */
19351 DisplayObject.prototype.getBBox = function () {
19352 var aabb = this.getBounds();
19353 var _a = __read(aabb.getMin(), 2), left = _a[0], top = _a[1];
19354 var _b = __read(aabb.getMax(), 2), right = _b[0], bottom = _b[1];
19355 return new Rectangle(left, top, right - left, bottom - top);
19356 };
19357 DisplayObject.prototype.setOrigin = function (position, y, z) {
19358 if (y === void 0) { y = 0; }
19359 if (z === void 0) { z = 0; }
19360 runtime.sceneGraphService.setOrigin(this, createVec3(position, y, z));
19361 return this;
19362 };
19363 DisplayObject.prototype.getOrigin = function () {
19364 return runtime.sceneGraphService.getOrigin(this);
19365 };
19366 /**
19367 * set position in world space
19368 */
19369 DisplayObject.prototype.setPosition = function (position, y, z) {
19370 if (y === void 0) { y = 0; }
19371 if (z === void 0) { z = 0; }
19372 runtime.sceneGraphService.setPosition(this, createVec3(position, y, z));
19373 return this;
19374 };
19375 /**
19376 * set position in local space
19377 */
19378 DisplayObject.prototype.setLocalPosition = function (position, y, z) {
19379 if (y === void 0) { y = 0; }
19380 if (z === void 0) { z = 0; }
19381 runtime.sceneGraphService.setLocalPosition(this, createVec3(position, y, z));
19382 return this;
19383 };
19384 /**
19385 * translate in world space
19386 */
19387 DisplayObject.prototype.translate = function (position, y, z) {
19388 if (y === void 0) { y = 0; }
19389 if (z === void 0) { z = 0; }
19390 runtime.sceneGraphService.translate(this, createVec3(position, y, z));
19391 return this;
19392 };
19393 /**
19394 * translate in local space
19395 */
19396 DisplayObject.prototype.translateLocal = function (position, y, z) {
19397 if (y === void 0) { y = 0; }
19398 if (z === void 0) { z = 0; }
19399 runtime.sceneGraphService.translateLocal(this, createVec3(position, y, z));
19400 return this;
19401 };
19402 DisplayObject.prototype.getPosition = function () {
19403 return runtime.sceneGraphService.getPosition(this);
19404 };
19405 DisplayObject.prototype.getLocalPosition = function () {
19406 return runtime.sceneGraphService.getLocalPosition(this);
19407 };
19408 /**
19409 * compatible with G 3.0
19410 *
19411 * scaling in local space
19412 * scale(10) = scale(10, 10, 10)
19413 *
19414 * we can't set scale in world space
19415 */
19416 DisplayObject.prototype.scale = function (scaling, y, z) {
19417 return this.scaleLocal(scaling, y, z);
19418 };
19419 DisplayObject.prototype.scaleLocal = function (scaling, y, z) {
19420 if (typeof scaling === 'number') {
19421 y = y || scaling;
19422 z = z || scaling;
19423 scaling = createVec3(scaling, y, z);
19424 }
19425 runtime.sceneGraphService.scaleLocal(this, scaling);
19426 return this;
19427 };
19428 /**
19429 * set scaling in local space
19430 */
19431 DisplayObject.prototype.setLocalScale = function (scaling, y, z) {
19432 if (typeof scaling === 'number') {
19433 y = y || scaling;
19434 z = z || scaling;
19435 scaling = createVec3(scaling, y, z);
19436 }
19437 runtime.sceneGraphService.setLocalScale(this, scaling);
19438 return this;
19439 };
19440 /**
19441 * get scaling in local space
19442 */
19443 DisplayObject.prototype.getLocalScale = function () {
19444 return runtime.sceneGraphService.getLocalScale(this);
19445 };
19446 /**
19447 * get scaling in world space
19448 */
19449 DisplayObject.prototype.getScale = function () {
19450 return runtime.sceneGraphService.getScale(this);
19451 };
19452 /**
19453 * only return degrees of Z axis in world space
19454 */
19455 DisplayObject.prototype.getEulerAngles = function () {
19456 var _a = __read(getEuler(create$2(), runtime.sceneGraphService.getWorldTransform(this)), 3), ez = _a[2];
19457 return rad2deg(ez);
19458 };
19459 /**
19460 * only return degrees of Z axis in local space
19461 */
19462 DisplayObject.prototype.getLocalEulerAngles = function () {
19463 var _a = __read(getEuler(create$2(), runtime.sceneGraphService.getLocalRotation(this)), 3), ez = _a[2];
19464 return rad2deg(ez);
19465 };
19466 /**
19467 * set euler angles(degrees) in world space
19468 */
19469 DisplayObject.prototype.setEulerAngles = function (z) {
19470 runtime.sceneGraphService.setEulerAngles(this, 0, 0, z);
19471 return this;
19472 };
19473 /**
19474 * set euler angles(degrees) in local space
19475 */
19476 DisplayObject.prototype.setLocalEulerAngles = function (z) {
19477 runtime.sceneGraphService.setLocalEulerAngles(this, 0, 0, z);
19478 return this;
19479 };
19480 DisplayObject.prototype.rotateLocal = function (x, y, z) {
19481 if (isNil(y) && isNil(z)) {
19482 runtime.sceneGraphService.rotateLocal(this, 0, 0, x);
19483 }
19484 else {
19485 runtime.sceneGraphService.rotateLocal(this, x, y, z);
19486 }
19487 return this;
19488 };
19489 DisplayObject.prototype.rotate = function (x, y, z) {
19490 if (isNil(y) && isNil(z)) {
19491 runtime.sceneGraphService.rotate(this, 0, 0, x);
19492 }
19493 else {
19494 runtime.sceneGraphService.rotate(this, x, y, z);
19495 }
19496 return this;
19497 };
19498 DisplayObject.prototype.setRotation = function (rotation, y, z, w) {
19499 runtime.sceneGraphService.setRotation(this, rotation, y, z, w);
19500 return this;
19501 };
19502 DisplayObject.prototype.setLocalRotation = function (rotation, y, z, w) {
19503 runtime.sceneGraphService.setLocalRotation(this, rotation, y, z, w);
19504 return this;
19505 };
19506 DisplayObject.prototype.setLocalSkew = function (skew, y) {
19507 runtime.sceneGraphService.setLocalSkew(this, skew, y);
19508 return this;
19509 };
19510 DisplayObject.prototype.getRotation = function () {
19511 return runtime.sceneGraphService.getRotation(this);
19512 };
19513 DisplayObject.prototype.getLocalRotation = function () {
19514 return runtime.sceneGraphService.getLocalRotation(this);
19515 };
19516 DisplayObject.prototype.getLocalSkew = function () {
19517 return runtime.sceneGraphService.getLocalSkew(this);
19518 };
19519 DisplayObject.prototype.getLocalTransform = function () {
19520 return runtime.sceneGraphService.getLocalTransform(this);
19521 };
19522 DisplayObject.prototype.getWorldTransform = function () {
19523 return runtime.sceneGraphService.getWorldTransform(this);
19524 };
19525 DisplayObject.prototype.setLocalTransform = function (transform) {
19526 runtime.sceneGraphService.setLocalTransform(this, transform);
19527 return this;
19528 };
19529 DisplayObject.prototype.resetLocalTransform = function () {
19530 runtime.sceneGraphService.resetLocalTransform(this);
19531 };
19532 // #endregion transformable
19533 // #region animatable
19534 /**
19535 * returns an array of all Animation objects affecting this element
19536 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getAnimations
19537 */
19538 DisplayObject.prototype.getAnimations = function () {
19539 return this.activeAnimations;
19540 };
19541 /**
19542 * create an animation with WAAPI
19543 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/animate
19544 */
19545 DisplayObject.prototype.animate = function (keyframes, options) {
19546 var _a;
19547 var timeline = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.timeline;
19548 if (timeline) {
19549 return timeline.play(this, keyframes, options);
19550 }
19551 return null;
19552 };
19553 // #endregion animatable
19554 // #region visible
19555 /**
19556 * shortcut for Used value of `visibility`
19557 */
19558 DisplayObject.prototype.isVisible = function () {
19559 var _a;
19560 return ((_a = this.parsedStyle) === null || _a === void 0 ? void 0 : _a.visibility) === 'visible';
19561 };
19562 Object.defineProperty(DisplayObject.prototype, "interactive", {
19563 get: function () {
19564 return this.isInteractive();
19565 },
19566 set: function (b) {
19567 this.style.pointerEvents = b ? 'auto' : 'none';
19568 },
19569 enumerable: false,
19570 configurable: true
19571 });
19572 DisplayObject.prototype.isInteractive = function () {
19573 var _a;
19574 return ((_a = this.parsedStyle) === null || _a === void 0 ? void 0 : _a.pointerEvents) !== 'none';
19575 };
19576 DisplayObject.prototype.isCulled = function () {
19577 return !!(this.cullable && this.cullable.enable && !this.cullable.visible);
19578 };
19579 /**
19580 * bring to front in current group
19581 */
19582 DisplayObject.prototype.toFront = function () {
19583 if (this.parentNode) {
19584 this.style.zIndex =
19585 Math.max.apply(Math, __spreadArray([], __read(this.parentNode.children.map(function (child) {
19586 return Number(child.style.zIndex);
19587 })), false)) + 1;
19588 }
19589 return this;
19590 };
19591 /**
19592 * send to back in current group
19593 */
19594 DisplayObject.prototype.toBack = function () {
19595 if (this.parentNode) {
19596 this.style.zIndex =
19597 Math.min.apply(Math, __spreadArray([], __read(this.parentNode.children.map(function (child) {
19598 return Number(child.style.zIndex);
19599 })), false)) - 1;
19600 }
19601 return this;
19602 };
19603 // #endregion visible
19604 // #region deprecated
19605 /**
19606 * compatible with G 3.0
19607 * @alias object.config
19608 * @deprecated
19609 */
19610 DisplayObject.prototype.getConfig = function () {
19611 return this.config;
19612 };
19613 DisplayObject.prototype.attr = function () {
19614 var _this = this;
19615 var args = [];
19616 for (var _i = 0; _i < arguments.length; _i++) {
19617 args[_i] = arguments[_i];
19618 }
19619 var _a = __read(args, 2), name = _a[0], value = _a[1];
19620 if (!name) {
19621 return this.attributes;
19622 }
19623 if (isObject(name)) {
19624 Object.keys(name).forEach(function (key) {
19625 _this.setAttribute(key, name[key]);
19626 });
19627 return this;
19628 }
19629 if (args.length === 2) {
19630 this.setAttribute(name, value);
19631 return this;
19632 }
19633 return this.attributes[name];
19634 };
19635 /**
19636 * return 3x3 matrix in world space
19637 * @deprecated
19638 */
19639 DisplayObject.prototype.getMatrix = function (transformMat4) {
19640 var transform = transformMat4 || this.getWorldTransform();
19641 var _a = __read(getTranslation(create$2(), transform), 2), tx = _a[0], ty = _a[1];
19642 var _b = __read(getScaling(create$2(), transform), 2), sx = _b[0], sy = _b[1];
19643 var rotation = getRotation(create$4(), transform);
19644 var _c = __read(getEuler(create$2(), rotation), 3), eux = _c[0], euz = _c[2];
19645 // gimbal lock at 90 degrees
19646 return fromRotationTranslationScale$1(eux || euz, tx, ty, sx, sy);
19647 };
19648 /**
19649 * return 3x3 matrix in local space
19650 * @deprecated
19651 */
19652 DisplayObject.prototype.getLocalMatrix = function () {
19653 return this.getMatrix(this.getLocalTransform());
19654 };
19655 /**
19656 * set 3x3 matrix in world space
19657 * @deprecated
19658 */
19659 DisplayObject.prototype.setMatrix = function (mat) {
19660 var _a = __read(decompose(mat), 5), tx = _a[0], ty = _a[1], scalingX = _a[2], scalingY = _a[3], angle = _a[4];
19661 this.setEulerAngles(angle)
19662 .setPosition(tx, ty)
19663 .setLocalScale(scalingX, scalingY);
19664 };
19665 /**
19666 * set 3x3 matrix in local space
19667 * @deprecated
19668 */
19669 DisplayObject.prototype.setLocalMatrix = function (mat) {
19670 var _a = __read(decompose(mat), 5), tx = _a[0], ty = _a[1], scalingX = _a[2], scalingY = _a[3], angle = _a[4];
19671 this.setLocalEulerAngles(angle)
19672 .setLocalPosition(tx, ty)
19673 .setLocalScale(scalingX, scalingY);
19674 };
19675 /**
19676 * Use `visibility: visible` instead.
19677 * @deprecated
19678 */
19679 DisplayObject.prototype.show = function () {
19680 if (runtime.enableCSSParsing) {
19681 this.style.visibility = 'visible';
19682 }
19683 else {
19684 this.forEach(function (object) {
19685 object.style.visibility = 'visible';
19686 });
19687 }
19688 };
19689 /**
19690 * Use `visibility: hidden` instead.
19691 * @deprecated
19692 */
19693 DisplayObject.prototype.hide = function () {
19694 if (runtime.enableCSSParsing) {
19695 this.style.visibility = 'hidden';
19696 }
19697 else {
19698 this.forEach(function (object) {
19699 object.style.visibility = 'hidden';
19700 });
19701 }
19702 };
19703 /**
19704 * Use `childElementCount` instead.
19705 * @deprecated
19706 */
19707 DisplayObject.prototype.getCount = function () {
19708 return this.childElementCount;
19709 };
19710 /**
19711 * Use `parentElement` instead.
19712 * @deprecated
19713 */
19714 DisplayObject.prototype.getParent = function () {
19715 return this.parentElement;
19716 };
19717 /**
19718 * Use `children` instead.
19719 * @deprecated
19720 */
19721 DisplayObject.prototype.getChildren = function () {
19722 return this.children;
19723 };
19724 /**
19725 * Use `firstElementChild` instead.
19726 * @deprecated
19727 */
19728 DisplayObject.prototype.getFirst = function () {
19729 return this.firstElementChild;
19730 };
19731 /**
19732 * Use `lastElementChild` instead.
19733 * @deprecated
19734 */
19735 DisplayObject.prototype.getLast = function () {
19736 return this.lastElementChild;
19737 };
19738 /**
19739 * Use `this.children[index]` instead.
19740 * @deprecated
19741 */
19742 DisplayObject.prototype.getChildByIndex = function (index) {
19743 return this.children[index] || null;
19744 };
19745 /**
19746 * Use `appendChild` instead.
19747 * @deprecated
19748 */
19749 DisplayObject.prototype.add = function (child, index) {
19750 return this.appendChild(child, index);
19751 };
19752 /**
19753 * Use `this.style.clipPath` instead.
19754 * @deprecated
19755 */
19756 DisplayObject.prototype.setClip = function (clipPath) {
19757 this.style.clipPath = clipPath;
19758 };
19759 /**
19760 * @deprecated
19761 */
19762 DisplayObject.prototype.set = function (name, value) {
19763 // @ts-ignore
19764 this.config[name] = value;
19765 };
19766 /**
19767 * @deprecated
19768 */
19769 DisplayObject.prototype.get = function (name) {
19770 return this.config[name];
19771 };
19772 /**
19773 * Use `setPosition` instead.
19774 * @deprecated
19775 */
19776 DisplayObject.prototype.moveTo = function (position, y, z) {
19777 if (y === void 0) { y = 0; }
19778 if (z === void 0) { z = 0; }
19779 this.setPosition(position, y, z);
19780 return this;
19781 };
19782 /**
19783 * Use `setPosition` instead.
19784 * @deprecated
19785 */
19786 DisplayObject.prototype.move = function (position, y, z) {
19787 if (y === void 0) { y = 0; }
19788 if (z === void 0) { z = 0; }
19789 this.setPosition(position, y, z);
19790 return this;
19791 };
19792 /**
19793 * Use `this.style.zIndex` instead.
19794 * @deprecated
19795 */
19796 DisplayObject.prototype.setZIndex = function (zIndex) {
19797 this.style.zIndex = zIndex;
19798 return this;
19799 };
19800 return DisplayObject;
19801 }(Element));
19802
19803 /**
19804 * holds useful CSS-related methods.
19805 * @see https://developer.mozilla.org/en-US/docs/Web/API/CSS
19806 *
19807 * * CSS Typed OM @see https://developer.mozilla.org/en-US/docs/Web/API/CSS/factory_functions
19808 * * register property @see https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty
19809 * * CSS Layout API
19810 */
19811 var CSS = {
19812 /**
19813 * <number>
19814 * @see https://drafts.csswg.org/css-values-4/#number-value
19815 */
19816 number: function (n) {
19817 return new CSSUnitValue(n);
19818 },
19819 /**
19820 * <percentage>
19821 * @see https://drafts.csswg.org/css-values-4/#percentage-value
19822 */
19823 percent: function (n) {
19824 return new CSSUnitValue(n, '%');
19825 },
19826 /**
19827 * <length>
19828 */
19829 px: function (n) {
19830 return new CSSUnitValue(n, 'px');
19831 },
19832 /**
19833 * <length>
19834 */
19835 em: function (n) {
19836 return new CSSUnitValue(n, 'em');
19837 },
19838 rem: function (n) {
19839 return new CSSUnitValue(n, 'rem');
19840 },
19841 /**
19842 * <angle>
19843 */
19844 deg: function (n) {
19845 return new CSSUnitValue(n, 'deg');
19846 },
19847 /**
19848 * <angle>
19849 */
19850 grad: function (n) {
19851 return new CSSUnitValue(n, 'grad');
19852 },
19853 /**
19854 * <angle>
19855 */
19856 rad: function (n) {
19857 return new CSSUnitValue(n, 'rad');
19858 },
19859 /**
19860 * <angle>
19861 */
19862 turn: function (n) {
19863 return new CSSUnitValue(n, 'turn');
19864 },
19865 /**
19866 * <time>
19867 */
19868 s: function (n) {
19869 return new CSSUnitValue(n, 's');
19870 },
19871 /**
19872 * <time>
19873 */
19874 ms: function (n) {
19875 return new CSSUnitValue(n, 'ms');
19876 },
19877 /**
19878 * CSS Properties & Values API
19879 *
19880 * @see https://developer.mozilla.org/en-US/docs/Web/API/CSS_Properties_and_Values_API
19881 * @see https://drafts.css-houdini.org/css-properties-values-api/#registering-custom-properties
19882 * @see https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty
19883 */
19884 registerProperty: function (definition) {
19885 var name = definition.name, inherits = definition.inherits, interpolable = definition.interpolable, initialValue = definition.initialValue, syntax = definition.syntax;
19886 runtime.styleValueRegistry.registerMetadata({
19887 n: name,
19888 inh: inherits,
19889 int: interpolable,
19890 d: initialValue,
19891 syntax: syntax,
19892 });
19893 },
19894 /**
19895 * CSS Layout API
19896 * register layout
19897 *
19898 * @see https://github.com/w3c/css-houdini-drafts/blob/main/css-layout-api/EXPLAINER.md
19899 * @see https://developer.mozilla.org/en-US/docs/Web/Guide/Houdini#css_layout_api
19900 */
19901 registerLayout: function (name, clazz) {
19902 runtime.layoutRegistry.registerLayout(name, clazz);
19903 },
19904 };
19905
19906 var Circle = /** @class */ (function (_super) {
19907 __extends(Circle, _super);
19908 function Circle(_a) {
19909 if (_a === void 0) { _a = {}; }
19910 var style = _a.style, rest = __rest(_a, ["style"]);
19911 return _super.call(this, __assign({ type: Shape.CIRCLE, style: runtime.enableCSSParsing
19912 ? __assign({ cx: '', cy: '', r: '' }, style) : __assign({}, style), initialParsedStyle: {
19913 anchor: [0.5, 0.5],
19914 transformOrigin: runtime.enableCSSParsing
19915 ? null
19916 : [PECENTAGE_50, PECENTAGE_50],
19917 } }, rest)) || this;
19918 }
19919 return Circle;
19920 }(DisplayObject));
19921
19922 /**
19923 * shadow root
19924 * @see https://yuque.antfin-inc.com/antv/czqvg5/pgqipg
19925 */
19926 var CustomElement = /** @class */ (function (_super) {
19927 __extends(CustomElement, _super);
19928 // private shadowNodes: DisplayObject[] = [];
19929 function CustomElement(_a) {
19930 var _this = this;
19931 if (_a === void 0) { _a = {}; }
19932 var style = _a.style, rest = __rest(_a, ["style"]);
19933 _this = _super.call(this, __assign({ style: runtime.enableCSSParsing
19934 ? __assign({ x: '', y: '' }, style) : __assign({}, style) }, rest)) || this;
19935 // static get observedAttributes(): string[] {
19936 // return [];
19937 // }
19938 _this.isCustomElement = true;
19939 return _this;
19940 }
19941 return CustomElement;
19942 }(DisplayObject));
19943
19944 var Ellipse = /** @class */ (function (_super) {
19945 __extends(Ellipse, _super);
19946 function Ellipse(_a) {
19947 if (_a === void 0) { _a = {}; }
19948 var style = _a.style, rest = __rest(_a, ["style"]);
19949 return _super.call(this, __assign({ type: Shape.ELLIPSE, style: runtime.enableCSSParsing
19950 ? __assign({ cx: '', cy: '', rx: '', ry: '' }, style) : __assign({}, style), initialParsedStyle: {
19951 anchor: [0.5, 0.5],
19952 transformOrigin: runtime.enableCSSParsing
19953 ? null
19954 : [PECENTAGE_50, PECENTAGE_50],
19955 } }, rest)) || this;
19956 }
19957 return Ellipse;
19958 }(DisplayObject));
19959
19960 /**
19961 * its attributes are inherited by its children.
19962 * @see https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/g
19963 *
19964 * @example
19965 * <g fill="white" stroke="green" stroke-width="5">
19966 <circle cx="40" cy="40" r="25" />
19967 <circle cx="60" cy="60" r="25" />
19968 </g>
19969 */
19970 var Group = /** @class */ (function (_super) {
19971 __extends(Group, _super);
19972 function Group(_a) {
19973 if (_a === void 0) { _a = {}; }
19974 var style = _a.style, rest = __rest(_a, ["style"]);
19975 return _super.call(this, __assign({ type: Shape.GROUP, style: runtime.enableCSSParsing
19976 ? __assign({ x: '', y: '', width: '', height: '' }, style) : __assign({}, style) }, rest)) || this;
19977 }
19978 return Group;
19979 }(DisplayObject));
19980
19981 /**
19982 * HTML container
19983 * @see https://github.com/pmndrs/drei#html
19984 */
19985 var HTML = /** @class */ (function (_super) {
19986 __extends(HTML, _super);
19987 function HTML(_a) {
19988 var _this = this;
19989 if (_a === void 0) { _a = {}; }
19990 var style = _a.style, rest = __rest(_a, ["style"]);
19991 _this = _super.call(this, __assign({ type: Shape.HTML, style: runtime.enableCSSParsing
19992 ? __assign({ x: '', y: '', width: 'auto', height: 'auto', innerHTML: '' }, style) : __assign({}, style) }, rest)) || this;
19993 _this.cullable.enable = false;
19994 return _this;
19995 }
19996 /**
19997 * return wrapper HTMLElement
19998 * * <div> in g-webgl/canvas
19999 * * <foreignObject> in g-svg
20000 */
20001 HTML.prototype.getDomElement = function () {
20002 return this.parsedStyle.$el;
20003 };
20004 /**
20005 * override with $el.getBoundingClientRect
20006 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect
20007 */
20008 HTML.prototype.getBoundingClientRect = function () {
20009 if (this.parsedStyle.$el) {
20010 return this.parsedStyle.$el.getBoundingClientRect();
20011 }
20012 else {
20013 var _a = this.parsedStyle, x = _a.x, y = _a.y, width = _a.width, height = _a.height;
20014 return new Rectangle(x, y, width, height);
20015 }
20016 };
20017 HTML.prototype.getClientRects = function () {
20018 return [this.getBoundingClientRect()];
20019 };
20020 HTML.prototype.getBounds = function () {
20021 var _a, _b;
20022 var clientRect = this.getBoundingClientRect();
20023 // calc context's offset
20024 // @ts-ignore
20025 var canvasRect = (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.getContextService().getBoundingClientRect();
20026 var aabb = new AABB();
20027 var minX = clientRect.left - ((canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.left) || 0);
20028 var minY = clientRect.top - ((canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.top) || 0);
20029 aabb.setMinMax([minX, minY, 0], [minX + clientRect.width, minY + clientRect.height, 0]);
20030 return aabb;
20031 };
20032 HTML.prototype.getLocalBounds = function () {
20033 if (this.parentNode) {
20034 var parentInvert = invert(create$1(), this.parentNode.getWorldTransform());
20035 var bounds = this.getBounds();
20036 if (!AABB.isEmpty(bounds)) {
20037 var localBounds = new AABB();
20038 localBounds.setFromTransformedAABB(bounds, parentInvert);
20039 return localBounds;
20040 }
20041 }
20042 return this.getBounds();
20043 };
20044 return HTML;
20045 }(DisplayObject));
20046
20047 var Image = /** @class */ (function (_super) {
20048 __extends(Image, _super);
20049 function Image(_a) {
20050 if (_a === void 0) { _a = {}; }
20051 var style = _a.style, rest = __rest(_a, ["style"]);
20052 return _super.call(this, __assign({ type: Shape.IMAGE, style: runtime.enableCSSParsing
20053 ? __assign({ x: '', y: '', img: '', width: '', height: '' }, style) : __assign({}, style) }, rest)) || this;
20054 }
20055 return Image;
20056 }(DisplayObject));
20057
20058 /**
20059 * Create a line connecting two points.
20060 * @see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line
20061 *
20062 * Also support for using marker.
20063 */
20064 var Line = /** @class */ (function (_super) {
20065 __extends(Line, _super);
20066 function Line(_a) {
20067 var _this = this;
20068 if (_a === void 0) { _a = {}; }
20069 var style = _a.style, rest = __rest(_a, ["style"]);
20070 _this = _super.call(this, __assign({ type: Shape.LINE, style: __assign({ x1: 0, y1: 0, x2: 0, y2: 0, z1: 0, z2: 0 }, style) }, rest)) || this;
20071 _this.markerStartAngle = 0;
20072 _this.markerEndAngle = 0;
20073 var _b = _this.parsedStyle, markerStart = _b.markerStart, markerEnd = _b.markerEnd;
20074 if (markerStart && isDisplayObject(markerStart)) {
20075 _this.markerStartAngle = markerStart.getLocalEulerAngles();
20076 _this.appendChild(markerStart);
20077 }
20078 if (markerEnd && isDisplayObject(markerEnd)) {
20079 _this.markerEndAngle = markerEnd.getLocalEulerAngles();
20080 _this.appendChild(markerEnd);
20081 }
20082 _this.transformMarker(true);
20083 _this.transformMarker(false);
20084 return _this;
20085 }
20086 Line.prototype.attributeChangedCallback = function (attrName, oldValue, newValue, prevParsedValue, newParsedValue) {
20087 if (attrName === 'x1' ||
20088 attrName === 'y1' ||
20089 attrName === 'x2' ||
20090 attrName === 'y2' ||
20091 attrName === 'markerStartOffset' ||
20092 attrName === 'markerEndOffset') {
20093 this.transformMarker(true);
20094 this.transformMarker(false);
20095 }
20096 else if (attrName === 'markerStart') {
20097 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20098 this.markerStartAngle = 0;
20099 prevParsedValue.remove();
20100 }
20101 // CSSKeyword 'unset'
20102 if (newParsedValue && isDisplayObject(newParsedValue)) {
20103 this.markerStartAngle = newParsedValue.getLocalEulerAngles();
20104 this.appendChild(newParsedValue);
20105 this.transformMarker(true);
20106 }
20107 }
20108 else if (attrName === 'markerEnd') {
20109 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20110 this.markerEndAngle = 0;
20111 prevParsedValue.remove();
20112 }
20113 if (newParsedValue && isDisplayObject(newParsedValue)) {
20114 this.markerEndAngle = newParsedValue.getLocalEulerAngles();
20115 this.appendChild(newParsedValue);
20116 this.transformMarker(false);
20117 }
20118 }
20119 };
20120 Line.prototype.transformMarker = function (isStart) {
20121 var _a = this.parsedStyle, markerStart = _a.markerStart, markerEnd = _a.markerEnd, markerStartOffset = _a.markerStartOffset, markerEndOffset = _a.markerEndOffset, x1 = _a.x1, x2 = _a.x2, y1 = _a.y1, y2 = _a.y2, defX = _a.defX, defY = _a.defY;
20122 var marker = isStart ? markerStart : markerEnd;
20123 if (!marker || !isDisplayObject(marker)) {
20124 return;
20125 }
20126 var rad = 0;
20127 var x;
20128 var y;
20129 var ox;
20130 var oy;
20131 var offset;
20132 var originalAngle;
20133 if (isStart) {
20134 ox = x1 - defX;
20135 oy = y1 - defY;
20136 x = x2 - x1;
20137 y = y2 - y1;
20138 offset = markerStartOffset || 0;
20139 originalAngle = this.markerStartAngle;
20140 }
20141 else {
20142 ox = x2 - defX;
20143 oy = y2 - defY;
20144 x = x1 - x2;
20145 y = y1 - y2;
20146 offset = markerEndOffset || 0;
20147 originalAngle = this.markerEndAngle;
20148 }
20149 rad = Math.atan2(y, x);
20150 // account for markerOffset
20151 marker.setLocalEulerAngles((rad * 180) / Math.PI + originalAngle);
20152 marker.setLocalPosition(ox + Math.cos(rad) * offset, oy + Math.sin(rad) * offset);
20153 };
20154 Line.prototype.getPoint = function (ratio, inWorldSpace) {
20155 if (inWorldSpace === void 0) { inWorldSpace = false; }
20156 // TODO: account for z1/z2 in 3D line
20157 var _a = this.parsedStyle, x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2, defX = _a.defX, defY = _a.defY;
20158 var _b = pointAt$3(x1, y1, x2, y2, ratio), x = _b.x, y = _b.y;
20159 var transformed = transformMat4(create$2(), fromValues$2(x - defX, y - defY, 0), inWorldSpace ? this.getWorldTransform() : this.getLocalTransform());
20160 // apply local transformation
20161 return new Point(transformed[0], transformed[1]);
20162 };
20163 Line.prototype.getPointAtLength = function (distance, inWorldSpace) {
20164 if (inWorldSpace === void 0) { inWorldSpace = false; }
20165 return this.getPoint(distance / this.getTotalLength(), inWorldSpace);
20166 };
20167 Line.prototype.getTotalLength = function () {
20168 // TODO: account for z1/z2 in 3D line
20169 var _a = this.parsedStyle, x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2;
20170 return length$4(x1, y1, x2, y2);
20171 };
20172 return Line;
20173 }(DisplayObject));
20174
20175 var Path = /** @class */ (function (_super) {
20176 __extends(Path, _super);
20177 function Path(_a) {
20178 var _this = this;
20179 if (_a === void 0) { _a = {}; }
20180 var style = _a.style, rest = __rest(_a, ["style"]);
20181 _this = _super.call(this, __assign({ type: Shape.PATH, style: runtime.enableCSSParsing
20182 ? __assign({ path: '', miterLimit: '' }, style) : __assign({}, style), initialParsedStyle: runtime.enableCSSParsing
20183 ? null
20184 : {
20185 miterLimit: 4,
20186 path: __assign({}, EMPTY_PARSED_PATH),
20187 } }, rest)) || this;
20188 _this.markerStartAngle = 0;
20189 _this.markerEndAngle = 0;
20190 /**
20191 * markers placed at the mid
20192 */
20193 _this.markerMidList = [];
20194 var _b = _this.parsedStyle, markerStart = _b.markerStart, markerEnd = _b.markerEnd, markerMid = _b.markerMid;
20195 if (markerStart && isDisplayObject(markerStart)) {
20196 _this.markerStartAngle = markerStart.getLocalEulerAngles();
20197 _this.appendChild(markerStart);
20198 }
20199 if (markerMid && isDisplayObject(markerMid)) {
20200 _this.placeMarkerMid(markerMid);
20201 }
20202 if (markerEnd && isDisplayObject(markerEnd)) {
20203 _this.markerEndAngle = markerEnd.getLocalEulerAngles();
20204 _this.appendChild(markerEnd);
20205 }
20206 _this.transformMarker(true);
20207 _this.transformMarker(false);
20208 return _this;
20209 }
20210 Path.prototype.attributeChangedCallback = function (attrName, oldValue, newValue, prevParsedValue, newParsedValue) {
20211 if (attrName === 'path') {
20212 // recalc markers
20213 this.transformMarker(true);
20214 this.transformMarker(false);
20215 this.placeMarkerMid(this.parsedStyle.markerMid);
20216 }
20217 else if (attrName === 'markerStartOffset' ||
20218 attrName === 'markerEndOffset') {
20219 this.transformMarker(true);
20220 this.transformMarker(false);
20221 }
20222 else if (attrName === 'markerStart') {
20223 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20224 this.markerStartAngle = 0;
20225 prevParsedValue.remove();
20226 }
20227 // CSSKeyword 'unset'
20228 if (newParsedValue && isDisplayObject(newParsedValue)) {
20229 this.markerStartAngle = newParsedValue.getLocalEulerAngles();
20230 this.appendChild(newParsedValue);
20231 this.transformMarker(true);
20232 }
20233 }
20234 else if (attrName === 'markerEnd') {
20235 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20236 this.markerEndAngle = 0;
20237 prevParsedValue.remove();
20238 }
20239 if (newParsedValue && isDisplayObject(newParsedValue)) {
20240 this.markerEndAngle = newParsedValue.getLocalEulerAngles();
20241 this.appendChild(newParsedValue);
20242 this.transformMarker(false);
20243 }
20244 }
20245 else if (attrName === 'markerMid') {
20246 this.placeMarkerMid(newParsedValue);
20247 }
20248 };
20249 Path.prototype.transformMarker = function (isStart) {
20250 var _a = this.parsedStyle, markerStart = _a.markerStart, markerEnd = _a.markerEnd, markerStartOffset = _a.markerStartOffset, markerEndOffset = _a.markerEndOffset, defX = _a.defX, defY = _a.defY;
20251 var marker = isStart ? markerStart : markerEnd;
20252 if (!marker || !isDisplayObject(marker)) {
20253 return;
20254 }
20255 var rad = 0;
20256 var x;
20257 var y;
20258 var ox;
20259 var oy;
20260 var offset;
20261 var originalAngle;
20262 if (isStart) {
20263 var _b = __read(this.getStartTangent(), 2), p1 = _b[0], p2 = _b[1];
20264 ox = p2[0] - defX;
20265 oy = p2[1] - defY;
20266 x = p1[0] - p2[0];
20267 y = p1[1] - p2[1];
20268 offset = markerStartOffset || 0;
20269 originalAngle = this.markerStartAngle;
20270 }
20271 else {
20272 var _c = __read(this.getEndTangent(), 2), p1 = _c[0], p2 = _c[1];
20273 ox = p2[0] - defX;
20274 oy = p2[1] - defY;
20275 x = p1[0] - p2[0];
20276 y = p1[1] - p2[1];
20277 offset = markerEndOffset || 0;
20278 originalAngle = this.markerEndAngle;
20279 }
20280 rad = Math.atan2(y, x);
20281 // account for markerOffset
20282 marker.setLocalEulerAngles((rad * 180) / Math.PI + originalAngle);
20283 marker.setLocalPosition(ox + Math.cos(rad) * offset, oy + Math.sin(rad) * offset);
20284 };
20285 Path.prototype.placeMarkerMid = function (marker) {
20286 var _a = this.parsedStyle, segments = _a.path.segments, defX = _a.defX, defY = _a.defY;
20287 // clear all existed markers
20288 this.markerMidList.forEach(function (marker) {
20289 marker.remove();
20290 });
20291 if (marker && isDisplayObject(marker)) {
20292 for (var i = 1; i < segments.length - 1; i++) {
20293 var _b = __read(segments[i].currentPoint, 2), ox = _b[0], oy = _b[1];
20294 var cloned = i === 1 ? marker : marker.cloneNode(true);
20295 this.markerMidList.push(cloned);
20296 this.appendChild(cloned);
20297 cloned.setLocalPosition(ox - defX, oy - defY);
20298 // TODO: orient of marker
20299 }
20300 }
20301 };
20302 /**
20303 * Returns the total length of the path.
20304 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength
20305 */
20306 Path.prototype.getTotalLength = function () {
20307 return getOrCalculatePathTotalLength(this);
20308 };
20309 /**
20310 * Returns the point at a given distance along the path.
20311 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getPointAtLength
20312 */
20313 Path.prototype.getPointAtLength = function (distance, inWorldSpace) {
20314 if (inWorldSpace === void 0) { inWorldSpace = false; }
20315 var _a = this.parsedStyle, defX = _a.defX, defY = _a.defY, absolutePath = _a.path.absolutePath;
20316 var _b = getPointAtLength(absolutePath, distance), x = _b.x, y = _b.y;
20317 var transformed = transformMat4(create$2(), fromValues$2(x - defX, y - defY, 0), inWorldSpace ? this.getWorldTransform() : this.getLocalTransform());
20318 // apply local transformation
20319 return new Point(transformed[0], transformed[1]);
20320 };
20321 /**
20322 * Returns the point at a given ratio of the total length in path.
20323 */
20324 Path.prototype.getPoint = function (ratio, inWorldSpace) {
20325 if (inWorldSpace === void 0) { inWorldSpace = false; }
20326 return this.getPointAtLength(ratio * getOrCalculatePathTotalLength(this), inWorldSpace);
20327 };
20328 /**
20329 * Get start tangent vector
20330 */
20331 Path.prototype.getStartTangent = function () {
20332 var segments = this.parsedStyle.path.segments;
20333 var result = [];
20334 if (segments.length > 1) {
20335 var startPoint = segments[0].currentPoint;
20336 var endPoint = segments[1].currentPoint;
20337 var tangent = segments[1].startTangent;
20338 result = [];
20339 if (tangent) {
20340 result.push([startPoint[0] - tangent[0], startPoint[1] - tangent[1]]);
20341 result.push([startPoint[0], startPoint[1]]);
20342 }
20343 else {
20344 result.push([endPoint[0], endPoint[1]]);
20345 result.push([startPoint[0], startPoint[1]]);
20346 }
20347 }
20348 return result;
20349 };
20350 /**
20351 * Get end tangent vector
20352 */
20353 Path.prototype.getEndTangent = function () {
20354 var segments = this.parsedStyle.path.segments;
20355 var length = segments.length;
20356 var result = [];
20357 if (length > 1) {
20358 var startPoint = segments[length - 2].currentPoint;
20359 var endPoint = segments[length - 1].currentPoint;
20360 var tangent = segments[length - 1].endTangent;
20361 result = [];
20362 if (tangent) {
20363 result.push([endPoint[0] - tangent[0], endPoint[1] - tangent[1]]);
20364 result.push([endPoint[0], endPoint[1]]);
20365 }
20366 else {
20367 result.push([startPoint[0], startPoint[1]]);
20368 result.push([endPoint[0], endPoint[1]]);
20369 }
20370 }
20371 return result;
20372 };
20373 return Path;
20374 }(DisplayObject));
20375
20376 var Polygon = /** @class */ (function (_super) {
20377 __extends(Polygon, _super);
20378 function Polygon(_a) {
20379 var _this = this;
20380 if (_a === void 0) { _a = {}; }
20381 var style = _a.style, rest = __rest(_a, ["style"]);
20382 _this = _super.call(this, __assign({ type: Shape.POLYGON, style: runtime.enableCSSParsing
20383 ? __assign({ points: '', miterLimit: '', isClosed: true }, style) : __assign({}, style), initialParsedStyle: runtime.enableCSSParsing
20384 ? null
20385 : {
20386 points: {
20387 points: [],
20388 totalLength: 0,
20389 segments: [],
20390 },
20391 miterLimit: 4,
20392 isClosed: true,
20393 } }, rest)) || this;
20394 _this.markerStartAngle = 0;
20395 _this.markerEndAngle = 0;
20396 /**
20397 * markers placed at the mid
20398 */
20399 _this.markerMidList = [];
20400 var _b = _this.parsedStyle, markerStart = _b.markerStart, markerEnd = _b.markerEnd, markerMid = _b.markerMid;
20401 if (markerStart && isDisplayObject(markerStart)) {
20402 _this.markerStartAngle = markerStart.getLocalEulerAngles();
20403 _this.appendChild(markerStart);
20404 }
20405 if (markerMid && isDisplayObject(markerMid)) {
20406 _this.placeMarkerMid(markerMid);
20407 }
20408 if (markerEnd && isDisplayObject(markerEnd)) {
20409 _this.markerEndAngle = markerEnd.getLocalEulerAngles();
20410 _this.appendChild(markerEnd);
20411 }
20412 _this.transformMarker(true);
20413 _this.transformMarker(false);
20414 return _this;
20415 }
20416 Polygon.prototype.attributeChangedCallback = function (attrName, oldValue, newValue, prevParsedValue, newParsedValue) {
20417 if (attrName === 'points') {
20418 // recalc markers
20419 this.transformMarker(true);
20420 this.transformMarker(false);
20421 this.placeMarkerMid(this.parsedStyle.markerMid);
20422 }
20423 else if (attrName === 'markerStartOffset' ||
20424 attrName === 'markerEndOffset') {
20425 this.transformMarker(true);
20426 this.transformMarker(false);
20427 }
20428 else if (attrName === 'markerStart') {
20429 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20430 this.markerStartAngle = 0;
20431 prevParsedValue.remove();
20432 }
20433 // CSSKeyword 'unset'
20434 if (newParsedValue && isDisplayObject(newParsedValue)) {
20435 this.markerStartAngle = newParsedValue.getLocalEulerAngles();
20436 this.appendChild(newParsedValue);
20437 this.transformMarker(true);
20438 }
20439 }
20440 else if (attrName === 'markerEnd') {
20441 if (prevParsedValue && isDisplayObject(prevParsedValue)) {
20442 this.markerEndAngle = 0;
20443 prevParsedValue.remove();
20444 }
20445 if (newParsedValue && isDisplayObject(newParsedValue)) {
20446 this.markerEndAngle = newParsedValue.getLocalEulerAngles();
20447 this.appendChild(newParsedValue);
20448 this.transformMarker(false);
20449 }
20450 }
20451 else if (attrName === 'markerMid') {
20452 this.placeMarkerMid(newParsedValue);
20453 }
20454 };
20455 Polygon.prototype.transformMarker = function (isStart) {
20456 var _a = this.parsedStyle, markerStart = _a.markerStart, markerEnd = _a.markerEnd, markerStartOffset = _a.markerStartOffset, markerEndOffset = _a.markerEndOffset, P = _a.points, defX = _a.defX, defY = _a.defY;
20457 var points = (P || {}).points;
20458 var marker = isStart ? markerStart : markerEnd;
20459 if (!marker || !isDisplayObject(marker) || !points) {
20460 return;
20461 }
20462 var rad = 0;
20463 var x;
20464 var y;
20465 var ox;
20466 var oy;
20467 var offset;
20468 var originalAngle;
20469 ox = points[0][0] - defX;
20470 oy = points[0][1] - defY;
20471 if (isStart) {
20472 x = points[1][0] - points[0][0];
20473 y = points[1][1] - points[0][1];
20474 offset = markerStartOffset || 0;
20475 originalAngle = this.markerStartAngle;
20476 }
20477 else {
20478 var length_1 = points.length;
20479 if (!this.parsedStyle.isClosed) {
20480 ox = points[length_1 - 1][0] - defX;
20481 oy = points[length_1 - 1][1] - defY;
20482 x = points[length_1 - 2][0] - points[length_1 - 1][0];
20483 y = points[length_1 - 2][1] - points[length_1 - 1][1];
20484 }
20485 else {
20486 x = points[length_1 - 1][0] - points[0][0];
20487 y = points[length_1 - 1][1] - points[0][1];
20488 }
20489 offset = markerEndOffset || 0;
20490 originalAngle = this.markerEndAngle;
20491 }
20492 rad = Math.atan2(y, x);
20493 // account for markerOffset
20494 marker.setLocalEulerAngles((rad * 180) / Math.PI + originalAngle);
20495 marker.setLocalPosition(ox + Math.cos(rad) * offset, oy + Math.sin(rad) * offset);
20496 };
20497 Polygon.prototype.placeMarkerMid = function (marker) {
20498 var _a = this.parsedStyle, P = _a.points, defX = _a.defX, defY = _a.defY;
20499 var points = (P || {}).points;
20500 // clear all existed markers
20501 this.markerMidList.forEach(function (marker) {
20502 marker.remove();
20503 });
20504 this.markerMidList = [];
20505 if (marker && isDisplayObject(marker) && points) {
20506 for (var i = 1; i < (this.parsedStyle.isClosed ? points.length : points.length - 1); i++) {
20507 var ox = points[i][0] - defX;
20508 var oy = points[i][1] - defY;
20509 var cloned = i === 1 ? marker : marker.cloneNode(true);
20510 this.markerMidList.push(cloned);
20511 this.appendChild(cloned);
20512 cloned.setLocalPosition(ox, oy);
20513 // TODO: orient of marker
20514 }
20515 }
20516 };
20517 return Polygon;
20518 }(DisplayObject));
20519
20520 /**
20521 * Polyline inherits the marker-related capabilities of Polygon.
20522 */
20523 var Polyline = /** @class */ (function (_super) {
20524 __extends(Polyline, _super);
20525 function Polyline(_a) {
20526 if (_a === void 0) { _a = {}; }
20527 var style = _a.style, rest = __rest(_a, ["style"]);
20528 return _super.call(this, __assign({ type: Shape.POLYLINE, style: runtime.enableCSSParsing
20529 ? __assign({ points: '', miterLimit: '', isClosed: false }, style) : __assign({}, style), initialParsedStyle: runtime.enableCSSParsing
20530 ? null
20531 : {
20532 points: {
20533 points: [],
20534 totalLength: 0,
20535 segments: [],
20536 },
20537 miterLimit: 4,
20538 isClosed: false,
20539 } }, rest)) || this;
20540 }
20541 Polyline.prototype.getTotalLength = function () {
20542 return this.parsedStyle.points.totalLength;
20543 };
20544 Polyline.prototype.getPointAtLength = function (distance, inWorldSpace) {
20545 if (inWorldSpace === void 0) { inWorldSpace = false; }
20546 return this.getPoint(distance / this.getTotalLength(), inWorldSpace);
20547 };
20548 Polyline.prototype.getPoint = function (ratio, inWorldSpace) {
20549 if (inWorldSpace === void 0) { inWorldSpace = false; }
20550 var _a = this.parsedStyle, defX = _a.defX, defY = _a.defY, _b = _a.points, points = _b.points, segments = _b.segments;
20551 var subt = 0;
20552 var index = 0;
20553 segments.forEach(function (v, i) {
20554 if (ratio >= v[0] && ratio <= v[1]) {
20555 subt = (ratio - v[0]) / (v[1] - v[0]);
20556 index = i;
20557 }
20558 });
20559 var _c = pointAt$3(points[index][0], points[index][1], points[index + 1][0], points[index + 1][1], subt), x = _c.x, y = _c.y;
20560 var transformed = transformMat4(create$2(), fromValues$2(x - defX, y - defY, 0), inWorldSpace ? this.getWorldTransform() : this.getLocalTransform());
20561 // apply local transformation
20562 return new Point(transformed[0], transformed[1]);
20563 };
20564 Polyline.prototype.getStartTangent = function () {
20565 var points = this.parsedStyle.points.points;
20566 var result = [];
20567 result.push([points[1][0], points[1][1]]);
20568 result.push([points[0][0], points[0][1]]);
20569 return result;
20570 };
20571 Polyline.prototype.getEndTangent = function () {
20572 var points = this.parsedStyle.points.points;
20573 var l = points.length - 1;
20574 var result = [];
20575 result.push([points[l - 1][0], points[l - 1][1]]);
20576 result.push([points[l][0], points[l][1]]);
20577 return result;
20578 };
20579 return Polyline;
20580 }(Polygon));
20581
20582 var Rect = /** @class */ (function (_super) {
20583 __extends(Rect, _super);
20584 function Rect(_a) {
20585 if (_a === void 0) { _a = {}; }
20586 var style = _a.style, rest = __rest(_a, ["style"]);
20587 return _super.call(this, __assign({ type: Shape.RECT, style: runtime.enableCSSParsing
20588 ? __assign({ x: '', y: '', width: '', height: '', radius: '' }, style) : __assign({}, style) }, rest)) || this;
20589 }
20590 return Rect;
20591 }(DisplayObject));
20592
20593 /**
20594 * <text> @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextElement
20595 */
20596 var Text = /** @class */ (function (_super) {
20597 __extends(Text, _super);
20598 /**
20599 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextContentElement#constants
20600 */
20601 // LENGTHADJUST_SPACING: number = 1;
20602 // LENGTHADJUST_SPACINGANDGLYPHS: number = 2;
20603 // LENGTHADJUST_UNKNOWN: number = 0;
20604 function Text(_a) {
20605 if (_a === void 0) { _a = {}; }
20606 var style = _a.style, rest = __rest(_a, ["style"]);
20607 return _super.call(this, __assign({ type: Shape.TEXT, style: runtime.enableCSSParsing
20608 ? __assign({ x: '', y: '', text: '', fontSize: '', fontFamily: '', fontStyle: '', fontWeight: '', fontVariant: '', textAlign: '', textBaseline: '', textTransform: '', fill: 'black', letterSpacing: '', lineHeight: '', miterLimit: '',
20609 // whiteSpace: 'pre',
20610 wordWrap: false, wordWrapWidth: 0, leading: 0, dx: '', dy: '' }, style) : __assign({ fill: 'black' }, style), initialParsedStyle: runtime.enableCSSParsing
20611 ? {}
20612 : {
20613 x: 0,
20614 y: 0,
20615 fontSize: 16,
20616 fontFamily: 'sans-serif',
20617 fontStyle: 'normal',
20618 fontWeight: 'normal',
20619 fontVariant: 'normal',
20620 lineHeight: 0,
20621 letterSpacing: 0,
20622 textBaseline: 'alphabetic',
20623 textAlign: 'start',
20624 wordWrap: false,
20625 wordWrapWidth: 0,
20626 leading: 0,
20627 dx: 0,
20628 dy: 0,
20629 } }, rest)) || this;
20630 }
20631 // lengthAdjust: SVGAnimatedEnumeration;
20632 // textLength: SVGAnimatedLength;
20633 // getCharNumAtPosition(point?: DOMPointInit): number {
20634 // throw new Error('Method not implemented.');
20635 // }
20636 /**
20637 * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextContentElement
20638 */
20639 Text.prototype.getComputedTextLength = function () {
20640 var _a;
20641 return ((_a = this.parsedStyle.metrics) === null || _a === void 0 ? void 0 : _a.maxLineWidth) || 0;
20642 };
20643 // getEndPositionOfChar(charnum: number): DOMPoint {
20644 // throw new Error('Method not implemented.');
20645 // }
20646 // getExtentOfChar(charnum: number): DOMRect {
20647 // throw new Error('Method not implemented.');
20648 // }
20649 // getNumberOfChars(): number {
20650 // throw new Error('Method not implemented.');
20651 // }
20652 // getRotationOfChar(charnum: number): number {
20653 // throw new Error('Method not implemented.');
20654 // }
20655 // getStartPositionOfChar(charnum: number): DOMPoint {
20656 // throw new Error('Method not implemented.');
20657 // }
20658 // getSubStringLength(charnum: number, nchars: number): number {
20659 // throw new Error('Method not implemented.');
20660 // }
20661 // selectSubString(charnum: number, nchars: number): void {
20662 // throw new Error('Method not implemented.');
20663 // }
20664 Text.prototype.getLineBoundingRects = function () {
20665 var _a;
20666 return ((_a = this.parsedStyle.metrics) === null || _a === void 0 ? void 0 : _a.lineMetrics) || [];
20667 };
20668 Text.prototype.isOverflowing = function () {
20669 return !!this.parsedStyle.isOverflowing;
20670 };
20671 return Text;
20672 }(DisplayObject));
20673
20674 /**
20675 * canvas.customElements
20676 *
20677 * @see https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry
20678 */
20679 var CustomElementRegistry = /** @class */ (function () {
20680 function CustomElementRegistry() {
20681 this.registry = {};
20682 this.define(Shape.CIRCLE, Circle);
20683 this.define(Shape.ELLIPSE, Ellipse);
20684 this.define(Shape.RECT, Rect);
20685 this.define(Shape.IMAGE, Image);
20686 this.define(Shape.LINE, Line);
20687 this.define(Shape.GROUP, Group);
20688 this.define(Shape.PATH, Path);
20689 this.define(Shape.POLYGON, Polygon);
20690 this.define(Shape.POLYLINE, Polyline);
20691 this.define(Shape.TEXT, Text);
20692 this.define(Shape.HTML, HTML);
20693 }
20694 CustomElementRegistry.prototype.define = function (name, constructor) {
20695 this.registry[name] = constructor;
20696 };
20697 /**
20698 * @see https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/get
20699 */
20700 CustomElementRegistry.prototype.get = function (name) {
20701 return this.registry[name];
20702 };
20703 return CustomElementRegistry;
20704 }());
20705
20706 /**
20707 * the entry of DOM tree
20708 * Document -> Node -> EventTarget
20709 * @see https://developer.mozilla.org/en-US/docs/Web/API/Document
20710 */
20711 var Document = /** @class */ (function (_super) {
20712 __extends(Document, _super);
20713 function Document() {
20714 var _this = _super.call(this) || this;
20715 /**
20716 * only document has defaultView, points to canvas,
20717 * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/defaultView
20718 */
20719 _this.defaultView = null;
20720 _this.ownerDocument = null;
20721 _this.nodeName = 'document';
20722 // create timeline
20723 try {
20724 _this.timeline = new runtime.AnimationTimeline(_this);
20725 }
20726 catch (e) { }
20727 /**
20728 * for inherited properties, the initial value is used on the root element only,
20729 * as long as no specified value is supplied.
20730 * @see https://developer.mozilla.org/en-US/docs/Web/CSS/initial_value
20731 */
20732 var initialStyle = {};
20733 BUILT_IN_PROPERTIES.forEach(function (_a) {
20734 var n = _a.n, inh = _a.inh, d = _a.d;
20735 if (inh && d) {
20736 initialStyle[n] = isFunction$1(d) ? d(Shape.GROUP) : d;
20737 }
20738 });
20739 // like <html> in DOM tree
20740 _this.documentElement = new Group({
20741 id: 'g-root',
20742 style: initialStyle,
20743 });
20744 _this.documentElement.ownerDocument = _this;
20745 _this.documentElement.parentNode = _this;
20746 _this.childNodes = [_this.documentElement];
20747 return _this;
20748 }
20749 Object.defineProperty(Document.prototype, "children", {
20750 get: function () {
20751 return this.childNodes;
20752 },
20753 enumerable: false,
20754 configurable: true
20755 });
20756 Object.defineProperty(Document.prototype, "childElementCount", {
20757 get: function () {
20758 return this.childNodes.length;
20759 },
20760 enumerable: false,
20761 configurable: true
20762 });
20763 Object.defineProperty(Document.prototype, "firstElementChild", {
20764 get: function () {
20765 return this.firstChild;
20766 },
20767 enumerable: false,
20768 configurable: true
20769 });
20770 Object.defineProperty(Document.prototype, "lastElementChild", {
20771 get: function () {
20772 return this.lastChild;
20773 },
20774 enumerable: false,
20775 configurable: true
20776 });
20777 /**
20778 * @example const circle = document.createElement('circle', { style: { r: 10 } });
20779 */
20780 Document.prototype.createElement = function (tagName, options) {
20781 // @observablehq/plot will create <svg>
20782 if (tagName === 'svg') {
20783 return this.documentElement;
20784 }
20785 // d3 will use <tspan>
20786 var clazz = this.defaultView.customElements.get(tagName);
20787 if (!clazz) {
20788 console.warn('Unsupported tagName: ', tagName);
20789 clazz = tagName === 'tspan' ? Text : Group;
20790 }
20791 var shape = new clazz(options);
20792 shape.ownerDocument = this;
20793 return shape;
20794 };
20795 Document.prototype.createElementNS = function (namespaceURI, tagName, options) {
20796 return this.createElement(tagName, options);
20797 };
20798 Document.prototype.cloneNode = function (deep) {
20799 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
20800 };
20801 Document.prototype.destroy = function () {
20802 try {
20803 this.documentElement.destroyChildren();
20804 this.timeline.destroy();
20805 }
20806 catch (e) { }
20807 };
20808 /**
20809 * Picking 2D graphics with RBush based on BBox, fast but inaccurate.
20810 */
20811 Document.prototype.elementsFromBBox = function (minX, minY, maxX, maxY) {
20812 var rBush = this.defaultView.context.rBushRoot;
20813 var rBushNodes = rBush.search({ minX: minX, minY: minY, maxX: maxX, maxY: maxY });
20814 var hitTestList = [];
20815 rBushNodes.forEach(function (_a) {
20816 var displayObject = _a.displayObject;
20817 var pointerEvents = displayObject.parsedStyle.pointerEvents;
20818 // account for `visibility`
20819 // @see https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
20820 var isVisibilityAffected = [
20821 'auto',
20822 'visiblepainted',
20823 'visiblefill',
20824 'visiblestroke',
20825 'visible',
20826 ].includes(pointerEvents);
20827 if ((!isVisibilityAffected ||
20828 (isVisibilityAffected && displayObject.isVisible())) &&
20829 !displayObject.isCulled() &&
20830 displayObject.isInteractive()) {
20831 hitTestList.push(displayObject);
20832 }
20833 });
20834 // find group with max z-index
20835 hitTestList.sort(function (a, b) { return b.sortable.renderOrder - a.sortable.renderOrder; });
20836 return hitTestList;
20837 };
20838 Document.prototype.elementFromPointSync = function (x, y) {
20839 var _a = this.defaultView.canvas2Viewport({
20840 x: x,
20841 y: y,
20842 }), viewportX = _a.x, viewportY = _a.y;
20843 var _b = this.defaultView.getConfig(), width = _b.width, height = _b.height;
20844 // outside canvas' viewport
20845 if (viewportX < 0 ||
20846 viewportY < 0 ||
20847 viewportX > width ||
20848 viewportY > height) {
20849 return null;
20850 }
20851 var _c = this.defaultView.viewport2Client({
20852 x: viewportX,
20853 y: viewportY,
20854 }), clientX = _c.x, clientY = _c.y;
20855 var picked = this.defaultView
20856 .getRenderingService()
20857 .hooks.pickSync.call({
20858 topmost: true,
20859 position: {
20860 x: x,
20861 y: y,
20862 viewportX: viewportX,
20863 viewportY: viewportY,
20864 clientX: clientX,
20865 clientY: clientY,
20866 },
20867 picked: [],
20868 }).picked;
20869 return (picked && picked[0]) || this.documentElement;
20870 };
20871 /**
20872 * Do picking with API instead of triggering interactive events.
20873 *
20874 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/elementFromPoint
20875 */
20876 Document.prototype.elementFromPoint = function (x, y) {
20877 return __awaiter(this, void 0, void 0, function () {
20878 var _a, viewportX, viewportY, _b, width, height, _c, clientX, clientY, picked;
20879 return __generator(this, function (_d) {
20880 switch (_d.label) {
20881 case 0:
20882 _a = this.defaultView.canvas2Viewport({
20883 x: x,
20884 y: y,
20885 }), viewportX = _a.x, viewportY = _a.y;
20886 _b = this.defaultView.getConfig(), width = _b.width, height = _b.height;
20887 // outside canvas' viewport
20888 if (viewportX < 0 ||
20889 viewportY < 0 ||
20890 viewportX > width ||
20891 viewportY > height) {
20892 return [2 /*return*/, null];
20893 }
20894 _c = this.defaultView.viewport2Client({
20895 x: viewportX,
20896 y: viewportY,
20897 }), clientX = _c.x, clientY = _c.y;
20898 return [4 /*yield*/, this.defaultView
20899 .getRenderingService()
20900 .hooks.pick.promise({
20901 topmost: true,
20902 position: {
20903 x: x,
20904 y: y,
20905 viewportX: viewportX,
20906 viewportY: viewportY,
20907 clientX: clientX,
20908 clientY: clientY,
20909 },
20910 picked: [],
20911 })];
20912 case 1:
20913 picked = (_d.sent()).picked;
20914 return [2 /*return*/, (picked && picked[0]) || this.documentElement];
20915 }
20916 });
20917 });
20918 };
20919 Document.prototype.elementsFromPointSync = function (x, y) {
20920 var _a = this.defaultView.canvas2Viewport({
20921 x: x,
20922 y: y,
20923 }), viewportX = _a.x, viewportY = _a.y;
20924 var _b = this.defaultView.getConfig(), width = _b.width, height = _b.height;
20925 // outside canvas' viewport
20926 if (viewportX < 0 ||
20927 viewportY < 0 ||
20928 viewportX > width ||
20929 viewportY > height) {
20930 return [];
20931 }
20932 var _c = this.defaultView.viewport2Client({
20933 x: viewportX,
20934 y: viewportY,
20935 }), clientX = _c.x, clientY = _c.y;
20936 var picked = this.defaultView
20937 .getRenderingService()
20938 .hooks.pickSync.call({
20939 topmost: false,
20940 position: {
20941 x: x,
20942 y: y,
20943 viewportX: viewportX,
20944 viewportY: viewportY,
20945 clientX: clientX,
20946 clientY: clientY,
20947 },
20948 picked: [],
20949 }).picked;
20950 if (picked[picked.length - 1] !== this.documentElement) {
20951 picked.push(this.documentElement);
20952 }
20953 return picked;
20954 };
20955 /**
20956 * Do picking with API instead of triggering interactive events.
20957 *
20958 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/elementsFromPoint
20959 */
20960 Document.prototype.elementsFromPoint = function (x, y) {
20961 return __awaiter(this, void 0, void 0, function () {
20962 var _a, viewportX, viewportY, _b, width, height, _c, clientX, clientY, picked;
20963 return __generator(this, function (_d) {
20964 switch (_d.label) {
20965 case 0:
20966 _a = this.defaultView.canvas2Viewport({
20967 x: x,
20968 y: y,
20969 }), viewportX = _a.x, viewportY = _a.y;
20970 _b = this.defaultView.getConfig(), width = _b.width, height = _b.height;
20971 // outside canvas' viewport
20972 if (viewportX < 0 ||
20973 viewportY < 0 ||
20974 viewportX > width ||
20975 viewportY > height) {
20976 return [2 /*return*/, []];
20977 }
20978 _c = this.defaultView.viewport2Client({
20979 x: viewportX,
20980 y: viewportY,
20981 }), clientX = _c.x, clientY = _c.y;
20982 return [4 /*yield*/, this.defaultView
20983 .getRenderingService()
20984 .hooks.pick.promise({
20985 topmost: false,
20986 position: {
20987 x: x,
20988 y: y,
20989 viewportX: viewportX,
20990 viewportY: viewportY,
20991 clientX: clientX,
20992 clientY: clientY,
20993 },
20994 picked: [],
20995 })];
20996 case 1:
20997 picked = (_d.sent()).picked;
20998 if (picked[picked.length - 1] !== this.documentElement) {
20999 picked.push(this.documentElement);
21000 }
21001 return [2 /*return*/, picked];
21002 }
21003 });
21004 });
21005 };
21006 /**
21007 * eg. Uncaught DOMException: Failed to execute 'appendChild' on 'Node': Only one element on document allowed.
21008 */
21009 Document.prototype.appendChild = function (newChild, index) {
21010 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21011 };
21012 Document.prototype.insertBefore = function (newChild, refChild) {
21013 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21014 };
21015 Document.prototype.removeChild = function (oldChild, destroy) {
21016 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21017 };
21018 Document.prototype.replaceChild = function (newChild, oldChild, destroy) {
21019 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21020 };
21021 Document.prototype.append = function () {
21022 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21023 };
21024 Document.prototype.prepend = function () {
21025 throw new Error(ERROR_MSG_USE_DOCUMENT_ELEMENT);
21026 };
21027 /**
21028 * Execute query on documentElement.
21029 */
21030 Document.prototype.getElementById = function (id) {
21031 return this.documentElement.getElementById(id);
21032 };
21033 Document.prototype.getElementsByName = function (name) {
21034 return this.documentElement.getElementsByName(name);
21035 };
21036 Document.prototype.getElementsByTagName = function (tagName) {
21037 return this.documentElement.getElementsByTagName(tagName);
21038 };
21039 Document.prototype.getElementsByClassName = function (className) {
21040 return this.documentElement.getElementsByClassName(className);
21041 };
21042 Document.prototype.querySelector = function (selectors) {
21043 return this.documentElement.querySelector(selectors);
21044 };
21045 Document.prototype.querySelectorAll = function (selectors) {
21046 return this.documentElement.querySelectorAll(selectors);
21047 };
21048 Document.prototype.find = function (filter) {
21049 return this.documentElement.find(filter);
21050 };
21051 Document.prototype.findAll = function (filter) {
21052 return this.documentElement.findAll(filter);
21053 };
21054 return Document;
21055 }(Node));
21056
21057 /**
21058 * apply following rules:
21059 * 1. `visibility` in scenegraph node
21060 * 2. other custom culling strategies, eg. frustum culling
21061 */
21062 var CullingPlugin = /** @class */ (function () {
21063 function CullingPlugin(strategies) {
21064 this.strategies = strategies;
21065 }
21066 CullingPlugin.prototype.apply = function (context) {
21067 var camera = context.camera, renderingService = context.renderingService, renderingContext = context.renderingContext;
21068 var strategies = this.strategies;
21069 renderingService.hooks.cull.tap(CullingPlugin.tag, function (object) {
21070 if (object) {
21071 var cullable = object.cullable;
21072 // cullable.visible = true;
21073 // const renderBounds = object.getRenderBounds();
21074 // if (AABB.isEmpty(renderBounds)) {
21075 // cullable.visible = false;
21076 // } else {
21077 // const isShape2D = shape2D.indexOf(object.nodeName as Shape) > -1;
21078 // const [p0, p1, p2, p3] = camera.getFrustum().planes;
21079 // tmpAABB.setMinMax([-p1.distance, -p3.distance, 0], [p0.distance, p2.distance, 0]);
21080 // cullable.visible = isShape2D ? renderBounds.intersects(tmpAABB) : true;
21081 // }
21082 if (strategies.length === 0) {
21083 cullable.visible = renderingContext.unculledEntities.indexOf(object.entity) > -1;
21084 }
21085 else {
21086 // eg. implemented by g-webgl(frustum culling)
21087 cullable.visible = strategies.every(function (strategy) { return strategy.isVisible(camera, object); });
21088 }
21089 if (!object.isCulled() && object.isVisible()) {
21090 return object;
21091 }
21092 else {
21093 // if (this.renderingContext.renderListLastFrame.indexOf(object) > -1) {
21094 object.dispatchEvent(new CustomEvent(ElementEvent.CULLED));
21095 // }
21096 }
21097 return null;
21098 }
21099 return object;
21100 });
21101 renderingService.hooks.afterRender.tap(CullingPlugin.tag, function (object) {
21102 object.cullable.visibilityPlaneMask = -1;
21103 });
21104 };
21105 CullingPlugin.tag = 'Culling';
21106 return CullingPlugin;
21107 }());
21108
21109 /**
21110 * support mouse & touch events
21111 * @see https://github.com/pixijs/pixi.js/blob/dev/packages/interaction/README.md
21112 *
21113 * also provide some extra events such as `drag`
21114 */
21115 var EventPlugin = /** @class */ (function () {
21116 function EventPlugin() {
21117 var _this = this;
21118 this.autoPreventDefault = false;
21119 this.rootPointerEvent = new FederatedPointerEvent(null);
21120 this.rootWheelEvent = new FederatedWheelEvent(null);
21121 this.onPointerMove = function (nativeEvent) {
21122 var e_1, _a;
21123 var _b, _c;
21124 var canvas = (_c = (_b = _this.context.renderingContext.root) === null || _b === void 0 ? void 0 : _b.ownerDocument) === null || _c === void 0 ? void 0 : _c.defaultView;
21125 if (canvas.supportsTouchEvents &&
21126 nativeEvent.pointerType === 'touch')
21127 return;
21128 var normalizedEvents = _this.normalizeToPointerEvent(nativeEvent, canvas);
21129 try {
21130 for (var normalizedEvents_1 = __values(normalizedEvents), normalizedEvents_1_1 = normalizedEvents_1.next(); !normalizedEvents_1_1.done; normalizedEvents_1_1 = normalizedEvents_1.next()) {
21131 var normalizedEvent = normalizedEvents_1_1.value;
21132 var event_1 = _this.bootstrapEvent(_this.rootPointerEvent, normalizedEvent, canvas, nativeEvent);
21133 _this.context.eventService.mapEvent(event_1);
21134 }
21135 }
21136 catch (e_1_1) { e_1 = { error: e_1_1 }; }
21137 finally {
21138 try {
21139 if (normalizedEvents_1_1 && !normalizedEvents_1_1.done && (_a = normalizedEvents_1.return)) _a.call(normalizedEvents_1);
21140 }
21141 finally { if (e_1) throw e_1.error; }
21142 }
21143 _this.setCursor(_this.context.eventService.cursor);
21144 };
21145 this.onClick = function (nativeEvent) {
21146 var e_2, _a;
21147 var _b, _c;
21148 var canvas = (_c = (_b = _this.context.renderingContext.root) === null || _b === void 0 ? void 0 : _b.ownerDocument) === null || _c === void 0 ? void 0 : _c.defaultView;
21149 var normalizedEvents = _this.normalizeToPointerEvent(nativeEvent, canvas);
21150 try {
21151 for (var normalizedEvents_2 = __values(normalizedEvents), normalizedEvents_2_1 = normalizedEvents_2.next(); !normalizedEvents_2_1.done; normalizedEvents_2_1 = normalizedEvents_2.next()) {
21152 var normalizedEvent = normalizedEvents_2_1.value;
21153 var event_2 = _this.bootstrapEvent(_this.rootPointerEvent, normalizedEvent, canvas, nativeEvent);
21154 _this.context.eventService.mapEvent(event_2);
21155 }
21156 }
21157 catch (e_2_1) { e_2 = { error: e_2_1 }; }
21158 finally {
21159 try {
21160 if (normalizedEvents_2_1 && !normalizedEvents_2_1.done && (_a = normalizedEvents_2.return)) _a.call(normalizedEvents_2);
21161 }
21162 finally { if (e_2) throw e_2.error; }
21163 }
21164 _this.setCursor(_this.context.eventService.cursor);
21165 };
21166 }
21167 EventPlugin.prototype.apply = function (context) {
21168 var _this = this;
21169 this.context = context;
21170 var renderingService = context.renderingService;
21171 var canvas = this.context.renderingContext.root.ownerDocument.defaultView;
21172 this.context.eventService.setPickHandler(function (position) {
21173 var picked = _this.context.renderingService.hooks.pickSync.call({
21174 position: position,
21175 picked: [],
21176 topmost: true, // we only concern the topmost element
21177 }).picked;
21178 return picked[0] || null;
21179 });
21180 renderingService.hooks.pointerWheel.tap(EventPlugin.tag, function (nativeEvent) {
21181 var wheelEvent = _this.normalizeWheelEvent(nativeEvent);
21182 _this.context.eventService.mapEvent(wheelEvent);
21183 });
21184 renderingService.hooks.pointerDown.tap(EventPlugin.tag, function (nativeEvent) {
21185 var e_3, _a;
21186 if (canvas.supportsTouchEvents &&
21187 nativeEvent.pointerType === 'touch')
21188 return;
21189 var events = _this.normalizeToPointerEvent(nativeEvent, canvas);
21190 if (_this.autoPreventDefault && events[0].isNormalized) {
21191 var cancelable = nativeEvent.cancelable || !('cancelable' in nativeEvent);
21192 if (cancelable) {
21193 nativeEvent.preventDefault();
21194 }
21195 }
21196 try {
21197 for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) {
21198 var event_3 = events_1_1.value;
21199 var federatedEvent = _this.bootstrapEvent(_this.rootPointerEvent, event_3, canvas, nativeEvent);
21200 _this.context.eventService.mapEvent(federatedEvent);
21201 }
21202 }
21203 catch (e_3_1) { e_3 = { error: e_3_1 }; }
21204 finally {
21205 try {
21206 if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
21207 }
21208 finally { if (e_3) throw e_3.error; }
21209 }
21210 _this.setCursor(_this.context.eventService.cursor);
21211 });
21212 renderingService.hooks.pointerUp.tap(EventPlugin.tag, function (nativeEvent) {
21213 var e_4, _a;
21214 if (canvas.supportsTouchEvents &&
21215 nativeEvent.pointerType === 'touch')
21216 return;
21217 // account for element in SVG
21218 var $element = _this.context.contextService.getDomElement();
21219 var outside = 'outside';
21220 try {
21221 outside =
21222 $element &&
21223 nativeEvent.target &&
21224 nativeEvent.target !== $element &&
21225 $element.contains &&
21226 !$element.contains(nativeEvent.target)
21227 ? 'outside'
21228 : '';
21229 }
21230 catch (e) {
21231 // nativeEvent.target maybe not Node, such as Window
21232 // @see https://github.com/antvis/G/issues/1235
21233 }
21234 var normalizedEvents = _this.normalizeToPointerEvent(nativeEvent, canvas);
21235 try {
21236 for (var normalizedEvents_3 = __values(normalizedEvents), normalizedEvents_3_1 = normalizedEvents_3.next(); !normalizedEvents_3_1.done; normalizedEvents_3_1 = normalizedEvents_3.next()) {
21237 var normalizedEvent = normalizedEvents_3_1.value;
21238 var event_4 = _this.bootstrapEvent(_this.rootPointerEvent, normalizedEvent, canvas, nativeEvent);
21239 event_4.type += outside;
21240 _this.context.eventService.mapEvent(event_4);
21241 }
21242 }
21243 catch (e_4_1) { e_4 = { error: e_4_1 }; }
21244 finally {
21245 try {
21246 if (normalizedEvents_3_1 && !normalizedEvents_3_1.done && (_a = normalizedEvents_3.return)) _a.call(normalizedEvents_3);
21247 }
21248 finally { if (e_4) throw e_4.error; }
21249 }
21250 _this.setCursor(_this.context.eventService.cursor);
21251 });
21252 renderingService.hooks.pointerMove.tap(EventPlugin.tag, this.onPointerMove);
21253 renderingService.hooks.pointerOver.tap(EventPlugin.tag, this.onPointerMove);
21254 renderingService.hooks.pointerOut.tap(EventPlugin.tag, this.onPointerMove);
21255 renderingService.hooks.click.tap(EventPlugin.tag, this.onClick);
21256 renderingService.hooks.pointerCancel.tap(EventPlugin.tag, function (nativeEvent) {
21257 var e_5, _a;
21258 var normalizedEvents = _this.normalizeToPointerEvent(nativeEvent, canvas);
21259 try {
21260 for (var normalizedEvents_4 = __values(normalizedEvents), normalizedEvents_4_1 = normalizedEvents_4.next(); !normalizedEvents_4_1.done; normalizedEvents_4_1 = normalizedEvents_4.next()) {
21261 var normalizedEvent = normalizedEvents_4_1.value;
21262 var event_5 = _this.bootstrapEvent(_this.rootPointerEvent, normalizedEvent, canvas, nativeEvent);
21263 _this.context.eventService.mapEvent(event_5);
21264 }
21265 }
21266 catch (e_5_1) { e_5 = { error: e_5_1 }; }
21267 finally {
21268 try {
21269 if (normalizedEvents_4_1 && !normalizedEvents_4_1.done && (_a = normalizedEvents_4.return)) _a.call(normalizedEvents_4);
21270 }
21271 finally { if (e_5) throw e_5.error; }
21272 }
21273 _this.setCursor(_this.context.eventService.cursor);
21274 });
21275 };
21276 EventPlugin.prototype.getViewportXY = function (nativeEvent) {
21277 var x;
21278 var y;
21279 /**
21280 * Should account for CSS Transform applied on container.
21281 * @see https://github.com/antvis/G/issues/1161
21282 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent/offsetX
21283 */
21284 var offsetX = nativeEvent.offsetX, offsetY = nativeEvent.offsetY, clientX = nativeEvent.clientX, clientY = nativeEvent.clientY;
21285 if (this.context.config.supportsCSSTransform &&
21286 !isNil(offsetX) &&
21287 !isNil(offsetY)) {
21288 x = offsetX;
21289 y = offsetY;
21290 }
21291 else {
21292 var point = this.context.eventService.client2Viewport(new Point(clientX, clientY));
21293 x = point.x;
21294 y = point.y;
21295 }
21296 return { x: x, y: y };
21297 };
21298 EventPlugin.prototype.bootstrapEvent = function (event, normalizedEvent, view, nativeEvent) {
21299 event.view = view;
21300 event.originalEvent = null;
21301 event.nativeEvent = nativeEvent;
21302 event.pointerId = normalizedEvent.pointerId;
21303 event.width = normalizedEvent.width;
21304 event.height = normalizedEvent.height;
21305 event.isPrimary = normalizedEvent.isPrimary;
21306 event.pointerType = normalizedEvent.pointerType;
21307 event.pressure = normalizedEvent.pressure;
21308 event.tangentialPressure = normalizedEvent.tangentialPressure;
21309 event.tiltX = normalizedEvent.tiltX;
21310 event.tiltY = normalizedEvent.tiltY;
21311 event.twist = normalizedEvent.twist;
21312 this.transferMouseData(event, normalizedEvent);
21313 var _a = this.getViewportXY(normalizedEvent), x = _a.x, y = _a.y;
21314 event.viewport.x = x;
21315 event.viewport.y = y;
21316 var _b = this.context.eventService.viewport2Canvas(event.viewport), canvasX = _b.x, canvasY = _b.y;
21317 event.canvas.x = canvasX;
21318 event.canvas.y = canvasY;
21319 event.global.copyFrom(event.canvas);
21320 event.offset.copyFrom(event.canvas);
21321 event.isTrusted = nativeEvent.isTrusted;
21322 if (event.type === 'pointerleave') {
21323 event.type = 'pointerout';
21324 }
21325 if (event.type.startsWith('mouse')) {
21326 event.type = event.type.replace('mouse', 'pointer');
21327 }
21328 if (event.type.startsWith('touch')) {
21329 event.type = TOUCH_TO_POINTER[event.type] || event.type;
21330 }
21331 return event;
21332 };
21333 EventPlugin.prototype.normalizeWheelEvent = function (nativeEvent) {
21334 var event = this.rootWheelEvent;
21335 this.transferMouseData(event, nativeEvent);
21336 event.deltaMode = nativeEvent.deltaMode;
21337 event.deltaX = nativeEvent.deltaX;
21338 event.deltaY = nativeEvent.deltaY;
21339 event.deltaZ = nativeEvent.deltaZ;
21340 var _a = this.getViewportXY(nativeEvent), x = _a.x, y = _a.y;
21341 event.viewport.x = x;
21342 event.viewport.y = y;
21343 var _b = this.context.eventService.viewport2Canvas(event.viewport), canvasX = _b.x, canvasY = _b.y;
21344 event.canvas.x = canvasX;
21345 event.canvas.y = canvasY;
21346 event.global.copyFrom(event.canvas);
21347 event.offset.copyFrom(event.canvas);
21348 event.nativeEvent = nativeEvent;
21349 event.type = nativeEvent.type;
21350 return event;
21351 };
21352 /**
21353 * Transfers base & mouse event data from the nativeEvent to the federated event.
21354 */
21355 EventPlugin.prototype.transferMouseData = function (event, nativeEvent) {
21356 event.isTrusted = nativeEvent.isTrusted;
21357 event.srcElement = nativeEvent.srcElement;
21358 event.timeStamp = clock.now();
21359 event.type = nativeEvent.type;
21360 event.altKey = nativeEvent.altKey;
21361 event.metaKey = nativeEvent.metaKey;
21362 event.shiftKey = nativeEvent.shiftKey;
21363 event.ctrlKey = nativeEvent.ctrlKey;
21364 event.button = nativeEvent.button;
21365 event.buttons = nativeEvent.buttons;
21366 event.client.x = nativeEvent.clientX;
21367 event.client.y = nativeEvent.clientY;
21368 event.movement.x = nativeEvent.movementX;
21369 event.movement.y = nativeEvent.movementY;
21370 event.page.x = nativeEvent.pageX;
21371 event.page.y = nativeEvent.pageY;
21372 event.screen.x = nativeEvent.screenX;
21373 event.screen.y = nativeEvent.screenY;
21374 event.relatedTarget = null;
21375 };
21376 EventPlugin.prototype.setCursor = function (cursor) {
21377 this.context.contextService.applyCursorStyle(cursor || this.context.config.cursor || 'default');
21378 };
21379 EventPlugin.prototype.normalizeToPointerEvent = function (event, canvas) {
21380 var normalizedEvents = [];
21381 if (canvas.isTouchEvent(event)) {
21382 for (var i = 0; i < event.changedTouches.length; i++) {
21383 var touch = event.changedTouches[i];
21384 // use changedTouches instead of touches since touchend has no touches
21385 // @see https://stackoverflow.com/a/10079076
21386 if (isUndefined(touch.button))
21387 touch.button = 0;
21388 if (isUndefined(touch.buttons))
21389 touch.buttons = 1;
21390 if (isUndefined(touch.isPrimary)) {
21391 touch.isPrimary =
21392 event.touches.length === 1 && event.type === 'touchstart';
21393 }
21394 if (isUndefined(touch.width))
21395 touch.width = touch.radiusX || 1;
21396 if (isUndefined(touch.height))
21397 touch.height = touch.radiusY || 1;
21398 if (isUndefined(touch.tiltX))
21399 touch.tiltX = 0;
21400 if (isUndefined(touch.tiltY))
21401 touch.tiltY = 0;
21402 if (isUndefined(touch.pointerType))
21403 touch.pointerType = 'touch';
21404 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Touch/identifier
21405 if (isUndefined(touch.pointerId))
21406 touch.pointerId = touch.identifier || 0;
21407 if (isUndefined(touch.pressure))
21408 touch.pressure = touch.force || 0.5;
21409 if (isUndefined(touch.twist))
21410 touch.twist = 0;
21411 if (isUndefined(touch.tangentialPressure))
21412 touch.tangentialPressure = 0;
21413 touch.isNormalized = true;
21414 touch.type = event.type;
21415 normalizedEvents.push(touch);
21416 }
21417 }
21418 else if (canvas.isMouseEvent(event)) {
21419 var tempEvent = event;
21420 if (isUndefined(tempEvent.isPrimary))
21421 tempEvent.isPrimary = true;
21422 if (isUndefined(tempEvent.width))
21423 tempEvent.width = 1;
21424 if (isUndefined(tempEvent.height))
21425 tempEvent.height = 1;
21426 if (isUndefined(tempEvent.tiltX))
21427 tempEvent.tiltX = 0;
21428 if (isUndefined(tempEvent.tiltY))
21429 tempEvent.tiltY = 0;
21430 if (isUndefined(tempEvent.pointerType))
21431 tempEvent.pointerType = 'mouse';
21432 if (isUndefined(tempEvent.pointerId))
21433 tempEvent.pointerId = MOUSE_POINTER_ID;
21434 if (isUndefined(tempEvent.pressure))
21435 tempEvent.pressure = 0.5;
21436 if (isUndefined(tempEvent.twist))
21437 tempEvent.twist = 0;
21438 if (isUndefined(tempEvent.tangentialPressure))
21439 tempEvent.tangentialPressure = 0;
21440 tempEvent.isNormalized = true;
21441 normalizedEvents.push(tempEvent);
21442 }
21443 else {
21444 normalizedEvents.push(event);
21445 }
21446 return normalizedEvents;
21447 };
21448 EventPlugin.tag = 'Event';
21449 return EventPlugin;
21450 }());
21451
21452 // group is not a 2d shape
21453 var shape2D = [
21454 Shape.CIRCLE,
21455 Shape.ELLIPSE,
21456 Shape.IMAGE,
21457 Shape.RECT,
21458 Shape.LINE,
21459 Shape.POLYLINE,
21460 Shape.POLYGON,
21461 Shape.TEXT,
21462 Shape.PATH,
21463 Shape.HTML,
21464 ];
21465 var FrustumCullingStrategy = /** @class */ (function () {
21466 function FrustumCullingStrategy() {
21467 }
21468 FrustumCullingStrategy.prototype.isVisible = function (camera, object) {
21469 // return true;
21470 var _a, _b;
21471 var cullable = object.cullable;
21472 if (!cullable.enable) {
21473 return true;
21474 }
21475 var renderBounds = object.getRenderBounds();
21476 if (AABB.isEmpty(renderBounds)) {
21477 return false;
21478 }
21479 // get VP matrix from camera
21480 var frustum = camera.getFrustum();
21481 var parentVisibilityPlaneMask = (_b = (_a = object.parentNode) === null || _a === void 0 ? void 0 : _a.cullable) === null || _b === void 0 ? void 0 : _b.visibilityPlaneMask;
21482 cullable.visibilityPlaneMask = this.computeVisibilityWithPlaneMask(object, renderBounds, parentVisibilityPlaneMask || Mask.INDETERMINATE, frustum.planes);
21483 cullable.visible = cullable.visibilityPlaneMask !== Mask.OUTSIDE;
21484 return cullable.visible;
21485 };
21486 /**
21487 *
21488 * @see「Optimized View Frustum Culling Algorithms for Bounding Boxes」
21489 * @see https://github.com/antvis/GWebGPUEngine/issues/3
21490 *
21491 * * 基础相交测试 the basic intersection test
21492 * * 标记 masking @see https://cesium.com/blog/2015/08/04/fast-hierarchical-culling/
21493 * * TODO: 平面一致性测试 the plane-coherency test
21494 * * TODO: 支持 mesh 指定自身的剔除策略,参考 Babylon.js @see https://doc.babylonjs.com/how_to/optimizing_your_scene#changing-mesh-culling-strategy
21495 *
21496 * @param aabb aabb
21497 * @param parentPlaneMask mask of parent
21498 * @param planes planes of frustum
21499 */
21500 FrustumCullingStrategy.prototype.computeVisibilityWithPlaneMask = function (object, aabb, parentPlaneMask, planes) {
21501 if (parentPlaneMask === Mask.OUTSIDE || parentPlaneMask === Mask.INSIDE) {
21502 // 父节点完全位于视锥内或者外部,直接返回
21503 return parentPlaneMask;
21504 }
21505 // Start with MASK_INSIDE (all zeros) so that after the loop, the return value can be compared with MASK_INSIDE.
21506 // (Because if there are fewer than 31 planes, the upper bits wont be changed.)
21507 var mask = Mask.INSIDE;
21508 var isShape2D = shape2D.indexOf(object.nodeName) > -1;
21509 // Use viewport culling for 2D shapes
21510 // @see https://github.com/antvis/g/issues/914
21511 for (var k = 0, len = planes.length; k < len; ++k) {
21512 // For k greater than 31 (since 31 is the maximum number of INSIDE/INTERSECTING bits we can store), skip the optimization.
21513 var flag = 1 << k;
21514 if ((parentPlaneMask & flag) === 0) {
21515 // 父节点处于当前面内部,可以跳过
21516 continue;
21517 }
21518 // skip near & far planes when testing 2D shapes
21519 if (isShape2D && (k === 4 || k === 5)) {
21520 continue;
21521 }
21522 // p-vertex n-vertex <-|plane p-vertex n-vertex
21523 // 使用 p-vertex 和 n-vertex 加速,避免进行平面和 aabb 全部顶点的相交检测
21524 var _a = planes[k], normal = _a.normal, distance = _a.distance;
21525 if (dot(normal, aabb.getPositiveFarPoint(planes[k])) + distance <
21526 0) {
21527 return Mask.OUTSIDE;
21528 }
21529 if (dot(normal, aabb.getNegativeFarPoint(planes[k])) + distance <
21530 0) {
21531 // 和当前面相交,对应位置为1,继续检测下一个面
21532 mask |= flag;
21533 }
21534 }
21535 return mask;
21536 };
21537 return FrustumCullingStrategy;
21538 }());
21539
21540 var PrepareRendererPlugin = /** @class */ (function () {
21541 function PrepareRendererPlugin() {
21542 /**
21543 * sync to RBush later
21544 */
21545 this.toSync = new Set();
21546 }
21547 // private isFirstTimeRendering = true;
21548 // private syncing = false;
21549 PrepareRendererPlugin.prototype.apply = function (context) {
21550 var _this = this;
21551 var renderingService = context.renderingService, renderingContext = context.renderingContext, rBushRoot = context.rBushRoot;
21552 var canvas = renderingContext.root.ownerDocument.defaultView;
21553 this.rBush = rBushRoot;
21554 var handleAttributeChanged = function (e) {
21555 var object = e.target;
21556 object.renderable.dirty = true;
21557 renderingService.dirtify();
21558 };
21559 var handleBoundsChanged = function (e) {
21560 var affectChildren = e.detail.affectChildren;
21561 var object = e.target;
21562 if (affectChildren) {
21563 object.forEach(function (node) {
21564 _this.toSync.add(node);
21565 });
21566 }
21567 var p = object;
21568 while (p) {
21569 if (p.renderable) {
21570 _this.toSync.add(p);
21571 }
21572 p = p.parentElement;
21573 }
21574 // this.pushToSync(e.composedPath().slice(0, -2) as DisplayObject[]);
21575 renderingService.dirtify();
21576 };
21577 var handleMounted = function (e) {
21578 var object = e.target;
21579 if (runtime.enableCSSParsing) {
21580 // recalc style values
21581 runtime.styleValueRegistry.recalc(object);
21582 }
21583 runtime.sceneGraphService.dirtifyToRoot(object);
21584 renderingService.dirtify();
21585 };
21586 var handleUnmounted = function (e) {
21587 var object = e.target;
21588 var rBushNode = object.rBushNode;
21589 if (rBushNode.aabb) {
21590 _this.rBush.remove(rBushNode.aabb);
21591 }
21592 _this.toSync.delete(object);
21593 runtime.sceneGraphService.dirtifyToRoot(object);
21594 renderingService.dirtify();
21595 };
21596 renderingService.hooks.init.tap(PrepareRendererPlugin.tag, function () {
21597 canvas.addEventListener(ElementEvent.MOUNTED, handleMounted);
21598 canvas.addEventListener(ElementEvent.UNMOUNTED, handleUnmounted);
21599 canvas.addEventListener(ElementEvent.ATTR_MODIFIED, handleAttributeChanged);
21600 canvas.addEventListener(ElementEvent.BOUNDS_CHANGED, handleBoundsChanged);
21601 });
21602 renderingService.hooks.destroy.tap(PrepareRendererPlugin.tag, function () {
21603 canvas.removeEventListener(ElementEvent.MOUNTED, handleMounted);
21604 canvas.removeEventListener(ElementEvent.UNMOUNTED, handleUnmounted);
21605 canvas.removeEventListener(ElementEvent.ATTR_MODIFIED, handleAttributeChanged);
21606 canvas.removeEventListener(ElementEvent.BOUNDS_CHANGED, handleBoundsChanged);
21607 _this.toSync.clear();
21608 });
21609 renderingService.hooks.endFrame.tap(PrepareRendererPlugin.tag, function () {
21610 // if (this.isFirstTimeRendering) {
21611 // this.isFirstTimeRendering = false;
21612 // this.syncing = true;
21613 // // @see https://github.com/antvis/G/issues/1117
21614 // setTimeout(() => {
21615 // this.syncRTree();
21616 // console.log('fcp...');
21617 // });
21618 // } else {
21619 // console.log('next...');
21620 _this.syncRTree();
21621 // }
21622 });
21623 };
21624 PrepareRendererPlugin.prototype.syncRTree = function () {
21625 // if (this.syncing) {
21626 // return;
21627 // }
21628 var _this = this;
21629 // bounds changed, need re-inserting its children
21630 var bulk = [];
21631 Array.from(this.toSync)
21632 // some objects may be removed since last frame
21633 .filter(function (object) { return object.isConnected; })
21634 .forEach(function (node) {
21635 var rBushNode = node.rBushNode;
21636 // clear dirty node
21637 if (rBushNode && rBushNode.aabb) {
21638 _this.rBush.remove(rBushNode.aabb);
21639 }
21640 var renderBounds = node.getRenderBounds();
21641 if (renderBounds) {
21642 var _a = __read(renderBounds.getMin(), 2), minX = _a[0], minY = _a[1];
21643 var _b = __read(renderBounds.getMax(), 2), maxX = _b[0], maxY = _b[1];
21644 if (!rBushNode.aabb) {
21645 rBushNode.aabb = {};
21646 }
21647 rBushNode.aabb.displayObject = node;
21648 rBushNode.aabb.minX = minX;
21649 rBushNode.aabb.minY = minY;
21650 rBushNode.aabb.maxX = maxX;
21651 rBushNode.aabb.maxY = maxY;
21652 }
21653 if (rBushNode.aabb) {
21654 // TODO: NaN occurs when width/height of Rect is 0
21655 if (!isNaN(rBushNode.aabb.maxX) &&
21656 !isNaN(rBushNode.aabb.maxX) &&
21657 !isNaN(rBushNode.aabb.minX) &&
21658 !isNaN(rBushNode.aabb.minY)) {
21659 bulk.push(rBushNode.aabb);
21660 }
21661 }
21662 });
21663 // use bulk inserting, which is ~2-3 times faster
21664 // @see https://github.com/mourner/rbush#bulk-inserting-data
21665 this.rBush.load(bulk);
21666 bulk.length = 0;
21667 this.toSync.clear();
21668 // this.syncing = false;
21669 };
21670 PrepareRendererPlugin.tag = 'Prepare';
21671 return PrepareRendererPlugin;
21672 }());
21673
21674 function isCanvas(value) {
21675 return !!value.document;
21676 }
21677 var CanvasEvent;
21678 (function (CanvasEvent) {
21679 CanvasEvent["READY"] = "ready";
21680 CanvasEvent["BEFORE_RENDER"] = "beforerender";
21681 CanvasEvent["RERENDER"] = "rerender";
21682 CanvasEvent["AFTER_RENDER"] = "afterrender";
21683 CanvasEvent["BEFORE_DESTROY"] = "beforedestroy";
21684 CanvasEvent["AFTER_DESTROY"] = "afterdestroy";
21685 CanvasEvent["RESIZE"] = "resize";
21686 CanvasEvent["DIRTY_RECTANGLE"] = "dirtyrectangle";
21687 CanvasEvent["RENDERER_CHANGED"] = "rendererchanged";
21688 })(CanvasEvent || (CanvasEvent = {}));
21689 var DEFAULT_CAMERA_Z = 500;
21690 var DEFAULT_CAMERA_NEAR = 0.1;
21691 var DEFAULT_CAMERA_FAR = 1000;
21692 /**
21693 * reuse custom event preventing from re-create them in every frame
21694 */
21695 var mountedEvent = new CustomEvent(ElementEvent.MOUNTED);
21696 var unmountedEvent = new CustomEvent(ElementEvent.UNMOUNTED);
21697 var beforeRenderEvent = new CustomEvent(CanvasEvent.BEFORE_RENDER);
21698 var rerenderEvent = new CustomEvent(CanvasEvent.RERENDER);
21699 var afterRenderEvent = new CustomEvent(CanvasEvent.AFTER_RENDER);
21700 /**
21701 * can be treated like Window in DOM
21702 * provide some extra methods like `window`, such as:
21703 * * `window.requestAnimationFrame`
21704 * * `window.devicePixelRatio`
21705 *
21706 * prototype chains: Canvas(Window) -> EventTarget
21707 */
21708 var Canvas = /** @class */ (function (_super) {
21709 __extends(Canvas, _super);
21710 function Canvas(config) {
21711 var _this = _super.call(this) || this;
21712 /**
21713 * @see https://developer.mozilla.org/en-US/docs/Web/API/Element
21714 */
21715 _this.Element = DisplayObject;
21716 _this.inited = false;
21717 _this.context = {};
21718 // create document
21719 _this.document = new Document();
21720 _this.document.defaultView = _this;
21721 // create registry of custom elements
21722 _this.customElements = new CustomElementRegistry();
21723 var container = config.container, canvas = config.canvas, offscreenCanvas = config.offscreenCanvas, width = config.width, height = config.height, devicePixelRatio = config.devicePixelRatio, renderer = config.renderer, background = config.background, cursor = config.cursor, document = config.document, requestAnimationFrame = config.requestAnimationFrame, cancelAnimationFrame = config.cancelAnimationFrame, createImage = config.createImage, supportsPointerEvents = config.supportsPointerEvents, supportsTouchEvents = config.supportsTouchEvents, supportsCSSTransform = config.supportsCSSTransform, supportsMutipleCanvasesInOneContainer = config.supportsMutipleCanvasesInOneContainer, useNativeClickEvent = config.useNativeClickEvent, alwaysTriggerPointerEventOnCanvas = config.alwaysTriggerPointerEventOnCanvas, isTouchEvent = config.isTouchEvent, isMouseEvent = config.isMouseEvent;
21724 if (!supportsMutipleCanvasesInOneContainer) {
21725 cleanExistedCanvas(container, _this);
21726 }
21727 var canvasWidth = width;
21728 var canvasHeight = height;
21729 var dpr = devicePixelRatio;
21730 // use user-defined <canvas> or OffscreenCanvas
21731 if (canvas) {
21732 // infer width & height with dpr
21733 dpr = devicePixelRatio || (isBrowser && window.devicePixelRatio) || 1;
21734 dpr = dpr >= 1 ? Math.ceil(dpr) : 1;
21735 canvasWidth = width || getWidth(canvas) || canvas.width / dpr;
21736 canvasHeight = height || getHeight(canvas) || canvas.height / dpr;
21737 }
21738 // override it in runtime
21739 if (offscreenCanvas) {
21740 runtime.offscreenCanvas = offscreenCanvas;
21741 }
21742 /**
21743 * implements `Window` interface
21744 */
21745 _this.devicePixelRatio = dpr;
21746 _this.requestAnimationFrame =
21747 requestAnimationFrame !== null && requestAnimationFrame !== void 0 ? requestAnimationFrame : raf.bind(runtime.globalThis);
21748 _this.cancelAnimationFrame =
21749 cancelAnimationFrame !== null && cancelAnimationFrame !== void 0 ? cancelAnimationFrame : caf.bind(runtime.globalThis);
21750 /**
21751 * limits query
21752 */
21753 // the following feature-detect from hammer.js
21754 // @see https://github.com/hammerjs/hammer.js/blob/master/src/inputjs/input-consts.js#L5
21755 _this.supportsTouchEvents =
21756 supportsTouchEvents !== null && supportsTouchEvents !== void 0 ? supportsTouchEvents : 'ontouchstart' in runtime.globalThis;
21757 _this.supportsPointerEvents =
21758 supportsPointerEvents !== null && supportsPointerEvents !== void 0 ? supportsPointerEvents : !!runtime.globalThis.PointerEvent;
21759 _this.isTouchEvent =
21760 isTouchEvent !== null && isTouchEvent !== void 0 ? isTouchEvent : (function (event) {
21761 return _this.supportsTouchEvents &&
21762 event instanceof runtime.globalThis.TouchEvent;
21763 });
21764 _this.isMouseEvent =
21765 isMouseEvent !== null && isMouseEvent !== void 0 ? isMouseEvent : (function (event) {
21766 return !runtime.globalThis.MouseEvent ||
21767 (event instanceof runtime.globalThis.MouseEvent &&
21768 (!_this.supportsPointerEvents ||
21769 !(event instanceof runtime.globalThis.PointerEvent)));
21770 });
21771 _this.initRenderingContext({
21772 container: container,
21773 canvas: canvas,
21774 width: canvasWidth,
21775 height: canvasHeight,
21776 renderer: renderer,
21777 offscreenCanvas: offscreenCanvas,
21778 devicePixelRatio: dpr,
21779 cursor: cursor || 'default',
21780 background: background || 'transparent',
21781 createImage: createImage,
21782 document: document,
21783 supportsCSSTransform: supportsCSSTransform,
21784 useNativeClickEvent: useNativeClickEvent,
21785 alwaysTriggerPointerEventOnCanvas: alwaysTriggerPointerEventOnCanvas,
21786 });
21787 _this.initDefaultCamera(canvasWidth, canvasHeight, renderer.clipSpaceNearZ);
21788 _this.initRenderer(renderer, true);
21789 return _this;
21790 }
21791 Canvas.prototype.initRenderingContext = function (mergedConfig) {
21792 this.context.config = mergedConfig;
21793 // bind rendering context, shared by all renderers
21794 this.context.renderingContext = {
21795 /**
21796 * the root node in scene graph
21797 */
21798 root: this.document.documentElement,
21799 renderListCurrentFrame: [],
21800 unculledEntities: [],
21801 renderReasons: new Set(),
21802 force: false,
21803 dirty: false,
21804 };
21805 };
21806 Canvas.prototype.initDefaultCamera = function (width, height, clipSpaceNearZ) {
21807 var _this = this;
21808 // set a default ortho camera
21809 var camera = new runtime.CameraContribution();
21810 camera.clipSpaceNearZ = clipSpaceNearZ;
21811 camera
21812 .setType(CameraType.EXPLORING, CameraTrackingMode.DEFAULT)
21813 .setPosition(width / 2, height / 2, DEFAULT_CAMERA_Z)
21814 .setFocalPoint(width / 2, height / 2, 0)
21815 .setOrthographic(width / -2, width / 2, height / 2, height / -2, DEFAULT_CAMERA_NEAR, DEFAULT_CAMERA_FAR);
21816 // keep ref since it will use raf in camera animation
21817 camera.canvas = this;
21818 // redraw when camera changed
21819 camera.eventEmitter.on(CameraEvent.UPDATED, function () {
21820 _this.context.renderingContext.renderReasons.add(RenderReason.CAMERA_CHANGED);
21821 });
21822 // bind camera
21823 this.context.camera = camera;
21824 };
21825 Canvas.prototype.getConfig = function () {
21826 return this.context.config;
21827 };
21828 /**
21829 * get the root displayObject in scenegraph
21830 * @alias this.document.documentElement
21831 */
21832 Canvas.prototype.getRoot = function () {
21833 return this.document.documentElement;
21834 };
21835 /**
21836 * get the camera of canvas
21837 */
21838 Canvas.prototype.getCamera = function () {
21839 return this.context.camera;
21840 };
21841 Canvas.prototype.getContextService = function () {
21842 return this.context.contextService;
21843 };
21844 Canvas.prototype.getEventService = function () {
21845 return this.context.eventService;
21846 };
21847 Canvas.prototype.getRenderingService = function () {
21848 return this.context.renderingService;
21849 };
21850 Canvas.prototype.getRenderingContext = function () {
21851 return this.context.renderingContext;
21852 };
21853 Canvas.prototype.getStats = function () {
21854 return this.getRenderingService().getStats();
21855 };
21856 Object.defineProperty(Canvas.prototype, "ready", {
21857 // /**
21858 // * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getComputedStyle
21859 // */
21860 // getComputedStyle(node: DisplayObject) {
21861 // return node.computedStyle;
21862 // }
21863 get: function () {
21864 var _this = this;
21865 if (!this.readyPromise) {
21866 this.readyPromise = new Promise(function (resolve) {
21867 _this.resolveReadyPromise = function () {
21868 resolve(_this);
21869 };
21870 });
21871 if (this.inited) {
21872 this.resolveReadyPromise();
21873 }
21874 }
21875 return this.readyPromise;
21876 },
21877 enumerable: false,
21878 configurable: true
21879 });
21880 /**
21881 * `cleanUp` means clean all the internal services of Canvas which happens when calling `canvas.destroy()`.
21882 */
21883 Canvas.prototype.destroy = function (cleanUp, skipTriggerEvent) {
21884 if (cleanUp === void 0) { cleanUp = true; }
21885 if (skipTriggerEvent === void 0) { skipTriggerEvent = false; }
21886 if (!skipTriggerEvent) {
21887 this.dispatchEvent(new CustomEvent(CanvasEvent.BEFORE_DESTROY));
21888 }
21889 if (this.frameId) {
21890 var cancelRAF = this.getConfig().cancelAnimationFrame || cancelAnimationFrame;
21891 cancelRAF(this.frameId);
21892 }
21893 // unmount all children
21894 var root = this.getRoot();
21895 this.unmountChildren(root);
21896 if (cleanUp) {
21897 // destroy Document
21898 this.document.destroy();
21899 this.getEventService().destroy();
21900 }
21901 // destroy services
21902 this.getRenderingService().destroy();
21903 this.getContextService().destroy();
21904 // clear root after renderservice destroyed
21905 if (cleanUp && this.context.rBushRoot) {
21906 // clear rbush
21907 this.context.rBushRoot.clear();
21908 this.context.rBushRoot = null;
21909 this.context.renderingContext.root = null;
21910 }
21911 if (!skipTriggerEvent) {
21912 this.dispatchEvent(new CustomEvent(CanvasEvent.AFTER_DESTROY));
21913 }
21914 };
21915 /**
21916 * compatible with G 3.0
21917 * @deprecated
21918 * @alias resize
21919 */
21920 Canvas.prototype.changeSize = function (width, height) {
21921 this.resize(width, height);
21922 };
21923 Canvas.prototype.resize = function (width, height) {
21924 // update canvas' config
21925 var canvasConfig = this.context.config;
21926 canvasConfig.width = width;
21927 canvasConfig.height = height;
21928 // resize context
21929 this.getContextService().resize(width, height);
21930 // resize camera
21931 var camera = this.context.camera;
21932 var projectionMode = camera.getProjectionMode();
21933 camera
21934 .setPosition(width / 2, height / 2, DEFAULT_CAMERA_Z)
21935 .setFocalPoint(width / 2, height / 2, 0);
21936 if (projectionMode === CameraProjectionMode.ORTHOGRAPHIC) {
21937 camera.setOrthographic(width / -2, width / 2, height / 2, height / -2, camera.getNear(), camera.getFar());
21938 }
21939 else {
21940 camera.setAspect(width / height);
21941 }
21942 this.dispatchEvent(new CustomEvent(CanvasEvent.RESIZE, { width: width, height: height }));
21943 };
21944 // proxy to document.documentElement
21945 Canvas.prototype.appendChild = function (child, index) {
21946 return this.document.documentElement.appendChild(child, index);
21947 };
21948 Canvas.prototype.insertBefore = function (newChild, refChild) {
21949 return this.document.documentElement.insertBefore(newChild, refChild);
21950 };
21951 Canvas.prototype.removeChild = function (child) {
21952 return this.document.documentElement.removeChild(child);
21953 };
21954 /**
21955 * Remove all children which can be appended to its original parent later again.
21956 */
21957 Canvas.prototype.removeChildren = function () {
21958 this.document.documentElement.removeChildren();
21959 };
21960 /**
21961 * Recursively destroy all children which can not be appended to its original parent later again.
21962 * But the canvas remains running which means display objects can be appended later.
21963 */
21964 Canvas.prototype.destroyChildren = function () {
21965 this.document.documentElement.destroyChildren();
21966 };
21967 Canvas.prototype.render = function () {
21968 var _this = this;
21969 this.dispatchEvent(beforeRenderEvent);
21970 var renderingService = this.getRenderingService();
21971 renderingService.render(this.getConfig(), function () {
21972 // trigger actual rerender event
21973 // @see https://github.com/antvis/G/issues/1268
21974 _this.dispatchEvent(rerenderEvent);
21975 });
21976 this.dispatchEvent(afterRenderEvent);
21977 };
21978 Canvas.prototype.run = function () {
21979 var _this = this;
21980 var tick = function () {
21981 _this.render();
21982 _this.frameId = _this.requestAnimationFrame(tick);
21983 };
21984 tick();
21985 };
21986 Canvas.prototype.initRenderer = function (renderer, firstContentfullPaint) {
21987 var _this = this;
21988 if (firstContentfullPaint === void 0) { firstContentfullPaint = false; }
21989 if (!renderer) {
21990 throw new Error('Renderer is required.');
21991 }
21992 // reset
21993 this.inited = false;
21994 this.readyPromise = undefined;
21995 // FIXME: should re-create here?
21996 this.context.rBushRoot = new RBush();
21997 // reset rendering plugins
21998 this.context.renderingPlugins = [];
21999 this.context.renderingPlugins.push(new EventPlugin(), new PrepareRendererPlugin(),
22000 // new DirtyCheckPlugin(),
22001 new CullingPlugin([new FrustumCullingStrategy()]));
22002 //
22003 this.loadRendererContainerModule(renderer);
22004 // init context service
22005 this.context.contextService = new this.context.ContextService(__assign(__assign({}, runtime), this.context));
22006 // init rendering service
22007 this.context.renderingService = new RenderingService(runtime, this.context);
22008 // init event service
22009 this.context.eventService = new EventService(runtime, this.context);
22010 this.context.eventService.init();
22011 if (this.context.contextService.init) {
22012 this.context.contextService.init();
22013 this.initRenderingService(renderer, firstContentfullPaint, true);
22014 }
22015 else {
22016 this.context.contextService.initAsync().then(function () {
22017 _this.initRenderingService(renderer, firstContentfullPaint);
22018 });
22019 }
22020 };
22021 Canvas.prototype.initRenderingService = function (renderer, firstContentfullPaint, async) {
22022 var _this = this;
22023 if (firstContentfullPaint === void 0) { firstContentfullPaint = false; }
22024 if (async === void 0) { async = false; }
22025 this.context.renderingService.init(function () {
22026 _this.inited = true;
22027 if (firstContentfullPaint) {
22028 if (async) {
22029 _this.requestAnimationFrame(function () {
22030 _this.dispatchEvent(new CustomEvent(CanvasEvent.READY));
22031 });
22032 }
22033 else {
22034 _this.dispatchEvent(new CustomEvent(CanvasEvent.READY));
22035 }
22036 if (_this.readyPromise) {
22037 _this.resolveReadyPromise();
22038 }
22039 }
22040 else {
22041 _this.dispatchEvent(new CustomEvent(CanvasEvent.RENDERER_CHANGED));
22042 }
22043 if (!firstContentfullPaint) {
22044 _this.getRoot().forEach(function (node) {
22045 var renderable = node.renderable;
22046 if (renderable) {
22047 renderable.renderBoundsDirty = true;
22048 renderable.boundsDirty = true;
22049 renderable.dirty = true;
22050 }
22051 });
22052 }
22053 // keep current scenegraph unchanged, just trigger mounted event
22054 _this.mountChildren(_this.getRoot());
22055 if (renderer.getConfig().enableAutoRendering) {
22056 _this.run();
22057 }
22058 });
22059 };
22060 Canvas.prototype.loadRendererContainerModule = function (renderer) {
22061 var _this = this;
22062 // load other container modules provided by g-canvas/g-svg/g-webgl
22063 var plugins = renderer.getPlugins();
22064 plugins.forEach(function (plugin) {
22065 plugin.context = _this.context;
22066 plugin.init(runtime);
22067 });
22068 };
22069 Canvas.prototype.setRenderer = function (renderer) {
22070 // update canvas' config
22071 var canvasConfig = this.getConfig();
22072 if (canvasConfig.renderer === renderer) {
22073 return;
22074 }
22075 var oldRenderer = canvasConfig.renderer;
22076 canvasConfig.renderer = renderer;
22077 // keep all children undestroyed
22078 this.destroy(false, true);
22079 // destroy all plugins, reverse will mutate origin array
22080 __spreadArray([], __read(oldRenderer === null || oldRenderer === void 0 ? void 0 : oldRenderer.getPlugins()), false).reverse().forEach(function (plugin) {
22081 plugin.destroy(runtime);
22082 });
22083 this.initRenderer(renderer);
22084 };
22085 Canvas.prototype.setCursor = function (cursor) {
22086 var canvasConfig = this.getConfig();
22087 canvasConfig.cursor = cursor;
22088 this.getContextService().applyCursorStyle(cursor);
22089 };
22090 Canvas.prototype.unmountChildren = function (parent) {
22091 var _this = this;
22092 // unmountChildren recursively
22093 parent.childNodes.forEach(function (child) {
22094 _this.unmountChildren(child);
22095 });
22096 if (this.inited) {
22097 if (parent.isMutationObserved) {
22098 parent.dispatchEvent(unmountedEvent);
22099 }
22100 else {
22101 unmountedEvent.target = parent;
22102 this.dispatchEvent(unmountedEvent, true);
22103 }
22104 // skip document.documentElement
22105 if (parent !== this.document.documentElement) {
22106 parent.ownerDocument = null;
22107 }
22108 parent.isConnected = false;
22109 }
22110 // trigger after unmounted
22111 if (parent.isCustomElement) {
22112 if (parent.disconnectedCallback) {
22113 parent.disconnectedCallback();
22114 }
22115 }
22116 };
22117 Canvas.prototype.mountChildren = function (parent) {
22118 var _this = this;
22119 if (this.inited) {
22120 if (!parent.isConnected) {
22121 parent.ownerDocument = this.document;
22122 parent.isConnected = true;
22123 if (parent.isMutationObserved) {
22124 parent.dispatchEvent(mountedEvent);
22125 }
22126 else {
22127 mountedEvent.target = parent;
22128 this.dispatchEvent(mountedEvent, true);
22129 }
22130 }
22131 }
22132 else {
22133 console.warn("[g]: You are trying to call `canvas.appendChild` before canvas' initialization finished. You can either await `canvas.ready` or listen to `CanvasEvent.READY` manually.", 'appended child: ', parent.nodeName);
22134 }
22135 // recursively mount children
22136 parent.childNodes.forEach(function (child) {
22137 _this.mountChildren(child);
22138 });
22139 // trigger after mounted
22140 if (parent.isCustomElement) {
22141 if (parent.connectedCallback) {
22142 parent.connectedCallback();
22143 }
22144 }
22145 };
22146 Canvas.prototype.client2Viewport = function (client) {
22147 return this.getEventService().client2Viewport(client);
22148 };
22149 Canvas.prototype.viewport2Client = function (canvas) {
22150 return this.getEventService().viewport2Client(canvas);
22151 };
22152 Canvas.prototype.viewport2Canvas = function (viewport) {
22153 return this.getEventService().viewport2Canvas(viewport);
22154 };
22155 Canvas.prototype.canvas2Viewport = function (canvas) {
22156 return this.getEventService().canvas2Viewport(canvas);
22157 };
22158 /**
22159 * @deprecated
22160 * @alias client2Viewport
22161 */
22162 Canvas.prototype.getPointByClient = function (clientX, clientY) {
22163 return this.client2Viewport({ x: clientX, y: clientY });
22164 };
22165 /**
22166 * @deprecated
22167 * @alias viewport2Client
22168 */
22169 Canvas.prototype.getClientByPoint = function (x, y) {
22170 return this.viewport2Client({ x: x, y: y });
22171 };
22172 return Canvas;
22173 }(EventTarget));
22174
22175 var polarToCartesian = function polarToCartesian(centerX, centerY, radius, angleInRadian) {
22176 return {
22177 x: centerX + radius * Math.cos(angleInRadian),
22178 y: centerY + radius * Math.sin(angleInRadian)
22179 };
22180 };
22181
22182 function computeArcSweep(startAngle, endAngle, anticlockwise) {
22183 // 顺时针方向
22184 if (!anticlockwise) {
22185 if (endAngle >= startAngle) {
22186 return endAngle - startAngle <= Math.PI ? 0 : 1;
22187 }
22188 return endAngle - startAngle <= -Math.PI ? 0 : 1;
22189 }
22190 // 逆时针方向
22191 if (endAngle >= startAngle) {
22192 return endAngle - startAngle <= Math.PI ? 1 : 0;
22193 }
22194 return endAngle - startAngle <= -Math.PI ? 1 : 0;
22195 }
22196 var Arc = /** @class */function (_super) {
22197 __extends(Arc, _super);
22198 function Arc(config) {
22199 var _this = _super.call(this, config) || this;
22200 _this.updatePath();
22201 return _this;
22202 }
22203 Arc.prototype.setAttribute = function (name, value, force) {
22204 _super.prototype.setAttribute.call(this, name, value, force);
22205 if (['cx', 'cy', 'startAngle', 'endAngle', 'r', 'anticlockwise'].indexOf(name) > -1) {
22206 this.updatePath();
22207 }
22208 };
22209 Arc.prototype.updatePath = function () {
22210 var _a = this.parsedStyle,
22211 _b = _a.cx,
22212 cx = _b === void 0 ? 0 : _b,
22213 _c = _a.cy,
22214 cy = _c === void 0 ? 0 : _c,
22215 startAngle = _a.startAngle,
22216 endAngle = _a.endAngle,
22217 r = _a.r,
22218 anticlockwise = _a.anticlockwise;
22219 if (isNil(startAngle) || isNil(endAngle) || startAngle === endAngle || isNil(r) || r <= 0) {
22220 _super.prototype.setAttribute.call(this, 'path', '');
22221 return;
22222 }
22223 var path = this.createPath(cx, cy, deg2rad(startAngle), deg2rad(endAngle), r, anticlockwise);
22224 _super.prototype.setAttribute.call(this, 'path', path);
22225 };
22226 Arc.prototype.createPath = function (x, y, startAngle, endAngle, r, anticlockwise) {
22227 var start = polarToCartesian(x, y, r, startAngle);
22228 var end = polarToCartesian(x, y, r, endAngle);
22229 var angle = Math.abs(endAngle - startAngle);
22230 if (angle >= Math.PI * 2 || isNumberEqual(angle, Math.PI * 2)) {
22231 var middlePoint = polarToCartesian(x, y, r, startAngle + Math.PI);
22232 return [['M', start.x, start.y], ['A', r, r, 0, 1, anticlockwise ? 0 : 1, middlePoint.x, middlePoint.y], ['A', r, r, 0, 1, anticlockwise ? 0 : 1, start.x, start.y], ['Z']];
22233 }
22234 var arcSweep = computeArcSweep(startAngle, endAngle, anticlockwise);
22235 return [['M', start.x, start.y], ['A', r, r, 0, arcSweep, anticlockwise ? 0 : 1, end.x, end.y]];
22236 };
22237 return Arc;
22238 }(Path);
22239
22240 var SYMBOLS = {
22241 circle: function circle(x, y, r) {
22242 return [['M', x - r, y], ['A', r, r, 0, 1, 0, x + r, y], ['A', r, r, 0, 1, 0, x - r, y]];
22243 },
22244 square: function square(x, y, r) {
22245 return [['M', x - r, y - r], ['L', x + r, y - r], ['L', x + r, y + r], ['L', x - r, y + r], ['Z']];
22246 },
22247 arrow: function arrow(x, y, r) {
22248 return [['M', x - r, y + 2 * r / Math.sqrt(3)], ['L', x + r, y + 2 * r / Math.sqrt(3)], ['L', x, y - 2 * r / Math.sqrt(3)], ['Z']];
22249 }
22250 };
22251 var Marker = /** @class */function (_super) {
22252 __extends(Marker, _super);
22253 function Marker(config) {
22254 var _this = _super.call(this, config) || this;
22255 _this.updatePath();
22256 return _this;
22257 }
22258 Marker.prototype.setAttribute = function (name, value, force) {
22259 _super.prototype.setAttribute.call(this, name, value, force);
22260 if (['x', 'y', 'symbol', 'radius'].indexOf(name) > -1) {
22261 this.updatePath();
22262 }
22263 };
22264 Marker.prototype.updatePath = function () {
22265 var _a = this.parsedStyle,
22266 _b = _a.x,
22267 x = _b === void 0 ? 0 : _b,
22268 _c = _a.y,
22269 y = _c === void 0 ? 0 : _c;
22270 var _d = this.attributes,
22271 radius = _d.radius,
22272 symbol = _d.symbol;
22273 if (!symbol) return;
22274 var method = SYMBOLS[symbol];
22275 if (!method) return;
22276 var path = method(x, y, radius);
22277 _super.prototype.setAttribute.call(this, 'path', path);
22278 };
22279 return Marker;
22280 }(Path);
22281
22282 var PI = Math.PI;
22283 var PI2 = PI * 2;
22284 var mathSin = Math.sin;
22285 var mathCos = Math.cos;
22286 var mathACos = Math.acos;
22287 var mathATan2 = Math.atan2;
22288 // const mathAbs = Math.abs;
22289 var mathSqrt = Math.sqrt;
22290 var mathMax = Math.max;
22291 var mathMin = Math.min;
22292 var e = 1e-4;
22293 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
22294 var dx10 = x1 - x0;
22295 var dy10 = y1 - y0;
22296 var dx32 = x3 - x2;
22297 var dy32 = y3 - y2;
22298 var t = dy32 * dx10 - dx32 * dy10;
22299 if (t * t < e) {
22300 return;
22301 }
22302 t = (dx32 * (y0 - y2) - dy32 * (x0 - x2)) / t;
22303 return [x0 + t * dx10, y0 + t * dy10];
22304 }
22305 // Compute perpendicular offset line of length rc.
22306 function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) {
22307 var x01 = x0 - x1;
22308 var y01 = y0 - y1;
22309 var lo = (clockwise ? cr : -cr) / mathSqrt(x01 * x01 + y01 * y01);
22310 var ox = lo * y01;
22311 var oy = -lo * x01;
22312 var x11 = x0 + ox;
22313 var y11 = y0 + oy;
22314 var x10 = x1 + ox;
22315 var y10 = y1 + oy;
22316 var x00 = (x11 + x10) / 2;
22317 var y00 = (y11 + y10) / 2;
22318 var dx = x10 - x11;
22319 var dy = y10 - y11;
22320 var d2 = dx * dx + dy * dy;
22321 var r = radius - cr;
22322 var s = x11 * y10 - x10 * y11;
22323 var d = (dy < 0 ? -1 : 1) * mathSqrt(mathMax(0, r * r * d2 - s * s));
22324 var cx0 = (s * dy - dx * d) / d2;
22325 var cy0 = (-s * dx - dy * d) / d2;
22326 var cx1 = (s * dy + dx * d) / d2;
22327 var cy1 = (-s * dx + dy * d) / d2;
22328 var dx0 = cx0 - x00;
22329 var dy0 = cy0 - y00;
22330 var dx1 = cx1 - x00;
22331 var dy1 = cy1 - y00;
22332 // Pick the closer of the two intersection points
22333 // TODO: Is there a faster way to determine which intersection to use?
22334 if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) {
22335 cx0 = cx1;
22336 cy0 = cy1;
22337 }
22338 return {
22339 cx: cx0,
22340 cy: cy0,
22341 x0: -ox,
22342 y0: -oy,
22343 x1: cx0 * (radius / r - 1),
22344 y1: cy0 * (radius / r - 1)
22345 };
22346 }
22347 function computeArcSweep$1(startAngle, endAngle, clockwise) {
22348 if (clockwise === void 0) {
22349 clockwise = true;
22350 }
22351 if (!clockwise) {
22352 var replaceAngle = endAngle;
22353 endAngle = startAngle;
22354 startAngle = replaceAngle;
22355 }
22356 endAngle = endAngle - startAngle < 0 ? endAngle + PI2 : endAngle;
22357 return Math.abs(endAngle - startAngle) % PI2 <= PI ? 0 : 1;
22358 }
22359 var Sector = /** @class */function (_super) {
22360 __extends(Sector, _super);
22361 function Sector(config) {
22362 var _this = _super.call(this, config) || this;
22363 _this.updatePath();
22364 return _this;
22365 }
22366 Sector.prototype.setAttribute = function (name, value, force) {
22367 _super.prototype.setAttribute.call(this, name, value, force);
22368 if (['startAngle', 'endAngle', 'r', 'r0', 'radius', 'cx', 'cy'].indexOf(name) > -1) {
22369 this.updatePath();
22370 }
22371 };
22372 Sector.prototype.updatePath = function () {
22373 var _a = this.parsedStyle,
22374 cx = _a.cx,
22375 cy = _a.cy,
22376 startAngle = _a.startAngle,
22377 endAngle = _a.endAngle,
22378 r = _a.r,
22379 r0 = _a.r0,
22380 radius = _a.radius,
22381 _b = _a.anticlockwise,
22382 anticlockwise = _b === void 0 ? false : _b;
22383 if (isNil(startAngle) || isNil(endAngle) || startAngle === endAngle || isNil(r) || r <= 0) {
22384 _super.prototype.setAttribute.call(this, 'path', '');
22385 return;
22386 }
22387 var path = this.createPath(cx, cy, deg2rad(startAngle), deg2rad(endAngle), r, r0 ? r0 : 0, radius ? radius : [0, 0, 0, 0], anticlockwise);
22388 _super.prototype.setAttribute.call(this, 'path', path);
22389 };
22390 Sector.prototype.createPath = function (x, y, startAngle, endAngle, r, r0, borderRadius, anticlockwise) {
22391 var start = polarToCartesian(x, y, r, startAngle);
22392 var end = polarToCartesian(x, y, r, endAngle);
22393 var innerStart = polarToCartesian(x, y, r0, startAngle);
22394 var innerEnd = polarToCartesian(x, y, r0, endAngle);
22395 var clockwise = !anticlockwise;
22396 var angle = clockwise ? endAngle - startAngle : startAngle - endAngle;
22397 // 整圆
22398 if (Math.abs(angle) >= PI2 || isNumberEqual(Math.abs(angle), PI2)) {
22399 // 整个圆是分割成两个圆
22400 var middlePoint = polarToCartesian(x, y, r, startAngle + Math.PI);
22401 var innerMiddlePoint = polarToCartesian(x, y, r0, startAngle + Math.PI);
22402 var circlePathCommands = [['M', start.x, start.y], ['A', r, r, 0, 1, clockwise ? 1 : 0, middlePoint.x, middlePoint.y], ['A', r, r, 0, 1, clockwise ? 1 : 0, end.x, end.y]];
22403 if (r0 > 0) {
22404 circlePathCommands.push(['M', innerStart.x, innerStart.y]);
22405 circlePathCommands.push(['A', r0, r0, 0, 1, clockwise ? 0 : 1, innerMiddlePoint.x, innerMiddlePoint.y]);
22406 circlePathCommands.push(['A', r0, r0, 0, 1, clockwise ? 0 : 1, innerEnd.x, innerEnd.y]);
22407 }
22408 circlePathCommands.push(['M', start.x, start.y]);
22409 circlePathCommands.push(['Z']);
22410 return circlePathCommands;
22411 }
22412 var xrs = r * mathCos(startAngle);
22413 var yrs = r * mathSin(startAngle);
22414 var xire = r0 * mathCos(endAngle);
22415 var yire = r0 * mathSin(endAngle);
22416 var xre = r * mathCos(endAngle);
22417 var yre = r * mathSin(endAngle);
22418 var xirs = r0 * mathCos(startAngle);
22419 var yirs = r0 * mathSin(startAngle);
22420 // 顺时针反向,同 radius
22421 var outStartRadius = borderRadius[0],
22422 outEndRadius = borderRadius[1],
22423 innerEndRadius = borderRadius[2],
22424 innerStartRadius = borderRadius[3];
22425 var halfRadius = (r - r0) / 2;
22426 var outStartBorderRadius = mathMin(halfRadius, outStartRadius);
22427 var outEndBorderRadius = mathMin(halfRadius, outEndRadius);
22428 var innerEndBorderRadius = mathMin(halfRadius, innerEndRadius);
22429 var innerStartBorderRadius = mathMin(halfRadius, innerStartRadius);
22430 var outBorderRadiusMax = mathMax(outStartBorderRadius, outEndBorderRadius);
22431 var innerBorderRadiusMax = mathMax(innerEndBorderRadius, innerStartBorderRadius);
22432 var limitedOutBorderRadiusMax = outBorderRadiusMax;
22433 var limitedInnerBorderRadiusMax = innerBorderRadiusMax;
22434 // draw corner radius
22435 if (outBorderRadiusMax > e || innerBorderRadiusMax > e) {
22436 // restrict the max value of corner radius
22437 if (angle < PI) {
22438 var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire);
22439 if (it_1) {
22440 var x0 = xrs - it_1[0];
22441 var y0 = yrs - it_1[1];
22442 var x1 = xre - it_1[0];
22443 var y1 = yre - it_1[1];
22444 var a = 1 / mathSin(mathACos((x0 * x1 + y0 * y1) / (mathSqrt(x0 * x0 + y0 * y0) * mathSqrt(x1 * x1 + y1 * y1))) / 2);
22445 var b = mathSqrt(it_1[0] * it_1[0] + it_1[1] * it_1[1]);
22446 limitedOutBorderRadiusMax = mathMin(outBorderRadiusMax, (r - b) / (a + 1));
22447 limitedInnerBorderRadiusMax = mathMin(innerBorderRadiusMax, (r0 - b) / (a - 1));
22448 }
22449 }
22450 }
22451 var arcSweep = computeArcSweep$1(startAngle, endAngle, clockwise);
22452 var sectorPathCommands = [];
22453 if (limitedOutBorderRadiusMax > e) {
22454 var crStart = mathMin(outStartRadius, limitedOutBorderRadiusMax);
22455 var crEnd = mathMin(outEndRadius, limitedOutBorderRadiusMax);
22456 var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, r, crStart, clockwise);
22457 var ct1 = computeCornerTangents(xre, yre, xire, yire, r, crEnd, clockwise);
22458 sectorPathCommands.push(['M', x + ct0.cx + ct0.x0, y + ct0.cy + ct0.y0]);
22459 // Have the corners merged?
22460 if (limitedOutBorderRadiusMax < outBorderRadiusMax && crStart === crEnd) {
22461 var outStartBorderRadiusStartAngle = mathATan2(ct0.cy + ct0.y0, ct0.cx + ct0.x0);
22462 var outStartBorderRadiusEndAngle = mathATan2(ct1.cy + ct1.y0, ct1.cx + ct1.x0);
22463 sectorPathCommands.push(['A', limitedOutBorderRadiusMax, limitedOutBorderRadiusMax, 0, computeArcSweep$1(outStartBorderRadiusStartAngle, outStartBorderRadiusEndAngle, !clockwise), clockwise ? 1 : 0, x + ct1.cx + ct1.x0, y + ct1.cy + ct1.y0]);
22464 } else {
22465 // draw the two corners and the ring
22466 if (crStart > 0) {
22467 var outStartBorderRadiusStartAngle = mathATan2(ct0.y0, ct0.x0);
22468 var outStartBorderRadiusEndAngle = mathATan2(ct0.y1, ct0.x1);
22469 var outStartBorderRadiusEndPoint = polarToCartesian(x, y, r, outStartBorderRadiusEndAngle);
22470 sectorPathCommands.push(['A', crStart, crStart, 0, computeArcSweep$1(outStartBorderRadiusStartAngle, outStartBorderRadiusEndAngle, clockwise), clockwise ? 1 : 0, outStartBorderRadiusEndPoint.x, outStartBorderRadiusEndPoint.y]);
22471 }
22472 var outRadiusStartAngle = mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1);
22473 var outRadiusEndAngle = mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1);
22474 var outRadiusEndPoint = polarToCartesian(x, y, r, outRadiusEndAngle);
22475 sectorPathCommands.push(['A', r, r, 1, computeArcSweep$1(outRadiusStartAngle, outRadiusEndAngle, clockwise), clockwise ? 1 : 0, outRadiusEndPoint.x, outRadiusEndPoint.y]);
22476 if (crEnd > 0) {
22477 var outEndBorderRadiusStartAngle = mathATan2(ct1.y1, ct1.x1);
22478 var outEndBorderRadiusEndAngle = mathATan2(ct1.y0, ct1.x0);
22479 sectorPathCommands.push(['A', crEnd, crEnd, 0, computeArcSweep$1(outEndBorderRadiusStartAngle, outEndBorderRadiusEndAngle, clockwise), clockwise ? 1 : 0, x + ct1.cx + ct1.x0, y + ct1.cy + ct1.y0]);
22480 }
22481 }
22482 } else {
22483 sectorPathCommands.push(['M', start.x, start.y]);
22484 sectorPathCommands.push(['A', r, r, 0, arcSweep, clockwise ? 1 : 0, end.x, end.y]);
22485 }
22486 // no inner ring, is a circular sector
22487 if (r0 < e) {
22488 sectorPathCommands.push(['L', innerEnd.x, innerEnd.y]);
22489 } else if (limitedInnerBorderRadiusMax > e) {
22490 var crStart = mathMin(innerStartRadius, limitedInnerBorderRadiusMax);
22491 var crEnd = mathMin(innerEndRadius, limitedInnerBorderRadiusMax);
22492 var ct0 = computeCornerTangents(0, 0, xire, yire, r0, -crEnd, clockwise);
22493 var ct1 = computeCornerTangents(xirs, yirs, 0, 0, r0, -crStart, clockwise);
22494 sectorPathCommands.push(['L', x + ct0.cx + ct0.x0, y + ct0.cy + ct0.y0]);
22495 // Have the corners merged?
22496 if (limitedInnerBorderRadiusMax < innerBorderRadiusMax && crStart === crEnd) {
22497 var innerStartBorderRadiusStartAngle = mathATan2(ct0.y0, ct0.x0);
22498 var innerStartBorderRadiusEndAngle = mathATan2(ct1.y0, ct1.x0);
22499 sectorPathCommands.push(['A', limitedInnerBorderRadiusMax, limitedInnerBorderRadiusMax, 0, computeArcSweep$1(innerStartBorderRadiusStartAngle, innerStartBorderRadiusEndAngle), 1, x + ct1.cx + ct1.x0, y + ct1.cy + ct1.y0]);
22500 } else {
22501 // draw the two corners and the ring
22502 if (crEnd > 0) {
22503 var innerStartBorderRadiusStartAngle = mathATan2(ct0.y0, ct0.x0);
22504 var innerStartBorderRadiusEndAngle = mathATan2(ct0.y1, ct0.x1);
22505 sectorPathCommands.push(['A', crEnd, crEnd, 0, computeArcSweep$1(innerStartBorderRadiusStartAngle, innerStartBorderRadiusEndAngle, clockwise), clockwise ? 1 : 0, x + ct0.cx + ct0.x1, y + ct0.cy + ct0.y1]);
22506 }
22507 var innerRadiusStartAngle = mathATan2(ct0.cy + ct0.y1, ct0.cx + ct0.x1);
22508 var innerRadiusEndAngle = mathATan2(ct1.cy + ct1.y1, ct1.cx + ct1.x1);
22509 var innerRadiusEndPoint = polarToCartesian(x, y, r0, innerRadiusEndAngle);
22510 sectorPathCommands.push(['A', r0, r0, 0, computeArcSweep$1(innerRadiusEndAngle, innerRadiusStartAngle, clockwise), clockwise ? 0 : 1, innerRadiusEndPoint.x, innerRadiusEndPoint.y]);
22511 if (crStart > 0) {
22512 var innerEndBorderRadiusStartAngle = mathATan2(ct1.y1, ct1.x1);
22513 var innerEndBorderRadiusEndAngle = mathATan2(ct1.y0, ct1.x0);
22514 sectorPathCommands.push(['A', crStart, crStart, 0, computeArcSweep$1(innerEndBorderRadiusStartAngle, innerEndBorderRadiusEndAngle, clockwise), clockwise ? 1 : 0, x + ct1.cx + ct1.x0, y + ct1.cy + ct1.y0]);
22515 }
22516 }
22517 }
22518 // the inner ring is just a circular arc
22519 else {
22520 sectorPathCommands.push(['L', innerEnd.x, innerEnd.y]);
22521 sectorPathCommands.push(['A', r0, r0, 0, arcSweep, clockwise ? 0 : 1, innerStart.x, innerStart.y]);
22522 }
22523 sectorPathCommands.push(['Z']);
22524 return sectorPathCommands;
22525 };
22526 return Sector;
22527 }(Path);
22528
22529 /**
22530 * @fileOverview convert the line to curve
22531 * @author dxq613@gmail.com
22532 */
22533 function getPoint(v) {
22534 return [v.x, v.y];
22535 }
22536 function smoothBezier(points, smooth, isLoop, constraint) {
22537 var cps = [];
22538 var prevPoint;
22539 var nextPoint;
22540 var hasConstraint = !!constraint;
22541 var min;
22542 var max;
22543 var point;
22544 var len;
22545 var l;
22546 var i;
22547 if (hasConstraint) {
22548 min = [Infinity, Infinity];
22549 max = [-Infinity, -Infinity];
22550 for (i = 0, l = points.length; i < l; i++) {
22551 point = getPoint(points[i]);
22552 min$1(min, min, point);
22553 max$1(max, max, point);
22554 }
22555 min$1(min, min, constraint[0]);
22556 max$1(max, max, constraint[1]);
22557 }
22558 for (i = 0, len = points.length; i < len; i++) {
22559 point = getPoint(points[i]);
22560 if (isLoop) {
22561 prevPoint = getPoint(points[i ? i - 1 : len - 1]);
22562 nextPoint = getPoint(points[(i + 1) % len]);
22563 } else {
22564 if (i === 0 || i === len - 1) {
22565 cps.push([point[0], point[1]]);
22566 continue;
22567 } else {
22568 prevPoint = getPoint(points[i - 1]);
22569 nextPoint = getPoint(points[i + 1]);
22570 }
22571 }
22572 var v = sub$1([], nextPoint, prevPoint);
22573 scale$2(v, v, smooth);
22574 var d0 = distance(point, prevPoint);
22575 var d1 = distance(point, nextPoint);
22576 var sum = d0 + d1;
22577 if (sum !== 0) {
22578 d0 /= sum;
22579 d1 /= sum;
22580 }
22581 var v1 = scale$2([], v, -d0);
22582 var v2 = scale$2([], v, d1);
22583 var cp0 = add$2([], point, v1);
22584 var cp1 = add$2([], point, v2);
22585 if (hasConstraint) {
22586 max$1(cp0, cp0, min);
22587 min$1(cp0, cp0, max);
22588 max$1(cp1, cp1, min);
22589 min$1(cp1, cp1, max);
22590 }
22591 cps.push([cp0[0], cp0[1]]);
22592 cps.push([cp1[0], cp1[1]]);
22593 }
22594 if (isLoop) {
22595 cps.push(cps.shift());
22596 }
22597 return cps;
22598 }
22599 function catmullRom2bezier(pointList, z, constraint) {
22600 var isLoop = !!z;
22601 var controlPointList = smoothBezier(pointList, 0.4, isLoop, constraint);
22602 var len = pointList.length;
22603 var d1 = [];
22604 var cp1;
22605 var cp2;
22606 var p;
22607 for (var i = 0; i < len - 1; i++) {
22608 cp1 = controlPointList[i * 2];
22609 cp2 = controlPointList[i * 2 + 1];
22610 p = pointList[i + 1];
22611 d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
22612 }
22613 if (isLoop) {
22614 cp1 = controlPointList[len];
22615 cp2 = controlPointList[len + 1];
22616 p = pointList[0];
22617 d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
22618 }
22619 return d1;
22620 }
22621
22622 var smooth = /*#__PURE__*/Object.freeze({
22623 __proto__: null,
22624 smooth: catmullRom2bezier
22625 });
22626
22627 var SmoothPolyline = /** @class */function (_super) {
22628 __extends(SmoothPolyline, _super);
22629 function SmoothPolyline(config) {
22630 var _this = _super.call(this, config) || this;
22631 _this.updatePath();
22632 return _this;
22633 }
22634 SmoothPolyline.prototype.setAttribute = function (name, value, force) {
22635 _super.prototype.setAttribute.call(this, name, value, force);
22636 if (['smooth', 'points'].indexOf(name) > -1) {
22637 this.updatePath();
22638 }
22639 };
22640 SmoothPolyline.prototype.updatePath = function () {
22641 var _a = this.parsedStyle,
22642 smooth$1 = _a.smooth,
22643 points = _a.points;
22644 var pos = points.points;
22645 var d = [['M', pos[0][0], pos[0][1]]];
22646 if (smooth$1) {
22647 var constaint = [[0, 0], [1, 1]];
22648 var sps = catmullRom2bezier(pos.map(function (d) {
22649 return {
22650 x: d[0],
22651 y: d[1]
22652 };
22653 }), false, constaint);
22654 for (var i = 0, n = sps.length; i < n; i++) {
22655 var sp = sps[i];
22656 d.push(['C', sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
22657 }
22658 } else {
22659 var i = void 0;
22660 var l = void 0;
22661 for (i = 1, l = pos.length - 1; i < l; i++) {
22662 d.push(['L', pos[i][0], pos[i][1]]);
22663 }
22664 d.push(['L', pos[l][0], pos[l][1]]);
22665 }
22666 _super.prototype.setAttribute.call(this, 'path', d);
22667 };
22668 SmoothPolyline.tag = 'smooth-polyline';
22669 return SmoothPolyline;
22670 }(Path);
22671
22672 var Gesture = /** @class */function () {
22673 function Gesture(element) {
22674 this.el = element;
22675 }
22676 Gesture.prototype.on = function (eventName, listener) {
22677 if (!eventName) return;
22678 var el = this.el;
22679 el.addEventListener(eventName, listener);
22680 };
22681 Gesture.prototype.off = function (eventName, listener) {
22682 if (!eventName) return;
22683 var el = this.el;
22684 el.removeEventListener(eventName, listener);
22685 };
22686 return Gesture;
22687 }();
22688
22689 var SHAPE_TAG = {};
22690 /**
22691 * 注册新的标签
22692 */
22693 var registerTag = function registerTag(name, ShapeConstructor) {
22694 SHAPE_TAG[name] = ShapeConstructor;
22695 };
22696 var getTag = function getTag(type) {
22697 return SHAPE_TAG[type];
22698 };
22699
22700 var EVENT_LIST = [['click', 'onClick'], ['touchstart', 'onTouchStart'], ['touchmove', 'onTouchMove'], ['touchend', 'onTouchEnd'], ['touchendoutside', 'onTouchEndOutside'],
22701 // drage 相关
22702 ['dragenter', 'onDragEnter'], ['dragleave', 'onDragLeave'], ['dragover', 'onDragOver'], ['drop', 'onDrop'], ['dragstart', 'onDragStart'], ['drag', 'onDrag'], ['dragend', 'onDragEnd'],
22703 // pan
22704 ['panstart', 'onPanStart'], ['pan', 'onPan'], ['panend', 'onPanEnd'],
22705 // press
22706 ['pressstart', 'onPressStart'], ['press', 'onPress'], ['pressend', 'onPressEnd'],
22707 // swipe
22708 ['swipe', 'onSwipe'],
22709 // pinch
22710 ['pinchstart', 'onPinchStart'], ['pinch', 'onPinch'], ['pinchend', 'onPinchEnd']];
22711 // 默认标签
22712 var TagElements = [['group', Rect], ['text', Text], ['circle', Circle], ['path', Path], ['ellipse', Ellipse], ['rect', Rect], ['image', Image], ['line', Line], ['polyline', SmoothPolyline], ['polygon', Polygon], ['arc', Arc], ['marker', Marker], ['sector', Sector]];
22713 TagElements.map(function (_a) {
22714 var type = _a[0],
22715 ShapeClass = _a[1];
22716 registerTag(type, ShapeClass);
22717 });
22718 // 注册 css 属性,不能注册已有属性,比如 r width等
22719 var SECTOR_CSS_PROPERTY = [{
22720 name: 'r0',
22721 inherits: false,
22722 interpolable: true,
22723 syntax: PropertySyntax.LENGTH_PERCENTAGE
22724 }, {
22725 name: 'startAngle',
22726 inherits: false,
22727 interpolable: true,
22728 syntax: PropertySyntax.ANGLE
22729 }, {
22730 name: 'endAngle',
22731 inherits: false,
22732 interpolable: true,
22733 syntax: PropertySyntax.ANGLE
22734 }];
22735 SECTOR_CSS_PROPERTY.forEach(function (property) {
22736 CSS.registerProperty(property);
22737 });
22738 function createShape(type, props) {
22739 if (!type) return null;
22740 var ShapeClass = getTag(type);
22741 if (!ShapeClass) return null;
22742 // const result = checkCSSRule(type, originStyle);
22743 var shape = new ShapeClass(props);
22744 // @ts-ignore
22745 shape.gesture = addEvent(shape, props);
22746 return shape;
22747 }
22748 function updateShape(shape, props, lastProps) {
22749 // @ts-ignore
22750 var gesture = shape.gesture;
22751 // 如果 shape 上存在 gesture,说明是 jsx 标签创建的元素,才需要更新事件
22752 if (gesture) {
22753 // 先清除上次 props 绑定的事件
22754 EVENT_LIST.forEach(function (_a) {
22755 var eventName = _a[0],
22756 handlerName = _a[1];
22757 if (!lastProps[handlerName]) return;
22758 gesture.off(eventName, lastProps[handlerName]);
22759 });
22760 // 绑定最新的事件
22761 EVENT_LIST.forEach(function (_a) {
22762 var eventName = _a[0],
22763 handlerName = _a[1];
22764 if (!props[handlerName]) return;
22765 gesture.on(eventName, props[handlerName]);
22766 });
22767 }
22768 return shape;
22769 }
22770 function addEvent(shape, props) {
22771 var gesture = new Gesture(shape);
22772 EVENT_LIST.forEach(function (_a) {
22773 var eventName = _a[0],
22774 handlerName = _a[1];
22775 if (!props[handlerName]) return;
22776 gesture.on(eventName, props[handlerName]);
22777 });
22778 return gesture;
22779 }
22780
22781 function _typeof(o) {
22782 "@babel/helpers - typeof";
22783
22784 return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
22785 return typeof o;
22786 } : function (o) {
22787 return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
22788 }, _typeof(o);
22789 }
22790
22791 function objToString(obj) {
22792 return Object.prototype.toString.call(obj);
22793 }
22794 function objectKeys(obj) {
22795 return Object.keys(obj);
22796 }
22797 function equal(a, b) {
22798 if (a === b) return true;
22799 if (_typeof(a) !== _typeof(b)) {
22800 return false;
22801 }
22802 // null 和 undefined
22803 if (a == null || b == null) {
22804 return false;
22805 }
22806 // 特殊处理NaN
22807 if (Number.isNaN(a) && Number.isNaN(b)) {
22808 return true;
22809 }
22810 if (objToString(a) !== objToString(b)) {
22811 return false;
22812 }
22813 // 函数不相等,也认为不同
22814 if (isFunction(a)) {
22815 return false;
22816 }
22817 // 值类型,Number String Boolean
22818 if (_typeof(a) !== 'object') {
22819 return false;
22820 }
22821 if (isArray(a)) {
22822 if (a.length !== b.length) {
22823 return false;
22824 }
22825 for (var i = a.length - 1; i >= 0; i--) {
22826 if (!equal(a[i], b[i])) {
22827 return false;
22828 }
22829 }
22830 return true;
22831 }
22832 if (!isPlainObject(a)) {
22833 return false;
22834 }
22835 var ka = objectKeys(a);
22836 var kb = objectKeys(b);
22837 // having the same number of owned properties (keys incorporates hasOwnProperty)
22838 if (ka.length !== kb.length) {
22839 return false;
22840 }
22841 // the same set of keys (although not necessarily the same order),
22842 ka.sort();
22843 kb.sort();
22844 // ~~~cheap key test
22845 for (var i = ka.length - 1; i >= 0; i--) {
22846 if (ka[i] != kb[i]) {
22847 return false;
22848 }
22849 }
22850 // equivalent values for every corresponding key, and ~~~possibly expensive deep test
22851 for (var i = ka.length - 1; i >= 0; i--) {
22852 var key = ka[i];
22853 if (!equal(a[key], b[key])) {
22854 return false;
22855 }
22856 }
22857 return true;
22858 }
22859
22860 var FunctionComponent = 0;
22861 var ClassComponent = 1;
22862 var Shape$1 = 2;
22863 function getWorkTag(type) {
22864 if (isString(type)) {
22865 return Shape$1;
22866 }
22867 if (type.prototype && type.prototype.isF2Component) {
22868 return ClassComponent;
22869 }
22870 return FunctionComponent;
22871 }
22872
22873 // 查找 transform 最近的 shape 元素
22874 function findClosestShapeNode(vNode) {
22875 var tag = vNode.tag,
22876 children = vNode.children;
22877 if (tag === Shape$1) {
22878 return vNode;
22879 }
22880 var shapeNode;
22881 Children.map(children, function (child) {
22882 if (shapeNode) return;
22883 shapeNode = findClosestShapeNode(child);
22884 });
22885 return shapeNode;
22886 }
22887
22888 var eventemitter3$1 = createCommonjsModule(function (module) {
22889
22890 var has = Object.prototype.hasOwnProperty
22891 , prefix = '~';
22892
22893 /**
22894 * Constructor to create a storage for our `EE` objects.
22895 * An `Events` instance is a plain object whose properties are event names.
22896 *
22897 * @constructor
22898 * @private
22899 */
22900 function Events() {}
22901
22902 //
22903 // We try to not inherit from `Object.prototype`. In some engines creating an
22904 // instance in this way is faster than calling `Object.create(null)` directly.
22905 // If `Object.create(null)` is not supported we prefix the event names with a
22906 // character to make sure that the built-in object properties are not
22907 // overridden or used as an attack vector.
22908 //
22909 if (Object.create) {
22910 Events.prototype = Object.create(null);
22911
22912 //
22913 // This hack is needed because the `__proto__` property is still inherited in
22914 // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
22915 //
22916 if (!new Events().__proto__) prefix = false;
22917 }
22918
22919 /**
22920 * Representation of a single event listener.
22921 *
22922 * @param {Function} fn The listener function.
22923 * @param {*} context The context to invoke the listener with.
22924 * @param {Boolean} [once=false] Specify if the listener is a one-time listener.
22925 * @constructor
22926 * @private
22927 */
22928 function EE(fn, context, once) {
22929 this.fn = fn;
22930 this.context = context;
22931 this.once = once || false;
22932 }
22933
22934 /**
22935 * Add a listener for a given event.
22936 *
22937 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
22938 * @param {(String|Symbol)} event The event name.
22939 * @param {Function} fn The listener function.
22940 * @param {*} context The context to invoke the listener with.
22941 * @param {Boolean} once Specify if the listener is a one-time listener.
22942 * @returns {EventEmitter}
22943 * @private
22944 */
22945 function addListener(emitter, event, fn, context, once) {
22946 if (typeof fn !== 'function') {
22947 throw new TypeError('The listener must be a function');
22948 }
22949
22950 var listener = new EE(fn, context || emitter, once)
22951 , evt = prefix ? prefix + event : event;
22952
22953 if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
22954 else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
22955 else emitter._events[evt] = [emitter._events[evt], listener];
22956
22957 return emitter;
22958 }
22959
22960 /**
22961 * Clear event by name.
22962 *
22963 * @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
22964 * @param {(String|Symbol)} evt The Event name.
22965 * @private
22966 */
22967 function clearEvent(emitter, evt) {
22968 if (--emitter._eventsCount === 0) emitter._events = new Events();
22969 else delete emitter._events[evt];
22970 }
22971
22972 /**
22973 * Minimal `EventEmitter` interface that is molded against the Node.js
22974 * `EventEmitter` interface.
22975 *
22976 * @constructor
22977 * @public
22978 */
22979 function EventEmitter() {
22980 this._events = new Events();
22981 this._eventsCount = 0;
22982 }
22983
22984 /**
22985 * Return an array listing the events for which the emitter has registered
22986 * listeners.
22987 *
22988 * @returns {Array}
22989 * @public
22990 */
22991 EventEmitter.prototype.eventNames = function eventNames() {
22992 var names = []
22993 , events
22994 , name;
22995
22996 if (this._eventsCount === 0) return names;
22997
22998 for (name in (events = this._events)) {
22999 if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
23000 }
23001
23002 if (Object.getOwnPropertySymbols) {
23003 return names.concat(Object.getOwnPropertySymbols(events));
23004 }
23005
23006 return names;
23007 };
23008
23009 /**
23010 * Return the listeners registered for a given event.
23011 *
23012 * @param {(String|Symbol)} event The event name.
23013 * @returns {Array} The registered listeners.
23014 * @public
23015 */
23016 EventEmitter.prototype.listeners = function listeners(event) {
23017 var evt = prefix ? prefix + event : event
23018 , handlers = this._events[evt];
23019
23020 if (!handlers) return [];
23021 if (handlers.fn) return [handlers.fn];
23022
23023 for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
23024 ee[i] = handlers[i].fn;
23025 }
23026
23027 return ee;
23028 };
23029
23030 /**
23031 * Return the number of listeners listening to a given event.
23032 *
23033 * @param {(String|Symbol)} event The event name.
23034 * @returns {Number} The number of listeners.
23035 * @public
23036 */
23037 EventEmitter.prototype.listenerCount = function listenerCount(event) {
23038 var evt = prefix ? prefix + event : event
23039 , listeners = this._events[evt];
23040
23041 if (!listeners) return 0;
23042 if (listeners.fn) return 1;
23043 return listeners.length;
23044 };
23045
23046 /**
23047 * Calls each of the listeners registered for a given event.
23048 *
23049 * @param {(String|Symbol)} event The event name.
23050 * @returns {Boolean} `true` if the event had listeners, else `false`.
23051 * @public
23052 */
23053 EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
23054 var evt = prefix ? prefix + event : event;
23055
23056 if (!this._events[evt]) return false;
23057
23058 var listeners = this._events[evt]
23059 , len = arguments.length
23060 , args
23061 , i;
23062
23063 if (listeners.fn) {
23064 if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
23065
23066 switch (len) {
23067 case 1: return listeners.fn.call(listeners.context), true;
23068 case 2: return listeners.fn.call(listeners.context, a1), true;
23069 case 3: return listeners.fn.call(listeners.context, a1, a2), true;
23070 case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
23071 case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
23072 case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
23073 }
23074
23075 for (i = 1, args = new Array(len -1); i < len; i++) {
23076 args[i - 1] = arguments[i];
23077 }
23078
23079 listeners.fn.apply(listeners.context, args);
23080 } else {
23081 var length = listeners.length
23082 , j;
23083
23084 for (i = 0; i < length; i++) {
23085 if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
23086
23087 switch (len) {
23088 case 1: listeners[i].fn.call(listeners[i].context); break;
23089 case 2: listeners[i].fn.call(listeners[i].context, a1); break;
23090 case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
23091 case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
23092 default:
23093 if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
23094 args[j - 1] = arguments[j];
23095 }
23096
23097 listeners[i].fn.apply(listeners[i].context, args);
23098 }
23099 }
23100 }
23101
23102 return true;
23103 };
23104
23105 /**
23106 * Add a listener for a given event.
23107 *
23108 * @param {(String|Symbol)} event The event name.
23109 * @param {Function} fn The listener function.
23110 * @param {*} [context=this] The context to invoke the listener with.
23111 * @returns {EventEmitter} `this`.
23112 * @public
23113 */
23114 EventEmitter.prototype.on = function on(event, fn, context) {
23115 return addListener(this, event, fn, context, false);
23116 };
23117
23118 /**
23119 * Add a one-time listener for a given event.
23120 *
23121 * @param {(String|Symbol)} event The event name.
23122 * @param {Function} fn The listener function.
23123 * @param {*} [context=this] The context to invoke the listener with.
23124 * @returns {EventEmitter} `this`.
23125 * @public
23126 */
23127 EventEmitter.prototype.once = function once(event, fn, context) {
23128 return addListener(this, event, fn, context, true);
23129 };
23130
23131 /**
23132 * Remove the listeners of a given event.
23133 *
23134 * @param {(String|Symbol)} event The event name.
23135 * @param {Function} fn Only remove the listeners that match this function.
23136 * @param {*} context Only remove the listeners that have this context.
23137 * @param {Boolean} once Only remove one-time listeners.
23138 * @returns {EventEmitter} `this`.
23139 * @public
23140 */
23141 EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
23142 var evt = prefix ? prefix + event : event;
23143
23144 if (!this._events[evt]) return this;
23145 if (!fn) {
23146 clearEvent(this, evt);
23147 return this;
23148 }
23149
23150 var listeners = this._events[evt];
23151
23152 if (listeners.fn) {
23153 if (
23154 listeners.fn === fn &&
23155 (!once || listeners.once) &&
23156 (!context || listeners.context === context)
23157 ) {
23158 clearEvent(this, evt);
23159 }
23160 } else {
23161 for (var i = 0, events = [], length = listeners.length; i < length; i++) {
23162 if (
23163 listeners[i].fn !== fn ||
23164 (once && !listeners[i].once) ||
23165 (context && listeners[i].context !== context)
23166 ) {
23167 events.push(listeners[i]);
23168 }
23169 }
23170
23171 //
23172 // Reset the array, or remove it completely if we have no more listeners.
23173 //
23174 if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
23175 else clearEvent(this, evt);
23176 }
23177
23178 return this;
23179 };
23180
23181 /**
23182 * Remove all listeners, or those of the specified event.
23183 *
23184 * @param {(String|Symbol)} [event] The event name.
23185 * @returns {EventEmitter} `this`.
23186 * @public
23187 */
23188 EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
23189 var evt;
23190
23191 if (event) {
23192 evt = prefix ? prefix + event : event;
23193 if (this._events[evt]) clearEvent(this, evt);
23194 } else {
23195 this._events = new Events();
23196 this._eventsCount = 0;
23197 }
23198
23199 return this;
23200 };
23201
23202 //
23203 // Alias methods names because people roll like that.
23204 //
23205 EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
23206 EventEmitter.prototype.addListener = EventEmitter.prototype.on;
23207
23208 //
23209 // Expose the prefix.
23210 //
23211 EventEmitter.prefixed = prefix;
23212
23213 //
23214 // Allow `EventEmitter` to be imported as module namespace.
23215 //
23216 EventEmitter.EventEmitter = EventEmitter;
23217
23218 //
23219 // Expose the module.
23220 //
23221 {
23222 module.exports = EventEmitter;
23223 }
23224 });
23225
23226 function applyStyle(shape, style) {
23227 if (!style) return;
23228 Object.keys(style).forEach(function (key) {
23229 // 特殊处理 clip 和 offset
23230 if (key === 'clip' || key === 'offset') {
23231 var effect = style[key];
23232 // value 为 ref
23233 if (isDisplayObject(effect === null || effect === void 0 ? void 0 : effect.current)) {
23234 shape.setAttribute("".concat(key, "Path"), effect.current);
23235 return;
23236 }
23237 var effectConfig = isFunction(effect) ? effect(style) : effect;
23238 if (effectConfig) {
23239 var type = effectConfig.type,
23240 style_1 = effectConfig.style;
23241 var effectShape = createShape(type, {
23242 style: style_1
23243 });
23244 shape.setAttribute("".concat(key, "Path"), effectShape);
23245 }
23246 } else {
23247 shape.setAttribute(key, style[key]);
23248 }
23249 });
23250 }
23251
23252 var Animator = /** @class */function (_super) {
23253 __extends(Animator, _super);
23254 function Animator(timeline) {
23255 var _this = _super.call(this) || this;
23256 _this.timeline = timeline;
23257 return _this;
23258 }
23259 Animator.prototype.animate = function (shape, start, end, effect) {
23260 this.shape = shape;
23261 this.start = start;
23262 this.end = end;
23263 this.effect = effect;
23264 };
23265 // 首次播放
23266 Animator.prototype.run = function () {
23267 var _a = this,
23268 vNode = _a.vNode,
23269 shape = _a.shape,
23270 start = _a.start,
23271 end = _a.end,
23272 effect = _a.effect,
23273 children = _a.children;
23274 var animations = [];
23275 if (effect) {
23276 var _b = effect.property,
23277 property = _b === void 0 ? [] : _b,
23278 easing = effect.easing,
23279 duration = effect.duration,
23280 delay = effect.delay,
23281 iterations = effect.iterations,
23282 clip = effect.clip,
23283 _c = effect.direction,
23284 direction = _c === void 0 ? 'normal' : _c,
23285 _d = effect.onFrame,
23286 onFrame = _d === void 0 ? function () {} : _d,
23287 _e = effect.onEnd,
23288 onEnd = _e === void 0 ? function () {} : _e;
23289 // shape 动画
23290 if (property.length && duration > 0) {
23291 // 应用样式
23292 var style = __assign(__assign({}, omit(start, property)), omit(end, property));
23293 applyStyle(shape, style);
23294 // 开始帧
23295 var keyframeStart = property.reduce(function (prev, cur) {
23296 prev[cur] = start[cur];
23297 return prev;
23298 }, {});
23299 // 结束帧
23300 var keyframeEnd = pick(end, property);
23301 var animation = shape.animate([keyframeStart, keyframeEnd], {
23302 fill: 'both',
23303 easing: easing,
23304 duration: duration,
23305 delay: delay,
23306 iterations: iterations,
23307 direction: direction
23308 });
23309 if (animation) {
23310 animation.onframe = onFrame;
23311 animation.onfinish = onEnd;
23312 // 过滤无限循环的动画
23313 if (iterations !== Infinity) {
23314 animations.push(animation);
23315 }
23316 } else {
23317 // 如果没有执行动画,直接应用结束样式
23318 applyStyle(shape, end);
23319 }
23320 } else {
23321 // 直接应用结束样式
23322 applyStyle(shape, end);
23323 }
23324 // clip 动画
23325 if (clip) {
23326 var clipConfig = isFunction(clip) ? clip(end) : clip;
23327 if (clipConfig) {
23328 var clipType = clipConfig.type,
23329 clipStyle = clipConfig.style,
23330 _f = clipConfig.property,
23331 clipProperty = _f === void 0 ? [] : _f,
23332 clipEasing = clipConfig.easing,
23333 clipDuration = clipConfig.duration,
23334 clipDelay = clipConfig.delay,
23335 clipIterations = clipConfig.iterations,
23336 clipStart = clipConfig.start,
23337 clipEnd = clipConfig.end,
23338 clipDirection = clipConfig.direction;
23339 if (clipProperty.length && (clipDuration || duration) > 0) {
23340 var clipStartStyle_1 = __assign(__assign({}, clipStyle), clipStart);
23341 var clipEndStyle = __assign(__assign({}, clipStyle), clipEnd);
23342 // 开始帧
23343 var clipKeyframeStart = clipProperty.reduce(function (prev, cur) {
23344 prev[cur] = clipStartStyle_1[cur];
23345 return prev;
23346 }, {});
23347 // 结束帧
23348 var clipKeyframeEnd = pick(clipEndStyle, clipProperty);
23349 var clipShape_1 = createShape(clipType, {
23350 style: clipStartStyle_1
23351 });
23352 shape.setAttribute('clipPath', clipShape_1);
23353 // g 中 clip 为全局,且如果要在 clip上加动画,需要手动加到canvas上
23354 shape.ownerDocument.documentElement.appendChild(clipShape_1);
23355 var clipAnimation = clipShape_1.animate([clipKeyframeStart, clipKeyframeEnd], {
23356 fill: 'both',
23357 easing: clipEasing || easing,
23358 duration: clipDuration || duration,
23359 delay: clipDelay || delay,
23360 iterations: clipIterations || iterations,
23361 direction: clipDirection || direction
23362 });
23363 // 过滤无限循环的动画
23364 if (clipAnimation) {
23365 var clipFinished = clipAnimation.finished;
23366 clipFinished.then(function () {
23367 // 删掉 clip
23368 shape.setAttribute('clipPath', null);
23369 clipShape_1.destroy();
23370 });
23371 if ((clipIterations || iterations) !== Infinity) {
23372 animations.push(clipAnimation);
23373 }
23374 } else {
23375 // 没有动画,直接删掉 clip
23376 shape.setAttribute('clipPath', null);
23377 clipShape_1.destroy();
23378 }
23379 }
23380 }
23381 }
23382 }
23383 if (children && children.length) {
23384 children.forEach(function (child) {
23385 if (!child) return;
23386 var childAnimator = child.run();
23387 if (childAnimator) {
23388 animations.push.apply(animations, childAnimator);
23389 }
23390 });
23391 }
23392 this.animations = animations;
23393 if (this.timeline) {
23394 this.timeline.push(animations);
23395 }
23396 // TODO:这段代码放这个位置感觉挺奇怪,看看是否有更合适的地方
23397 if (vNode) {
23398 var component = vNode.component;
23399 if (vNode && vNode.component) {
23400 // @ts-ignore
23401 component.animationWillPlay && component.animationWillPlay();
23402 }
23403 }
23404 this.endEmit(animations);
23405 return animations;
23406 };
23407 Animator.prototype.play = function () {
23408 var animations = this.animations;
23409 if (!animations || !animations.length) return;
23410 animations.forEach(function (d) {
23411 d.play();
23412 });
23413 };
23414 Animator.prototype.pause = function () {
23415 var animations = this.animations;
23416 if (!animations || !animations.length) return;
23417 animations.forEach(function (d) {
23418 d.pause();
23419 });
23420 };
23421 Animator.prototype.goTo = function (frame) {
23422 var animations = this.animations;
23423 if (!animations || !animations.length) return;
23424 animations.forEach(function (d) {
23425 d.currentTime = frame;
23426 });
23427 };
23428 Animator.prototype.finish = function () {
23429 var animations = this.animations;
23430 if (!animations || !animations.length) return;
23431 animations.forEach(function (d) {
23432 d.finish();
23433 });
23434 };
23435 Animator.prototype.endEmit = function (animations) {
23436 var _this = this;
23437 if (!animations.length) {
23438 this.emit('end');
23439 return null;
23440 }
23441 var finished = Promise.all(animations.map(function (d) {
23442 return d.finished;
23443 }));
23444 finished.then(function () {
23445 _this.emit('end');
23446 });
23447 };
23448 Animator.prototype.reset = function (shape) {
23449 this.shape = shape;
23450 this.start = null;
23451 this.end = null;
23452 this.effect = null;
23453 this.children = null;
23454 };
23455 return Animator;
23456 }(eventemitter3$1);
23457
23458 function findAllShapeNode(vNode) {
23459 var shapeNodes = [];
23460 Children.map(vNode, function (node) {
23461 if (!node) return;
23462 var tag = node.tag,
23463 type = node.type,
23464 children = node.children;
23465 if (tag === Shape$1 && type !== 'group') {
23466 shapeNodes.push(node);
23467 }
23468 if (children) {
23469 shapeNodes.push.apply(shapeNodes, findAllShapeNode(children));
23470 }
23471 });
23472 return shapeNodes;
23473 }
23474 function morphShape(lastNode, nextNode, animator) {
23475 var nextProps = nextNode.props,
23476 nextShape = nextNode.shape,
23477 nextStyle = nextNode.style,
23478 context = nextNode.context;
23479 var lastShape = lastNode.shape,
23480 lastStyle = lastNode.style,
23481 lastAnimation = lastNode.animator;
23482 // 形变动画之前先把原 shape 销毁
23483 lastShape.destroy();
23484 var animate = nextProps.animate,
23485 animation = nextProps.animation;
23486 var animationEffect = animation ? animation.update : null;
23487 if (animate === false || !animationEffect) {
23488 return animator;
23489 }
23490 animator = animator || new Animator(context.timeline);
23491 // shape 形变
23492 var start = animationEffect.start,
23493 end = animationEffect.end,
23494 _a = animationEffect.property,
23495 property = _a === void 0 ? [] : _a;
23496 var nextParsedStyle = nextShape.parsedStyle;
23497 var lastParsedStyle = lastShape.parsedStyle;
23498 var lastPath = convertToPath(lastShape);
23499 var nextPath = convertToPath(nextShape);
23500 var startStyle = __assign(__assign(__assign({}, lastStyle), start), {
23501 path: lastPath
23502 });
23503 var endStyle = __assign(__assign(__assign({}, nextStyle), end), {
23504 path: nextPath
23505 });
23506 var pathShape = createShape('path', {
23507 style: __assign(__assign({}, startStyle), {
23508 path: ''
23509 })
23510 });
23511 // 形变双方都有的属性才能动画
23512 var animateProperty = property.filter(function (key) {
23513 return nextParsedStyle.hasOwnProperty(key) && lastParsedStyle.hasOwnProperty(key);
23514 }).concat('path');
23515 animator.animate(pathShape, startStyle, endStyle, __assign(__assign({}, animationEffect), {
23516 property: animateProperty
23517 }));
23518 var timeline = (nextNode === null || nextNode === void 0 ? void 0 : nextNode.context).timeline;
23519 timeline && timeline.delete(lastAnimation);
23520 animator.once('end', function () {
23521 if (nextShape.destroyed) {
23522 return;
23523 }
23524 applyStyle(nextShape, endStyle);
23525 pathShape.replaceWith(nextShape);
23526 });
23527 return animator;
23528 }
23529 function appearAnimation(vNode) {
23530 return Children.map(vNode, function (node) {
23531 if (!node) return;
23532 var tag = node.tag,
23533 shape = node.shape,
23534 style = node.style,
23535 children = node.children,
23536 animate = node.animate,
23537 props = node.props,
23538 animator = node.animator;
23539 animator.reset(shape);
23540 // 有叶子节点,先执行叶子节点
23541 animator.children = children ? createAnimation(node, children, null) : null;
23542 // 不需要执行动画
23543 if (animate === false || tag !== Shape$1) {
23544 applyStyle(shape, style);
23545 return animator;
23546 }
23547 var animation = props.animation;
23548 var animationEffect = animation ? animation.appear : null;
23549 if (!animationEffect) {
23550 // 没有动画直接应用样式
23551 applyStyle(shape, style);
23552 return animator;
23553 }
23554 var _a = animationEffect.start,
23555 start = _a === void 0 ? {} : _a,
23556 end = animationEffect.end;
23557 var endStyle = __assign(__assign({}, style), end);
23558 animator.animate(shape, start, endStyle, animationEffect);
23559 return animator;
23560 });
23561 }
23562 function updateAnimation(nextNode, lastNode) {
23563 var nextTag = nextNode.tag,
23564 nextType = nextNode.type,
23565 nextStyle = nextNode.style,
23566 nextChildren = nextNode.children,
23567 nextProps = nextNode.props,
23568 nextShape = nextNode.shape,
23569 animator = nextNode.animator,
23570 animate = nextNode.animate;
23571 var lastTag = lastNode.tag,
23572 lastType = lastNode.type,
23573 lastStyle = lastNode.style,
23574 lastChildren = lastNode.children,
23575 lastShape = lastNode.shape;
23576 animator.reset(nextShape);
23577 // 先处理叶子节点
23578 animator.children = createAnimation(nextNode, nextChildren, lastChildren);
23579 var animation = nextProps.animation;
23580 var animationEffect = animation ? animation.update : null;
23581 // 类型相同
23582 if (nextType === lastType) {
23583 // 清除之前的样式
23584 var resetStyle = lastStyle ? Object.keys(lastStyle).reduce(function (prev, cur) {
23585 prev[cur] = '';
23586 return prev;
23587 }, {}) : null;
23588 // 需要更新的样式
23589 var style = __assign(__assign({}, resetStyle), nextStyle);
23590 // 组件,直接更新
23591 if (nextTag !== Shape$1) {
23592 applyStyle(nextShape, style);
23593 return animator;
23594 }
23595 // 样式无改变,无更新
23596 if (isEqual(nextStyle, lastStyle)) {
23597 return animator;
23598 }
23599 // 没有动画直接应用样式
23600 if (animate === false || !animationEffect) {
23601 applyStyle(nextShape, style);
23602 return animator;
23603 }
23604 var start = animationEffect.start,
23605 end = animationEffect.end;
23606 var startStyle = __assign(__assign({}, lastStyle), start);
23607 var endStyle = __assign(__assign({}, style), end);
23608 animator.animate(nextShape, startStyle, endStyle, animationEffect);
23609 return animator;
23610 }
23611 // 无法处理形变
23612 if (nextTag !== Shape$1 || lastTag !== Shape$1) {
23613 lastShape.destroy();
23614 return animator;
23615 }
23616 // 从 shape 到 group
23617 if (nextType === 'group') {
23618 var shapeNodes = findAllShapeNode(nextNode.children);
23619 return shapeNodes.map(function (node) {
23620 return morphShape(lastNode, node);
23621 });
23622 }
23623 // 从 group 到 shape
23624 if (lastType === 'group') {
23625 var shapeNodes = findAllShapeNode(lastNode.children);
23626 return shapeNodes.map(function (node) {
23627 return morphShape(node, nextNode);
23628 });
23629 }
23630 // 没有动画直接应用样式
23631 if (animate === false || !animationEffect) {
23632 applyStyle(nextShape, nextStyle);
23633 return animator;
23634 }
23635 return morphShape(lastNode, nextNode, animator);
23636 }
23637 function destroyAnimation(node) {
23638 return Children.map(node, function (vNode) {
23639 if (!vNode) return null;
23640 var tag = vNode.tag,
23641 shape = vNode.shape,
23642 children = vNode.children,
23643 animate = vNode.animate,
23644 style = vNode.style,
23645 props = vNode.props,
23646 animator = vNode.animator,
23647 context = vNode.context;
23648 var timeline = context.timeline;
23649 if (shape.destroyed) {
23650 return null;
23651 }
23652 // 重置
23653 animator.reset(shape);
23654 // 先处理叶子节点
23655 var childrenAnimation = children ? Children.toArray(children).map(function (child) {
23656 return destroyAnimation(child);
23657 }).filter(Boolean) : null;
23658 // 不需要动画直接删除
23659 if (animate === false) {
23660 shape.destroy();
23661 return animator;
23662 }
23663 var animation = props.animation;
23664 var animationEffect = animation ? animation.leave : null;
23665 // 没有叶子节点的动画, 直接删除
23666 if (!(childrenAnimation && childrenAnimation.length) && !animationEffect) {
23667 shape.destroy();
23668 return animator;
23669 }
23670 animator.children = childrenAnimation;
23671 // 图形有动画
23672 if (animationEffect && tag === Shape$1) {
23673 var start = animationEffect.start,
23674 _a = animationEffect.end,
23675 end = _a === void 0 ? {} : _a;
23676 var startStyle = __assign(__assign({}, style), start);
23677 var endStyle = end;
23678 animator.animate(shape, startStyle, endStyle, animationEffect);
23679 timeline && timeline.delete(animator.animations);
23680 }
23681 // 动画结束后,删除图形(包括子元素动画)
23682 animator.once('end', function () {
23683 shape.destroy();
23684 });
23685 return animator;
23686 });
23687 }
23688 function createAnimator(nextNode, lastNode) {
23689 if (!nextNode && !lastNode) {
23690 return null;
23691 }
23692 // delete 动画
23693 if (!nextNode && lastNode) {
23694 return destroyAnimation(lastNode);
23695 }
23696 // 如果有 transform 则从 transform 比
23697 var transform = nextNode.transform;
23698 if (transform) {
23699 var closestShapeNode = findClosestShapeNode(nextNode);
23700 nextNode.transform = null;
23701 closestShapeNode.transform = transform;
23702 }
23703 if (nextNode.transform) {
23704 if (!lastNode) {
23705 return updateAnimation(nextNode, nextNode.transform);
23706 }
23707 return [updateAnimation(nextNode, nextNode.transform), destroyAnimation(lastNode)];
23708 }
23709 // appear 动画
23710 if (nextNode && !lastNode) {
23711 return appearAnimation(nextNode);
23712 }
23713 // update 动画
23714 return updateAnimation(nextNode, lastNode);
23715 }
23716 function insertShape(parent, shape, nextSibling) {
23717 if (nextSibling) {
23718 parent.insertBefore(shape, nextSibling);
23719 } else {
23720 parent.appendChild(shape);
23721 }
23722 }
23723 // 处理 children 的动画
23724 function createAnimation(parent, nextChildren, lastChildren) {
23725 if (!nextChildren && !lastChildren) {
23726 return [];
23727 }
23728 var parentShape = parent.shape;
23729 // 上一个处理的元素
23730 var prevSibling;
23731 var childrenAnimator = [];
23732 Children.compare(nextChildren, lastChildren, function (nextNode, lastNode) {
23733 // shape 层才执行动画
23734 var animator = createAnimator(nextNode, lastNode);
23735 Children.map(animator, function (item) {
23736 if (!item) return;
23737 childrenAnimator.push(item);
23738 var shape = item.shape;
23739 if (!shape || shape.destroyed) return;
23740 var nextSibling;
23741 // 更新文档流
23742 if (!prevSibling) {
23743 nextSibling = parentShape.firstChild;
23744 } else {
23745 nextSibling = prevSibling.nextSibling;
23746 }
23747 if (nextSibling !== shape) {
23748 insertShape(parentShape, shape, nextSibling);
23749 }
23750 prevSibling = shape;
23751 });
23752 });
23753 return childrenAnimator;
23754 }
23755
23756 var rect = (function (layout) {
23757 var left = layout.left,
23758 top = layout.top,
23759 width = layout.width,
23760 height = layout.height;
23761 return {
23762 x: left,
23763 y: top,
23764 width: width,
23765 height: height
23766 };
23767 });
23768
23769 var line = (function (layout) {
23770 var left = layout.left,
23771 top = layout.top,
23772 width = layout.width,
23773 height = layout.height;
23774 return {
23775 x1: left,
23776 y1: top,
23777 x2: left + width,
23778 y2: top + height
23779 };
23780 });
23781
23782 var text = (function (layout) {
23783 var height = layout.height,
23784 left = layout.left,
23785 top = layout.top;
23786 return {
23787 x: left,
23788 y: top + height / 2,
23789 // 通过middle + top 才能比较好的实现文本对齐
23790 textBaseline: 'middle'
23791 };
23792 });
23793
23794 var circle = (function (layout) {
23795 var left = layout.left,
23796 top = layout.top,
23797 width = layout.width;
23798 var r = width / 2;
23799 return {
23800 cx: left + r,
23801 cy: top + r,
23802 r: r
23803 };
23804 });
23805
23806 var marker = (function (layout) {
23807 var left = layout.left,
23808 top = layout.top,
23809 width = layout.width;
23810 var r = width / 2;
23811 return {
23812 x: left + r,
23813 y: top,
23814 radius: r
23815 };
23816 });
23817
23818 var map$2 = {
23819 rect: rect,
23820 line: line,
23821 text: text,
23822 circle: circle,
23823 marker: marker,
23824 group: rect
23825 };
23826 var getShapeAttrs = (function (type, layout) {
23827 if (!layout) return null;
23828 var fn = map$2[type] || rect;
23829 return fn(layout);
23830 });
23831
23832 /* eslint-disable */
23833 // @ts-nocheck
23834 // from css-layout
23835 var CSS_UNDEFINED;
23836 var CSS_DIRECTION_INHERIT = 'inherit';
23837 var CSS_DIRECTION_LTR = 'ltr';
23838 var CSS_DIRECTION_RTL = 'rtl';
23839 var CSS_FLEX_DIRECTION_ROW = 'row';
23840 var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';
23841 var CSS_FLEX_DIRECTION_COLUMN = 'column';
23842 var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';
23843 var CSS_JUSTIFY_FLEX_START = 'flex-start';
23844 var CSS_JUSTIFY_CENTER = 'center';
23845 var CSS_JUSTIFY_FLEX_END = 'flex-end';
23846 var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';
23847 var CSS_JUSTIFY_SPACE_AROUND = 'space-around';
23848 var CSS_ALIGN_FLEX_START = 'flex-start';
23849 var CSS_ALIGN_CENTER = 'center';
23850 var CSS_ALIGN_FLEX_END = 'flex-end';
23851 var CSS_ALIGN_STRETCH = 'stretch';
23852 var CSS_POSITION_RELATIVE = 'relative';
23853 var CSS_POSITION_ABSOLUTE = 'absolute';
23854 var leading = {
23855 row: 'left',
23856 'row-reverse': 'right',
23857 column: 'top',
23858 'column-reverse': 'bottom'
23859 };
23860 var trailing = {
23861 row: 'right',
23862 'row-reverse': 'left',
23863 column: 'bottom',
23864 'column-reverse': 'top'
23865 };
23866 var pos = {
23867 row: 'left',
23868 'row-reverse': 'right',
23869 column: 'top',
23870 'column-reverse': 'bottom'
23871 };
23872 var dim = {
23873 row: 'width',
23874 'row-reverse': 'width',
23875 column: 'height',
23876 'column-reverse': 'height'
23877 };
23878 // When transpiled to Java / C the node type has layout, children and style
23879 // properties. For the JavaScript version this function adds these properties
23880 // if they don't already exist.
23881 function fillNodes(node) {
23882 if (!node.layout || node.isDirty) {
23883 node.layout = {
23884 width: undefined,
23885 height: undefined,
23886 top: 0,
23887 left: 0,
23888 right: 0,
23889 bottom: 0
23890 };
23891 }
23892 if (!node.style) {
23893 node.style = {};
23894 }
23895 if (!node.children) {
23896 node.children = [];
23897 }
23898 node.children.forEach(fillNodes);
23899 return node;
23900 }
23901 function isUndefined$1(value) {
23902 return value === undefined;
23903 }
23904 function isRowDirection(flexDirection) {
23905 return flexDirection === CSS_FLEX_DIRECTION_ROW || flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;
23906 }
23907 function isColumnDirection(flexDirection) {
23908 return flexDirection === CSS_FLEX_DIRECTION_COLUMN || flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;
23909 }
23910 function getLeadingMargin(node, axis) {
23911 if (node.style.marginStart !== undefined && isRowDirection(axis)) {
23912 return node.style.marginStart;
23913 }
23914 var value = null;
23915 switch (axis) {
23916 case 'row':
23917 value = node.style.marginLeft;
23918 break;
23919 case 'row-reverse':
23920 value = node.style.marginRight;
23921 break;
23922 case 'column':
23923 value = node.style.marginTop;
23924 break;
23925 case 'column-reverse':
23926 value = node.style.marginBottom;
23927 break;
23928 }
23929 if (value !== undefined) {
23930 return value;
23931 }
23932 if (node.style.margin !== undefined) {
23933 return node.style.margin;
23934 }
23935 return 0;
23936 }
23937 function getTrailingMargin(node, axis) {
23938 if (node.style.marginEnd !== undefined && isRowDirection(axis)) {
23939 return node.style.marginEnd;
23940 }
23941 var value = null;
23942 switch (axis) {
23943 case 'row':
23944 value = node.style.marginRight;
23945 break;
23946 case 'row-reverse':
23947 value = node.style.marginLeft;
23948 break;
23949 case 'column':
23950 value = node.style.marginBottom;
23951 break;
23952 case 'column-reverse':
23953 value = node.style.marginTop;
23954 break;
23955 }
23956 if (value != null) {
23957 return value;
23958 }
23959 if (node.style.margin !== undefined) {
23960 return node.style.margin;
23961 }
23962 return 0;
23963 }
23964 function getLeadingPadding(node, axis) {
23965 if (node.style.paddingStart !== undefined && node.style.paddingStart >= 0 && isRowDirection(axis)) {
23966 return node.style.paddingStart;
23967 }
23968 var value = null;
23969 switch (axis) {
23970 case 'row':
23971 value = node.style.paddingLeft;
23972 break;
23973 case 'row-reverse':
23974 value = node.style.paddingRight;
23975 break;
23976 case 'column':
23977 value = node.style.paddingTop;
23978 break;
23979 case 'column-reverse':
23980 value = node.style.paddingBottom;
23981 break;
23982 }
23983 if (value != null && value >= 0) {
23984 return value;
23985 }
23986 if (node.style.padding !== undefined && node.style.padding >= 0) {
23987 return node.style.padding;
23988 }
23989 return 0;
23990 }
23991 function getTrailingPadding(node, axis) {
23992 if (node.style.paddingEnd !== undefined && node.style.paddingEnd >= 0 && isRowDirection(axis)) {
23993 return node.style.paddingEnd;
23994 }
23995 var value = null;
23996 switch (axis) {
23997 case 'row':
23998 value = node.style.paddingRight;
23999 break;
24000 case 'row-reverse':
24001 value = node.style.paddingLeft;
24002 break;
24003 case 'column':
24004 value = node.style.paddingBottom;
24005 break;
24006 case 'column-reverse':
24007 value = node.style.paddingTop;
24008 break;
24009 }
24010 if (value != null && value >= 0) {
24011 return value;
24012 }
24013 if (node.style.padding !== undefined && node.style.padding >= 0) {
24014 return node.style.padding;
24015 }
24016 return 0;
24017 }
24018 function getLeadingBorder(node, axis) {
24019 if (node.style.borderStartWidth !== undefined && node.style.borderStartWidth >= 0 && isRowDirection(axis)) {
24020 return node.style.borderStartWidth;
24021 }
24022 var value = null;
24023 switch (axis) {
24024 case 'row':
24025 value = node.style.borderLeftWidth;
24026 break;
24027 case 'row-reverse':
24028 value = node.style.borderRightWidth;
24029 break;
24030 case 'column':
24031 value = node.style.borderTopWidth;
24032 break;
24033 case 'column-reverse':
24034 value = node.style.borderBottomWidth;
24035 break;
24036 }
24037 if (value != null && value >= 0) {
24038 return value;
24039 }
24040 if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {
24041 return node.style.borderWidth;
24042 }
24043 return 0;
24044 }
24045 function getTrailingBorder(node, axis) {
24046 if (node.style.borderEndWidth !== undefined && node.style.borderEndWidth >= 0 && isRowDirection(axis)) {
24047 return node.style.borderEndWidth;
24048 }
24049 var value = null;
24050 switch (axis) {
24051 case 'row':
24052 value = node.style.borderRightWidth;
24053 break;
24054 case 'row-reverse':
24055 value = node.style.borderLeftWidth;
24056 break;
24057 case 'column':
24058 value = node.style.borderBottomWidth;
24059 break;
24060 case 'column-reverse':
24061 value = node.style.borderTopWidth;
24062 break;
24063 }
24064 if (value != null && value >= 0) {
24065 return value;
24066 }
24067 if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {
24068 return node.style.borderWidth;
24069 }
24070 return 0;
24071 }
24072 function getLeadingPaddingAndBorder(node, axis) {
24073 return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
24074 }
24075 function getTrailingPaddingAndBorder(node, axis) {
24076 return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
24077 }
24078 function getBorderAxis(node, axis) {
24079 return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);
24080 }
24081 function getMarginAxis(node, axis) {
24082 return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
24083 }
24084 function getPaddingAndBorderAxis(node, axis) {
24085 return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
24086 }
24087 function getJustifyContent(node) {
24088 if (node.style.justifyContent) {
24089 return node.style.justifyContent;
24090 }
24091 return 'flex-start';
24092 }
24093 function getAlignContent(node) {
24094 if (node.style.alignContent) {
24095 return node.style.alignContent;
24096 }
24097 return 'flex-start';
24098 }
24099 function getAlignItem(node, child) {
24100 if (child.style.alignSelf) {
24101 return child.style.alignSelf;
24102 }
24103 if (node.style.alignItems) {
24104 return node.style.alignItems;
24105 }
24106 return 'stretch';
24107 }
24108 function resolveAxis(axis, direction) {
24109 if (direction === CSS_DIRECTION_RTL) {
24110 if (axis === CSS_FLEX_DIRECTION_ROW) {
24111 return CSS_FLEX_DIRECTION_ROW_REVERSE;
24112 } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {
24113 return CSS_FLEX_DIRECTION_ROW;
24114 }
24115 }
24116 return axis;
24117 }
24118 function resolveDirection(node, parentDirection) {
24119 var direction;
24120 if (node.style.direction) {
24121 direction = node.style.direction;
24122 } else {
24123 direction = CSS_DIRECTION_INHERIT;
24124 }
24125 if (direction === CSS_DIRECTION_INHERIT) {
24126 direction = parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection;
24127 }
24128 return direction;
24129 }
24130 function getFlexDirection(node) {
24131 if (node.style.flexDirection) {
24132 return node.style.flexDirection;
24133 }
24134 return CSS_FLEX_DIRECTION_COLUMN;
24135 }
24136 function getCrossFlexDirection(flexDirection, direction) {
24137 if (isColumnDirection(flexDirection)) {
24138 return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
24139 } else {
24140 return CSS_FLEX_DIRECTION_COLUMN;
24141 }
24142 }
24143 function getPositionType(node) {
24144 if (node.style.position) {
24145 return node.style.position;
24146 }
24147 return 'relative';
24148 }
24149 function isFlex(node) {
24150 return getPositionType(node) === CSS_POSITION_RELATIVE && node.style.flex > 0;
24151 }
24152 function isFlexWrap(node) {
24153 return node.style.flexWrap === 'wrap';
24154 }
24155 function getDimWithMargin(node, axis) {
24156 return node.layout[dim[axis]] + getMarginAxis(node, axis);
24157 }
24158 function isDimDefined(node, axis) {
24159 return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;
24160 }
24161 function isPosDefined(node, pos) {
24162 return node.style[pos] !== undefined;
24163 }
24164 function isMeasureDefined(node) {
24165 return node.style.measure !== undefined;
24166 }
24167 function getPosition(node, pos) {
24168 if (node.style[pos] !== undefined) {
24169 return node.style[pos];
24170 }
24171 return 0;
24172 }
24173 function boundAxis(node, axis, value) {
24174 var min = {
24175 row: node.style.minWidth,
24176 'row-reverse': node.style.minWidth,
24177 column: node.style.minHeight,
24178 'column-reverse': node.style.minHeight
24179 }[axis];
24180 var max = {
24181 row: node.style.maxWidth,
24182 'row-reverse': node.style.maxWidth,
24183 column: node.style.maxHeight,
24184 'column-reverse': node.style.maxHeight
24185 }[axis];
24186 var boundValue = value;
24187 if (max !== undefined && max >= 0 && boundValue > max) {
24188 boundValue = max;
24189 }
24190 if (min !== undefined && min >= 0 && boundValue < min) {
24191 boundValue = min;
24192 }
24193 return boundValue;
24194 }
24195 function fmaxf(a, b) {
24196 if (a > b) {
24197 return a;
24198 }
24199 return b;
24200 }
24201 // When the user specifically sets a value for width or height
24202 function setDimensionFromStyle(node, axis) {
24203 // The parent already computed us a width or height. We just skip it
24204 if (node.layout[dim[axis]] !== undefined) {
24205 return;
24206 }
24207 // We only run if there's a width or height defined
24208 if (!isDimDefined(node, axis)) {
24209 return;
24210 }
24211 // The dimensions can never be smaller than the padding and border
24212 node.layout[dim[axis]] = fmaxf(boundAxis(node, axis, node.style[dim[axis]]), getPaddingAndBorderAxis(node, axis));
24213 }
24214 function setTrailingPosition(node, child, axis) {
24215 child.layout[trailing[axis]] = node.layout[dim[axis]] - child.layout[dim[axis]] - child.layout[pos[axis]];
24216 }
24217 // If both left and right are defined, then use left. Otherwise return
24218 // +left or -right depending on which is defined.
24219 function getRelativePosition(node, axis) {
24220 if (node.style[leading[axis]] !== undefined) {
24221 return getPosition(node, leading[axis]);
24222 }
24223 return -getPosition(node, trailing[axis]);
24224 }
24225 function layoutNodeImpl(node, parentMaxWidth, /*css_direction_t*/parentDirection) {
24226 var /*css_direction_t*/direction = resolveDirection(node, parentDirection);
24227 var /*(c)!css_flex_direction_t*/ /*(java)!int*/mainAxis = resolveAxis(getFlexDirection(node), direction);
24228 var /*(c)!css_flex_direction_t*/ /*(java)!int*/crossAxis = getCrossFlexDirection(mainAxis, direction);
24229 var /*(c)!css_flex_direction_t*/ /*(java)!int*/resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
24230 // Handle width and height style attributes
24231 setDimensionFromStyle(node, mainAxis);
24232 setDimensionFromStyle(node, crossAxis);
24233 // Set the resolved resolution in the node's layout
24234 node.layout.direction = direction;
24235 // The position is set by the parent, but we need to complete it with a
24236 // delta composed of the margin and left/top/right/bottom
24237 node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) + getRelativePosition(node, mainAxis);
24238 node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) + getRelativePosition(node, mainAxis);
24239 node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) + getRelativePosition(node, crossAxis);
24240 node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) + getRelativePosition(node, crossAxis);
24241 // Inline immutable values from the target node to avoid excessive method
24242 // invocations during the layout calculation.
24243 var /*int*/childCount = node.children.length;
24244 var /*float*/paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);
24245 if (isMeasureDefined(node)) {
24246 var /*bool*/isResolvedRowDimDefined = !isUndefined$1(node.layout[dim[resolvedRowAxis]]);
24247 var /*float*/width = CSS_UNDEFINED;
24248 if (isDimDefined(node, resolvedRowAxis)) {
24249 width = node.style.width;
24250 } else if (isResolvedRowDimDefined) {
24251 width = node.layout[dim[resolvedRowAxis]];
24252 } else {
24253 width = parentMaxWidth - getMarginAxis(node, resolvedRowAxis);
24254 }
24255 width -= paddingAndBorderAxisResolvedRow;
24256 // We only need to give a dimension for the text if we haven't got any
24257 // for it computed yet. It can either be from the style attribute or because
24258 // the element is flexible.
24259 var /*bool*/isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;
24260 var /*bool*/isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && isUndefined$1(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);
24261 // Let's not measure the text if we already know both dimensions
24262 if (isRowUndefined || isColumnUndefined) {
24263 var /*css_dim_t*/measureDim = node.style.measure( /*(c)!node->context,*/
24264 /*(java)!layoutContext.measureOutput,*/
24265 width);
24266 if (isRowUndefined) {
24267 node.layout.width = measureDim.width + paddingAndBorderAxisResolvedRow;
24268 }
24269 if (isColumnUndefined) {
24270 node.layout.height = measureDim.height + getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
24271 }
24272 }
24273 if (childCount === 0) {
24274 return;
24275 }
24276 }
24277 var /*bool*/isNodeFlexWrap = isFlexWrap(node);
24278 var /*css_justify_t*/justifyContent = getJustifyContent(node);
24279 var /*float*/leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
24280 var /*float*/leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
24281 var /*float*/paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
24282 var /*float*/paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
24283 var /*bool*/isMainDimDefined = !isUndefined$1(node.layout[dim[mainAxis]]);
24284 var /*bool*/isCrossDimDefined = !isUndefined$1(node.layout[dim[crossAxis]]);
24285 var /*bool*/isMainRowDirection = isRowDirection(mainAxis);
24286 var /*int*/i;
24287 var /*int*/ii;
24288 var /*css_node_t**/child;
24289 var /*(c)!css_flex_direction_t*/ /*(java)!int*/axis;
24290 var /*css_node_t**/firstAbsoluteChild = null;
24291 var /*css_node_t**/currentAbsoluteChild = null;
24292 var /*float*/definedMainDim = CSS_UNDEFINED;
24293 if (isMainDimDefined) {
24294 definedMainDim = node.layout[dim[mainAxis]] - paddingAndBorderAxisMain;
24295 }
24296 // We want to execute the next two loops one per line with flex-wrap
24297 var /*int*/startLine = 0;
24298 var /*int*/endLine = 0;
24299 // var/*int*/ nextOffset = 0;
24300 var /*int*/alreadyComputedNextLayout = 0;
24301 // We aggregate the total dimensions of the container in those two variables
24302 var /*float*/linesCrossDim = 0;
24303 var /*float*/linesMainDim = 0;
24304 var /*int*/linesCount = 0;
24305 while (endLine < childCount) {
24306 // <Loop A> Layout non flexible children and count children by type
24307 // mainContentDim is accumulation of the dimensions and margin of all the
24308 // non flexible children. This will be used in order to either set the
24309 // dimensions of the node if none already exist, or to compute the
24310 // remaining space left for the flexible children.
24311 var /*float*/mainContentDim = 0;
24312 // There are three kind of children, non flexible, flexible and absolute.
24313 // We need to know how many there are in order to distribute the space.
24314 var /*int*/flexibleChildrenCount = 0;
24315 var /*float*/totalFlexible = 0;
24316 var /*int*/nonFlexibleChildrenCount = 0;
24317 // Use the line loop to position children in the main axis for as long
24318 // as they are using a simple stacking behaviour. Children that are
24319 // immediately stacked in the initial loop will not be touched again
24320 // in <Loop C>.
24321 var /*bool*/isSimpleStackMain = isMainDimDefined && justifyContent === CSS_JUSTIFY_FLEX_START || !isMainDimDefined && justifyContent !== CSS_JUSTIFY_CENTER;
24322 var /*int*/firstComplexMain = isSimpleStackMain ? childCount : startLine;
24323 // Use the initial line loop to position children in the cross axis for
24324 // as long as they are relatively positioned with alignment STRETCH or
24325 // FLEX_START. Children that are immediately stacked in the initial loop
24326 // will not be touched again in <Loop D>.
24327 var /*bool*/isSimpleStackCross = true;
24328 var /*int*/firstComplexCross = childCount;
24329 var /*css_node_t**/firstFlexChild = null;
24330 var /*css_node_t**/currentFlexChild = null;
24331 var /*float*/mainDim = leadingPaddingAndBorderMain;
24332 var /*float*/crossDim = 0;
24333 var /*float*/maxWidth;
24334 for (i = startLine; i < childCount; ++i) {
24335 child = node.children[i];
24336 child.lineIndex = linesCount;
24337 child.nextAbsoluteChild = null;
24338 child.nextFlexChild = null;
24339 var /*css_align_t*/alignItem = getAlignItem(node, child);
24340 // Pre-fill cross axis dimensions when the child is using stretch before
24341 // we call the recursive layout pass
24342 if (alignItem === CSS_ALIGN_STRETCH && getPositionType(child) === CSS_POSITION_RELATIVE && isCrossDimDefined && !isDimDefined(child, crossAxis)) {
24343 child.layout[dim[crossAxis]] = fmaxf(boundAxis(child, crossAxis, node.layout[dim[crossAxis]] - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
24344 // You never want to go smaller than padding
24345 getPaddingAndBorderAxis(child, crossAxis));
24346 } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {
24347 // Store a private linked list of absolutely positioned children
24348 // so that we can efficiently traverse them later.
24349 if (firstAbsoluteChild === null) {
24350 firstAbsoluteChild = child;
24351 }
24352 if (currentAbsoluteChild !== null) {
24353 currentAbsoluteChild.nextAbsoluteChild = child;
24354 }
24355 currentAbsoluteChild = child;
24356 // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
24357 // left and right or top and bottom).
24358 for (ii = 0; ii < 2; ii++) {
24359 axis = ii !== 0 ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
24360 if (!isUndefined$1(node.layout[dim[axis]]) && !isDimDefined(child, axis) && isPosDefined(child, leading[axis]) && isPosDefined(child, trailing[axis])) {
24361 child.layout[dim[axis]] = fmaxf(boundAxis(child, axis, node.layout[dim[axis]] - getPaddingAndBorderAxis(node, axis) - getMarginAxis(child, axis) - getPosition(child, leading[axis]) - getPosition(child, trailing[axis])),
24362 // You never want to go smaller than padding
24363 getPaddingAndBorderAxis(child, axis));
24364 }
24365 }
24366 }
24367 var /*float*/nextContentDim = 0;
24368 // It only makes sense to consider a child flexible if we have a computed
24369 // dimension for the node.
24370 if (isMainDimDefined && isFlex(child)) {
24371 flexibleChildrenCount++;
24372 totalFlexible += child.style.flex;
24373 // Store a private linked list of flexible children so that we can
24374 // efficiently traverse them later.
24375 if (firstFlexChild === null) {
24376 firstFlexChild = child;
24377 }
24378 if (currentFlexChild !== null) {
24379 currentFlexChild.nextFlexChild = child;
24380 }
24381 currentFlexChild = child;
24382 // Even if we don't know its exact size yet, we already know the padding,
24383 // border and margin. We'll use this partial information, which represents
24384 // the smallest possible size for the child, to compute the remaining
24385 // available space.
24386 nextContentDim = getPaddingAndBorderAxis(child, mainAxis) + getMarginAxis(child, mainAxis);
24387 } else {
24388 maxWidth = CSS_UNDEFINED;
24389 if (!isMainRowDirection) {
24390 if (isDimDefined(node, resolvedRowAxis)) {
24391 maxWidth = node.layout[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow;
24392 } else {
24393 maxWidth = parentMaxWidth - getMarginAxis(node, resolvedRowAxis) - paddingAndBorderAxisResolvedRow;
24394 }
24395 }
24396 // This is the main recursive call. We layout non flexible children.
24397 if (alreadyComputedNextLayout === 0) {
24398 layoutNode( /*(java)!layoutContext, */child, maxWidth, direction);
24399 }
24400 // Absolute positioned elements do not take part of the layout, so we
24401 // don't use them to compute mainContentDim
24402 if (getPositionType(child) === CSS_POSITION_RELATIVE) {
24403 nonFlexibleChildrenCount++;
24404 // At this point we know the final size and margin of the element.
24405 nextContentDim = getDimWithMargin(child, mainAxis);
24406 }
24407 }
24408 // The element we are about to add would make us go to the next line
24409 if (isNodeFlexWrap && isMainDimDefined && mainContentDim + nextContentDim > definedMainDim &&
24410 // If there's only one element, then it's bigger than the content
24411 // and needs its own line
24412 i !== startLine) {
24413 nonFlexibleChildrenCount--;
24414 alreadyComputedNextLayout = 1;
24415 break;
24416 }
24417 // Disable simple stacking in the main axis for the current line as
24418 // we found a non-trivial child. The remaining children will be laid out
24419 // in <Loop C>.
24420 if (isSimpleStackMain && (getPositionType(child) !== CSS_POSITION_RELATIVE || isFlex(child))) {
24421 isSimpleStackMain = false;
24422 firstComplexMain = i;
24423 }
24424 // Disable simple stacking in the cross axis for the current line as
24425 // we found a non-trivial child. The remaining children will be laid out
24426 // in <Loop D>.
24427 if (isSimpleStackCross && (getPositionType(child) !== CSS_POSITION_RELATIVE || alignItem !== CSS_ALIGN_STRETCH && alignItem !== CSS_ALIGN_FLEX_START || isUndefined$1(child.layout[dim[crossAxis]]))) {
24428 isSimpleStackCross = false;
24429 firstComplexCross = i;
24430 }
24431 if (isSimpleStackMain) {
24432 child.layout[pos[mainAxis]] += mainDim;
24433 if (isMainDimDefined) {
24434 setTrailingPosition(node, child, mainAxis);
24435 }
24436 mainDim += getDimWithMargin(child, mainAxis);
24437 crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
24438 }
24439 if (isSimpleStackCross) {
24440 child.layout[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;
24441 if (isCrossDimDefined) {
24442 setTrailingPosition(node, child, crossAxis);
24443 }
24444 }
24445 alreadyComputedNextLayout = 0;
24446 mainContentDim += nextContentDim;
24447 endLine = i + 1;
24448 }
24449 // <Loop B> Layout flexible children and allocate empty space
24450 // In order to position the elements in the main axis, we have two
24451 // controls. The space between the beginning and the first element
24452 // and the space between each two elements.
24453 var /*float*/leadingMainDim = 0;
24454 var /*float*/betweenMainDim = 0;
24455 // The remaining available space that needs to be allocated
24456 var /*float*/remainingMainDim = 0;
24457 if (isMainDimDefined) {
24458 remainingMainDim = definedMainDim - mainContentDim;
24459 } else {
24460 remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
24461 }
24462 // If there are flexible children in the mix, they are going to fill the
24463 // remaining space
24464 if (flexibleChildrenCount !== 0) {
24465 var /*float*/flexibleMainDim = remainingMainDim / totalFlexible;
24466 var /*float*/baseMainDim;
24467 var /*float*/boundMainDim;
24468 // If the flex share of remaining space doesn't meet min/max bounds,
24469 // remove this child from flex calculations.
24470 currentFlexChild = firstFlexChild;
24471 while (currentFlexChild !== null) {
24472 baseMainDim = flexibleMainDim * currentFlexChild.style.flex + getPaddingAndBorderAxis(currentFlexChild, mainAxis);
24473 boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);
24474 if (baseMainDim !== boundMainDim) {
24475 remainingMainDim -= boundMainDim;
24476 totalFlexible -= currentFlexChild.style.flex;
24477 }
24478 currentFlexChild = currentFlexChild.nextFlexChild;
24479 }
24480 flexibleMainDim = remainingMainDim / totalFlexible;
24481 // The non flexible children can overflow the container, in this case
24482 // we should just assume that there is no space available.
24483 if (flexibleMainDim < 0) {
24484 flexibleMainDim = 0;
24485 }
24486 currentFlexChild = firstFlexChild;
24487 while (currentFlexChild !== null) {
24488 // At this point we know the final size of the element in the main
24489 // dimension
24490 currentFlexChild.layout[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis, flexibleMainDim * currentFlexChild.style.flex + getPaddingAndBorderAxis(currentFlexChild, mainAxis));
24491 maxWidth = CSS_UNDEFINED;
24492 if (isDimDefined(node, resolvedRowAxis)) {
24493 maxWidth = node.layout[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow;
24494 } else if (!isMainRowDirection) {
24495 maxWidth = parentMaxWidth - getMarginAxis(node, resolvedRowAxis) - paddingAndBorderAxisResolvedRow;
24496 }
24497 // And we recursively call the layout algorithm for this child
24498 layoutNode( /*(java)!layoutContext, */currentFlexChild, maxWidth, direction);
24499 child = currentFlexChild;
24500 currentFlexChild = currentFlexChild.nextFlexChild;
24501 child.nextFlexChild = null;
24502 }
24503 // We use justifyContent to figure out how to allocate the remaining
24504 // space available
24505 } else if (justifyContent !== CSS_JUSTIFY_FLEX_START) {
24506 if (justifyContent === CSS_JUSTIFY_CENTER) {
24507 leadingMainDim = remainingMainDim / 2;
24508 } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {
24509 leadingMainDim = remainingMainDim;
24510 } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {
24511 remainingMainDim = fmaxf(remainingMainDim, 0);
24512 if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {
24513 betweenMainDim = remainingMainDim / (flexibleChildrenCount + nonFlexibleChildrenCount - 1);
24514 } else {
24515 betweenMainDim = 0;
24516 }
24517 } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {
24518 // Space on the edges is half of the space between elements
24519 betweenMainDim = remainingMainDim / (flexibleChildrenCount + nonFlexibleChildrenCount);
24520 leadingMainDim = betweenMainDim / 2;
24521 }
24522 }
24523 // <Loop C> Position elements in the main axis and compute dimensions
24524 // At this point, all the children have their dimensions set. We need to
24525 // find their position. In order to do that, we accumulate data in
24526 // variables that are also useful to compute the total dimensions of the
24527 // container!
24528 mainDim += leadingMainDim;
24529 for (i = firstComplexMain; i < endLine; ++i) {
24530 child = node.children[i];
24531 if (getPositionType(child) === CSS_POSITION_ABSOLUTE && isPosDefined(child, leading[mainAxis])) {
24532 // In case the child is position absolute and has left/top being
24533 // defined, we override the position to whatever the user said
24534 // (and margin/border).
24535 child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) + getLeadingBorder(node, mainAxis) + getLeadingMargin(child, mainAxis);
24536 } else {
24537 // If the child is position absolute (without top/left) or relative,
24538 // we put it at the current accumulated offset.
24539 child.layout[pos[mainAxis]] += mainDim;
24540 // Define the trailing position accordingly.
24541 if (isMainDimDefined) {
24542 setTrailingPosition(node, child, mainAxis);
24543 }
24544 // Now that we placed the element, we need to update the variables
24545 // We only need to do that for relative elements. Absolute elements
24546 // do not take part in that phase.
24547 if (getPositionType(child) === CSS_POSITION_RELATIVE) {
24548 // The main dimension is the sum of all the elements dimension plus
24549 // the spacing.
24550 mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
24551 // The cross dimension is the max of the elements dimension since there
24552 // can only be one element in that cross dimension.
24553 crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
24554 }
24555 }
24556 }
24557 var /*float*/containerCrossAxis = node.layout[dim[crossAxis]];
24558 if (!isCrossDimDefined) {
24559 containerCrossAxis = fmaxf(
24560 // For the cross dim, we add both sides at the end because the value
24561 // is aggregate via a max function. Intermediate negative values
24562 // can mess this computation otherwise
24563 boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross), paddingAndBorderAxisCross);
24564 }
24565 // <Loop D> Position elements in the cross axis
24566 for (i = firstComplexCross; i < endLine; ++i) {
24567 child = node.children[i];
24568 if (getPositionType(child) === CSS_POSITION_ABSOLUTE && isPosDefined(child, leading[crossAxis])) {
24569 // In case the child is absolutely positionned and has a
24570 // top/left/bottom/right being set, we override all the previously
24571 // computed positions to set it correctly.
24572 child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) + getLeadingBorder(node, crossAxis) + getLeadingMargin(child, crossAxis);
24573 } else {
24574 var /*float*/leadingCrossDim = leadingPaddingAndBorderCross;
24575 // For a relative children, we're either using alignItems (parent) or
24576 // alignSelf (child) in order to determine the position in the cross axis
24577 if (getPositionType(child) === CSS_POSITION_RELATIVE) {
24578 // This variable is intentionally re-defined as the code is transpiled to a block scope language
24579 var /*css_align_t*/alignItem = getAlignItem(node, child);
24580 if (alignItem === CSS_ALIGN_STRETCH) {
24581 // You can only stretch if the dimension has not already been set
24582 // previously.
24583 if (isUndefined$1(child.layout[dim[crossAxis]])) {
24584 child.layout[dim[crossAxis]] = fmaxf(boundAxis(child, crossAxis, containerCrossAxis - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
24585 // You never want to go smaller than padding
24586 getPaddingAndBorderAxis(child, crossAxis));
24587 }
24588 } else if (alignItem !== CSS_ALIGN_FLEX_START) {
24589 // The remaining space between the parent dimensions+padding and child
24590 // dimensions+margin.
24591 var /*float*/remainingCrossDim = containerCrossAxis - paddingAndBorderAxisCross - getDimWithMargin(child, crossAxis);
24592 if (alignItem === CSS_ALIGN_CENTER) {
24593 leadingCrossDim += remainingCrossDim / 2;
24594 } else {
24595 // CSS_ALIGN_FLEX_END
24596 leadingCrossDim += remainingCrossDim;
24597 }
24598 }
24599 }
24600 // And we apply the position
24601 child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
24602 // Define the trailing position accordingly.
24603 if (isCrossDimDefined) {
24604 setTrailingPosition(node, child, crossAxis);
24605 }
24606 }
24607 }
24608 linesCrossDim += crossDim;
24609 linesMainDim = fmaxf(linesMainDim, mainDim);
24610 linesCount += 1;
24611 startLine = endLine;
24612 }
24613 // <Loop E>
24614 //
24615 // Note(prenaux): More than one line, we need to layout the crossAxis
24616 // according to alignContent.
24617 //
24618 // Note that we could probably remove <Loop D> and handle the one line case
24619 // here too, but for the moment this is safer since it won't interfere with
24620 // previously working code.
24621 //
24622 // See specs:
24623 // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
24624 // section 9.4
24625 //
24626 if (linesCount > 1 && isCrossDimDefined) {
24627 var /*float*/nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] - paddingAndBorderAxisCross;
24628 var /*float*/remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
24629 var /*float*/crossDimLead = 0;
24630 var /*float*/currentLead = leadingPaddingAndBorderCross;
24631 var /*css_align_t*/alignContent = getAlignContent(node);
24632 if (alignContent === CSS_ALIGN_FLEX_END) {
24633 currentLead += remainingAlignContentDim;
24634 } else if (alignContent === CSS_ALIGN_CENTER) {
24635 currentLead += remainingAlignContentDim / 2;
24636 } else if (alignContent === CSS_ALIGN_STRETCH) {
24637 if (nodeCrossAxisInnerSize > linesCrossDim) {
24638 crossDimLead = remainingAlignContentDim / linesCount;
24639 }
24640 }
24641 var /*int*/endIndex = 0;
24642 for (i = 0; i < linesCount; ++i) {
24643 var /*int*/startIndex = endIndex;
24644 // compute the line's height and find the endIndex
24645 var /*float*/lineHeight = 0;
24646 for (ii = startIndex; ii < childCount; ++ii) {
24647 child = node.children[ii];
24648 if (getPositionType(child) !== CSS_POSITION_RELATIVE) {
24649 continue;
24650 }
24651 if (child.lineIndex !== i) {
24652 break;
24653 }
24654 if (!isUndefined$1(child.layout[dim[crossAxis]])) {
24655 lineHeight = fmaxf(lineHeight, child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis));
24656 }
24657 }
24658 endIndex = ii;
24659 lineHeight += crossDimLead;
24660 for (ii = startIndex; ii < endIndex; ++ii) {
24661 child = node.children[ii];
24662 if (getPositionType(child) !== CSS_POSITION_RELATIVE) {
24663 continue;
24664 }
24665 var /*css_align_t*/alignContentAlignItem = getAlignItem(node, child);
24666 if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {
24667 child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
24668 } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {
24669 child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]];
24670 } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {
24671 var /*float*/childHeight = child.layout[dim[crossAxis]];
24672 child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
24673 } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {
24674 child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
24675 // TODO(prenaux): Correctly set the height of items with undefined
24676 // (auto) crossAxis dimension.
24677 }
24678 }
24679
24680 currentLead += lineHeight;
24681 }
24682 }
24683 var /*bool*/needsMainTrailingPos = false;
24684 var /*bool*/needsCrossTrailingPos = false;
24685 // If the user didn't specify a width or height, and it has not been set
24686 // by the container, then we set it via the children.
24687 if (!isMainDimDefined) {
24688 node.layout[dim[mainAxis]] = fmaxf(
24689 // We're missing the last padding at this point to get the final
24690 // dimension
24691 boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),
24692 // We can never assign a width smaller than the padding and borders
24693 paddingAndBorderAxisMain);
24694 if (mainAxis === CSS_FLEX_DIRECTION_ROW_REVERSE || mainAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
24695 needsMainTrailingPos = true;
24696 }
24697 }
24698 if (!isCrossDimDefined) {
24699 node.layout[dim[crossAxis]] = fmaxf(
24700 // For the cross dim, we add both sides at the end because the value
24701 // is aggregate via a max function. Intermediate negative values
24702 // can mess this computation otherwise
24703 boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross), paddingAndBorderAxisCross);
24704 if (crossAxis === CSS_FLEX_DIRECTION_ROW_REVERSE || crossAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
24705 needsCrossTrailingPos = true;
24706 }
24707 }
24708 // <Loop F> Set trailing position if necessary
24709 if (needsMainTrailingPos || needsCrossTrailingPos) {
24710 for (i = 0; i < childCount; ++i) {
24711 child = node.children[i];
24712 if (needsMainTrailingPos) {
24713 setTrailingPosition(node, child, mainAxis);
24714 }
24715 if (needsCrossTrailingPos) {
24716 setTrailingPosition(node, child, crossAxis);
24717 }
24718 }
24719 }
24720 // <Loop G> Calculate dimensions for absolutely positioned elements
24721 currentAbsoluteChild = firstAbsoluteChild;
24722 while (currentAbsoluteChild !== null) {
24723 // Pre-fill dimensions when using absolute position and both offsets for
24724 // the axis are defined (either both left and right or top and bottom).
24725 for (ii = 0; ii < 2; ii++) {
24726 axis = ii !== 0 ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
24727 if (!isUndefined$1(node.layout[dim[axis]]) && !isDimDefined(currentAbsoluteChild, axis) && isPosDefined(currentAbsoluteChild, leading[axis]) && isPosDefined(currentAbsoluteChild, trailing[axis])) {
24728 currentAbsoluteChild.layout[dim[axis]] = fmaxf(boundAxis(currentAbsoluteChild, axis, node.layout[dim[axis]] - getBorderAxis(node, axis) - getMarginAxis(currentAbsoluteChild, axis) - getPosition(currentAbsoluteChild, leading[axis]) - getPosition(currentAbsoluteChild, trailing[axis])),
24729 // You never want to go smaller than padding
24730 getPaddingAndBorderAxis(currentAbsoluteChild, axis));
24731 }
24732 if (isPosDefined(currentAbsoluteChild, trailing[axis]) && !isPosDefined(currentAbsoluteChild, leading[axis])) {
24733 currentAbsoluteChild.layout[leading[axis]] = node.layout[dim[axis]] - currentAbsoluteChild.layout[dim[axis]] - getPosition(currentAbsoluteChild, trailing[axis]);
24734 }
24735 }
24736 child = currentAbsoluteChild;
24737 currentAbsoluteChild = currentAbsoluteChild.nextAbsoluteChild;
24738 child.nextAbsoluteChild = null;
24739 }
24740 }
24741 // 在外层做的margin补丁
24742 function saveMargin(node) {
24743 var style = node.style;
24744 var margin = {};
24745 ['marginTop', 'marginRight', 'marginBottom', 'marginLeft' // 只支持marginLeft
24746 ].forEach(function (key) {
24747 // 只处理百分号
24748 var value = style[key];
24749 if (value && /^-?\d+%$/.test(value)) {
24750 margin[key] = value;
24751 style[key] = 0;
24752 }
24753 });
24754 node.margin = margin;
24755 }
24756 function percent2Num(value) {
24757 var percent = Number(value.substr(0, value.length - 1));
24758 return percent / 100;
24759 }
24760 function layoutMargin(node) {
24761 var margin = node.margin,
24762 layout = node.layout;
24763 Object.keys(margin).forEach(function (key) {
24764 var percent = percent2Num(margin[key]);
24765 if ((key === 'marginLeft' || key === 'marginRight') && layout.width) {
24766 layout.left += layout.width * percent;
24767 } else if ((key === 'marginTop' || key === 'marginBottom') && layout.height) {
24768 layout.top += layout.height * percent;
24769 }
24770 });
24771 }
24772 function layoutNode(node, parentMaxWidth, parentDirection) {
24773 node.shouldUpdate = true;
24774 // hack
24775 saveMargin(node);
24776 var direction = node.style.direction || CSS_DIRECTION_LTR;
24777 var skipLayout = !node.isDirty && node.lastLayout && node.lastLayout.requestedHeight === node.layout.height && node.lastLayout.requestedWidth === node.layout.width && node.lastLayout.parentMaxWidth === parentMaxWidth && node.lastLayout.direction === direction;
24778 if (skipLayout) {
24779 node.layout.width = node.lastLayout.width;
24780 node.layout.height = node.lastLayout.height;
24781 node.layout.top = node.lastLayout.top;
24782 node.layout.left = node.lastLayout.left;
24783 } else {
24784 if (!node.lastLayout) {
24785 node.lastLayout = {};
24786 }
24787 node.lastLayout.requestedWidth = node.layout.width;
24788 node.lastLayout.requestedHeight = node.layout.height;
24789 node.lastLayout.parentMaxWidth = parentMaxWidth;
24790 node.lastLayout.direction = direction;
24791 // Reset child layouts
24792 node.children.forEach(function (child) {
24793 child.layout.width = undefined;
24794 child.layout.height = undefined;
24795 child.layout.top = 0;
24796 child.layout.left = 0;
24797 });
24798 layoutNodeImpl(node, parentMaxWidth, parentDirection);
24799 node.lastLayout.width = node.layout.width;
24800 node.lastLayout.height = node.layout.height;
24801 node.lastLayout.top = node.layout.top;
24802 node.lastLayout.left = node.layout.left;
24803 }
24804 // hack
24805 layoutMargin(node);
24806 }
24807 /* eslint-enable */
24808 function computeLayout(node) {
24809 if (!node) return node;
24810 fillNodes(node);
24811 layoutNode(node, null, null);
24812 return node;
24813 }
24814
24815 function createMeasure(style, measureText) {
24816 return function /* width */
24817 () {
24818 var text = style.text,
24819 width = style.width,
24820 height = style.height;
24821 var outputWidth = width;
24822 var outputHeight = height;
24823 if (!isNumber(width) || !isNumber(height)) {
24824 var _a = measureText(text, style),
24825 measureWidth = _a.width,
24826 measureHeight = _a.height;
24827 if (!isNumber(width)) {
24828 outputWidth = measureWidth;
24829 }
24830 if (!isNumber(height)) {
24831 outputHeight = measureHeight;
24832 }
24833 }
24834 return {
24835 width: outputWidth,
24836 height: outputHeight
24837 };
24838 };
24839 }
24840 function getChildrenLayout(nodeTree) {
24841 if (!nodeTree) return;
24842 var left = 0;
24843 var top = 0;
24844 var right = 0;
24845 var bottom = 0;
24846 var width = 0;
24847 var height = 0;
24848 nodeTree.forEach(function (node) {
24849 var layout = node.layout;
24850 if (!layout) return;
24851 left = Math.min(left, layout.left);
24852 top = Math.min(top, layout.top);
24853 right = Math.min(right, layout.left + layout.width);
24854 bottom = Math.min(bottom, layout.top + layout.height);
24855 width = Math.max(width, layout.width);
24856 height = Math.max(height, layout.height);
24857 });
24858 return {
24859 left: left,
24860 top: top,
24861 right: right,
24862 bottom: bottom,
24863 width: width,
24864 height: height
24865 };
24866 }
24867 var NodeTree = /** @class */function () {
24868 function NodeTree(node) {
24869 var className = node.className,
24870 children = node.children,
24871 layout = node.layout;
24872 var nodeChildren = children && children.length ? children.map(function (child) {
24873 return new NodeTree(child);
24874 }) : undefined;
24875 var nodeLayout = layout ? layout : getChildrenLayout(nodeChildren);
24876 this.children = nodeChildren;
24877 this.layout = nodeLayout;
24878 this.className = className;
24879 }
24880 NodeTree.prototype.getElementsByClassName = function (targetClassName) {
24881 var result = [];
24882 var _a = this,
24883 className = _a.className,
24884 children = _a.children;
24885 if (className === targetClassName) {
24886 result.push(this);
24887 }
24888 if (children) {
24889 children.forEach(function (child) {
24890 result.push.apply(result, child.getElementsByClassName(targetClassName));
24891 });
24892 }
24893 return result;
24894 };
24895 return NodeTree;
24896 }();
24897 // 展开数组
24898 function extendMap(arr, fn) {
24899 if (!arr) {
24900 return arr;
24901 }
24902 var newArray = [];
24903 if (!isArray(arr)) {
24904 var rst = fn(arr);
24905 if (!rst) {
24906 return newArray;
24907 }
24908 if (isArray(rst)) {
24909 newArray = newArray.concat(rst);
24910 } else {
24911 newArray.push(rst);
24912 }
24913 return newArray;
24914 }
24915 for (var i = 0; i < arr.length; i++) {
24916 var element = arr[i];
24917 if (isArray(element)) {
24918 newArray = newArray.concat(extendMap(element, fn));
24919 } else if (element) {
24920 var rst = fn(element);
24921 if (!rst) {
24922 continue;
24923 }
24924 if (isArray(rst)) {
24925 newArray = newArray.concat(rst);
24926 } else {
24927 newArray.push(rst);
24928 }
24929 }
24930 }
24931 return newArray;
24932 }
24933 // 主要是把function节点,全部转换成string标签节点
24934 function renderJSXElement(element, context, updater) {
24935 if (!element) return element;
24936 var px2hd = context.px2hd,
24937 measureText = context.measureText;
24938 var type = element.type,
24939 props = element.props;
24940 var tag = getWorkTag(type);
24941 // 只处理 function 组件
24942 if (tag === FunctionComponent) {
24943 // @ts-ignore
24944 var newElement = type(element.props, context, updater);
24945 // return element if type is string
24946 return renderJSXElement(newElement, context, updater);
24947 }
24948 var className = props.className,
24949 _a = props.style,
24950 customStyle = _a === void 0 ? {} : _a,
24951 attrs = props.attrs,
24952 newChildren = props.children;
24953 var style = px2hd(__assign(__assign({}, customStyle), attrs));
24954 // 文本需要计算文本的宽高来进行flex布局
24955 if (type === 'text') {
24956 style.measure = createMeasure(style, measureText);
24957 }
24958 // render children first
24959 var nextChildren = newChildren ? Children.toArray(newChildren).map(function (child) {
24960 return renderJSXElement(child, context, updater);
24961 }) : [];
24962 return {
24963 type: type,
24964 className: className,
24965 children: nextChildren.filter(Boolean),
24966 style: style
24967 };
24968 }
24969 // 计算布局
24970 function computeLayout$1(component, newChildren) {
24971 var context = component.context,
24972 updater = component.updater;
24973 var nodeTree = renderJSXElement(newChildren, context, updater);
24974 computeLayout(nodeTree);
24975 // 构造一个 NodeTree, 方便外部使用
24976 return new NodeTree(nodeTree);
24977 }
24978 function createChildNodeTree(parent, vNodeChildren) {
24979 var tag = parent.tag;
24980 var children = extendMap(vNodeChildren, function (child) {
24981 var childTag = child.tag,
24982 childStyle = child.style,
24983 childChildren = child.children;
24984 // 如果组件的根节点不是 flex, 则该组件不需要计算 flex 布局
24985 if (tag !== Shape$1 && childTag === Shape$1 && childStyle.display !== 'flex') {
24986 return null;
24987 }
24988 // 如果子组件不是 shape,则布局计算时,忽略当前节点
24989 if (childTag !== Shape$1) {
24990 return createChildNodeTree(child, childChildren);
24991 }
24992 return createNodeTree(child);
24993 });
24994 return children;
24995 }
24996 // 创建组件的布局树
24997 function createNodeTree(vNode) {
24998 var tag = vNode.tag,
24999 type = vNode.type,
25000 style = vNode.style,
25001 context = vNode.context,
25002 vNodeChildren = vNode.children;
25003 var measureText = context.measureText;
25004 var children = createChildNodeTree(vNode, vNodeChildren);
25005 // 文本需要计算文本的宽高来进行flex布局
25006 if (type === 'text') {
25007 style.measure = createMeasure(style, measureText);
25008 }
25009 return {
25010 tag: tag,
25011 type: type,
25012 style: style,
25013 children: children,
25014 // 保留对 vNode 的引用,用于把布局结果回填
25015 vNode: vNode
25016 };
25017 }
25018 function fillElementLayout(node) {
25019 var type = node.type,
25020 style = node.style,
25021 vNode = node.vNode,
25022 children = node.children,
25023 layout = node.layout;
25024 var attrs = getShapeAttrs(type, layout);
25025 if (style.measure) {
25026 delete style.measure;
25027 }
25028 // 更新布局和样式
25029 vNode.layout = layout;
25030 vNode.style = __assign(__assign({}, attrs), style);
25031 if (!children || !children.length) {
25032 return;
25033 }
25034 for (var i = 0, len = children.length; i < len; i++) {
25035 var child = children[i];
25036 fillElementLayout(child);
25037 }
25038 }
25039 function fillComponentLayout(vNode) {
25040 var layout = vNode.layout,
25041 vNodeChildren = vNode.children;
25042 Children.map(vNodeChildren, function (child) {
25043 if (!child) {
25044 return;
25045 }
25046 var childTag = child.tag,
25047 childLayout = child.layout,
25048 style = child.style;
25049 if (childTag !== Shape$1 && layout && !childLayout) {
25050 child.layout = layout;
25051 child.style = __assign({
25052 width: layout.width,
25053 height: layout.height
25054 }, style);
25055 }
25056 fillComponentLayout(child);
25057 });
25058 }
25059
25060 function pickElement(element) {
25061 if (!element) return element;
25062 return Children.map(element, function (item) {
25063 if (!item) return item;
25064 // 只需要这几个元素就可以了
25065 return pick(item, ['key', 'ref', 'type', 'props']);
25066 });
25067 }
25068 function getStyle$1(tagType, props, context) {
25069 var _a = props.style,
25070 customStyle = _a === void 0 ? {} : _a,
25071 attrs = props.attrs,
25072 zIndex = props.zIndex;
25073 if (tagType === Shape$1) {
25074 return context.px2hd(__assign(__assign({}, customStyle), attrs));
25075 }
25076 if (isNumber(zIndex)) {
25077 return {
25078 zIndex: zIndex
25079 };
25080 }
25081 return {};
25082 }
25083 // vnode 上的 context 做父子节点的 context 传递
25084 function readVNodeContext(vNodeType, parentContext) {
25085 // @ts-ignore
25086 var contextInjecter = vNodeType.contextInjecter;
25087 if (!contextInjecter) {
25088 return parentContext;
25089 }
25090 // copy parentContext
25091 return __assign({}, parentContext);
25092 }
25093 // component 上的 context 是实际使用的 context
25094 function readComponentContext(vNodeType, vNodeContext) {
25095 // @ts-ignore
25096 var contextType = vNodeType.contextType;
25097 if (!contextType) {
25098 return vNodeContext;
25099 }
25100 var _currentValue = contextType._currentValue;
25101 if (!_currentValue) {
25102 return vNodeContext;
25103 }
25104 return _currentValue;
25105 }
25106 function createVNode(parent, vNode) {
25107 var canvas = parent.canvas,
25108 parentContext = parent.context,
25109 updater = parent.updater,
25110 parentAnimate = parent.animate;
25111 var ref = vNode.ref,
25112 type = vNode.type,
25113 originProps = vNode.props;
25114 var animate = originProps.animate,
25115 transformFrom = originProps.transformFrom,
25116 props = __rest(originProps, ["animate", "transformFrom"]);
25117 var tag = getWorkTag(type);
25118 var context = readVNodeContext(type, parentContext);
25119 var animator = new Animator(context.timeline);
25120 var style = getStyle$1(tag, props, context);
25121 animator.vNode = vNode;
25122 vNode.parent = parent;
25123 vNode.tag = tag;
25124 vNode.style = style;
25125 vNode.context = context;
25126 vNode.updater = updater;
25127 vNode.canvas = canvas;
25128 vNode.animate = isBoolean(animate) ? animate : parentAnimate;
25129 vNode.animator = animator;
25130 // shape 标签
25131 if (tag === Shape$1) {
25132 var shape = createShape(type, __assign(__assign({}, props), {
25133 style: style
25134 }));
25135 if (ref) {
25136 ref.current = shape;
25137 }
25138 // @ts-ignore
25139 shape._vNode = vNode; // shape 保留 vNode 的引用
25140 vNode.shape = shape;
25141 } else {
25142 var componentContext_1 = readComponentContext(type, context);
25143 // 组件
25144 var component = void 0;
25145 if (tag === ClassComponent) {
25146 // @ts-ignore
25147 component = new type(props, componentContext_1, updater);
25148 } else {
25149 component = new Component(props, componentContext_1, updater);
25150 component.render = function () {
25151 // @ts-ignore
25152 return type(this.props, componentContext_1, updater);
25153 };
25154 }
25155 var group = new Group();
25156 component.container = group;
25157 // 设置ref
25158 if (ref) {
25159 ref.current = component;
25160 }
25161 component.context = componentContext_1;
25162 component.updater = updater;
25163 component.animator = animator;
25164 component._vNode = vNode;
25165 vNode.shape = group;
25166 vNode.component = component;
25167 }
25168 if (transformFrom && transformFrom.current) {
25169 var transformVNode = transformFrom.current._vNode;
25170 vNode.transform = findClosestShapeNode(transformVNode);
25171 if (vNode.transform) {
25172 vNode.transform.parent.children = null;
25173 }
25174 }
25175 return vNode;
25176 }
25177 function updateVNode(parent, nextNode, lastNode) {
25178 var canvas = parent.canvas,
25179 context = parent.context,
25180 updater = parent.updater,
25181 parentAnimate = parent.animate;
25182 var tag = lastNode.tag,
25183 animator = lastNode.animator,
25184 component = lastNode.component,
25185 shape = lastNode.shape,
25186 children = lastNode.children,
25187 lastProps = lastNode.props;
25188 var type = nextNode.type,
25189 props = nextNode.props;
25190 var animate = props.animate;
25191 animator.vNode = nextNode;
25192 nextNode.parent = parent;
25193 nextNode.tag = tag;
25194 nextNode.canvas = canvas;
25195 nextNode.context = readVNodeContext(type, context);
25196 nextNode.updater = updater;
25197 nextNode.component = component;
25198 nextNode.shape = updateShape(shape, props, lastProps);
25199 nextNode.parent = parent;
25200 nextNode.children = children;
25201 nextNode.animate = isBoolean(animate) ? animate : parentAnimate;
25202 nextNode.animator = animator;
25203 nextNode.style = getStyle$1(tag, props, context);
25204 // 更新 component
25205 if (component) {
25206 component._vNode = nextNode;
25207 } else {
25208 // 说明是 shape 标签
25209 // @ts-ignore
25210 shape._vNode = nextNode;
25211 }
25212 return nextNode;
25213 }
25214 function createElement(parent, element) {
25215 return Children.map(element, function (el) {
25216 if (!el) return el;
25217 return createVNode(parent, el);
25218 });
25219 }
25220 function destroyElement(vNode) {
25221 Children.map(vNode, function (node) {
25222 if (!node) return;
25223 var component = node.component,
25224 children = node.children;
25225 if (component) {
25226 component.willUnmount();
25227 destroyElement(children);
25228 component.didUnmount();
25229 component.destroy();
25230 } else {
25231 destroyElement(children);
25232 }
25233 });
25234 }
25235 function updateElement(parent, nextElement, lastElement) {
25236 var nextType = nextElement.type,
25237 nextProps = nextElement.props;
25238 var lastType = lastElement.type,
25239 lastProps = lastElement.props;
25240 if (nextType === lastType) {
25241 var nextVNode_1 = updateVNode(parent, nextElement, lastElement);
25242 // props 无变化 和 context 都无变化
25243 if (equal(nextProps, lastProps) && parent.context === lastElement.context) {
25244 return null;
25245 }
25246 return nextVNode_1;
25247 }
25248 var nextVNode = createVNode(parent, nextElement);
25249 destroyElement(lastElement);
25250 return nextVNode;
25251 }
25252 function diffElement(parent, nextElement, lastElement) {
25253 if (!nextElement && !lastElement) {
25254 return null;
25255 }
25256 // 删除
25257 if (!nextElement && lastElement) {
25258 destroyElement(lastElement);
25259 return null;
25260 }
25261 // 新建
25262 if (nextElement && !lastElement) {
25263 return createElement(parent, nextElement);
25264 }
25265 // 更新
25266 return updateElement(parent, nextElement, lastElement);
25267 }
25268 function renderComponentNodes(componentNodes) {
25269 if (!componentNodes || !componentNodes.length) {
25270 return;
25271 }
25272 // 1. shouldUpdate & willReceiveProps
25273 var shouldProcessChildren = componentNodes.filter(function (node) {
25274 var type = node.type,
25275 component = node.component,
25276 props = node.props,
25277 context = node.context,
25278 layout = node.layout;
25279 // 更新组件 layout
25280 component.layout = layout;
25281 // 新创建的 component
25282 if (!component.isMounted) return true;
25283 // 不需要更新
25284 if (component.shouldUpdate(props) === false) {
25285 return false;
25286 }
25287 var componentContext = readComponentContext(type, context);
25288 component.willReceiveProps(props, componentContext);
25289 component.props = props;
25290 component.context = context;
25291 return true;
25292 });
25293 if (!shouldProcessChildren.length) {
25294 return;
25295 }
25296 // 2. willMount / willUpdate
25297 shouldProcessChildren.forEach(function (child) {
25298 var component = child.component;
25299 if (!component.isMounted) {
25300 component.willMount();
25301 } else {
25302 component.willUpdate();
25303 }
25304 });
25305 // 3. render
25306 shouldProcessChildren.forEach(function (child) {
25307 var canvas = child.canvas,
25308 component = child.component,
25309 children = child.children;
25310 var newChildren = canvas.toRawChildren(component.render());
25311 renderChildren(child, newChildren, children);
25312 if (!component.isMounted) {
25313 component.didMount();
25314 component.isMounted = true;
25315 } else {
25316 component.didUpdate();
25317 }
25318 });
25319 }
25320 function renderVNode(vNode, nextChildren, lastChildren) {
25321 var component = vNode.component;
25322 // 不修改原始对象,这里重新 pick 一次,
25323 var newChildren = pickElement(nextChildren);
25324 // 设置新的 children
25325 vNode.children = newChildren;
25326 // 如果是组件,需要同时更新组件的 children
25327 // 等同于 vNode.tag === ClassComponent || vNode.tag === FunctionComponent
25328 if (component) {
25329 component.children = newChildren;
25330 }
25331 var componentNodeChildren = [];
25332 Children.compare(newChildren, lastChildren, function (next, last) {
25333 var element = diffElement(vNode, next, last);
25334 Children.map(element, function (child) {
25335 if (!child) return;
25336 var tag = child.tag,
25337 childProps = child.props,
25338 childLastChildren = child.children;
25339 var childrenNode = [];
25340 if (tag === Shape$1) {
25341 childrenNode = renderVNode(child, childProps.children, childLastChildren);
25342 } else {
25343 childrenNode = [child];
25344 }
25345 componentNodeChildren = componentNodeChildren.concat(childrenNode);
25346 });
25347 });
25348 return componentNodeChildren;
25349 }
25350 function renderChildren(parent, nextChildren, lastChildren) {
25351 // 返回的都是 classComponent 的节点
25352 var componentNodeChildren = renderVNode(parent, nextChildren, lastChildren);
25353 // 计算 flex 布局
25354 var nodeTree = createNodeTree(parent);
25355 computeLayout(nodeTree);
25356 fillElementLayout(nodeTree);
25357 fillComponentLayout(parent);
25358 var newChildren = parent.children;
25359 if (!componentNodeChildren.length) {
25360 return newChildren;
25361 }
25362 renderComponentNodes(componentNodeChildren);
25363 return newChildren;
25364 }
25365 function render(vNode) {
25366 var lastChildren = vNode.children,
25367 props = vNode.props;
25368 var nextChildren = props.children;
25369 // render 节点
25370 var children = renderChildren(vNode, nextChildren, lastChildren);
25371 // 创建动画
25372 var childrenAnimation = createAnimation(vNode, children, lastChildren);
25373 // 执行动画
25374 if (childrenAnimation.length) {
25375 childrenAnimation.forEach(function (animator) {
25376 animator.run();
25377 });
25378 }
25379 }
25380 // setState 触发的更新
25381 function updateComponents(components) {
25382 if (!components.length) return;
25383 components.forEach(function (component) {
25384 var vNode = component._vNode,
25385 lastChildren = component.children,
25386 props = component.props,
25387 animator = component.animator;
25388 // 是否需要更新
25389 if (component.shouldUpdate(props) === false) {
25390 return false;
25391 }
25392 component.willUpdate();
25393 var canvas = vNode.canvas,
25394 context = vNode.context;
25395 var newChildren = canvas.toRawChildren(component.render());
25396 var nextChildren = renderChildren(vNode, newChildren, lastChildren);
25397 // 更新 children
25398 component.children = nextChildren;
25399 vNode.children = nextChildren;
25400 // 创建动画
25401 var childrenAnimation = createAnimation(vNode, nextChildren, lastChildren);
25402 if (childrenAnimation.length) {
25403 animator.children = childrenAnimation;
25404 }
25405 // 执行动画
25406 animator.run();
25407 var timeline = context.timeline;
25408 if (timeline) {
25409 timeline.play.animationWillPlay();
25410 }
25411 component.didUpdate();
25412 });
25413 }
25414
25415 function generatePath$6(context, parsedStyle) {
25416 var r = parsedStyle.r;
25417 context.arc(r, r, r, 0, Math.PI * 2, false);
25418 }
25419
25420 function generatePath$5(context, parsedStyle) {
25421 var rxInPixels = parsedStyle.rx, ryInPixels = parsedStyle.ry;
25422 var rx = rxInPixels;
25423 var ry = ryInPixels;
25424 // @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse
25425 if (context.ellipse) {
25426 context.ellipse(rx, ry, rx, ry, 0, 0, Math.PI * 2, false);
25427 }
25428 else {
25429 // 如果不支持,则使用圆来绘制,进行变形
25430 var r = rx > ry ? rx : ry;
25431 var scaleX = rx > ry ? 1 : rx / ry;
25432 var scaleY = rx > ry ? ry / rx : 1;
25433 context.save();
25434 context.scale(scaleX, scaleY);
25435 context.arc(r, r, r, 0, Math.PI * 2);
25436 }
25437 }
25438
25439 function generatePath$4(context, parsedStyle) {
25440 var x1 = parsedStyle.x1, y1 = parsedStyle.y1, x2 = parsedStyle.x2, y2 = parsedStyle.y2, _a = parsedStyle.defX, defX = _a === void 0 ? 0 : _a, _b = parsedStyle.defY, defY = _b === void 0 ? 0 : _b, markerStart = parsedStyle.markerStart, markerEnd = parsedStyle.markerEnd, markerStartOffset = parsedStyle.markerStartOffset, markerEndOffset = parsedStyle.markerEndOffset;
25441 var startOffsetX = 0;
25442 var startOffsetY = 0;
25443 var endOffsetX = 0;
25444 var endOffsetY = 0;
25445 var rad = 0;
25446 var x;
25447 var y;
25448 if (markerStart && isDisplayObject(markerStart) && markerStartOffset) {
25449 x = x2 - x1;
25450 y = y2 - y1;
25451 rad = Math.atan2(y, x);
25452 startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
25453 startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
25454 }
25455 if (markerEnd && isDisplayObject(markerEnd) && markerEndOffset) {
25456 x = x1 - x2;
25457 y = y1 - y2;
25458 rad = Math.atan2(y, x);
25459 endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
25460 endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
25461 }
25462 context.moveTo(x1 - defX + startOffsetX, y1 - defY + startOffsetY);
25463 context.lineTo(x2 - defX + endOffsetX, y2 - defY + endOffsetY);
25464 }
25465
25466 function generatePath$3(context, parsedStyle) {
25467 var _a = parsedStyle.defX, defX = _a === void 0 ? 0 : _a, _b = parsedStyle.defY, defY = _b === void 0 ? 0 : _b, markerStart = parsedStyle.markerStart, markerEnd = parsedStyle.markerEnd, markerStartOffset = parsedStyle.markerStartOffset, markerEndOffset = parsedStyle.markerEndOffset;
25468 var _c = parsedStyle.path, absolutePath = _c.absolutePath, segments = _c.segments;
25469 var startOffsetX = 0;
25470 var startOffsetY = 0;
25471 var endOffsetX = 0;
25472 var endOffsetY = 0;
25473 var rad = 0;
25474 var x;
25475 var y;
25476 if (markerStart && isDisplayObject(markerStart) && markerStartOffset) {
25477 var _d = __read(markerStart.parentNode.getStartTangent(), 2), p1 = _d[0], p2 = _d[1];
25478 x = p1[0] - p2[0];
25479 y = p1[1] - p2[1];
25480 rad = Math.atan2(y, x);
25481 startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
25482 startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
25483 }
25484 if (markerEnd && isDisplayObject(markerEnd) && markerEndOffset) {
25485 var _e = __read(markerEnd.parentNode.getEndTangent(), 2), p1 = _e[0], p2 = _e[1];
25486 x = p1[0] - p2[0];
25487 y = p1[1] - p2[1];
25488 rad = Math.atan2(y, x);
25489 endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
25490 endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
25491 }
25492 for (var i = 0; i < absolutePath.length; i++) {
25493 var params = absolutePath[i];
25494 var command = params[0];
25495 var nextSegment = absolutePath[i + 1];
25496 var useStartOffset = i === 0 && (startOffsetX !== 0 || startOffsetY !== 0);
25497 var useEndOffset = (i === absolutePath.length - 1 ||
25498 (nextSegment && (nextSegment[0] === 'M' || nextSegment[0] === 'Z'))) &&
25499 endOffsetX !== 0 &&
25500 endOffsetY !== 0;
25501 switch (command) {
25502 case 'M':
25503 // Use start marker offset
25504 if (useStartOffset) {
25505 context.moveTo(params[1] - defX + startOffsetX, params[2] - defY + startOffsetY);
25506 context.lineTo(params[1] - defX, params[2] - defY);
25507 }
25508 else {
25509 context.moveTo(params[1] - defX, params[2] - defY);
25510 }
25511 break;
25512 case 'L':
25513 if (useEndOffset) {
25514 context.lineTo(params[1] - defX + endOffsetX, params[2] - defY + endOffsetY);
25515 }
25516 else {
25517 context.lineTo(params[1] - defX, params[2] - defY);
25518 }
25519 break;
25520 case 'Q':
25521 context.quadraticCurveTo(params[1] - defX, params[2] - defY, params[3] - defX, params[4] - defY);
25522 if (useEndOffset) {
25523 context.lineTo(params[3] - defX + endOffsetX, params[4] - defY + endOffsetY);
25524 }
25525 break;
25526 case 'C':
25527 context.bezierCurveTo(params[1] - defX, params[2] - defY, params[3] - defX, params[4] - defY, params[5] - defX, params[6] - defY);
25528 if (useEndOffset) {
25529 context.lineTo(params[5] - defX + endOffsetX, params[6] - defY + endOffsetY);
25530 }
25531 break;
25532 case 'A': {
25533 var arcParams = segments[i].arcParams;
25534 var cx = arcParams.cx, cy = arcParams.cy, rx = arcParams.rx, ry = arcParams.ry, startAngle = arcParams.startAngle, endAngle = arcParams.endAngle, xRotation = arcParams.xRotation, sweepFlag = arcParams.sweepFlag;
25535 // @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse
25536 if (context.ellipse) {
25537 context.ellipse(cx - defX, cy - defY, rx, ry, xRotation, startAngle, endAngle, !!(1 - sweepFlag));
25538 }
25539 else {
25540 // @see https://stackoverflow.com/a/47494351
25541 var r = rx > ry ? rx : ry;
25542 var scaleX = rx > ry ? 1 : rx / ry;
25543 var scaleY = rx > ry ? ry / rx : 1;
25544 context.translate(cx - defX, cy - defY);
25545 context.rotate(xRotation);
25546 context.scale(scaleX, scaleY);
25547 context.arc(0, 0, r, startAngle, endAngle, !!(1 - sweepFlag));
25548 context.scale(1 / scaleX, 1 / scaleY);
25549 context.rotate(-xRotation);
25550 context.translate(-(cx - defX), -(cy - defY));
25551 }
25552 if (useEndOffset) {
25553 context.lineTo(params[6] - defX + endOffsetX, params[7] - defY + endOffsetY);
25554 }
25555 break;
25556 }
25557 case 'Z':
25558 context.closePath();
25559 break;
25560 }
25561 }
25562 }
25563
25564 function generatePath$2(context, parsedStyle) {
25565 var _a = parsedStyle.defX, defX = _a === void 0 ? 0 : _a, _b = parsedStyle.defY, defY = _b === void 0 ? 0 : _b, markerStart = parsedStyle.markerStart, markerEnd = parsedStyle.markerEnd, markerStartOffset = parsedStyle.markerStartOffset, markerEndOffset = parsedStyle.markerEndOffset;
25566 var points = parsedStyle.points.points;
25567 var length = points.length;
25568 var x1 = points[0][0] - defX;
25569 var y1 = points[0][1] - defY;
25570 var x2 = points[length - 1][0] - defX;
25571 var y2 = points[length - 1][1] - defY;
25572 var startOffsetX = 0;
25573 var startOffsetY = 0;
25574 var endOffsetX = 0;
25575 var endOffsetY = 0;
25576 var rad = 0;
25577 var x;
25578 var y;
25579 if (markerStart && isDisplayObject(markerStart) && markerStartOffset) {
25580 x = points[1][0] - points[0][0];
25581 y = points[1][1] - points[0][1];
25582 rad = Math.atan2(y, x);
25583 startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
25584 startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
25585 }
25586 if (markerEnd && isDisplayObject(markerEnd) && markerEndOffset) {
25587 x = points[length - 1][0] - points[0][0];
25588 y = points[length - 1][1] - points[0][1];
25589 rad = Math.atan2(y, x);
25590 endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
25591 endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
25592 }
25593 context.moveTo(x1 + (startOffsetX || endOffsetX), y1 + (startOffsetY || endOffsetY));
25594 for (var i = 1; i < length - 1; i++) {
25595 var point = points[i];
25596 context.lineTo(point[0] - defX, point[1] - defY);
25597 }
25598 context.lineTo(x2, y2);
25599 }
25600
25601 function generatePath$1(context, parsedStyle) {
25602 var _a = parsedStyle.defX, defX = _a === void 0 ? 0 : _a, _b = parsedStyle.defY, defY = _b === void 0 ? 0 : _b, markerStart = parsedStyle.markerStart, markerEnd = parsedStyle.markerEnd, markerStartOffset = parsedStyle.markerStartOffset, markerEndOffset = parsedStyle.markerEndOffset;
25603 var points = parsedStyle.points.points;
25604 var length = points.length;
25605 var x1 = points[0][0] - defX;
25606 var y1 = points[0][1] - defY;
25607 var x2 = points[length - 1][0] - defX;
25608 var y2 = points[length - 1][1] - defY;
25609 var startOffsetX = 0;
25610 var startOffsetY = 0;
25611 var endOffsetX = 0;
25612 var endOffsetY = 0;
25613 var rad = 0;
25614 var x;
25615 var y;
25616 if (markerStart && isDisplayObject(markerStart) && markerStartOffset) {
25617 x = points[1][0] - points[0][0];
25618 y = points[1][1] - points[0][1];
25619 rad = Math.atan2(y, x);
25620 startOffsetX = Math.cos(rad) * (markerStartOffset || 0);
25621 startOffsetY = Math.sin(rad) * (markerStartOffset || 0);
25622 }
25623 if (markerEnd && isDisplayObject(markerEnd) && markerEndOffset) {
25624 x = points[length - 2][0] - points[length - 1][0];
25625 y = points[length - 2][1] - points[length - 1][1];
25626 rad = Math.atan2(y, x);
25627 endOffsetX = Math.cos(rad) * (markerEndOffset || 0);
25628 endOffsetY = Math.sin(rad) * (markerEndOffset || 0);
25629 }
25630 context.moveTo(x1 + startOffsetX, y1 + startOffsetY);
25631 for (var i = 1; i < length - 1; i++) {
25632 var point = points[i];
25633 context.lineTo(point[0] - defX, point[1] - defY);
25634 }
25635 context.lineTo(x2 + endOffsetX, y2 + endOffsetY);
25636 }
25637
25638 function generatePath(context, parsedStyle) {
25639 var radius = parsedStyle.radius, width = parsedStyle.width, height = parsedStyle.height;
25640 var w = width;
25641 var h = height;
25642 var hasRadius = radius && radius.some(function (r) { return r !== 0; });
25643 if (!hasRadius) {
25644 // Canvas support negative width/height of rect
25645 context.rect(0, 0, w, h);
25646 }
25647 else {
25648 var signX = width > 0 ? 1 : -1;
25649 var signY = height > 0 ? 1 : -1;
25650 var sweepFlag = signX + signY === 0;
25651 var _a = __read(radius.map(function (r) {
25652 return clamp(r, 0, Math.min(Math.abs(w) / 2, Math.abs(h) / 2));
25653 }), 4), tlr = _a[0], trr = _a[1], brr = _a[2], blr = _a[3];
25654 context.moveTo(signX * tlr, 0);
25655 context.lineTo(w - signX * trr, 0);
25656 if (trr !== 0) {
25657 context.arc(w - signX * trr, signY * trr, trr, (-signY * Math.PI) / 2, signX > 0 ? 0 : Math.PI, sweepFlag);
25658 }
25659 context.lineTo(w, h - signY * brr);
25660 if (brr !== 0) {
25661 context.arc(w - signX * brr, h - signY * brr, brr, signX > 0 ? 0 : Math.PI, signY > 0 ? Math.PI / 2 : 1.5 * Math.PI, sweepFlag);
25662 }
25663 context.lineTo(signX * blr, h);
25664 if (blr !== 0) {
25665 context.arc(signX * blr, h - signY * blr, blr, signY > 0 ? Math.PI / 2 : -Math.PI / 2, signX > 0 ? Math.PI : 0, sweepFlag);
25666 }
25667 context.lineTo(0, signY * tlr);
25668 if (tlr !== 0) {
25669 context.arc(signX * tlr, signY * tlr, tlr, signX > 0 ? Math.PI : 0, signY > 0 ? Math.PI * 1.5 : Math.PI / 2, sweepFlag);
25670 }
25671 }
25672 }
25673
25674 var Plugin = /** @class */ (function (_super) {
25675 __extends(Plugin, _super);
25676 function Plugin() {
25677 var _this = _super !== null && _super.apply(this, arguments) || this;
25678 _this.name = 'canvas-path-generator';
25679 return _this;
25680 }
25681 Plugin.prototype.init = function () {
25682 var _a;
25683 var pathGeneratorFactory = (_a = {},
25684 _a[Shape.CIRCLE] = generatePath$6,
25685 _a[Shape.ELLIPSE] = generatePath$5,
25686 _a[Shape.RECT] = generatePath,
25687 _a[Shape.LINE] = generatePath$4,
25688 _a[Shape.POLYLINE] = generatePath$1,
25689 _a[Shape.POLYGON] = generatePath$2,
25690 _a[Shape.PATH] = generatePath$3,
25691 _a[Shape.TEXT] = undefined,
25692 _a[Shape.GROUP] = undefined,
25693 _a[Shape.IMAGE] = undefined,
25694 _a[Shape.HTML] = undefined,
25695 _a[Shape.MESH] = undefined,
25696 _a);
25697 // @ts-ignore
25698 this.context.pathGeneratorFactory = pathGeneratorFactory;
25699 };
25700 Plugin.prototype.destroy = function () {
25701 // @ts-ignore
25702 delete this.context.pathGeneratorFactory;
25703 };
25704 return Plugin;
25705 }(AbstractRendererPlugin));
25706
25707 var tmpVec3a = create$2();
25708 var tmpVec3b = create$2();
25709 var tmpVec3c = create$2();
25710 var tmpMat4$1 = create$1();
25711 /**
25712 * pick shape(s) with Mouse/Touch event
25713 *
25714 * 1. find AABB with r-tree
25715 * 2. do math calculation with geometry in an accurate way
25716 */
25717 var CanvasPickerPlugin = /** @class */ (function () {
25718 function CanvasPickerPlugin() {
25719 var _this = this;
25720 this.isHit = function (displayObject, position, worldTransform, isClipPath) {
25721 // use picker for current shape's type
25722 var pick = _this.context.pointInPathPickerFactory[displayObject.nodeName];
25723 if (pick) {
25724 // invert with world matrix
25725 var invertWorldMat = invert(tmpMat4$1, worldTransform);
25726 // transform client position to local space, do picking in local space
25727 var localPosition = transformMat4(tmpVec3b, set$1(tmpVec3c, position[0], position[1], 0), invertWorldMat);
25728 // account for anchor
25729 var halfExtents = displayObject.getGeometryBounds().halfExtents;
25730 var anchor = displayObject.parsedStyle.anchor;
25731 localPosition[0] += ((anchor && anchor[0]) || 0) * halfExtents[0] * 2;
25732 localPosition[1] += ((anchor && anchor[1]) || 0) * halfExtents[1] * 2;
25733 if (pick(displayObject, new Point(localPosition[0], localPosition[1]), isClipPath, _this.isPointInPath, _this.context, _this.runtime)) {
25734 return true;
25735 }
25736 }
25737 return false;
25738 };
25739 /**
25740 * use native picking method
25741 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/isPointInPath
25742 */
25743 this.isPointInPath = function (displayObject, position) {
25744 var context = _this.runtime.offscreenCanvasCreator.getOrCreateContext(_this.context.config.offscreenCanvas);
25745 var generatePath = _this.context.pathGeneratorFactory[displayObject.nodeName];
25746 if (generatePath) {
25747 context.beginPath();
25748 generatePath(context, displayObject.parsedStyle);
25749 context.closePath();
25750 }
25751 return context.isPointInPath(position.x, position.y);
25752 };
25753 }
25754 CanvasPickerPlugin.prototype.apply = function (context, runtime) {
25755 var _this = this;
25756 var _a;
25757 var renderingService = context.renderingService, renderingContext = context.renderingContext;
25758 this.context = context;
25759 this.runtime = runtime;
25760 var document = (_a = renderingContext.root) === null || _a === void 0 ? void 0 : _a.ownerDocument;
25761 renderingService.hooks.pick.tapPromise(CanvasPickerPlugin.tag, function (result) { return __awaiter(_this, void 0, void 0, function () {
25762 return __generator(this, function (_a) {
25763 return [2 /*return*/, this.pick(document, result)];
25764 });
25765 }); });
25766 renderingService.hooks.pickSync.tap(CanvasPickerPlugin.tag, function (result) {
25767 return _this.pick(document, result);
25768 });
25769 };
25770 CanvasPickerPlugin.prototype.pick = function (document, result) {
25771 var e_1, _a;
25772 var topmost = result.topmost, _b = result.position, x = _b.x, y = _b.y;
25773 // position in world space
25774 var position = set$1(tmpVec3a, x, y, 0);
25775 // query by AABB first with spatial index(r-tree)
25776 var hitTestList = document.elementsFromBBox(position[0], position[1], position[0], position[1]);
25777 // test with clip path & origin shape
25778 // @see https://github.com/antvis/g/issues/1064
25779 var pickedDisplayObjects = [];
25780 try {
25781 for (var hitTestList_1 = __values(hitTestList), hitTestList_1_1 = hitTestList_1.next(); !hitTestList_1_1.done; hitTestList_1_1 = hitTestList_1.next()) {
25782 var displayObject = hitTestList_1_1.value;
25783 var worldTransform = displayObject.getWorldTransform();
25784 var isHitOriginShape = this.isHit(displayObject, position, worldTransform, false);
25785 if (isHitOriginShape) {
25786 // should look up in the ancestor node
25787 var clipped = findClosestClipPathTarget(displayObject);
25788 if (clipped) {
25789 var clipPath = clipped.parsedStyle.clipPath;
25790 var isHitClipPath = this.isHit(clipPath, position, clipPath.getWorldTransform(), true);
25791 if (isHitClipPath) {
25792 if (topmost) {
25793 result.picked = [displayObject];
25794 return result;
25795 }
25796 else {
25797 pickedDisplayObjects.push(displayObject);
25798 }
25799 }
25800 }
25801 else {
25802 if (topmost) {
25803 result.picked = [displayObject];
25804 return result;
25805 }
25806 else {
25807 pickedDisplayObjects.push(displayObject);
25808 }
25809 }
25810 }
25811 }
25812 }
25813 catch (e_1_1) { e_1 = { error: e_1_1 }; }
25814 finally {
25815 try {
25816 if (hitTestList_1_1 && !hitTestList_1_1.done && (_a = hitTestList_1.return)) _a.call(hitTestList_1);
25817 }
25818 finally { if (e_1) throw e_1.error; }
25819 }
25820 result.picked = pickedDisplayObjects;
25821 return result;
25822 };
25823 CanvasPickerPlugin.tag = 'CanvasPicker';
25824 return CanvasPickerPlugin;
25825 }());
25826
25827 function isPointInPath$7(displayObject, position, isClipPath) {
25828 var _a = displayObject.parsedStyle, r = _a.r, fill = _a.fill, stroke = _a.stroke, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, pointerEvents = _a.pointerEvents;
25829 var halfLineWidth = ((lineWidth || 0) + (increasedLineWidthForHitTesting || 0)) / 2;
25830 var absDistance = distance$1(r, r, position.x, position.y);
25831 var _b = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasFill = _b[0], hasStroke = _b[1];
25832 if ((hasFill && hasStroke) || isClipPath) {
25833 return absDistance <= r + halfLineWidth;
25834 }
25835 if (hasFill) {
25836 return absDistance <= r;
25837 }
25838 if (hasStroke) {
25839 return absDistance >= r - halfLineWidth && absDistance <= r + halfLineWidth;
25840 }
25841 return false;
25842 }
25843
25844 function ellipseDistance(squareX, squareY, rx, ry) {
25845 return squareX / (rx * rx) + squareY / (ry * ry);
25846 }
25847 function isPointInPath$6(displayObject, position, isClipPath) {
25848 var _a = displayObject.parsedStyle, rx = _a.rx, ry = _a.ry, fill = _a.fill, stroke = _a.stroke, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, pointerEvents = _a.pointerEvents;
25849 var x = position.x, y = position.y;
25850 var _b = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasFill = _b[0], hasStroke = _b[1];
25851 var halfLineWith = ((lineWidth || 0) + (increasedLineWidthForHitTesting || 0)) / 2;
25852 var squareX = (x - rx) * (x - rx);
25853 var squareY = (y - ry) * (y - ry);
25854 // 使用椭圆的公式: x*x/rx*rx + y*y/ry*ry = 1;
25855 if ((hasFill && hasStroke) || isClipPath) {
25856 return (ellipseDistance(squareX, squareY, rx + halfLineWith, ry + halfLineWith) <=
25857 1);
25858 }
25859 if (hasFill) {
25860 return ellipseDistance(squareX, squareY, rx, ry) <= 1;
25861 }
25862 if (hasStroke) {
25863 return (ellipseDistance(squareX, squareY, rx - halfLineWith, ry - halfLineWith) >=
25864 1 &&
25865 ellipseDistance(squareX, squareY, rx + halfLineWith, ry + halfLineWith) <=
25866 1);
25867 }
25868 return false;
25869 }
25870
25871 function inBox(minX, minY, width, height, x, y) {
25872 return x >= minX && x <= minX + width && y >= minY && y <= minY + height;
25873 }
25874 function inRect(minX, minY, width, height, lineWidth, x, y) {
25875 var halfWidth = lineWidth / 2;
25876 // 将四个边看做矩形来检测,比边的检测算法要快
25877 return (inBox(minX - halfWidth, minY - halfWidth, width, lineWidth, x, y) || // 上边
25878 inBox(minX + width - halfWidth, minY - halfWidth, lineWidth, height, x, y) || // 右边
25879 inBox(minX + halfWidth, minY + height - halfWidth, width, lineWidth, x, y) || // 下边
25880 inBox(minX - halfWidth, minY + halfWidth, lineWidth, height, x, y)); // 左边
25881 }
25882 function inArc(cx, cy, r, startAngle, endAngle, lineWidth, x, y) {
25883 var angle = (Math.atan2(y - cy, x - cx) + Math.PI * 2) % (Math.PI * 2); // 转换到 0 - 2 * Math.PI 之间
25884 // if (angle < startAngle || angle > endAngle) {
25885 // return false;
25886 // }
25887 var point = {
25888 x: cx + r * Math.cos(angle),
25889 y: cy + r * Math.sin(angle),
25890 };
25891 return distance$1(point.x, point.y, x, y) <= lineWidth / 2;
25892 }
25893 function inLine(x1, y1, x2, y2, lineWidth, x, y) {
25894 var minX = Math.min(x1, x2);
25895 var maxX = Math.max(x1, x2);
25896 var minY = Math.min(y1, y2);
25897 var maxY = Math.max(y1, y2);
25898 var halfWidth = lineWidth / 2;
25899 // 因为目前的方案是计算点到直线的距离,而有可能会在延长线上,所以要先判断是否在包围盒内
25900 // 这种方案会在水平或者竖直的情况下载线的延长线上有半 lineWidth 的误差
25901 if (!(x >= minX - halfWidth &&
25902 x <= maxX + halfWidth &&
25903 y >= minY - halfWidth &&
25904 y <= maxY + halfWidth)) {
25905 return false;
25906 }
25907 // 因为已经计算了包围盒,所以仅需要计算到直线的距离即可,可以显著提升性能
25908 return pointToLine(x1, y1, x2, y2, x, y) <= lineWidth / 2;
25909 }
25910 function inPolyline(points, lineWidth, x, y, isClose) {
25911 var count = points.length;
25912 if (count < 2) {
25913 return false;
25914 }
25915 for (var i = 0; i < count - 1; i++) {
25916 var x1 = points[i][0];
25917 var y1 = points[i][1];
25918 var x2 = points[i + 1][0];
25919 var y2 = points[i + 1][1];
25920 if (inLine(x1, y1, x2, y2, lineWidth, x, y)) {
25921 return true;
25922 }
25923 }
25924 // 如果封闭,则计算起始点和结束点的边
25925 if (isClose) {
25926 var first = points[0];
25927 var last = points[count - 1];
25928 if (inLine(first[0], first[1], last[0], last[1], lineWidth, x, y)) {
25929 return true;
25930 }
25931 }
25932 return false;
25933 }
25934 // 多边形的射线检测,参考:https://blog.csdn.net/WilliamSun0122/article/details/77994526
25935 var tolerance = 1e-6;
25936 // 三态函数,判断两个double在eps精度下的大小关系
25937 function dcmp(x) {
25938 if (Math.abs(x) < tolerance) {
25939 return 0;
25940 }
25941 return x < 0 ? -1 : 1;
25942 }
25943 // 判断点Q是否在p1和p2的线段上
25944 function onSegment(p1, p2, q) {
25945 if ((q[0] - p1[0]) * (p2[1] - p1[1]) === (p2[0] - p1[0]) * (q[1] - p1[1]) &&
25946 Math.min(p1[0], p2[0]) <= q[0] &&
25947 q[0] <= Math.max(p1[0], p2[0]) &&
25948 Math.min(p1[1], p2[1]) <= q[1] &&
25949 q[1] <= Math.max(p1[1], p2[1])) {
25950 return true;
25951 }
25952 return false;
25953 }
25954 // 判断点P在多边形内-射线法
25955 function inPolygon(points, x, y) {
25956 var isHit = false;
25957 var n = points.length;
25958 if (n <= 2) {
25959 // svg 中点小于 3 个时,不显示,也无法被拾取
25960 return false;
25961 }
25962 for (var i = 0; i < n; i++) {
25963 var p1 = points[i];
25964 var p2 = points[(i + 1) % n];
25965 if (onSegment(p1, p2, [x, y])) {
25966 // 点在多边形一条边上
25967 return true;
25968 }
25969 // 前一个判断min(p1[1],p2[1])<P.y<=max(p1[1],p2[1])
25970 // 后一个判断被测点 在 射线与边交点 的左边
25971 if (dcmp(p1[1] - y) > 0 !== dcmp(p2[1] - y) > 0 &&
25972 dcmp(x - ((y - p1[1]) * (p1[0] - p2[0])) / (p1[1] - p2[1]) - p1[0]) < 0) {
25973 isHit = !isHit;
25974 }
25975 }
25976 return isHit;
25977 }
25978 function inPolygons(polygons, x, y) {
25979 var isHit = false;
25980 for (var i = 0; i < polygons.length; i++) {
25981 var points = polygons[i];
25982 isHit = inPolygon(points, x, y);
25983 if (isHit) {
25984 break;
25985 }
25986 }
25987 return isHit;
25988 }
25989
25990 function isPointInPath$5(displayObject, position, isClipPath) {
25991 var _a = displayObject.parsedStyle, x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, _b = _a.defX, x = _b === void 0 ? 0 : _b, _c = _a.defY, y = _c === void 0 ? 0 : _c, pointerEvents = _a.pointerEvents, fill = _a.fill, stroke = _a.stroke;
25992 var _d = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasStroke = _d[1];
25993 if ((!hasStroke && !isClipPath) || !lineWidth) {
25994 return false;
25995 }
25996 return inLine(x1, y1, x2, y2, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y);
25997 }
25998
25999 // TODO: replace it with method in @antv/util
26000 function isPointInStroke(segments, lineWidth, px, py, length) {
26001 var isHit = false;
26002 var halfWidth = lineWidth / 2;
26003 for (var i = 0; i < segments.length; i++) {
26004 var segment = segments[i];
26005 var currentPoint = segment.currentPoint, params = segment.params, prePoint = segment.prePoint, box = segment.box;
26006 // 如果在前面已经生成过包围盒,直接按照包围盒计算
26007 if (box &&
26008 !inBox(box.x - halfWidth, box.y - halfWidth, box.width + lineWidth, box.height + lineWidth, px, py)) {
26009 continue;
26010 }
26011 switch (segment.command) {
26012 // L 和 Z 都是直线, M 不进行拾取
26013 case 'L':
26014 case 'Z':
26015 isHit = inLine(prePoint[0], prePoint[1], currentPoint[0], currentPoint[1], lineWidth, px, py);
26016 if (isHit) {
26017 return true;
26018 }
26019 break;
26020 case 'Q':
26021 var qDistance = pointDistance(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4], px, py);
26022 isHit = qDistance <= lineWidth / 2;
26023 if (isHit) {
26024 return true;
26025 }
26026 break;
26027 case 'C':
26028 var cDistance = pointDistance$3(prePoint[0], // 上一段结束位置, 即 C 的起始点
26029 prePoint[1], params[1], // 'C' 的参数,1、2 为第一个控制点,3、4 为第二个控制点,5、6 为结束点
26030 params[2], params[3], params[4], params[5], params[6], px, py, length);
26031 isHit = cDistance <= lineWidth / 2;
26032 if (isHit) {
26033 return true;
26034 }
26035 break;
26036 case 'A':
26037 // cache conversion result
26038 if (!segment.cubicParams) {
26039 segment.cubicParams = arcToCubic(prePoint[0], prePoint[1], params[1], params[2], params[3], params[4], params[5], params[6], params[7], undefined);
26040 }
26041 var args = segment.cubicParams;
26042 // fixArc
26043 var prePointInCubic = prePoint;
26044 for (var i_1 = 0; i_1 < args.length; i_1 += 6) {
26045 var cDistance_1 = pointDistance$3(prePointInCubic[0], // 上一段结束位置, 即 C 的起始点
26046 prePointInCubic[1], args[i_1], args[i_1 + 1], args[i_1 + 2], args[i_1 + 3], args[i_1 + 4], args[i_1 + 5], px, py, length);
26047 prePointInCubic = [args[i_1 + 4], args[i_1 + 5]];
26048 isHit = cDistance_1 <= lineWidth / 2;
26049 if (isHit) {
26050 return true;
26051 }
26052 }
26053 break;
26054 }
26055 }
26056 return isHit;
26057 }
26058 function isPointInPath$4(displayObject, position, isClipPath, isPointInPath, renderingPluginContext, runtime) {
26059 var _a = displayObject.parsedStyle, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, stroke = _a.stroke, fill = _a.fill, _b = _a.defX, x = _b === void 0 ? 0 : _b, _c = _a.defY, y = _c === void 0 ? 0 : _c, path = _a.path, pointerEvents = _a.pointerEvents;
26060 var segments = path.segments, hasArc = path.hasArc, polylines = path.polylines, polygons = path.polygons;
26061 var _d = __read(isFillOrStrokeAffected(pointerEvents,
26062 // Only a closed path can be filled.
26063 (polygons === null || polygons === void 0 ? void 0 : polygons.length) && fill, stroke), 2), hasFill = _d[0], hasStroke = _d[1];
26064 var totalLength = getOrCalculatePathTotalLength(displayObject);
26065 var isHit = false;
26066 if (hasFill || isClipPath) {
26067 if (hasArc) {
26068 // 存在曲线时,暂时使用 canvas 的 api 计算,后续可以进行多边形切割
26069 isHit = isPointInPath(displayObject, position);
26070 }
26071 else {
26072 // 提取出来的多边形包含闭合的和非闭合的,在这里统一按照多边形处理
26073 isHit =
26074 inPolygons(polygons, position.x + x, position.y + y) ||
26075 inPolygons(polylines, position.x + x, position.y + y);
26076 }
26077 return isHit;
26078 }
26079 else if (hasStroke || isClipPath) {
26080 isHit = isPointInStroke(segments, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, totalLength);
26081 }
26082 return isHit;
26083 }
26084
26085 function isPointInPath$3(displayObject, position, isClipPath) {
26086 var _a = displayObject.parsedStyle, stroke = _a.stroke, fill = _a.fill, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, points = _a.points, _b = _a.defX, x = _b === void 0 ? 0 : _b, _c = _a.defY, y = _c === void 0 ? 0 : _c, pointerEvents = _a.pointerEvents;
26087 var _d = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasFill = _d[0], hasStroke = _d[1];
26088 var isHit = false;
26089 if (hasStroke || isClipPath) {
26090 isHit = inPolyline(points.points, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, true);
26091 }
26092 if (!isHit && (hasFill || isClipPath)) {
26093 isHit = inPolygon(points.points, position.x + x, position.y + y);
26094 }
26095 return isHit;
26096 }
26097
26098 function isPointInPath$2(displayObject, position, isClipPath) {
26099 var _a = displayObject.parsedStyle, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, points = _a.points, _b = _a.defX, x = _b === void 0 ? 0 : _b, _c = _a.defY, y = _c === void 0 ? 0 : _c, pointerEvents = _a.pointerEvents, fill = _a.fill, stroke = _a.stroke;
26100 var _d = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasStroke = _d[1];
26101 if ((!hasStroke && !isClipPath) || !lineWidth) {
26102 return false;
26103 }
26104 return inPolyline(points.points, (lineWidth || 0) + (increasedLineWidthForHitTesting || 0), position.x + x, position.y + y, false);
26105 }
26106
26107 function isPointInPath$1(displayObject, position, isClipPath, isPointInPath, runtime) {
26108 var _a = displayObject.parsedStyle, radius = _a.radius, fill = _a.fill, stroke = _a.stroke, lineWidth = _a.lineWidth, increasedLineWidthForHitTesting = _a.increasedLineWidthForHitTesting, width = _a.width, height = _a.height, pointerEvents = _a.pointerEvents;
26109 var _b = __read(isFillOrStrokeAffected(pointerEvents, fill, stroke), 2), hasFill = _b[0], hasStroke = _b[1];
26110 var hasRadius = radius && radius.some(function (r) { return r !== 0; });
26111 var lineWidthForHitTesting = (lineWidth || 0) + (increasedLineWidthForHitTesting || 0);
26112 // 无圆角时的策略
26113 if (!hasRadius) {
26114 var halfWidth = lineWidthForHitTesting / 2;
26115 // 同时填充和带有边框
26116 if ((hasFill && hasStroke) || isClipPath) {
26117 return inBox(0 - halfWidth, 0 - halfWidth, width + halfWidth, height + halfWidth, position.x, position.y);
26118 }
26119 // 仅填充
26120 if (hasFill) {
26121 return inBox(0, 0, width, height, position.x, position.y);
26122 }
26123 if (hasStroke) {
26124 return inRect(0, 0, width, height, lineWidthForHitTesting, position.x, position.y);
26125 }
26126 }
26127 else {
26128 var isHit = false;
26129 if (hasStroke || isClipPath) {
26130 isHit = inRectWithRadius(0, 0, width, height, radius.map(function (r) {
26131 return clamp(r, 0, Math.min(Math.abs(width) / 2, Math.abs(height) / 2));
26132 }), lineWidthForHitTesting, position.x, position.y);
26133 }
26134 // 仅填充时带有圆角的矩形直接通过图形拾取
26135 // 以后可以改成纯数学的近似拾取,将圆弧切割成多边形
26136 if (!isHit && (hasFill || isClipPath)) {
26137 isHit = isPointInPath(displayObject, position);
26138 }
26139 return isHit;
26140 }
26141 return false;
26142 }
26143 function inRectWithRadius(minX, minY, width, height, radiusArray, lineWidth, x, y) {
26144 var _a = __read(radiusArray, 4), tlr = _a[0], trr = _a[1], brr = _a[2], blr = _a[3];
26145 return (inLine(minX + tlr, minY, minX + width - trr, minY, lineWidth, x, y) ||
26146 inLine(minX + width, minY + trr, minX + width, minY + height - brr, lineWidth, x, y) ||
26147 inLine(minX + width - brr, minY + height, minX + blr, minY + height, lineWidth, x, y) ||
26148 inLine(minX, minY + height - blr, minX, minY + tlr, lineWidth, x, y) ||
26149 inArc(minX + width - trr, minY + trr, trr, 1.5 * Math.PI, 2 * Math.PI, lineWidth, x, y) ||
26150 inArc(minX + width - brr, minY + height - brr, brr, 0, 0.5 * Math.PI, lineWidth, x, y) ||
26151 inArc(minX + blr, minY + height - blr, blr, 0.5 * Math.PI, Math.PI, lineWidth, x, y) ||
26152 inArc(minX + tlr, minY + tlr, tlr, Math.PI, 1.5 * Math.PI, lineWidth, x, y));
26153 }
26154
26155 function isPointInPath(displayObject, position, isClipPath, isPointInPath, renderingPluginContext, runtime) {
26156 var _a = displayObject.parsedStyle, pointerEvents = _a.pointerEvents, width = _a.width, height = _a.height;
26157 if (pointerEvents === 'non-transparent-pixel') {
26158 var offscreenCanvas = renderingPluginContext.config.offscreenCanvas;
26159 var canvas = runtime.offscreenCanvasCreator.getOrCreateCanvas(offscreenCanvas);
26160 var context = runtime.offscreenCanvasCreator.getOrCreateContext(offscreenCanvas, {
26161 willReadFrequently: true,
26162 });
26163 canvas.width = width;
26164 canvas.height = height;
26165 renderingPluginContext.defaultStyleRendererFactory[Shape.IMAGE].render(context, displayObject.parsedStyle, displayObject, undefined, undefined, undefined);
26166 var imagedata = context.getImageData(position.x, position.y, 1, 1).data;
26167 return imagedata.every(function (component) { return component !== 0; });
26168 }
26169 return true;
26170 }
26171
26172 var Plugin$1 = /** @class */ (function (_super) {
26173 __extends(Plugin, _super);
26174 function Plugin() {
26175 var _this = _super !== null && _super.apply(this, arguments) || this;
26176 _this.name = 'canvas-picker';
26177 return _this;
26178 }
26179 Plugin.prototype.init = function () {
26180 var _a;
26181 var trueFunc = function () { return true; };
26182 var pointInPathPickerFactory = (_a = {},
26183 _a[Shape.CIRCLE] = isPointInPath$7,
26184 _a[Shape.ELLIPSE] = isPointInPath$6,
26185 _a[Shape.RECT] = isPointInPath$1,
26186 _a[Shape.LINE] = isPointInPath$5,
26187 _a[Shape.POLYLINE] = isPointInPath$2,
26188 _a[Shape.POLYGON] = isPointInPath$3,
26189 _a[Shape.PATH] = isPointInPath$4,
26190 _a[Shape.TEXT] = trueFunc,
26191 _a[Shape.GROUP] = null,
26192 _a[Shape.IMAGE] = isPointInPath,
26193 _a[Shape.HTML] = null,
26194 _a[Shape.MESH] = null,
26195 _a);
26196 // @ts-ignore
26197 this.context.pointInPathPickerFactory = pointInPathPickerFactory;
26198 this.addRenderingPlugin(new CanvasPickerPlugin());
26199 };
26200 Plugin.prototype.destroy = function () {
26201 // @ts-ignore
26202 delete this.context.pointInPathPickerFactory;
26203 this.removeAllRenderingPlugins();
26204 };
26205 return Plugin;
26206 }(AbstractRendererPlugin));
26207
26208 /**
26209 * support 2 modes in rendering:
26210 * * immediate
26211 * * delayed: render at the end of frame with dirty-rectangle
26212 */
26213 var CanvasRendererPlugin = /** @class */ (function () {
26214 function CanvasRendererPlugin(canvasRendererPluginOptions) {
26215 this.canvasRendererPluginOptions = canvasRendererPluginOptions;
26216 this.removedRBushNodeAABBs = [];
26217 this.renderQueue = [];
26218 /**
26219 * This stack is only used by clipPath for now.
26220 */
26221 this.restoreStack = [];
26222 this.clearFullScreen = false;
26223 /**
26224 * view projection matrix
26225 */
26226 this.vpMatrix = create$1();
26227 this.dprMatrix = create$1();
26228 this.tmpMat4 = create$1();
26229 this.vec3a = create$2();
26230 this.vec3b = create$2();
26231 this.vec3c = create$2();
26232 this.vec3d = create$2();
26233 }
26234 CanvasRendererPlugin.prototype.apply = function (context, runtime) {
26235 var _this = this;
26236 this.context = context;
26237 var config = context.config, camera = context.camera, renderingService = context.renderingService, renderingContext = context.renderingContext, rBushRoot = context.rBushRoot,
26238 // @ts-ignore
26239 pathGeneratorFactory = context.pathGeneratorFactory;
26240 this.rBush = rBushRoot;
26241 this.pathGeneratorFactory = pathGeneratorFactory;
26242 var contextService = context.contextService;
26243 var canvas = renderingContext.root.ownerDocument.defaultView;
26244 var handleUnmounted = function (e) {
26245 var object = e.target;
26246 // remove r-bush node
26247 // @ts-ignore
26248 var rBushNode = object.rBushNode;
26249 if (rBushNode.aabb) {
26250 // save removed aabbs for dirty-rectangle rendering later
26251 _this.removedRBushNodeAABBs.push(rBushNode.aabb);
26252 }
26253 };
26254 var handleCulled = function (e) {
26255 var object = e.target;
26256 // @ts-ignore
26257 var rBushNode = object.rBushNode;
26258 if (rBushNode.aabb) {
26259 // save removed aabbs for dirty-rectangle rendering later
26260 _this.removedRBushNodeAABBs.push(rBushNode.aabb);
26261 }
26262 };
26263 renderingService.hooks.init.tap(CanvasRendererPlugin.tag, function () {
26264 canvas.addEventListener(ElementEvent.UNMOUNTED, handleUnmounted);
26265 canvas.addEventListener(ElementEvent.CULLED, handleCulled);
26266 // clear fullscreen
26267 var dpr = contextService.getDPR();
26268 var width = config.width, height = config.height;
26269 var context = contextService.getContext();
26270 _this.clearRect(context, 0, 0, width * dpr, height * dpr, config.background);
26271 });
26272 renderingService.hooks.destroy.tap(CanvasRendererPlugin.tag, function () {
26273 canvas.removeEventListener(ElementEvent.UNMOUNTED, handleUnmounted);
26274 canvas.removeEventListener(ElementEvent.CULLED, handleCulled);
26275 _this.renderQueue = [];
26276 _this.removedRBushNodeAABBs = [];
26277 _this.restoreStack = [];
26278 });
26279 renderingService.hooks.beginFrame.tap(CanvasRendererPlugin.tag, function () {
26280 var context = contextService.getContext();
26281 var dpr = contextService.getDPR();
26282 var width = config.width, height = config.height;
26283 var _a = _this.canvasRendererPluginOptions, dirtyObjectNumThreshold = _a.dirtyObjectNumThreshold, dirtyObjectRatioThreshold = _a.dirtyObjectRatioThreshold;
26284 // some heuristic conditions such as 80% object changed
26285 var _b = renderingService.getStats(), total = _b.total, rendered = _b.rendered;
26286 var ratio = rendered / total;
26287 _this.clearFullScreen =
26288 renderingService.disableDirtyRectangleRendering() ||
26289 (rendered > dirtyObjectNumThreshold &&
26290 ratio > dirtyObjectRatioThreshold);
26291 if (context) {
26292 context.resetTransform
26293 ? context.resetTransform()
26294 : context.setTransform(1, 0, 0, 1, 0, 0);
26295 if (_this.clearFullScreen) {
26296 _this.clearRect(context, 0, 0, width * dpr, height * dpr, config.background);
26297 }
26298 }
26299 });
26300 var renderByZIndex = function (object, context) {
26301 if (object.isVisible() && !object.isCulled()) {
26302 _this.renderDisplayObject(object, context, _this.context, _this.restoreStack, runtime);
26303 // if (object.renderable.) {
26304 // if we did a full screen rendering last frame
26305 _this.saveDirtyAABB(object);
26306 // }
26307 }
26308 var sorted = object.sortable.sorted || object.childNodes;
26309 // should account for z-index
26310 sorted.forEach(function (child) {
26311 renderByZIndex(child, context);
26312 });
26313 };
26314 // render at the end of frame
26315 renderingService.hooks.endFrame.tap(CanvasRendererPlugin.tag, function () {
26316 var context = contextService.getContext();
26317 // clear & clip dirty rectangle
26318 var dpr = contextService.getDPR();
26319 fromScaling(_this.dprMatrix, [dpr, dpr, 1]);
26320 multiply(_this.vpMatrix, _this.dprMatrix, camera.getOrthoMatrix());
26321 // if (this.clearFullScreen) {
26322 if (_this.clearFullScreen) {
26323 // console.log('canvas renderer fcp...');
26324 renderByZIndex(renderingContext.root, context);
26325 }
26326 else {
26327 // console.log('canvas renderer next...');
26328 // merge removed AABB
26329 var dirtyRenderBounds = _this.safeMergeAABB.apply(_this, __spreadArray([_this.mergeDirtyAABBs(_this.renderQueue)], __read(_this.removedRBushNodeAABBs.map(function (_a) {
26330 var minX = _a.minX, minY = _a.minY, maxX = _a.maxX, maxY = _a.maxY;
26331 var aabb = new AABB();
26332 aabb.setMinMax(
26333 // vec3.fromValues(minX, minY, 0),
26334 // vec3.fromValues(maxX, maxY, 0),
26335 [minX, minY, 0], [maxX, maxY, 0]);
26336 return aabb;
26337 })), false));
26338 _this.removedRBushNodeAABBs = [];
26339 if (AABB.isEmpty(dirtyRenderBounds)) {
26340 _this.renderQueue = [];
26341 return;
26342 }
26343 var dirtyRect = _this.convertAABB2Rect(dirtyRenderBounds);
26344 var x = dirtyRect.x, y = dirtyRect.y, width = dirtyRect.width, height = dirtyRect.height;
26345 var tl = transformMat4(_this.vec3a, [x, y, 0], _this.vpMatrix);
26346 var tr = transformMat4(_this.vec3b, [x + width, y, 0], _this.vpMatrix);
26347 var bl = transformMat4(_this.vec3c, [x, y + height, 0], _this.vpMatrix);
26348 var br = transformMat4(_this.vec3d, [x + width, y + height, 0], _this.vpMatrix);
26349 var minx = Math.min(tl[0], tr[0], br[0], bl[0]);
26350 var miny = Math.min(tl[1], tr[1], br[1], bl[1]);
26351 var maxx = Math.max(tl[0], tr[0], br[0], bl[0]);
26352 var maxy = Math.max(tl[1], tr[1], br[1], bl[1]);
26353 var ix = Math.floor(minx);
26354 var iy = Math.floor(miny);
26355 var iwidth = Math.ceil(maxx - minx);
26356 var iheight = Math.ceil(maxy - miny);
26357 context.save();
26358 _this.clearRect(context, ix, iy, iwidth, iheight, config.background);
26359 context.beginPath();
26360 context.rect(ix, iy, iwidth, iheight);
26361 context.clip();
26362 // @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
26363 context.setTransform(_this.vpMatrix[0], _this.vpMatrix[1], _this.vpMatrix[4], _this.vpMatrix[5], _this.vpMatrix[12], _this.vpMatrix[13]);
26364 // draw dirty rectangle
26365 var enableDirtyRectangleRenderingDebug = config.renderer.getConfig().enableDirtyRectangleRenderingDebug;
26366 if (enableDirtyRectangleRenderingDebug) {
26367 canvas.dispatchEvent(new CustomEvent(CanvasEvent.DIRTY_RECTANGLE, {
26368 dirtyRect: {
26369 x: ix,
26370 y: iy,
26371 width: iwidth,
26372 height: iheight,
26373 },
26374 }));
26375 }
26376 // search objects intersect with dirty rectangle
26377 var dirtyObjects = _this.searchDirtyObjects(dirtyRenderBounds);
26378 // do rendering
26379 dirtyObjects
26380 // sort by z-index
26381 .sort(function (a, b) { return a.sortable.renderOrder - b.sortable.renderOrder; })
26382 .forEach(function (object) {
26383 // culled object should not be rendered
26384 if (object && object.isVisible() && !object.isCulled()) {
26385 _this.renderDisplayObject(object, context, _this.context, _this.restoreStack, runtime);
26386 }
26387 });
26388 context.restore();
26389 // save dirty AABBs in last frame
26390 _this.renderQueue.forEach(function (object) {
26391 _this.saveDirtyAABB(object);
26392 });
26393 // clear queue
26394 _this.renderQueue = [];
26395 }
26396 // pop restore stack, eg. root -> parent -> child
26397 _this.restoreStack.forEach(function () {
26398 context.restore();
26399 });
26400 // clear restore stack
26401 _this.restoreStack = [];
26402 });
26403 renderingService.hooks.render.tap(CanvasRendererPlugin.tag, function (object) {
26404 if (!_this.clearFullScreen) {
26405 // render at the end of frame
26406 _this.renderQueue.push(object);
26407 }
26408 });
26409 };
26410 CanvasRendererPlugin.prototype.clearRect = function (context, x, y, width, height, background) {
26411 // clearRect is faster than fillRect @see https://stackoverflow.com/a/30830253
26412 context.clearRect(x, y, width, height);
26413 if (background) {
26414 context.fillStyle = background;
26415 context.fillRect(x, y, width, height);
26416 }
26417 };
26418 CanvasRendererPlugin.prototype.renderDisplayObject = function (object, context, canvasContext, restoreStack, runtime) {
26419 var nodeName = object.nodeName;
26420 // console.log('canvas render:', object);
26421 // restore to its ancestor
26422 var parent = restoreStack[restoreStack.length - 1];
26423 if (parent &&
26424 !(object.compareDocumentPosition(parent) & Node.DOCUMENT_POSITION_CONTAINS)) {
26425 context.restore();
26426 restoreStack.pop();
26427 }
26428 // @ts-ignore
26429 var styleRenderer = this.context.styleRendererFactory[nodeName];
26430 var generatePath = this.pathGeneratorFactory[nodeName];
26431 // clip path
26432 var clipPath = object.parsedStyle.clipPath;
26433 if (clipPath) {
26434 this.applyWorldTransform(context, clipPath);
26435 // generate path in local space
26436 var generatePath_1 = this.pathGeneratorFactory[clipPath.nodeName];
26437 if (generatePath_1) {
26438 context.save();
26439 // save clip
26440 restoreStack.push(object);
26441 context.beginPath();
26442 generatePath_1(context, clipPath.parsedStyle);
26443 context.closePath();
26444 context.clip();
26445 }
26446 }
26447 // fill & stroke
26448 if (styleRenderer) {
26449 this.applyWorldTransform(context, object);
26450 context.save();
26451 // apply attributes to context
26452 this.applyAttributesToContext(context, object);
26453 }
26454 if (generatePath) {
26455 context.beginPath();
26456 generatePath(context, object.parsedStyle);
26457 if (object.nodeName !== Shape.LINE &&
26458 object.nodeName !== Shape.PATH &&
26459 object.nodeName !== Shape.POLYLINE) {
26460 context.closePath();
26461 }
26462 }
26463 // fill & stroke
26464 if (styleRenderer) {
26465 styleRenderer.render(context, object.parsedStyle, object, canvasContext, this, runtime);
26466 // restore applied attributes, eg. shadowBlur shadowColor...
26467 context.restore();
26468 }
26469 // finish rendering, clear dirty flag
26470 object.renderable.dirty = false;
26471 };
26472 CanvasRendererPlugin.prototype.convertAABB2Rect = function (aabb) {
26473 var min = aabb.getMin();
26474 var max = aabb.getMax();
26475 // expand the rectangle a bit to avoid artifacts
26476 // @see https://www.yuque.com/antv/ou292n/bi8nix#ExvCu
26477 var minX = Math.floor(min[0]);
26478 var minY = Math.floor(min[1]);
26479 var maxX = Math.ceil(max[0]);
26480 var maxY = Math.ceil(max[1]);
26481 var width = maxX - minX;
26482 var height = maxY - minY;
26483 return { x: minX, y: minY, width: width, height: height };
26484 };
26485 /**
26486 * TODO: merge dirty rectangles with some strategies.
26487 * For now, we just simply merge all the rectangles into one.
26488 * @see https://idom.me/articles/841.html
26489 */
26490 CanvasRendererPlugin.prototype.mergeDirtyAABBs = function (dirtyObjects) {
26491 // merge into a big AABB
26492 // TODO: skip descendant if ancestor is caculated, but compareNodePosition is really slow
26493 var aabb = new AABB();
26494 dirtyObjects.forEach(function (object) {
26495 var renderBounds = object.getRenderBounds();
26496 aabb.add(renderBounds);
26497 var dirtyRenderBounds = object.renderable.dirtyRenderBounds;
26498 if (dirtyRenderBounds) {
26499 aabb.add(dirtyRenderBounds);
26500 }
26501 });
26502 return aabb;
26503 };
26504 CanvasRendererPlugin.prototype.searchDirtyObjects = function (dirtyRectangle) {
26505 // search in r-tree, get all affected nodes
26506 var _a = __read(dirtyRectangle.getMin(), 2), minX = _a[0], minY = _a[1];
26507 var _b = __read(dirtyRectangle.getMax(), 2), maxX = _b[0], maxY = _b[1];
26508 var rBushNodes = this.rBush.search({
26509 minX: minX,
26510 minY: minY,
26511 maxX: maxX,
26512 maxY: maxY,
26513 });
26514 return rBushNodes.map(function (_a) {
26515 var displayObject = _a.displayObject;
26516 return displayObject;
26517 });
26518 };
26519 CanvasRendererPlugin.prototype.saveDirtyAABB = function (object) {
26520 var renderable = object.renderable;
26521 if (!renderable.dirtyRenderBounds) {
26522 renderable.dirtyRenderBounds = new AABB();
26523 }
26524 var renderBounds = object.getRenderBounds();
26525 if (renderBounds) {
26526 // save last dirty aabb
26527 renderable.dirtyRenderBounds.update(renderBounds.center, renderBounds.halfExtents);
26528 }
26529 };
26530 /**
26531 * TODO: batch the same global attributes
26532 */
26533 CanvasRendererPlugin.prototype.applyAttributesToContext = function (context, object) {
26534 var _a = object.parsedStyle, stroke = _a.stroke, fill = _a.fill, opacity = _a.opacity, lineDash = _a.lineDash, lineDashOffset = _a.lineDashOffset;
26535 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/setLineDash
26536 if (lineDash) {
26537 context.setLineDash(lineDash);
26538 }
26539 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
26540 if (!isNil(lineDashOffset)) {
26541 context.lineDashOffset = lineDashOffset;
26542 }
26543 if (!isNil(opacity)) {
26544 context.globalAlpha *= opacity;
26545 }
26546 if (!isNil(stroke) &&
26547 !Array.isArray(stroke) &&
26548 !stroke.isNone) {
26549 context.strokeStyle = object.attributes.stroke;
26550 }
26551 if (!isNil(fill) && !Array.isArray(fill) && !fill.isNone) {
26552 context.fillStyle = object.attributes.fill;
26553 }
26554 };
26555 CanvasRendererPlugin.prototype.applyWorldTransform = function (context, object, matrix) {
26556 var tx = 0;
26557 var ty = 0;
26558 var anchor = (object.parsedStyle || {}).anchor;
26559 var anchorX = (anchor && anchor[0]) || 0;
26560 var anchorY = (anchor && anchor[1]) || 0;
26561 if (anchorX !== 0 || anchorY !== 0) {
26562 // const bounds = object.getGeometryBounds();
26563 var bounds = object.geometry.contentBounds;
26564 var width = (bounds && bounds.halfExtents[0] * 2) || 0;
26565 var height = (bounds && bounds.halfExtents[1] * 2) || 0;
26566 tx = -(anchorX * width);
26567 ty = -(anchorY * height);
26568 }
26569 // apply clip shape's RTS
26570 if (matrix) {
26571 copy(this.tmpMat4, object.getLocalTransform());
26572 this.vec3a[0] = tx;
26573 this.vec3a[1] = ty;
26574 this.vec3a[2] = 0;
26575 translate(this.tmpMat4, this.tmpMat4, this.vec3a);
26576 multiply(this.tmpMat4, matrix, this.tmpMat4);
26577 multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
26578 }
26579 else {
26580 // apply RTS transformation in world space
26581 copy(this.tmpMat4, object.getWorldTransform());
26582 this.vec3a[0] = tx;
26583 this.vec3a[1] = ty;
26584 this.vec3a[2] = 0;
26585 translate(this.tmpMat4, this.tmpMat4, this.vec3a);
26586 multiply(this.tmpMat4, this.vpMatrix, this.tmpMat4);
26587 }
26588 // @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations
26589 context.setTransform(this.tmpMat4[0], this.tmpMat4[1], this.tmpMat4[4], this.tmpMat4[5], this.tmpMat4[12], this.tmpMat4[13]);
26590 };
26591 CanvasRendererPlugin.prototype.safeMergeAABB = function () {
26592 var aabbs = [];
26593 for (var _i = 0; _i < arguments.length; _i++) {
26594 aabbs[_i] = arguments[_i];
26595 }
26596 var merged = new AABB();
26597 aabbs.forEach(function (aabb) {
26598 merged.add(aabb);
26599 });
26600 return merged;
26601 };
26602 CanvasRendererPlugin.tag = 'CanvasRenderer';
26603 return CanvasRendererPlugin;
26604 }());
26605
26606 var DefaultRenderer = /** @class */ (function () {
26607 function DefaultRenderer(imagePool) {
26608 this.imagePool = imagePool;
26609 }
26610 DefaultRenderer.prototype.render = function (context, parsedStyle, object, canvasContext, plugin, runtime) {
26611 var fill = parsedStyle.fill, fillRule = parsedStyle.fillRule, opacity = parsedStyle.opacity, fillOpacity = parsedStyle.fillOpacity, stroke = parsedStyle.stroke, strokeOpacity = parsedStyle.strokeOpacity, lineWidth = parsedStyle.lineWidth, lineCap = parsedStyle.lineCap, lineJoin = parsedStyle.lineJoin, shadowType = parsedStyle.shadowType, shadowColor = parsedStyle.shadowColor, shadowBlur = parsedStyle.shadowBlur, filter = parsedStyle.filter, miterLimit = parsedStyle.miterLimit;
26612 var hasFill = !isNil(fill) && !fill.isNone;
26613 var hasStroke = !isNil(stroke) && !stroke.isNone && lineWidth > 0;
26614 var isFillTransparent = fill.alpha === 0;
26615 var hasFilter = !!(filter && filter.length);
26616 var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
26617 var nodeName = object.nodeName;
26618 var isInnerShadow = shadowType === 'inner';
26619 var shouldDrawShadowWithStroke = hasStroke &&
26620 hasShadow &&
26621 (nodeName === Shape.PATH ||
26622 nodeName === Shape.LINE ||
26623 nodeName === Shape.POLYLINE ||
26624 isFillTransparent ||
26625 isInnerShadow);
26626 if (hasFill) {
26627 context.globalAlpha = opacity * fillOpacity;
26628 if (!shouldDrawShadowWithStroke) {
26629 setShadowAndFilter(object, context, hasShadow);
26630 }
26631 this.fill(context, object, fill, fillRule, canvasContext, plugin, runtime);
26632 if (!shouldDrawShadowWithStroke) {
26633 this.clearShadowAndFilter(context, hasFilter, hasShadow);
26634 }
26635 }
26636 if (hasStroke) {
26637 context.globalAlpha = opacity * strokeOpacity;
26638 context.lineWidth = lineWidth;
26639 if (!isNil(miterLimit)) {
26640 context.miterLimit = miterLimit;
26641 }
26642 if (!isNil(lineCap)) {
26643 context.lineCap = lineCap;
26644 }
26645 if (!isNil(lineJoin)) {
26646 context.lineJoin = lineJoin;
26647 }
26648 if (shouldDrawShadowWithStroke) {
26649 if (isInnerShadow) {
26650 context.globalCompositeOperation = 'source-atop';
26651 }
26652 setShadowAndFilter(object, context, true);
26653 if (isInnerShadow) {
26654 this.stroke(context, object, stroke, canvasContext, plugin, runtime);
26655 context.globalCompositeOperation = 'source-over';
26656 this.clearShadowAndFilter(context, hasFilter, true);
26657 }
26658 }
26659 this.stroke(context, object, stroke, canvasContext, plugin, runtime);
26660 }
26661 };
26662 DefaultRenderer.prototype.clearShadowAndFilter = function (context, hasFilter, hasShadow) {
26663 if (hasShadow) {
26664 context.shadowColor = 'transparent';
26665 context.shadowBlur = 0;
26666 }
26667 if (hasFilter) {
26668 // save drop-shadow filter
26669 var oldFilter = context.filter;
26670 if (!isNil(oldFilter) && oldFilter.indexOf('drop-shadow') > -1) {
26671 context.filter =
26672 oldFilter.replace(/drop-shadow\([^)]*\)/, '').trim() || 'none';
26673 }
26674 }
26675 };
26676 DefaultRenderer.prototype.fill = function (context, object, fill, fillRule, canvasContext, plugin, runtime) {
26677 var _this = this;
26678 if (Array.isArray(fill)) {
26679 fill.forEach(function (gradient) {
26680 context.fillStyle = _this.getColor(gradient, object, context);
26681 fillRule ? context.fill(fillRule) : context.fill();
26682 });
26683 }
26684 else {
26685 if (isPattern(fill)) {
26686 context.fillStyle = this.getPattern(fill, object, context, canvasContext, plugin, runtime);
26687 }
26688 fillRule ? context.fill(fillRule) : context.fill();
26689 }
26690 };
26691 DefaultRenderer.prototype.stroke = function (context, object, stroke, canvasContext, plugin, runtime) {
26692 var _this = this;
26693 if (Array.isArray(stroke)) {
26694 stroke.forEach(function (gradient) {
26695 context.strokeStyle = _this.getColor(gradient, object, context);
26696 context.stroke();
26697 });
26698 }
26699 else {
26700 if (isPattern(stroke)) {
26701 context.strokeStyle = this.getPattern(stroke, object, context, canvasContext, plugin, runtime);
26702 }
26703 context.stroke();
26704 }
26705 };
26706 DefaultRenderer.prototype.getPattern = function (pattern, object, context, canvasContext, plugin, runtime) {
26707 var $offscreenCanvas;
26708 var dpr;
26709 if (pattern.image.nodeName === 'rect') {
26710 var _a = pattern.image.parsedStyle, width = _a.width, height = _a.height;
26711 dpr = canvasContext.contextService.getDPR();
26712 var offscreenCanvas = canvasContext.config.offscreenCanvas;
26713 $offscreenCanvas = runtime.offscreenCanvasCreator.getOrCreateCanvas(offscreenCanvas);
26714 $offscreenCanvas.width = width * dpr;
26715 $offscreenCanvas.height = height * dpr;
26716 var offscreenCanvasContext_1 = runtime.offscreenCanvasCreator.getOrCreateContext(offscreenCanvas);
26717 var restoreStack_1 = [];
26718 // offscreenCanvasContext.scale(1 / dpr, 1 / dpr);
26719 pattern.image.forEach(function (object) {
26720 plugin.renderDisplayObject(object, offscreenCanvasContext_1, canvasContext, restoreStack_1, runtime);
26721 });
26722 restoreStack_1.forEach(function () {
26723 offscreenCanvasContext_1.restore();
26724 });
26725 }
26726 var canvasPattern = this.imagePool.getOrCreatePatternSync(pattern, context, $offscreenCanvas, dpr, function () {
26727 // set dirty rectangle flag
26728 object.renderable.dirty = true;
26729 canvasContext.renderingService.dirtify();
26730 });
26731 return canvasPattern;
26732 };
26733 DefaultRenderer.prototype.getColor = function (parsedColor, object, context) {
26734 var color;
26735 if (parsedColor.type === GradientType.LinearGradient ||
26736 parsedColor.type === GradientType.RadialGradient) {
26737 var bounds = object.getGeometryBounds();
26738 var width = (bounds && bounds.halfExtents[0] * 2) || 1;
26739 var height = (bounds && bounds.halfExtents[1] * 2) || 1;
26740 color = this.imagePool.getOrCreateGradient(__assign(__assign({ type: parsedColor.type }, parsedColor.value), { width: width, height: height }), context);
26741 }
26742 return color;
26743 };
26744 return DefaultRenderer;
26745 }());
26746 /**
26747 * apply before fill and stroke but only once
26748 */
26749 function setShadowAndFilter(object, context, hasShadow) {
26750 var _a = object.parsedStyle, filter = _a.filter, shadowColor = _a.shadowColor, shadowBlur = _a.shadowBlur, shadowOffsetX = _a.shadowOffsetX, shadowOffsetY = _a.shadowOffsetY;
26751 if (filter && filter.length) {
26752 // use raw filter string
26753 context.filter = object.style.filter;
26754 }
26755 if (hasShadow) {
26756 context.shadowColor = shadowColor.toString();
26757 context.shadowBlur = shadowBlur || 0;
26758 context.shadowOffsetX = shadowOffsetX || 0;
26759 context.shadowOffsetY = shadowOffsetY || 0;
26760 }
26761 }
26762
26763 var ImageRenderer = /** @class */ (function () {
26764 function ImageRenderer(imagePool) {
26765 this.imagePool = imagePool;
26766 }
26767 ImageRenderer.prototype.render = function (context, parsedStyle, object) {
26768 var width = parsedStyle.width, height = parsedStyle.height, img = parsedStyle.img, shadowColor = parsedStyle.shadowColor, shadowBlur = parsedStyle.shadowBlur;
26769 var image;
26770 var iw = width;
26771 var ih = height;
26772 if (isString(img)) {
26773 // image has been loaded in `mounted` hook
26774 image = this.imagePool.getImageSync(img);
26775 }
26776 else {
26777 iw || (iw = img.width);
26778 ih || (ih = img.height);
26779 image = img;
26780 }
26781 if (image) {
26782 var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
26783 setShadowAndFilter(object, context, hasShadow);
26784 // node-canvas will throw the following err:
26785 // Error: Image given has not completed loading
26786 try {
26787 context.drawImage(image, 0, 0, iw, ih);
26788 }
26789 catch (e) { }
26790 }
26791 };
26792 return ImageRenderer;
26793 }());
26794
26795 var TextRenderer = /** @class */ (function () {
26796 function TextRenderer() {
26797 }
26798 TextRenderer.prototype.render = function (context, parsedStyle, object, canvasContext, plugin, runtime) {
26799 var _a = parsedStyle, lineWidth = _a.lineWidth, textAlign = _a.textAlign, textBaseline = _a.textBaseline, lineJoin = _a.lineJoin, miterLimit = _a.miterLimit, letterSpacing = _a.letterSpacing, stroke = _a.stroke, fill = _a.fill, fillOpacity = _a.fillOpacity, strokeOpacity = _a.strokeOpacity, opacity = _a.opacity, metrics = _a.metrics, dx = _a.dx, dy = _a.dy, shadowColor = _a.shadowColor, shadowBlur = _a.shadowBlur;
26800 var font = metrics.font, lines = metrics.lines, height = metrics.height, lineHeight = metrics.lineHeight, lineMetrics = metrics.lineMetrics;
26801 context.font = font;
26802 context.lineWidth = lineWidth;
26803 context.textAlign = textAlign === 'middle' ? 'center' : textAlign;
26804 var formattedTextBaseline = textBaseline;
26805 if (
26806 // formattedTextBaseline === 'bottom' ||
26807 !runtime.enableCSSParsing &&
26808 formattedTextBaseline === 'alphabetic') {
26809 formattedTextBaseline = 'bottom';
26810 }
26811 context.lineJoin = lineJoin;
26812 if (!isNil(miterLimit)) {
26813 context.miterLimit = miterLimit;
26814 }
26815 var linePositionY = 0;
26816 // handle vertical text baseline
26817 if (textBaseline === 'middle') {
26818 linePositionY = -height / 2 - lineHeight / 2;
26819 }
26820 else if (textBaseline === 'bottom' ||
26821 textBaseline === 'alphabetic' ||
26822 textBaseline === 'ideographic') {
26823 linePositionY = -height;
26824 }
26825 else if (textBaseline === 'top' || textBaseline === 'hanging') {
26826 linePositionY = -lineHeight;
26827 }
26828 // account for dx & dy
26829 var offsetX = dx || 0;
26830 linePositionY += dy || 0;
26831 if (lines.length === 1) {
26832 if (formattedTextBaseline === 'bottom') {
26833 formattedTextBaseline = 'middle';
26834 linePositionY -= 0.5 * height;
26835 }
26836 else if (formattedTextBaseline === 'top') {
26837 formattedTextBaseline = 'middle';
26838 linePositionY += 0.5 * height;
26839 }
26840 }
26841 context.textBaseline = formattedTextBaseline;
26842 var hasShadow = !isNil(shadowColor) && shadowBlur > 0;
26843 setShadowAndFilter(object, context, hasShadow);
26844 // draw lines line by line
26845 for (var i = 0; i < lines.length; i++) {
26846 var linePositionX = lineWidth / 2 + offsetX;
26847 linePositionY += lineHeight;
26848 // no need to re-position X, cause we already set text align
26849 // @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
26850 if (!isNil(stroke) && !stroke.isNone && lineWidth) {
26851 this.drawLetterSpacing(context, lines[i], lineMetrics[i], textAlign, linePositionX, linePositionY, letterSpacing, fillOpacity, strokeOpacity, opacity, true);
26852 }
26853 if (!isNil(fill)) {
26854 this.drawLetterSpacing(context, lines[i], lineMetrics[i], textAlign, linePositionX, linePositionY, letterSpacing, fillOpacity, strokeOpacity, opacity);
26855 }
26856 }
26857 };
26858 TextRenderer.prototype.drawLetterSpacing = function (context, text, lineMetrics, textAlign, x, y, letterSpacing, fillOpacity, strokeOpacity, opacity, isStroke) {
26859 if (isStroke === void 0) { isStroke = false; }
26860 // letterSpacing of 0 means normal, render all texts directly
26861 if (letterSpacing === 0) {
26862 if (isStroke) {
26863 this.strokeText(context, text, x, y, strokeOpacity);
26864 }
26865 else {
26866 this.fillText(context, text, x, y, fillOpacity, opacity);
26867 }
26868 return;
26869 }
26870 // draw text using left align
26871 var currentTextAlign = context.textAlign;
26872 context.textAlign = 'left';
26873 var currentPosition = x;
26874 if (textAlign === 'center' || textAlign === 'middle') {
26875 currentPosition = x - lineMetrics.width / 2;
26876 }
26877 else if (textAlign === 'right' || textAlign === 'end') {
26878 currentPosition = x - lineMetrics.width;
26879 }
26880 var stringArray = Array.from(text);
26881 var previousWidth = context.measureText(text).width;
26882 var currentWidth = 0;
26883 for (var i = 0; i < stringArray.length; ++i) {
26884 var currentChar = stringArray[i];
26885 if (isStroke) {
26886 this.strokeText(context, currentChar, currentPosition, y, strokeOpacity);
26887 }
26888 else {
26889 this.fillText(context, currentChar, currentPosition, y, fillOpacity, opacity);
26890 }
26891 currentWidth = context.measureText(text.substring(i + 1)).width;
26892 currentPosition += previousWidth - currentWidth + letterSpacing;
26893 previousWidth = currentWidth;
26894 }
26895 context.textAlign = currentTextAlign;
26896 };
26897 TextRenderer.prototype.fillText = function (context, text, x, y, fillOpacity, opacity) {
26898 var currentGlobalAlpha;
26899 var applyOpacity = !isNil(fillOpacity) && fillOpacity !== 1;
26900 if (applyOpacity) {
26901 currentGlobalAlpha = context.globalAlpha;
26902 context.globalAlpha = fillOpacity * opacity;
26903 }
26904 context.fillText(text, x, y);
26905 if (applyOpacity) {
26906 context.globalAlpha = currentGlobalAlpha;
26907 }
26908 };
26909 TextRenderer.prototype.strokeText = function (context, text, x, y, strokeOpacity) {
26910 var currentGlobalAlpha;
26911 var applyOpacity = !isNil(strokeOpacity) && strokeOpacity !== 1;
26912 if (applyOpacity) {
26913 currentGlobalAlpha = context.globalAlpha;
26914 context.globalAlpha = strokeOpacity;
26915 }
26916 context.strokeText(text, x, y);
26917 if (applyOpacity) {
26918 context.globalAlpha = currentGlobalAlpha;
26919 }
26920 };
26921 return TextRenderer;
26922 }());
26923
26924 var RectRenderer = /** @class */ (function (_super) {
26925 __extends(RectRenderer, _super);
26926 function RectRenderer() {
26927 return _super !== null && _super.apply(this, arguments) || this;
26928 }
26929 return RectRenderer;
26930 }(DefaultRenderer));
26931
26932 var CircleRenderer = /** @class */ (function (_super) {
26933 __extends(CircleRenderer, _super);
26934 function CircleRenderer() {
26935 return _super !== null && _super.apply(this, arguments) || this;
26936 }
26937 return CircleRenderer;
26938 }(DefaultRenderer));
26939
26940 var EllipseRenderer = /** @class */ (function (_super) {
26941 __extends(EllipseRenderer, _super);
26942 function EllipseRenderer() {
26943 return _super !== null && _super.apply(this, arguments) || this;
26944 }
26945 return EllipseRenderer;
26946 }(DefaultRenderer));
26947
26948 var LineRenderer = /** @class */ (function (_super) {
26949 __extends(LineRenderer, _super);
26950 function LineRenderer() {
26951 return _super !== null && _super.apply(this, arguments) || this;
26952 }
26953 return LineRenderer;
26954 }(DefaultRenderer));
26955
26956 var PolylineRenderer = /** @class */ (function (_super) {
26957 __extends(PolylineRenderer, _super);
26958 function PolylineRenderer() {
26959 return _super !== null && _super.apply(this, arguments) || this;
26960 }
26961 return PolylineRenderer;
26962 }(DefaultRenderer));
26963
26964 var PolygonRenderer = /** @class */ (function (_super) {
26965 __extends(PolygonRenderer, _super);
26966 function PolygonRenderer() {
26967 return _super !== null && _super.apply(this, arguments) || this;
26968 }
26969 return PolygonRenderer;
26970 }(DefaultRenderer));
26971
26972 var PathRenderer = /** @class */ (function (_super) {
26973 __extends(PathRenderer, _super);
26974 function PathRenderer() {
26975 return _super !== null && _super.apply(this, arguments) || this;
26976 }
26977 return PathRenderer;
26978 }(DefaultRenderer));
26979
26980 var Plugin$2 = /** @class */ (function (_super) {
26981 __extends(Plugin, _super);
26982 function Plugin(options) {
26983 if (options === void 0) { options = {}; }
26984 var _this = _super.call(this) || this;
26985 _this.options = options;
26986 _this.name = 'canvas-renderer';
26987 return _this;
26988 }
26989 Plugin.prototype.init = function () {
26990 var _a;
26991 var canvasRendererPluginOptions = __assign({ dirtyObjectNumThreshold: 500, dirtyObjectRatioThreshold: 0.8 }, this.options);
26992 // @ts-ignore
26993 var imagePool = this.context.imagePool;
26994 var defaultRenderer = new DefaultRenderer(imagePool);
26995 var defaultStyleRendererFactory = (_a = {},
26996 _a[Shape.CIRCLE] = defaultRenderer,
26997 _a[Shape.ELLIPSE] = defaultRenderer,
26998 _a[Shape.RECT] = defaultRenderer,
26999 _a[Shape.IMAGE] = new ImageRenderer(imagePool),
27000 _a[Shape.TEXT] = new TextRenderer(),
27001 _a[Shape.LINE] = defaultRenderer,
27002 _a[Shape.POLYLINE] = defaultRenderer,
27003 _a[Shape.POLYGON] = defaultRenderer,
27004 _a[Shape.PATH] = defaultRenderer,
27005 _a[Shape.GROUP] = undefined,
27006 _a[Shape.HTML] = undefined,
27007 _a[Shape.MESH] = undefined,
27008 _a);
27009 this.context.defaultStyleRendererFactory = defaultStyleRendererFactory;
27010 this.context.styleRendererFactory = defaultStyleRendererFactory;
27011 this.addRenderingPlugin(new CanvasRendererPlugin(canvasRendererPluginOptions));
27012 };
27013 Plugin.prototype.destroy = function () {
27014 this.removeAllRenderingPlugins();
27015 delete this.context.defaultStyleRendererFactory;
27016 delete this.context.styleRendererFactory;
27017 };
27018 return Plugin;
27019 }(AbstractRendererPlugin));
27020
27021 var DragndropPlugin = /** @class */ (function () {
27022 function DragndropPlugin(dragndropPluginOptions) {
27023 this.dragndropPluginOptions = dragndropPluginOptions;
27024 }
27025 DragndropPlugin.prototype.apply = function (context) {
27026 var _this = this;
27027 var renderingService = context.renderingService, renderingContext = context.renderingContext;
27028 var document = renderingContext.root.ownerDocument;
27029 // TODO: should we add an option like `draggable` to Canvas
27030 var canvas = document.defaultView;
27031 var handlePointerdown = function (event) {
27032 var target = event.target;
27033 var isDocument = target === document;
27034 var draggableEventTarget = isDocument && _this.dragndropPluginOptions.isDocumentDraggable
27035 ? document
27036 : target.closest && target.closest('[draggable=true]');
27037 // `draggable` may be set on ancestor nodes:
27038 // @see https://github.com/antvis/G/issues/1088
27039 if (draggableEventTarget) {
27040 // delay triggering dragstart event
27041 var dragstartTriggered_1 = false;
27042 var dragstartTimeStamp_1 = event.timeStamp;
27043 var dragstartClientCoordinates_1 = [
27044 event.clientX,
27045 event.clientY,
27046 ];
27047 var currentDroppable_1 = null;
27048 var lastDragClientCoordinates_1 = [event.clientX, event.clientY];
27049 // @ts-ignore
27050 // eslint-disable-next-line no-inner-declarations
27051 var handlePointermove_1 = function (event) { return __awaiter(_this, void 0, void 0, function () {
27052 var timeElapsed, distanceMoved, point, elementsBelow, elementBelow, droppableBelow;
27053 return __generator(this, function (_a) {
27054 switch (_a.label) {
27055 case 0:
27056 if (!dragstartTriggered_1) {
27057 timeElapsed = event.timeStamp - dragstartTimeStamp_1;
27058 distanceMoved = distanceSquareRoot([event.clientX, event.clientY], dragstartClientCoordinates_1);
27059 // check thresholds
27060 if (timeElapsed <=
27061 this.dragndropPluginOptions.dragstartTimeThreshold ||
27062 distanceMoved <=
27063 this.dragndropPluginOptions.dragstartDistanceThreshold) {
27064 return [2 /*return*/];
27065 }
27066 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/dragstart_event
27067 event.type = 'dragstart';
27068 draggableEventTarget.dispatchEvent(event);
27069 dragstartTriggered_1 = true;
27070 }
27071 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/drag_event
27072 event.type = 'drag';
27073 // @ts-ignore
27074 event.dx = event.clientX - lastDragClientCoordinates_1[0];
27075 // @ts-ignore
27076 event.dy = event.clientY - lastDragClientCoordinates_1[1];
27077 draggableEventTarget.dispatchEvent(event);
27078 lastDragClientCoordinates_1 = [event.clientX, event.clientY];
27079 if (!!isDocument) return [3 /*break*/, 2];
27080 point = this.dragndropPluginOptions.overlap === 'pointer'
27081 ? [event.canvasX, event.canvasY]
27082 : target.getBounds().center;
27083 return [4 /*yield*/, document.elementsFromPoint(point[0], point[1])];
27084 case 1:
27085 elementsBelow = _a.sent();
27086 elementBelow = elementsBelow[elementsBelow.indexOf(target) + 1];
27087 droppableBelow = (elementBelow === null || elementBelow === void 0 ? void 0 : elementBelow.closest('[droppable=true]')) ||
27088 (this.dragndropPluginOptions.isDocumentDroppable
27089 ? document
27090 : null);
27091 if (currentDroppable_1 !== droppableBelow) {
27092 if (currentDroppable_1) {
27093 // null when we were not over a droppable before this event
27094 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/dragleave_event
27095 event.type = 'dragleave';
27096 event.target = currentDroppable_1;
27097 currentDroppable_1.dispatchEvent(event);
27098 }
27099 if (droppableBelow) {
27100 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/dragleave_event
27101 event.type = 'dragenter';
27102 event.target = droppableBelow;
27103 droppableBelow.dispatchEvent(event);
27104 }
27105 currentDroppable_1 = droppableBelow;
27106 if (currentDroppable_1) {
27107 // null if we're not coming over a droppable now
27108 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/dragover_event
27109 event.type = 'dragover';
27110 event.target = currentDroppable_1;
27111 currentDroppable_1.dispatchEvent(event);
27112 }
27113 }
27114 _a.label = 2;
27115 case 2: return [2 /*return*/];
27116 }
27117 });
27118 }); };
27119 canvas.addEventListener('pointermove', handlePointermove_1);
27120 var stopDragging = function (originalPointerUpEvent) {
27121 if (dragstartTriggered_1) {
27122 // prevent click event being triggerd
27123 // @see https://github.com/antvis/G/issues/1091
27124 originalPointerUpEvent.detail = {
27125 preventClick: true,
27126 };
27127 // clone event first
27128 var event_1 = originalPointerUpEvent.clone();
27129 // drop should fire before dragend
27130 // @see https://javascript.tutorialink.com/is-there-a-defined-ordering-between-dragend-and-drop-events/
27131 if (currentDroppable_1) {
27132 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/drop_event
27133 event_1.type = 'drop';
27134 event_1.target = currentDroppable_1;
27135 currentDroppable_1.dispatchEvent(event_1);
27136 }
27137 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/Document/dragend_event
27138 event_1.type = 'dragend';
27139 draggableEventTarget.dispatchEvent(event_1);
27140 dragstartTriggered_1 = false;
27141 }
27142 canvas.removeEventListener('pointermove', handlePointermove_1);
27143 };
27144 target.addEventListener('pointerup', stopDragging, { once: true });
27145 target.addEventListener('pointerupoutside', stopDragging, {
27146 once: true,
27147 });
27148 }
27149 };
27150 renderingService.hooks.init.tap(DragndropPlugin.tag, function () {
27151 canvas.addEventListener('pointerdown', handlePointerdown);
27152 });
27153 renderingService.hooks.destroy.tap(DragndropPlugin.tag, function () {
27154 canvas.removeEventListener('pointerdown', handlePointerdown);
27155 });
27156 };
27157 DragndropPlugin.tag = 'Dragndrop';
27158 return DragndropPlugin;
27159 }());
27160
27161 var Plugin$3 = /** @class */ (function (_super) {
27162 __extends(Plugin, _super);
27163 function Plugin(options) {
27164 if (options === void 0) { options = {}; }
27165 var _this = _super.call(this) || this;
27166 _this.options = options;
27167 _this.name = 'dragndrop';
27168 return _this;
27169 }
27170 Plugin.prototype.init = function () {
27171 this.addRenderingPlugin(new DragndropPlugin(__assign({ overlap: 'pointer', isDocumentDraggable: false, isDocumentDroppable: false, dragstartDistanceThreshold: 0, dragstartTimeThreshold: 0 }, this.options)));
27172 };
27173 Plugin.prototype.destroy = function () {
27174 this.removeAllRenderingPlugins();
27175 };
27176 Plugin.prototype.setOptions = function (options) {
27177 Object.assign(this.plugins[0].dragndropPluginOptions, options);
27178 };
27179 return Plugin;
27180 }(AbstractRendererPlugin));
27181
27182 var ImagePool = /** @class */ (function () {
27183 function ImagePool(canvasConfig) {
27184 this.canvasConfig = canvasConfig;
27185 this.imageCache = {};
27186 this.gradientCache = {};
27187 this.patternCache = {};
27188 }
27189 ImagePool.prototype.getImageSync = function (src, callback) {
27190 if (!this.imageCache[src]) {
27191 this.getOrCreateImage(src).then(function (img) {
27192 if (callback) {
27193 callback(img);
27194 }
27195 });
27196 }
27197 else {
27198 if (callback) {
27199 callback(this.imageCache[src]);
27200 }
27201 }
27202 return this.imageCache[src];
27203 };
27204 ImagePool.prototype.getOrCreateImage = function (src) {
27205 var _this = this;
27206 if (this.imageCache[src]) {
27207 return Promise.resolve(this.imageCache[src]);
27208 }
27209 // @see https://github.com/antvis/g/issues/938
27210 var createImage = this.canvasConfig.createImage;
27211 return new Promise(function (resolve, reject) {
27212 var image;
27213 if (createImage) {
27214 image = createImage(src);
27215 }
27216 else if (isBrowser) {
27217 image = new window.Image();
27218 }
27219 if (image) {
27220 image.onload = function () {
27221 _this.imageCache[src] = image;
27222 resolve(image);
27223 };
27224 image.onerror = function (ev) {
27225 reject(ev);
27226 };
27227 image.crossOrigin = 'Anonymous';
27228 image.src = src;
27229 }
27230 });
27231 };
27232 ImagePool.prototype.getOrCreatePatternSync = function (pattern, context, $offscreenCanvas, dpr, callback) {
27233 var patternKey = this.generatePatternKey(pattern);
27234 if (patternKey && this.patternCache[patternKey]) {
27235 return this.patternCache[patternKey];
27236 }
27237 var image = pattern.image, repetition = pattern.repetition, transform = pattern.transform;
27238 var src;
27239 var needScaleWithDPR = false;
27240 // Image URL
27241 if (isString(image)) {
27242 src = this.getImageSync(image, callback);
27243 }
27244 else if ($offscreenCanvas) {
27245 src = $offscreenCanvas;
27246 needScaleWithDPR = true;
27247 }
27248 else {
27249 src = image;
27250 }
27251 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createPattern
27252 var canvasPattern = src && context.createPattern(src, repetition);
27253 if (canvasPattern) {
27254 var mat = void 0;
27255 // @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasPattern/setTransform
27256 if (transform) {
27257 mat = parsedTransformToMat4(parseTransform(transform), new DisplayObject({}));
27258 }
27259 else {
27260 mat = identity$1(create$1());
27261 }
27262 if (needScaleWithDPR) {
27263 scale(mat, mat, [1 / dpr, 1 / dpr, 1]);
27264 }
27265 canvasPattern.setTransform({
27266 a: mat[0],
27267 b: mat[1],
27268 c: mat[4],
27269 d: mat[5],
27270 e: mat[12],
27271 f: mat[13],
27272 });
27273 }
27274 if (patternKey && canvasPattern) {
27275 this.patternCache[patternKey] = canvasPattern;
27276 }
27277 return canvasPattern;
27278 };
27279 ImagePool.prototype.getOrCreateGradient = function (params, context) {
27280 var key = this.generateGradientKey(params);
27281 var type = params.type, steps = params.steps, width = params.width, height = params.height, angle = params.angle, cx = params.cx, cy = params.cy, size = params.size;
27282 if (this.gradientCache[key]) {
27283 return this.gradientCache[key];
27284 }
27285 var gradient = null;
27286 if (type === GradientType.LinearGradient) {
27287 var _a = computeLinearGradient(width, height, angle), x1 = _a.x1, y1 = _a.y1, x2 = _a.x2, y2 = _a.y2;
27288 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createLinearGradient
27289 gradient = context.createLinearGradient(x1, y1, x2, y2);
27290 }
27291 else if (type === GradientType.RadialGradient) {
27292 var _b = computeRadialGradient(width, height, cx, cy, size), x = _b.x, y = _b.y, r = _b.r;
27293 // @see https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/createRadialGradient
27294 gradient = context.createRadialGradient(x, y, 0, x, y, r);
27295 }
27296 if (gradient) {
27297 steps.forEach(function (_a) {
27298 var offset = _a.offset, color = _a.color;
27299 if (offset.unit === UnitType.kPercentage) {
27300 gradient === null || gradient === void 0 ? void 0 : gradient.addColorStop(offset.value / 100, color.toString());
27301 }
27302 });
27303 this.gradientCache[key] = gradient;
27304 }
27305 return this.gradientCache[key];
27306 };
27307 ImagePool.prototype.generateGradientKey = function (params) {
27308 var type = params.type, width = params.width, height = params.height, steps = params.steps, angle = params.angle, cx = params.cx, cy = params.cy, size = params.size;
27309 return "gradient-".concat(type, "-").concat((angle === null || angle === void 0 ? void 0 : angle.toString()) || 0, "-").concat((cx === null || cx === void 0 ? void 0 : cx.toString()) || 0, "-").concat((cy === null || cy === void 0 ? void 0 : cy.toString()) || 0, "-").concat((size === null || size === void 0 ? void 0 : size.toString()) || 0, "-").concat(width, "-").concat(height, "-").concat(steps
27310 .map(function (_a) {
27311 var offset = _a.offset, color = _a.color;
27312 return "".concat(offset).concat(color);
27313 })
27314 .join('-'));
27315 };
27316 ImagePool.prototype.generatePatternKey = function (pattern) {
27317 var image = pattern.image, repetition = pattern.repetition;
27318 // only generate cache for Image
27319 if (isString(image)) {
27320 return "pattern-".concat(image, "-").concat(repetition);
27321 }
27322 else if (image.nodeName === 'rect') {
27323 return "pattern-".concat(image.entity, "-").concat(repetition);
27324 }
27325 };
27326 return ImagePool;
27327 }());
27328
27329 var LoadImagePlugin = /** @class */ (function () {
27330 function LoadImagePlugin() {
27331 }
27332 LoadImagePlugin.prototype.apply = function (context) {
27333 var renderingService = context.renderingService, renderingContext = context.renderingContext, imagePool = context.imagePool;
27334 var canvas = renderingContext.root.ownerDocument.defaultView;
27335 var calculateWithAspectRatio = function (object, imageWidth, imageHeight) {
27336 var _a = object.parsedStyle, width = _a.width, height = _a.height;
27337 if (width && !height) {
27338 object.setAttribute('height', (imageHeight / imageWidth) * width);
27339 }
27340 else if (!width && height) {
27341 object.setAttribute('width', (imageWidth / imageHeight) * height);
27342 }
27343 };
27344 var handleMounted = function (e) {
27345 var object = e.target;
27346 var nodeName = object.nodeName, attributes = object.attributes;
27347 if (nodeName === Shape.IMAGE) {
27348 var img = attributes.img, keepAspectRatio_1 = attributes.keepAspectRatio;
27349 if (isString(img)) {
27350 imagePool.getImageSync(img, function (_a) {
27351 var width = _a.width, height = _a.height;
27352 if (keepAspectRatio_1) {
27353 calculateWithAspectRatio(object, width, height);
27354 }
27355 // set dirty rectangle flag
27356 object.renderable.dirty = true;
27357 renderingService.dirtify();
27358 });
27359 }
27360 }
27361 };
27362 var handleAttributeChanged = function (e) {
27363 var object = e.target;
27364 var attrName = e.attrName, newValue = e.newValue;
27365 if (object.nodeName === Shape.IMAGE) {
27366 if (attrName === 'img') {
27367 if (isString(newValue)) {
27368 imagePool.getOrCreateImage(newValue).then(function (_a) {
27369 var width = _a.width, height = _a.height;
27370 if (object.attributes.keepAspectRatio) {
27371 calculateWithAspectRatio(object, width, height);
27372 }
27373 // set dirty rectangle flag
27374 object.renderable.dirty = true;
27375 renderingService.dirtify();
27376 });
27377 }
27378 }
27379 }
27380 };
27381 renderingService.hooks.init.tap(LoadImagePlugin.tag, function () {
27382 canvas.addEventListener(ElementEvent.MOUNTED, handleMounted);
27383 canvas.addEventListener(ElementEvent.ATTR_MODIFIED, handleAttributeChanged);
27384 });
27385 renderingService.hooks.destroy.tap(LoadImagePlugin.tag, function () {
27386 canvas.removeEventListener(ElementEvent.MOUNTED, handleMounted);
27387 canvas.removeEventListener(ElementEvent.ATTR_MODIFIED, handleAttributeChanged);
27388 });
27389 };
27390 LoadImagePlugin.tag = 'LoadImage';
27391 return LoadImagePlugin;
27392 }());
27393
27394 var Plugin$4 = /** @class */ (function (_super) {
27395 __extends(Plugin, _super);
27396 function Plugin() {
27397 var _this = _super !== null && _super.apply(this, arguments) || this;
27398 _this.name = 'image-loader';
27399 return _this;
27400 }
27401 Plugin.prototype.init = function () {
27402 // @ts-ignore
27403 this.context.imagePool = new ImagePool(this.context.config);
27404 this.addRenderingPlugin(new LoadImagePlugin());
27405 };
27406 Plugin.prototype.destroy = function () {
27407 this.removeAllRenderingPlugins();
27408 };
27409 return Plugin;
27410 }(AbstractRendererPlugin));
27411
27412 /**
27413 * listen to mouse/touch/pointer events on DOM wrapper, trigger pointer events
27414 */
27415 var MobileInteractionPlugin = /** @class */ (function () {
27416 function MobileInteractionPlugin() {
27417 }
27418 MobileInteractionPlugin.prototype.apply = function (context) {
27419 var renderingService = context.renderingService, contextService = context.contextService, config = context.config;
27420 // 获取小程序上下文
27421 var canvasEl = contextService.getDomElement();
27422 var onPointerDown = function (ev) {
27423 renderingService.hooks.pointerDown.call(ev);
27424 };
27425 var onPointerUp = function (ev) {
27426 renderingService.hooks.pointerUp.call(ev);
27427 };
27428 var onPointerMove = function (ev) {
27429 // 触发 G 定义的标准 pointerMove 事件
27430 renderingService.hooks.pointerMove.call(ev);
27431 };
27432 var onPointerOver = function (ev) {
27433 renderingService.hooks.pointerOver.call(ev);
27434 };
27435 var onPointerOut = function (ev) {
27436 renderingService.hooks.pointerOut.call(ev);
27437 };
27438 var onClick = function (ev) {
27439 renderingService.hooks.click.call(ev);
27440 };
27441 var onPointerCancel = function (ev) {
27442 renderingService.hooks.pointerCancel.call(ev);
27443 };
27444 renderingService.hooks.init.tap(MobileInteractionPlugin.tag, function () {
27445 // 基于小程序上下文的事件监听方式,绑定事件监听,可以参考下面基于 DOM 的方式
27446 canvasEl.addEventListener('touchstart', onPointerDown, true);
27447 canvasEl.addEventListener('touchend', onPointerUp, true);
27448 canvasEl.addEventListener('touchmove', onPointerMove, true);
27449 canvasEl.addEventListener('touchcancel', onPointerCancel, true);
27450 // FIXME: 这里不应该只在 canvasEl 上监听 mousemove 和 mouseup,而应该在更高层级的节点上例如 document 监听。
27451 // 否则无法判断是否移出了 canvasEl
27452 // canvasEl.addEventListener('mousemove', onPointerMove, true);
27453 // canvasEl.addEventListener('mousedown', onPointerDown, true);
27454 canvasEl.addEventListener('mouseout', onPointerOut, true);
27455 canvasEl.addEventListener('mouseover', onPointerOver, true);
27456 // canvasEl.addEventListener('mouseup', onPointerUp, true);
27457 if (config.useNativeClickEvent) {
27458 canvasEl.addEventListener('click', onClick, true);
27459 }
27460 });
27461 renderingService.hooks.destroy.tap(MobileInteractionPlugin.tag, function () {
27462 // 基于小程序上下文的事件监听方式,移除事件监听
27463 canvasEl.removeEventListener('touchstart', onPointerDown, true);
27464 canvasEl.removeEventListener('touchend', onPointerUp, true);
27465 canvasEl.removeEventListener('touchmove', onPointerMove, true);
27466 canvasEl.removeEventListener('touchcancel', onPointerCancel, true);
27467 // canvasEl.removeEventListener('mousemove', onPointerMove, true);
27468 // canvasEl.removeEventListener('mousedown', onPointerDown, true);
27469 canvasEl.removeEventListener('mouseout', onPointerOut, true);
27470 canvasEl.removeEventListener('mouseover', onPointerOver, true);
27471 // canvasEl.removeEventListener('mouseup', onPointerUp, true);
27472 if (config.useNativeClickEvent) {
27473 canvasEl.removeEventListener('click', onClick, true);
27474 }
27475 });
27476 };
27477 MobileInteractionPlugin.tag = 'MobileInteraction';
27478 return MobileInteractionPlugin;
27479 }());
27480
27481 var Plugin$5 = /** @class */ (function (_super) {
27482 __extends(Plugin, _super);
27483 function Plugin() {
27484 var _this = _super !== null && _super.apply(this, arguments) || this;
27485 _this.name = 'mobile-interaction';
27486 return _this;
27487 }
27488 Plugin.prototype.init = function () {
27489 this.addRenderingPlugin(new MobileInteractionPlugin());
27490 };
27491 Plugin.prototype.destroy = function () {
27492 this.removeAllRenderingPlugins();
27493 };
27494 return Plugin;
27495 }(AbstractRendererPlugin));
27496
27497 /**
27498 * TODO: use clock from g later.
27499 */
27500 var clock$1 = typeof performance === 'object' && performance.now ? performance : Date;
27501 // 计算滑动的方向
27502 var calcDirection = function (start, end) {
27503 var xDistance = end.x - start.x;
27504 var yDistance = end.y - start.y;
27505 // x 的距离大于y 说明是横向,否则就是纵向
27506 if (Math.abs(xDistance) > Math.abs(yDistance)) {
27507 return xDistance > 0 ? 'right' : 'left';
27508 }
27509 return yDistance > 0 ? 'down' : 'up';
27510 };
27511 // 计算2点之间的距离
27512 var calcDistance = function (point1, point2) {
27513 var xDistance = Math.abs(point2.x - point1.x);
27514 var yDistance = Math.abs(point2.y - point1.y);
27515 return Math.sqrt(xDistance * xDistance + yDistance * yDistance);
27516 };
27517 var getCenter = function (point1, point2) {
27518 var x = point1.x + (point2.x - point1.x) / 2;
27519 var y = point1.y + (point2.y - point1.y) / 2;
27520 return { x: x, y: y };
27521 };
27522
27523 var PRESS_DELAY = 250;
27524 var GesturePlugin = /** @class */ (function () {
27525 function GesturePlugin(options) {
27526 var _this = this;
27527 this.options = options;
27528 this.evCache = [];
27529 this.startPoints = [];
27530 // 用来记录当前触发的事件
27531 this.processEvent = {};
27532 this.throttleTimer = 0;
27533 this.emitThrottles = [];
27534 this._start = function (ev, target) {
27535 var _a;
27536 // 每次触点开始都重置事件
27537 _this.reset();
27538 // 记录touch start 的时间
27539 _this.startTime = clock$1.now();
27540 var _b = _this, evCache = _b.evCache, startPoints = _b.startPoints;
27541 if (ev) {
27542 var pointerId_1 = ev.pointerId, x = ev.x, y = ev.y;
27543 // evcache 已经存在的 pointerId, 做替换
27544 var existIdx = evCache.findIndex(function (item) { return pointerId_1 === item.pointerId; });
27545 if (existIdx !== -1) {
27546 evCache.splice(existIdx, 1);
27547 }
27548 // evCache 不存在的 pointerId, 添加
27549 evCache.push({
27550 pointerId: pointerId_1,
27551 x: x,
27552 y: y,
27553 ev: ev,
27554 });
27555 // @ts-ignore 对齐touches evCache 存在,touches 不存在,移除
27556 var evTouches = __spreadArray([], __read((((_a = ev.nativeEvent) === null || _a === void 0 ? void 0 : _a.touches) || [])), false);
27557 var _loop_1 = function (i) {
27558 var isInTouches = evTouches.find(function (touch) {
27559 return evCache[i].pointerId === touch.identifier;
27560 });
27561 // 在touches中存在
27562 if (isInTouches) {
27563 return "continue";
27564 }
27565 // 在touches中不存在
27566 evCache.splice(i, 1);
27567 };
27568 for (var i = evCache.length - 1; i > -1; i--) {
27569 _loop_1(i);
27570 }
27571 }
27572 // 重置 startPoints
27573 startPoints.length = evCache.length;
27574 for (var i = 0; i < evCache.length; i++) {
27575 var _c = evCache[i], x = _c.x, y = _c.y;
27576 var point = { x: x, y: y };
27577 startPoints[i] = point;
27578 }
27579 // 单指事件
27580 if (startPoints.length === 1) {
27581 var event_1 = evCache[0].ev;
27582 // 如果touchstart后停顿250ms, 则也触发press事件
27583 // @ts-ignore
27584 _this.pressTimeout = setTimeout(function () {
27585 // 这里固定触发press事件
27586 var eventType = 'press';
27587 var direction = 'none';
27588 event_1.direction = direction;
27589 event_1.deltaX = 0;
27590 event_1.deltaY = 0;
27591 event_1.points = startPoints;
27592 _this.emitStart(eventType, event_1, target);
27593 event_1.type = eventType;
27594 target.dispatchEvent(event_1);
27595 _this.eventType = eventType;
27596 _this.direction = direction;
27597 _this.movingTarget = target;
27598 }, PRESS_DELAY);
27599 return;
27600 }
27601 // 目前只处理双指
27602 _this.startDistance = calcDistance(startPoints[0], startPoints[1]);
27603 _this.center = getCenter(startPoints[0], startPoints[1]);
27604 };
27605 this._move = function (ev, target) {
27606 _this.clearPressTimeout();
27607 var _a = _this, startPoints = _a.startPoints, evCache = _a.evCache;
27608 if (!startPoints.length)
27609 return;
27610 var x = ev.x, y = ev.y, pointerId = ev.pointerId;
27611 // Find this event in the cache and update its record with this event
27612 for (var i = 0, len = evCache.length; i < len; i++) {
27613 if (pointerId === evCache[i].pointerId) {
27614 evCache[i] = {
27615 pointerId: pointerId,
27616 x: x,
27617 y: y,
27618 ev: ev,
27619 };
27620 break;
27621 }
27622 }
27623 var point = { x: x, y: y };
27624 var points = evCache.map(function (ev) {
27625 return { x: ev.x, y: ev.y };
27626 });
27627 // 记录最后2次move的时间和坐标,为了给swipe事件用
27628 var now = clock$1.now();
27629 _this.prevMoveTime = _this.lastMoveTime;
27630 _this.prevMovePoint = _this.lastMovePoint;
27631 _this.lastMoveTime = now;
27632 _this.lastMovePoint = point;
27633 if (startPoints.length === 1) {
27634 var startPoint = startPoints[0];
27635 var deltaX = x - startPoint.x;
27636 var deltaY = y - startPoint.y;
27637 var direction = _this.direction || calcDirection(startPoint, point);
27638 _this.direction = direction;
27639 // 获取press或者pan的事件类型
27640 // press 按住滑动, pan表示平移
27641 // 如果start后立刻move,则触发pan, 如果有停顿,则触发press
27642 var eventType = _this.getEventType(point, target, ev);
27643 ev.direction = direction;
27644 ev.deltaX = deltaX;
27645 ev.deltaY = deltaY;
27646 ev.points = points;
27647 _this.emitStart(eventType, ev, target);
27648 ev.type = eventType;
27649 _this.refreshAndGetTarget(target).dispatchEvent(ev);
27650 return;
27651 }
27652 // 多指触控
27653 var startDistance = _this.startDistance;
27654 var currentDistance = calcDistance(points[0], points[1]);
27655 // 缩放比例
27656 ev.zoom = currentDistance / startDistance;
27657 ev.center = _this.center;
27658 ev.points = points;
27659 // 触发缩放事件
27660 _this.emitStart('pinch', ev, target);
27661 // touch 多指会被拆成多个手指的 move, 会触发多次 move,所以这里需要做节流
27662 _this._throttleEmit('pinch', ev, target);
27663 };
27664 this._end = function (ev, target) {
27665 var _a = _this, evCache = _a.evCache, startPoints = _a.startPoints;
27666 var points = evCache.map(function (ev) {
27667 return { x: ev.x, y: ev.y };
27668 });
27669 ev.points = points;
27670 _this.emitEnd(ev, _this.refreshAndGetTarget(target));
27671 // 单指
27672 if (evCache.length === 1) {
27673 // swipe事件处理, 在end之后触发
27674 var now = clock$1.now();
27675 var lastMoveTime = _this.lastMoveTime;
27676 // 做这个判断是为了最后一次touchmove后到end前,是否还有一个停顿的过程
27677 // 100 是拍的一个值,理论这个值会很短,一般不卡顿的话在10ms以内
27678 if (now - lastMoveTime < 100) {
27679 var prevMoveTime = _this.prevMoveTime || _this.startTime;
27680 var intervalTime = lastMoveTime - prevMoveTime;
27681 // 时间间隔一定要大于0, 否则计算没意义
27682 if (intervalTime > 0) {
27683 var prevMovePoint = _this.prevMovePoint || startPoints[0];
27684 var lastMovePoint = _this.lastMovePoint || startPoints[0];
27685 // move速率
27686 var velocity = calcDistance(prevMovePoint, lastMovePoint) / intervalTime;
27687 // 0.3 是参考hammerjs的设置
27688 if (velocity > 0.3) {
27689 ev.velocity = velocity;
27690 ev.direction = calcDirection(prevMovePoint, lastMovePoint);
27691 ev.type = 'swipe';
27692 target.dispatchEvent(ev);
27693 }
27694 }
27695 }
27696 }
27697 // remove event from cache
27698 for (var i = 0, len = evCache.length; i < len; i++) {
27699 if (evCache[i].pointerId === ev.pointerId) {
27700 evCache.splice(i, 1);
27701 startPoints.splice(i, 1);
27702 break;
27703 }
27704 }
27705 _this.reset();
27706 // 多指离开 1 指后,重新触发一次start
27707 if (evCache.length > 0) {
27708 _this._start(undefined, target);
27709 }
27710 };
27711 this._cancel = function (ev, target) {
27712 var evCache = _this.evCache;
27713 var points = evCache.map(function (ev) {
27714 return { x: ev.x, y: ev.y };
27715 });
27716 ev.points = points;
27717 _this.emitEnd(ev, _this.refreshAndGetTarget(target));
27718 _this.evCache = [];
27719 _this.reset();
27720 };
27721 }
27722 GesturePlugin.prototype.apply = function (context) {
27723 var _this = this;
27724 var renderingService = context.renderingService, renderingContext = context.renderingContext;
27725 var document = renderingContext.root.ownerDocument;
27726 var canvas = document.defaultView;
27727 this.canvas = canvas;
27728 var getGestureEventTarget = function (target) {
27729 var isDocument = target === document;
27730 return isDocument && _this.options.isDocumentGestureEnabled
27731 ? document
27732 : target;
27733 };
27734 var handlePointermove = function (ev) {
27735 var target = getGestureEventTarget(ev.target);
27736 target && _this._move(ev, target);
27737 };
27738 var handlePointerdown = function (ev) {
27739 var target = getGestureEventTarget(ev.target);
27740 target && _this._start(ev, target);
27741 };
27742 var handlePointerup = function (ev) {
27743 var target = getGestureEventTarget(ev.target);
27744 target && _this._end(ev, target);
27745 };
27746 var handlePointercancel = function (ev) {
27747 var target = getGestureEventTarget(ev.target);
27748 target && _this._cancel(ev, target);
27749 };
27750 var handlePointercanceloutside = function (ev) {
27751 var target = getGestureEventTarget(ev.target);
27752 target && _this._end(ev, target);
27753 };
27754 renderingService.hooks.init.tap(GesturePlugin.tag, function () {
27755 canvas.addEventListener('pointermove', handlePointermove);
27756 canvas.addEventListener('pointerdown', handlePointerdown);
27757 canvas.addEventListener('pointerup', handlePointerup);
27758 canvas.addEventListener('pointercancel', handlePointercancel);
27759 canvas.addEventListener('pointerupoutside', handlePointercanceloutside);
27760 });
27761 renderingService.hooks.destroy.tap(GesturePlugin.tag, function () {
27762 canvas.removeEventListener('pointermove', handlePointermove);
27763 canvas.removeEventListener('pointerdown', handlePointerdown);
27764 canvas.removeEventListener('pointerup', handlePointerup);
27765 canvas.removeEventListener('pointercancel', handlePointercancel);
27766 canvas.removeEventListener('pointerupoutside', handlePointercanceloutside);
27767 });
27768 };
27769 GesturePlugin.prototype.getEventType = function (point, target, ev) {
27770 var _a = this, eventType = _a.eventType, startTime = _a.startTime, startPoints = _a.startPoints;
27771 if (eventType) {
27772 return eventType;
27773 }
27774 // move的时候缓存节点,后续move和end都会使用这个target派发事件
27775 this.movingTarget = target;
27776 // 冒泡路径中是否有pan事件
27777 this.isPanListenerInPath = ev.path.some(function (ele) { var _a, _b; return !!((_b = (_a = ele.emitter) === null || _a === void 0 ? void 0 : _a.eventNames()) === null || _b === void 0 ? void 0 : _b.includes('pan')); });
27778 var type;
27779 // 如果没有pan事件的监听,默认都是press
27780 if (!this.isPanListenerInPath) {
27781 type = 'press';
27782 }
27783 else {
27784 // 如果有pan事件的处理,press则需要停顿250ms, 且移动距离小于10
27785 var now = clock$1.now();
27786 if (now - startTime > PRESS_DELAY &&
27787 calcDistance(startPoints[0], point) < 10) {
27788 type = 'press';
27789 }
27790 else {
27791 type = 'pan';
27792 }
27793 }
27794 this.eventType = type;
27795 return type;
27796 };
27797 GesturePlugin.prototype.enable = function (eventType) {
27798 this.processEvent[eventType] = true;
27799 };
27800 // 是否进行中的事件
27801 GesturePlugin.prototype.isProcess = function (eventType) {
27802 return this.processEvent[eventType];
27803 };
27804 // 触发start事件
27805 GesturePlugin.prototype.emitStart = function (type, ev, target) {
27806 if (this.isProcess(type)) {
27807 return;
27808 }
27809 this.enable(type);
27810 ev.type = "".concat(type, "start");
27811 target.dispatchEvent(ev);
27812 };
27813 // 触发事件
27814 GesturePlugin.prototype._throttleEmit = function (type, ev, target) {
27815 var _this = this;
27816 // 主要是节流处理
27817 this.pushEvent(type, ev);
27818 var _a = this, throttleTimer = _a.throttleTimer, emitThrottles = _a.emitThrottles, processEvent = _a.processEvent;
27819 if (throttleTimer) {
27820 return;
27821 }
27822 this.throttleTimer = this.canvas.requestAnimationFrame(function () {
27823 for (var i = 0, len = emitThrottles.length; i < len; i++) {
27824 var _a = emitThrottles[i], type_1 = _a.type, ev_1 = _a.ev;
27825 if (processEvent[type_1]) {
27826 ev_1.type = type_1;
27827 target.dispatchEvent(ev_1);
27828 }
27829 }
27830 // 清空
27831 _this.throttleTimer = 0;
27832 _this.emitThrottles.length = 0;
27833 });
27834 };
27835 // 触发end事件
27836 GesturePlugin.prototype.emitEnd = function (ev, target) {
27837 var processEvent = this.processEvent;
27838 Object.keys(processEvent).forEach(function (type) {
27839 ev.type = "".concat(type, "end");
27840 target.dispatchEvent(ev);
27841 delete processEvent[type];
27842 });
27843 };
27844 GesturePlugin.prototype.pushEvent = function (type, ev) {
27845 var emitThrottles = this.emitThrottles;
27846 var newEvent = { type: type, ev: ev };
27847 for (var i = 0, len = emitThrottles.length; i < len; i++) {
27848 if (emitThrottles[i].type === type) {
27849 emitThrottles.splice(i, 1, newEvent);
27850 return;
27851 }
27852 }
27853 emitThrottles.push(newEvent);
27854 };
27855 GesturePlugin.prototype.clearPressTimeout = function () {
27856 if (this.pressTimeout) {
27857 clearTimeout(this.pressTimeout);
27858 this.pressTimeout = null;
27859 }
27860 };
27861 GesturePlugin.prototype.refreshAndGetTarget = function (target) {
27862 if (this.movingTarget) {
27863 // @ts-ignore
27864 if (this.movingTarget && !this.movingTarget.isConnected) {
27865 this.movingTarget = target;
27866 }
27867 return this.movingTarget;
27868 }
27869 return target;
27870 };
27871 GesturePlugin.prototype.reset = function () {
27872 this.clearPressTimeout();
27873 this.startTime = 0;
27874 this.startDistance = 0;
27875 this.direction = null;
27876 this.eventType = null;
27877 this.prevMoveTime = 0;
27878 this.prevMovePoint = null;
27879 this.lastMoveTime = 0;
27880 this.lastMovePoint = null;
27881 this.movingTarget = null;
27882 this.isPanListenerInPath = null;
27883 };
27884 GesturePlugin.tag = 'Gesture';
27885 return GesturePlugin;
27886 }());
27887
27888 var Plugin$6 = /** @class */ (function (_super) {
27889 __extends(Plugin, _super);
27890 function Plugin(options) {
27891 if (options === void 0) { options = {}; }
27892 var _this = _super.call(this) || this;
27893 _this.options = options;
27894 _this.name = 'gesture';
27895 return _this;
27896 }
27897 Plugin.prototype.init = function () {
27898 this.addRenderingPlugin(new GesturePlugin(__assign({ isDocumentGestureEnabled: false }, this.options)));
27899 };
27900 Plugin.prototype.destroy = function () {
27901 this.removeAllRenderingPlugins();
27902 };
27903 return Plugin;
27904 }(AbstractRendererPlugin));
27905
27906 function isCanvasElement(el) {
27907 if (!el || typeof el !== 'object')
27908 return false;
27909 if (el.nodeType === 1 && el.nodeName) {
27910 // HTMLCanvasElement
27911 return true;
27912 }
27913 // CanvasElement
27914 return !!el.isCanvasElement;
27915 }
27916
27917 var Canvas2DContextService = /** @class */ (function () {
27918 function Canvas2DContextService(context) {
27919 this.canvasConfig = context.config;
27920 }
27921 Canvas2DContextService.prototype.init = function () {
27922 return __awaiter(this, void 0, void 0, function () {
27923 var _a, canvas, devicePixelRatio, dpr;
27924 return __generator(this, function (_b) {
27925 _a = this.canvasConfig, canvas = _a.canvas, devicePixelRatio = _a.devicePixelRatio;
27926 this.$canvas = canvas;
27927 // 实际获取到小程序环境的上下文
27928 this.context = this.$canvas.getContext('2d');
27929 dpr = devicePixelRatio || 1;
27930 dpr = dpr >= 1 ? Math.ceil(dpr) : 1;
27931 this.dpr = dpr;
27932 this.resize(this.canvasConfig.width, this.canvasConfig.height);
27933 return [2 /*return*/];
27934 });
27935 });
27936 };
27937 Canvas2DContextService.prototype.getContext = function () {
27938 return this.context;
27939 };
27940 Canvas2DContextService.prototype.getDomElement = function () {
27941 return this.$canvas;
27942 };
27943 Canvas2DContextService.prototype.getDPR = function () {
27944 return this.dpr;
27945 };
27946 Canvas2DContextService.prototype.getBoundingClientRect = function () {
27947 if (this.$canvas.getBoundingClientRect) {
27948 return this.$canvas.getBoundingClientRect();
27949 }
27950 };
27951 Canvas2DContextService.prototype.destroy = function () {
27952 // TODO: 小程序环境销毁 context
27953 this.context = null;
27954 this.$canvas = null;
27955 };
27956 Canvas2DContextService.prototype.resize = function (width, height) {
27957 var devicePixelRatio = this.canvasConfig.devicePixelRatio;
27958 var pixelRatio = devicePixelRatio;
27959 var canvasDOM = this.$canvas; // HTMLCanvasElement or canvasElement
27960 // 浏览器环境设置style样式
27961 if (canvasDOM.style) {
27962 canvasDOM.style.width = width + 'px';
27963 canvasDOM.style.height = height + 'px';
27964 }
27965 if (isCanvasElement(canvasDOM)) {
27966 canvasDOM.width = width * pixelRatio;
27967 canvasDOM.height = height * pixelRatio;
27968 if (pixelRatio !== 1) {
27969 this.context.scale(pixelRatio, pixelRatio);
27970 }
27971 }
27972 };
27973 Canvas2DContextService.prototype.applyCursorStyle = function (cursor) {
27974 // 小程序环境无需设置鼠标样式
27975 };
27976 Canvas2DContextService.prototype.toDataURL = function (options) {
27977 return __awaiter(this, void 0, void 0, function () {
27978 var type, encoderOptions;
27979 return __generator(this, function (_a) {
27980 type = options.type, encoderOptions = options.encoderOptions;
27981 return [2 /*return*/, this.context.canvas.toDataURL(type, encoderOptions)];
27982 });
27983 });
27984 };
27985 return Canvas2DContextService;
27986 }());
27987
27988 var ContextRegisterPlugin = /** @class */ (function (_super) {
27989 __extends(ContextRegisterPlugin, _super);
27990 function ContextRegisterPlugin() {
27991 var _this = _super !== null && _super.apply(this, arguments) || this;
27992 _this.name = 'mobile-canvas-context-register';
27993 return _this;
27994 }
27995 ContextRegisterPlugin.prototype.init = function () {
27996 this.context.ContextService = Canvas2DContextService;
27997 };
27998 ContextRegisterPlugin.prototype.destroy = function () {
27999 delete this.context.ContextService;
28000 };
28001 return ContextRegisterPlugin;
28002 }(AbstractRendererPlugin));
28003
28004 var Renderer = /** @class */ (function (_super) {
28005 __extends(Renderer, _super);
28006 function Renderer(config) {
28007 var _this = _super.call(this, config) || this;
28008 // register Canvas2DContext
28009 _this.registerPlugin(new ContextRegisterPlugin());
28010 _this.registerPlugin(new Plugin$4());
28011 _this.registerPlugin(new Plugin());
28012 // enable rendering with Canvas2D API
28013 _this.registerPlugin(new Plugin$2());
28014 _this.registerPlugin(new Plugin$5());
28015 // enable picking with Canvas2D API
28016 _this.registerPlugin(new Plugin$1());
28017 _this.registerPlugin(new Plugin$3({
28018 isDocumentDraggable: isNil(config === null || config === void 0 ? void 0 : config.isDocumentDraggable)
28019 ? true
28020 : config.isDocumentDraggable,
28021 isDocumentDroppable: isNil(config === null || config === void 0 ? void 0 : config.isDocumentDroppable)
28022 ? true
28023 : config.isDocumentDroppable,
28024 dragstartDistanceThreshold: isNil(config === null || config === void 0 ? void 0 : config.dragstartDistanceThreshold)
28025 ? 10
28026 : config.dragstartDistanceThreshold,
28027 dragstartTimeThreshold: isNil(config === null || config === void 0 ? void 0 : config.dragstartTimeThreshold)
28028 ? 50
28029 : config.dragstartTimeThreshold,
28030 }));
28031 _this.registerPlugin(new Plugin$6({
28032 isDocumentGestureEnabled: true,
28033 }));
28034 return _this;
28035 }
28036 return Renderer;
28037 }(AbstractRenderer));
28038
28039 // 实现jsx-classic 入口
28040 function jsx(type, config) {
28041 var children = [];
28042 for (var _i = 2; _i < arguments.length; _i++) {
28043 children[_i - 2] = arguments[_i];
28044 }
28045 var _a = config || {},
28046 key = _a.key,
28047 ref = _a.ref,
28048 props = __rest(_a, ["key", "ref"]);
28049 // 保持和automatic模式一致
28050 if (children.length) {
28051 props.children = children.length === 1 ? children[0] : children;
28052 }
28053 return {
28054 key: key,
28055 ref: ref,
28056 type: type,
28057 props: props
28058 };
28059 }
28060
28061 var fragment = (function (props) {
28062 return props.children;
28063 });
28064
28065 var CanvasElement = /** @class */ (function () {
28066 function CanvasElement(ctx) {
28067 this.isCanvasElement = true;
28068 this.emitter = new eventemitter3();
28069 this.context = ctx;
28070 // 有可能是 node canvas 创建的 context 对象
28071 var canvas = ctx.canvas || {};
28072 this.width = canvas.width || 0;
28073 this.height = canvas.height || 0;
28074 }
28075 CanvasElement.prototype.getContext = function (contextId, contextAttributes) {
28076 return this.context;
28077 };
28078 CanvasElement.prototype.getBoundingClientRect = function () {
28079 var width = this.width;
28080 var height = this.height;
28081 // 默认都处理成可视窗口的顶部位置
28082 return {
28083 top: 0,
28084 right: width,
28085 bottom: height,
28086 left: 0,
28087 width: width,
28088 height: height,
28089 x: 0,
28090 y: 0,
28091 };
28092 };
28093 CanvasElement.prototype.addEventListener = function (type, listener, options) {
28094 // TODO: implement options
28095 this.emitter.on(type, listener);
28096 };
28097 CanvasElement.prototype.removeEventListener = function (type, listener, options) {
28098 this.emitter.off(type, listener);
28099 };
28100 /**
28101 * @see https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget-dispatchEvent
28102 */
28103 CanvasElement.prototype.dispatchEvent = function (e) {
28104 this.emitter.emit(e.type, e);
28105 return true;
28106 };
28107 return CanvasElement;
28108 }());
28109 function supportEventListener(canvas) {
28110 if (!canvas) {
28111 return false;
28112 }
28113 // 非 HTMLCanvasElement
28114 if (canvas.nodeType !== 1 ||
28115 !canvas.nodeName ||
28116 canvas.nodeName.toLowerCase() !== 'canvas') {
28117 return false;
28118 }
28119 // 微信小程序canvas.getContext('2d')时也是CanvasRenderingContext2D
28120 // 也会有ctx.canvas, 而且nodeType也是1,所以还要在看下是否支持addEventListener
28121 var support = false;
28122 try {
28123 canvas.addEventListener('eventTest', function () {
28124 support = true;
28125 });
28126 canvas.dispatchEvent(new Event('eventTest'));
28127 }
28128 catch (error) {
28129 support = false;
28130 }
28131 return support;
28132 }
28133 function createMobileCanvasElement(ctx) {
28134 if (!ctx) {
28135 return null;
28136 }
28137 if (supportEventListener(ctx.canvas)) {
28138 return ctx.canvas;
28139 }
28140 return new CanvasElement(ctx);
28141 }
28142
28143 function createUpdater(canvas) {
28144 var setStateQueue = [];
28145 function process() {
28146 var item;
28147 var renderComponents = [];
28148 var renderCallbackQueue = [];
28149 while (item = setStateQueue.shift()) {
28150 var state = item.state,
28151 component = item.component,
28152 callback = item.callback;
28153 // 组件已销毁,不再触发 setState
28154 if (component.destroyed) {
28155 continue;
28156 }
28157 // 如果没有prevState,则将当前的state作为初始的prevState
28158 if (!component.prevState) {
28159 component.prevState = Object.assign({}, component.state);
28160 }
28161 // 如果stateChange是一个方法,也就是setState的第二种形式
28162 if (typeof state === 'function') {
28163 Object.assign(component.state, state(component.prevState, component.props));
28164 } else {
28165 // 如果stateChange是一个对象,则直接合并到setState中
28166 Object.assign(component.state, state);
28167 }
28168 component.prevState = component.state;
28169 if (typeof callback === 'function') {
28170 renderCallbackQueue.push({
28171 callback: callback,
28172 component: component
28173 });
28174 }
28175 if (renderComponents.indexOf(component) < 0) {
28176 renderComponents.push(component);
28177 }
28178 }
28179 canvas.updateComponents(renderComponents);
28180 // callback queue
28181 commitRenderQueue(renderCallbackQueue);
28182 }
28183 function enqueueSetState(component, state, callback) {
28184 if (setStateQueue.length === 0) {
28185 setTimeout(process, 0);
28186 }
28187 setStateQueue.push({
28188 component: component,
28189 state: state,
28190 callback: callback
28191 });
28192 }
28193 function commitRenderQueue(callbackQueue) {
28194 for (var i = 0; i < callbackQueue.length; i++) {
28195 var _a = callbackQueue[i],
28196 callback = _a.callback,
28197 component = _a.component;
28198 callback.call(component);
28199 }
28200 }
28201 var updater = {
28202 // isMounted: function(publicInstance) {
28203 // return false;
28204 // },
28205 enqueueForceUpdate: enqueueSetState,
28206 // enqueueReplaceState: function(publicInstance, completeState) {
28207 // },
28208 enqueueSetState: enqueueSetState
28209 };
28210 return updater;
28211 }
28212
28213 var THEME = {
28214 fontSize: '24px',
28215 fontFamily: '"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif',
28216 pixelRatio: 1,
28217 padding: [0, 0, 0, 0]
28218 };
28219
28220 var elementStyle = {
28221 fillStyle: 'String',
28222 font: 'String',
28223 globalAlpha: 'Number',
28224 lineCap: 'String',
28225 lineWidth: ['Number', 'String'],
28226 lineJoin: 'String',
28227 miterLimit: 'Number',
28228 shadowBlur: 'Number',
28229 shadowColor: 'String',
28230 shadowOffsetX: 'Number',
28231 shadowOffsetY: 'Number',
28232 strokeStyle: 'String',
28233 textAlign: 'String',
28234 textBaseline: 'String',
28235 lineDash: ['Array', 'Number'],
28236 shadow: 'String',
28237 matrix: 'Array',
28238 stroke: 'String',
28239 fill: ['String', 'Object'],
28240 opacity: 'Number',
28241 fillOpacity: 'Number',
28242 strokeOpacity: 'Number'
28243 };
28244 // css规则表 TODO:补充 / 多种类型
28245 var DEFAULT_CSS_RULE = {
28246 group: __assign({}, elementStyle),
28247 text: __assign(__assign({}, elementStyle), {
28248 x: 'Number',
28249 y: 'Number',
28250 text: 'String',
28251 width: 'Number',
28252 height: 'Number',
28253 fontSize: ['Number', 'String'],
28254 fontFamily: 'String',
28255 fontStyle: 'String',
28256 fontWeight: ['Number', 'String'],
28257 fontVariant: 'String'
28258 }),
28259 circle: __assign(__assign({}, elementStyle), {
28260 cx: 'Number',
28261 cy: 'Number',
28262 r: 'Number'
28263 }),
28264 path: __assign({}, elementStyle),
28265 ellipse: __assign(__assign({}, elementStyle), {
28266 cy: 'Number',
28267 cx: 'Number',
28268 ry: 'Number',
28269 rx: 'Number'
28270 }),
28271 rect: __assign(__assign({}, elementStyle), {
28272 width: 'Number',
28273 height: 'Number',
28274 x: 'Number',
28275 y: 'Number',
28276 radius: ['Array', 'Number']
28277 }),
28278 image: __assign(__assign({}, elementStyle), {
28279 width: 'Number',
28280 height: 'Number',
28281 x: 'Number',
28282 y: 'Number',
28283 img: 'String',
28284 src: 'String'
28285 }),
28286 line: __assign(__assign({}, elementStyle), {
28287 x1: 'Number',
28288 x2: 'Number',
28289 y1: 'Number',
28290 y2: 'Number'
28291 }),
28292 polyline: __assign(__assign({}, elementStyle), {
28293 points: 'Array',
28294 smooth: 'Boolean'
28295 }),
28296 polygon: __assign(__assign({}, elementStyle), {
28297 points: 'Array'
28298 }),
28299 arc: __assign(__assign({}, elementStyle), {
28300 x: 'Number',
28301 y: 'Number',
28302 r: 'Number',
28303 startAngle: ['Number', 'String'],
28304 endAngle: ['Number', 'String'],
28305 anticlockwise: 'Boolean'
28306 }),
28307 marker: __assign(__assign({}, elementStyle), {
28308 x: 'Number',
28309 y: 'Number',
28310 radius: 'Number',
28311 symbol: 'String'
28312 }),
28313 sector: __assign(__assign({}, elementStyle), {
28314 x: 'Number',
28315 y: 'Number',
28316 startAngle: ['Number', 'String'],
28317 endAngle: ['Number', 'String'],
28318 r: 'Number',
28319 r0: 'Number',
28320 anticlockwise: 'Boolean'
28321 })
28322 };
28323 function checkCSSRule(type, style) {
28324 if (!style) {
28325 return style;
28326 }
28327 var cssStyle = {};
28328 Object.keys(style).forEach(function (key) {
28329 var value = style[key];
28330 if (isNil(value)) {
28331 return;
28332 }
28333 var rule = DEFAULT_CSS_RULE[type] && DEFAULT_CSS_RULE[type][key];
28334 if (!rule) {
28335 cssStyle[key] = value;
28336 return;
28337 }
28338 var valueType = Object.prototype.toString.call(value);
28339 if (isArray(rule)) {
28340 for (var i = 0, len = rule.length; i < len; i++) {
28341 if (valueType === "[object ".concat(rule[i], "]")) {
28342 cssStyle[key] = value;
28343 return;
28344 }
28345 }
28346 // 没有匹配的类型
28347 return;
28348 }
28349 // string
28350 if (valueType === "[object ".concat(rule, "]")) {
28351 cssStyle[key] = value;
28352 }
28353 });
28354 return cssStyle;
28355 }
28356
28357 // 默认设置50
28358 var ONE_REM;
28359 try {
28360 // xgraph下这段会抛错
28361 ONE_REM = parseInt(document.documentElement.style.fontSize, 10) || 50;
28362 } catch (e) {
28363 ONE_REM = 50;
28364 }
28365 var SCALE = ONE_REM / 100;
28366 /**
28367 * 像素转换
28368 * @param {Number} px - 750视觉稿像素
28369 * @return {Number} 屏幕上实际像素
28370 */
28371 function defaultPx2hd(px) {
28372 if (!px) {
28373 return 0;
28374 }
28375 return Number((px * SCALE).toFixed(1));
28376 }
28377 function parsePadding(padding) {
28378 if (isNumber(padding)) {
28379 return [padding, padding, padding, padding];
28380 }
28381 var top = padding[0];
28382 var right = isNumber(padding[1]) ? padding[1] : padding[0];
28383 var bottom = isNumber(padding[2]) ? padding[2] : top;
28384 var left = isNumber(padding[3]) ? padding[3] : right;
28385 return [top, right, bottom, left];
28386 }
28387 function batch2hd(px2hd) {
28388 var batchPx2hd = function batchPx2hd(value) {
28389 // 处理带px的数据
28390 if (isString(value) && /^-?\d+(\.\d+)?px$/.test(value)) {
28391 var num = value.substr(0, value.length - 2);
28392 return px2hd(Number(num));
28393 }
28394 if (isArray(value)) {
28395 return value.map(function (v) {
28396 return batchPx2hd(v);
28397 });
28398 }
28399 if (isPlainObject(value)) {
28400 var result = {};
28401 for (var key in value) {
28402 if (value.hasOwnProperty(key)) {
28403 var rst = batchPx2hd(value[key]);
28404 if (!rst) {
28405 result[key] = rst;
28406 continue;
28407 }
28408 if (key === 'padding' || key === 'margin') {
28409 var paddingArray = parsePadding(rst);
28410 result[key] = paddingArray;
28411 result["".concat(key, "Top")] = paddingArray[0];
28412 result["".concat(key, "Right")] = paddingArray[1];
28413 result["".concat(key, "Bottom")] = paddingArray[2];
28414 result["".concat(key, "Left")] = paddingArray[3];
28415 continue;
28416 }
28417 result[key] = rst;
28418 }
28419 }
28420 return result;
28421 }
28422 // 默认直接返回
28423 return value;
28424 };
28425 return batchPx2hd;
28426 }
28427 var px2hd = batch2hd(defaultPx2hd);
28428
28429 /**
28430 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationPlaybackEvent
28431 */
28432 // @ts-ignore
28433 var AnimationEvent = /** @class */ (function (_super) {
28434 __extends(AnimationEvent, _super);
28435 function AnimationEvent(manager, target, currentTime, timelineTime) {
28436 var _this = _super.call(this, manager) || this;
28437 _this.currentTime = currentTime;
28438 _this.timelineTime = timelineTime;
28439 // @ts-ignore
28440 _this.target = target;
28441 _this.type = 'finish';
28442 _this.bubbles = false;
28443 // @ts-ignore
28444 _this.currentTarget = target;
28445 _this.defaultPrevented = false;
28446 _this.eventPhase = _this.AT_TARGET;
28447 _this.timeStamp = Date.now();
28448 _this.currentTime = currentTime;
28449 _this.timelineTime = timelineTime;
28450 return _this;
28451 }
28452 return AnimationEvent;
28453 }(FederatedEvent));
28454
28455 var sequenceNumber = 0;
28456 /**
28457 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/Animation
28458 */
28459 var Animation = /** @class */ (function () {
28460 function Animation(effect, timeline) {
28461 var _a;
28462 this.currentTimePending = false;
28463 /**
28464 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/playState
28465 */
28466 // playState: AnimationPlayState;
28467 this._idle = true;
28468 this._paused = false;
28469 this._finishedFlag = true;
28470 /**
28471 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/currentTime
28472 */
28473 this._currentTime = 0;
28474 this._playbackRate = 1;
28475 this._inTimeline = true;
28476 this.effect = effect;
28477 effect.animation = this;
28478 this.timeline = timeline;
28479 this.id = "".concat(sequenceNumber++);
28480 this._inEffect = !!this.effect.update(0);
28481 this._totalDuration = Number((_a = this.effect) === null || _a === void 0 ? void 0 : _a.getComputedTiming().endTime);
28482 this._holdTime = 0;
28483 this._paused = false;
28484 this.oldPlayState = 'idle';
28485 this.updatePromises();
28486 }
28487 Object.defineProperty(Animation.prototype, "pending", {
28488 // animation: InternalAnimation | null;
28489 /**
28490 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/pending
28491 */
28492 get: function () {
28493 return ((this._startTime === null && !this._paused && this.playbackRate !== 0) ||
28494 this.currentTimePending);
28495 },
28496 enumerable: false,
28497 configurable: true
28498 });
28499 Object.defineProperty(Animation.prototype, "playState", {
28500 get: function () {
28501 if (this._idle)
28502 return 'idle';
28503 if (this._isFinished)
28504 return 'finished';
28505 if (this._paused)
28506 return 'paused';
28507 return 'running';
28508 },
28509 enumerable: false,
28510 configurable: true
28511 });
28512 Object.defineProperty(Animation.prototype, "ready", {
28513 /**
28514 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/ready
28515 * @example
28516 animation.pause();
28517 animation.ready.then(function() {
28518 // Displays 'running'
28519 alert(animation.playState);
28520 });
28521 animation.play();
28522 */
28523 get: function () {
28524 var _this = this;
28525 if (!this.readyPromise) {
28526 if (this.timeline.animationsWithPromises.indexOf(this) === -1) {
28527 this.timeline.animationsWithPromises.push(this);
28528 }
28529 this.readyPromise = new Promise(function (resolve, reject) {
28530 _this.resolveReadyPromise = function () {
28531 resolve(_this);
28532 };
28533 _this.rejectReadyPromise = function () {
28534 reject(new Error());
28535 };
28536 });
28537 if (!this.pending) {
28538 this.resolveReadyPromise();
28539 }
28540 }
28541 return this.readyPromise;
28542 },
28543 enumerable: false,
28544 configurable: true
28545 });
28546 Object.defineProperty(Animation.prototype, "finished", {
28547 /**
28548 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/finished
28549 * @example
28550 Promise.all(
28551 elem.getAnimations().map(
28552 function(animation) {
28553 return animation.finished
28554 }
28555 )
28556 ).then(
28557 function() {
28558 return elem.remove();
28559 }
28560 );
28561 */
28562 get: function () {
28563 var _this = this;
28564 if (!this.finishedPromise) {
28565 if (this.timeline.animationsWithPromises.indexOf(this) === -1) {
28566 this.timeline.animationsWithPromises.push(this);
28567 }
28568 this.finishedPromise = new Promise(function (resolve, reject) {
28569 _this.resolveFinishedPromise = function () {
28570 resolve(_this);
28571 };
28572 _this.rejectFinishedPromise = function () {
28573 reject(new Error());
28574 };
28575 });
28576 if (this.playState === 'finished') {
28577 this.resolveFinishedPromise();
28578 }
28579 }
28580 return this.finishedPromise;
28581 },
28582 enumerable: false,
28583 configurable: true
28584 });
28585 Object.defineProperty(Animation.prototype, "currentTime", {
28586 get: function () {
28587 this.updatePromises();
28588 return this._idle || this.currentTimePending ? null : this._currentTime;
28589 },
28590 set: function (newTime) {
28591 var _a;
28592 newTime = Number(newTime);
28593 if (isNaN(newTime))
28594 return;
28595 this.timeline.restart();
28596 if (!this._paused && this._startTime !== null) {
28597 this._startTime =
28598 Number((_a = this.timeline) === null || _a === void 0 ? void 0 : _a.currentTime) - newTime / this.playbackRate;
28599 }
28600 this.currentTimePending = false;
28601 if (this._currentTime === newTime) {
28602 return;
28603 }
28604 if (this._idle) {
28605 this._idle = false;
28606 this._paused = true;
28607 }
28608 this.tickCurrentTime(newTime, true);
28609 this.timeline.applyDirtiedAnimation(this);
28610 },
28611 enumerable: false,
28612 configurable: true
28613 });
28614 Object.defineProperty(Animation.prototype, "startTime", {
28615 get: function () {
28616 return this._startTime;
28617 },
28618 set: function (newTime) {
28619 if (newTime !== null) {
28620 this.updatePromises();
28621 newTime = Number(newTime);
28622 if (isNaN(newTime))
28623 return;
28624 if (this._paused || this._idle)
28625 return;
28626 this._startTime = newTime;
28627 this.tickCurrentTime((Number(this.timeline.currentTime) - this._startTime) *
28628 this.playbackRate);
28629 this.timeline.applyDirtiedAnimation(this);
28630 this.updatePromises();
28631 }
28632 },
28633 enumerable: false,
28634 configurable: true
28635 });
28636 Object.defineProperty(Animation.prototype, "playbackRate", {
28637 get: function () {
28638 return this._playbackRate;
28639 },
28640 set: function (value) {
28641 if (value === this._playbackRate) {
28642 return;
28643 }
28644 this.updatePromises();
28645 var oldCurrentTime = this.currentTime;
28646 this._playbackRate = value;
28647 this.startTime = null;
28648 if (this.playState !== 'paused' && this.playState !== 'idle') {
28649 this._finishedFlag = false;
28650 this._idle = false;
28651 this.ensureAlive();
28652 this.timeline.applyDirtiedAnimation(this);
28653 }
28654 if (oldCurrentTime !== null) {
28655 this.currentTime = oldCurrentTime;
28656 }
28657 this.updatePromises();
28658 },
28659 enumerable: false,
28660 configurable: true
28661 });
28662 Object.defineProperty(Animation.prototype, "_isFinished", {
28663 get: function () {
28664 return (!this._idle &&
28665 ((this._playbackRate > 0 &&
28666 Number(this._currentTime) >= this._totalDuration) ||
28667 (this._playbackRate < 0 && Number(this._currentTime) <= 0)));
28668 },
28669 enumerable: false,
28670 configurable: true
28671 });
28672 Object.defineProperty(Animation.prototype, "totalDuration", {
28673 get: function () {
28674 return this._totalDuration;
28675 },
28676 enumerable: false,
28677 configurable: true
28678 });
28679 Object.defineProperty(Animation.prototype, "_needsTick", {
28680 get: function () {
28681 return this.pending || this.playState === 'running' || !this._finishedFlag;
28682 },
28683 enumerable: false,
28684 configurable: true
28685 });
28686 /**
28687 * state machine,
28688 * resolve/reject ready/finished Promise according to current state
28689 */
28690 Animation.prototype.updatePromises = function () {
28691 var oldPlayState = this.oldPlayState;
28692 var newPlayState = this.pending ? 'pending' : this.playState;
28693 if (this.readyPromise && newPlayState !== oldPlayState) {
28694 if (newPlayState === 'idle') {
28695 this.rejectReadyPromise();
28696 this.readyPromise = undefined;
28697 }
28698 else if (oldPlayState === 'pending') {
28699 this.resolveReadyPromise();
28700 }
28701 else if (newPlayState === 'pending') {
28702 this.readyPromise = undefined;
28703 }
28704 }
28705 if (this.finishedPromise && newPlayState !== oldPlayState) {
28706 if (newPlayState === 'idle') {
28707 this.rejectFinishedPromise();
28708 this.finishedPromise = undefined;
28709 }
28710 else if (newPlayState === 'finished') {
28711 this.resolveFinishedPromise();
28712 }
28713 else if (oldPlayState === 'finished') {
28714 this.finishedPromise = undefined;
28715 }
28716 }
28717 this.oldPlayState = newPlayState;
28718 return this.readyPromise || this.finishedPromise;
28719 };
28720 Animation.prototype.play = function () {
28721 this.updatePromises();
28722 this._paused = false;
28723 if (this._isFinished || this._idle) {
28724 this.rewind();
28725 this._startTime = null;
28726 }
28727 this._finishedFlag = false;
28728 this._idle = false;
28729 this.ensureAlive();
28730 this.timeline.applyDirtiedAnimation(this);
28731 if (this.timeline.animations.indexOf(this) === -1) {
28732 this.timeline.animations.push(this);
28733 }
28734 this.updatePromises();
28735 };
28736 Animation.prototype.pause = function () {
28737 this.updatePromises();
28738 if (this.currentTime) {
28739 this._holdTime = this.currentTime;
28740 }
28741 if (!this._isFinished && !this._paused && !this._idle) {
28742 this.currentTimePending = true;
28743 }
28744 else if (this._idle) {
28745 this.rewind();
28746 this._idle = false;
28747 }
28748 this._startTime = null;
28749 this._paused = true;
28750 this.updatePromises();
28751 };
28752 Animation.prototype.finish = function () {
28753 this.updatePromises();
28754 if (this._idle)
28755 return;
28756 this.currentTime = this._playbackRate > 0 ? this._totalDuration : 0;
28757 this._startTime = this._totalDuration - this.currentTime;
28758 this.currentTimePending = false;
28759 this.timeline.applyDirtiedAnimation(this);
28760 this.updatePromises();
28761 };
28762 Animation.prototype.cancel = function () {
28763 var _this = this;
28764 this.updatePromises();
28765 if (!this._inEffect)
28766 return;
28767 this._inEffect = false;
28768 this._idle = true;
28769 this._paused = false;
28770 this._finishedFlag = true;
28771 this._currentTime = 0;
28772 this._startTime = null;
28773 this.effect.update(null);
28774 // effects are invalid after cancellation as the animation state
28775 // needs to un-apply.
28776 this.timeline.applyDirtiedAnimation(this);
28777 this.updatePromises();
28778 /**
28779 * 1. Reject the current finished promise with a DOMException named "AbortError".
28780 * 2. Let current finished promise be a new promise
28781 * @see https://w3c.github.io/csswg-drafts/web-animations-1/#canceling-an-animation-section
28782 */
28783 // if (this.finishedPromise) {
28784 // this.rejectFinishedPromise();
28785 // this.finishedPromise = undefined;
28786 // }
28787 if (this.oncancel) {
28788 var event_1 = new AnimationEvent(null, this, this.currentTime, null);
28789 setTimeout(function () {
28790 _this.oncancel(event_1);
28791 });
28792 }
28793 };
28794 Animation.prototype.reverse = function () {
28795 this.updatePromises();
28796 var oldCurrentTime = this.currentTime;
28797 this.playbackRate *= -1;
28798 this.play();
28799 if (oldCurrentTime !== null) {
28800 this.currentTime = oldCurrentTime;
28801 }
28802 this.updatePromises();
28803 };
28804 /**
28805 * @see https://developer.mozilla.org/en-US/docs/Web/API/Animation/updatePlaybackRate
28806 */
28807 Animation.prototype.updatePlaybackRate = function (playbackRate) {
28808 this.playbackRate = playbackRate;
28809 };
28810 Animation.prototype.targetAnimations = function () {
28811 var _a;
28812 var target = (_a = this.effect) === null || _a === void 0 ? void 0 : _a.target;
28813 return target.getAnimations();
28814 };
28815 Animation.prototype.markTarget = function () {
28816 var animations = this.targetAnimations();
28817 if (animations.indexOf(this) === -1) {
28818 animations.push(this);
28819 }
28820 };
28821 Animation.prototype.unmarkTarget = function () {
28822 var animations = this.targetAnimations();
28823 var index = animations.indexOf(this);
28824 if (index !== -1) {
28825 animations.splice(index, 1);
28826 }
28827 };
28828 Animation.prototype.tick = function (timelineTime, isAnimationFrame) {
28829 if (!this._idle && !this._paused) {
28830 if (this._startTime === null) {
28831 if (isAnimationFrame) {
28832 this.startTime = timelineTime - this._currentTime / this.playbackRate;
28833 }
28834 }
28835 else if (!this._isFinished) {
28836 this.tickCurrentTime((timelineTime - this._startTime) * this.playbackRate);
28837 }
28838 }
28839 if (isAnimationFrame) {
28840 this.currentTimePending = false;
28841 this.fireEvents(timelineTime);
28842 }
28843 };
28844 Animation.prototype.rewind = function () {
28845 if (this.playbackRate >= 0) {
28846 this.currentTime = 0;
28847 }
28848 else if (this._totalDuration < Infinity) {
28849 this.currentTime = this._totalDuration;
28850 }
28851 else {
28852 throw new Error('Unable to rewind negative playback rate animation with infinite duration');
28853 }
28854 };
28855 Animation.prototype.persist = function () {
28856 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
28857 };
28858 Animation.prototype.addEventListener = function (type, listener, options) {
28859 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
28860 };
28861 Animation.prototype.removeEventListener = function (type, listener, options) {
28862 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
28863 };
28864 Animation.prototype.dispatchEvent = function (event) {
28865 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
28866 };
28867 // replaceState: AnimationReplaceState;
28868 Animation.prototype.commitStyles = function () {
28869 throw new Error(ERROR_MSG_METHOD_NOT_IMPLEMENTED);
28870 };
28871 Animation.prototype.ensureAlive = function () {
28872 var _a, _b;
28873 // If an animation is playing backwards and is not fill backwards/both
28874 // then it should go out of effect when it reaches the start of its
28875 // active interval (currentTime === 0).
28876 if (this.playbackRate < 0 && this.currentTime === 0) {
28877 this._inEffect = !!((_a = this.effect) === null || _a === void 0 ? void 0 : _a.update(-1));
28878 }
28879 else {
28880 this._inEffect = !!((_b = this.effect) === null || _b === void 0 ? void 0 : _b.update(this.currentTime));
28881 }
28882 if (!this._inTimeline && (this._inEffect || !this._finishedFlag)) {
28883 this._inTimeline = true;
28884 this.timeline.animations.push(this);
28885 }
28886 };
28887 Animation.prototype.tickCurrentTime = function (newTime, ignoreLimit) {
28888 if (newTime !== this._currentTime) {
28889 this._currentTime = newTime;
28890 if (this._isFinished && !ignoreLimit) {
28891 this._currentTime = this._playbackRate > 0 ? this._totalDuration : 0;
28892 }
28893 this.ensureAlive();
28894 }
28895 };
28896 Animation.prototype.fireEvents = function (baseTime) {
28897 var _this = this;
28898 if (this._isFinished) {
28899 if (!this._finishedFlag) {
28900 if (this.onfinish) {
28901 var event_2 = new AnimationEvent(null, this, this.currentTime, baseTime);
28902 setTimeout(function () {
28903 if (_this.onfinish) {
28904 _this.onfinish(event_2);
28905 }
28906 });
28907 }
28908 this._finishedFlag = true;
28909 }
28910 }
28911 else {
28912 if (this.onframe && this.playState === 'running') {
28913 var event_3 = new AnimationEvent(null, this, this.currentTime, baseTime);
28914 this.onframe(event_3);
28915 }
28916 this._finishedFlag = false;
28917 }
28918 };
28919 return Animation;
28920 }());
28921
28922 /**
28923 * https://github.com/gre/bezier-easing
28924 * BezierEasing - use bezier curve for transition easing function
28925 * by Gaëtan Renaudeau 2014 - 2015 – MIT License
28926 */
28927 // These values are established by empiricism with tests (tradeoff: performance VS precision)
28928 var NEWTON_ITERATIONS = 4;
28929 var NEWTON_MIN_SLOPE = 0.001;
28930 var SUBDIVISION_PRECISION = 0.0000001;
28931 var SUBDIVISION_MAX_ITERATIONS = 10;
28932 var kSplineTableSize = 11;
28933 var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
28934 var float32ArraySupported = typeof Float32Array === 'function';
28935 var A = function (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; };
28936 var B = function (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; };
28937 var C = function (aA1) { return 3.0 * aA1; };
28938 // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
28939 var calcBezier = function (aT, aA1, aA2) {
28940 return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
28941 };
28942 // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
28943 var getSlope = function (aT, aA1, aA2) {
28944 return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
28945 };
28946 var binarySubdivide = function (aX, aA, aB, mX1, mX2) {
28947 var currentX, currentT, i = 0;
28948 do {
28949 currentT = aA + (aB - aA) / 2.0;
28950 currentX = calcBezier(currentT, mX1, mX2) - aX;
28951 if (currentX > 0.0)
28952 aB = currentT;
28953 else
28954 aA = currentT;
28955 } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
28956 return currentT;
28957 };
28958 var newtonRaphsonIterate = function (aX, aGuessT, mX1, mX2) {
28959 for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
28960 var currentSlope = getSlope(aGuessT, mX1, mX2);
28961 if (currentSlope === 0.0)
28962 return aGuessT;
28963 var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
28964 aGuessT -= currentX / currentSlope;
28965 }
28966 return aGuessT;
28967 };
28968 var bezier = function (mX1, mY1, mX2, mY2) {
28969 if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1))
28970 throw new Error('bezier x values must be in [0, 1] range');
28971 if (mX1 === mY1 && mX2 === mY2)
28972 return function (t) { return t; };
28973 // Precompute samples table
28974 var sampleValues = float32ArraySupported
28975 ? new Float32Array(kSplineTableSize)
28976 : new Array(kSplineTableSize);
28977 for (var i = 0; i < kSplineTableSize; ++i) {
28978 sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
28979 }
28980 var getTForX = function (aX) {
28981 var intervalStart = 0.0;
28982 var currentSample = 1;
28983 var lastSample = kSplineTableSize - 1;
28984 for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample)
28985 intervalStart += kSampleStepSize;
28986 --currentSample;
28987 // Interpolate to provide an initial guess for t
28988 var dist = (aX - sampleValues[currentSample]) /
28989 (sampleValues[currentSample + 1] - sampleValues[currentSample]);
28990 var guessForT = intervalStart + dist * kSampleStepSize;
28991 var initialSlope = getSlope(guessForT, mX1, mX2);
28992 if (initialSlope >= NEWTON_MIN_SLOPE)
28993 return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
28994 else if (initialSlope === 0.0)
28995 return guessForT;
28996 else {
28997 return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
28998 }
28999 };
29000 return function (t) {
29001 // Because JavaScript number are imprecise, we should guarantee the extremes are right.
29002 if (t === 0 || t === 1)
29003 return t;
29004 return calcBezier(getTForX(t), mY1, mY2);
29005 };
29006 };
29007
29008 var convertToDash = function (str) {
29009 str = str.replace(/([A-Z])/g, function (letter) { return "-".concat(letter.toLowerCase()); });
29010 // Remove first dash
29011 return str.charAt(0) === '-' ? str.substring(1) : str;
29012 };
29013 /**
29014 Easing Functions from anime.js, they are tried and true, so, its better to use them instead of other alternatives
29015 */
29016 var Quad = function (t) { return Math.pow(t, 2); };
29017 var Cubic = function (t) { return Math.pow(t, 3); };
29018 var Quart = function (t) { return Math.pow(t, 4); };
29019 var Quint = function (t) { return Math.pow(t, 5); };
29020 var Expo = function (t) { return Math.pow(t, 6); };
29021 var Sine = function (t) { return 1 - Math.cos((t * Math.PI) / 2); };
29022 var Circ = function (t) { return 1 - Math.sqrt(1 - t * t); };
29023 var Back = function (t) { return t * t * (3 * t - 2); };
29024 var Bounce = function (t) {
29025 var pow2, b = 4;
29026 while (t < ((pow2 = Math.pow(2, --b)) - 1) / 11) { }
29027 return 1 / Math.pow(4, 3 - b) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - t, 2);
29028 };
29029 var Elastic = function (t, params) {
29030 if (params === void 0) { params = []; }
29031 var _a = __read(params, 2), _b = _a[0], amplitude = _b === void 0 ? 1 : _b, _c = _a[1], period = _c === void 0 ? 0.5 : _c;
29032 var a = clamp(Number(amplitude), 1, 10);
29033 var p = clamp(Number(period), 0.1, 2);
29034 if (t === 0 || t === 1)
29035 return t;
29036 return (-a *
29037 Math.pow(2, 10 * (t - 1)) *
29038 Math.sin(((t - 1 - (p / (Math.PI * 2)) * Math.asin(1 / a)) * (Math.PI * 2)) / p));
29039 };
29040 var Spring = function (t, params, duration) {
29041 if (params === void 0) { params = []; }
29042 var _a = __read(params, 4), _b = _a[0], mass = _b === void 0 ? 1 : _b, _c = _a[1], stiffness = _c === void 0 ? 100 : _c, _d = _a[2], damping = _d === void 0 ? 10 : _d, _e = _a[3], velocity = _e === void 0 ? 0 : _e;
29043 mass = clamp(mass, 0.1, 1000);
29044 stiffness = clamp(stiffness, 0.1, 1000);
29045 damping = clamp(damping, 0.1, 1000);
29046 velocity = clamp(velocity, 0.1, 1000);
29047 var w0 = Math.sqrt(stiffness / mass);
29048 var zeta = damping / (2 * Math.sqrt(stiffness * mass));
29049 var wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0;
29050 var a = 1;
29051 var b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0;
29052 var progress = duration ? (duration * t) / 1000 : t;
29053 if (zeta < 1) {
29054 progress =
29055 Math.exp(-progress * zeta * w0) * (a * Math.cos(wd * progress) + b * Math.sin(wd * progress));
29056 }
29057 else {
29058 progress = (a + b * progress) * Math.exp(-progress * w0);
29059 }
29060 if (t === 0 || t === 1)
29061 return t;
29062 return 1 - progress;
29063 };
29064 /**
29065 * Cache the durations at set easing parameters
29066 */
29067 // export const EasingDurationCache: Map<string | TypeEasingFunction, number> = new Map();
29068 /**
29069 * The threshold for an infinite loop
29070 */
29071 // const INTINITE_LOOP_LIMIT = 10000;
29072 /** Convert easing parameters to Array of numbers, e.g. "spring(2, 500)" to [2, 500] */
29073 // export const parseEasingParameters = (str: string) => {
29074 // const match = /(\(|\s)([^)]+)\)?/.exec(str);
29075 // return match
29076 // ? match[2].split(',').map((value) => {
29077 // const num = parseFloat(value);
29078 // return !Number.isNaN(num) ? num : value.trim();
29079 // })
29080 // : [];
29081 // };
29082 /**
29083 * The spring easing function will only look smooth at certain durations, with certain parameters.
29084 * This functions returns the optimal duration to create a smooth springy animation based on physics
29085 *
29086 * Note: it can also be used to determine the optimal duration of other types of easing function, but be careful of 'in-'
29087 * easing functions, because of the nature of the function it can sometimes create an infinite loop, I suggest only using
29088 * `getEasingDuration` for `spring`, specifically 'out-spring' and 'spring'
29089 */
29090 // export const getEasingDuration = (easing: string | TypeEasingFunction = 'spring') => {
29091 // if (EasingDurationCache.has(easing)) return EasingDurationCache.get(easing);
29092 // // eslint-disable-next-line @typescript-eslint/no-use-before-define
29093 // const easingFunction = typeof easing == 'function' ? easing : getEasingFunction(easing as string);
29094 // const params = typeof easing == 'function' ? [] : parseEasingParameters(easing);
29095 // const frame = 1 / 6;
29096 // let elapsed = 0;
29097 // let rest = 0;
29098 // let count = 0;
29099 // while (++count < INTINITE_LOOP_LIMIT) {
29100 // elapsed += frame;
29101 // if (easingFunction(elapsed, params, undefined) === 1) {
29102 // rest++;
29103 // if (rest >= 16) break;
29104 // } else {
29105 // rest = 0;
29106 // }
29107 // }
29108 // const duration = elapsed * frame * 1000;
29109 // EasingDurationCache.set(easing, duration);
29110 // return duration;
29111 // };
29112 /**
29113 These Easing Functions are based off of the Sozi Project's easing functions
29114 https://github.com/sozi-projects/Sozi/blob/d72e44ebd580dc7579d1e177406ad41e632f961d/src/js/player/Timing.js
29115 */
29116 var Steps = function (t, params) {
29117 if (params === void 0) { params = []; }
29118 var _a = __read(params, 2), _b = _a[0], steps = _b === void 0 ? 10 : _b, type = _a[1];
29119 var trunc = type == 'start' ? Math.ceil : Math.floor;
29120 return trunc(clamp(t, 0, 1) * steps) / steps;
29121 };
29122 // @ts-ignore
29123 var Bezier = function (t, params) {
29124 if (params === void 0) { params = []; }
29125 var _a = __read(params, 4), mX1 = _a[0], mY1 = _a[1], mX2 = _a[2], mY2 = _a[3];
29126 return bezier(mX1, mY1, mX2, mY2)(t);
29127 };
29128 /** The default `ease-in` easing function */
29129 var easein = bezier(0.42, 0.0, 1.0, 1.0);
29130 /** Converts easing functions to their `out`counter parts */
29131 var EaseOut = function (ease) {
29132 return function (t, params, duration) {
29133 if (params === void 0) { params = []; }
29134 return 1 - ease(1 - t, params, duration);
29135 };
29136 };
29137 /** Converts easing functions to their `in-out` counter parts */
29138 var EaseInOut = function (ease) {
29139 return function (t, params, duration) {
29140 if (params === void 0) { params = []; }
29141 return t < 0.5 ? ease(t * 2, params, duration) / 2 : 1 - ease(t * -2 + 2, params, duration) / 2;
29142 };
29143 };
29144 /** Converts easing functions to their `out-in` counter parts */
29145 var EaseOutIn = function (ease) {
29146 return function (t, params, duration) {
29147 if (params === void 0) { params = []; }
29148 return t < 0.5
29149 ? (1 - ease(1 - t * 2, params, duration)) / 2
29150 : (ease(t * 2 - 1, params, duration) + 1) / 2;
29151 };
29152 };
29153 var EasingFunctions = {
29154 steps: Steps,
29155 'step-start': function (t) { return Steps(t, [1, 'start']); },
29156 'step-end': function (t) { return Steps(t, [1, 'end']); },
29157 linear: function (t) { return t; },
29158 'cubic-bezier': Bezier,
29159 ease: function (t) { return Bezier(t, [0.25, 0.1, 0.25, 1.0]); },
29160 in: easein,
29161 out: EaseOut(easein),
29162 'in-out': EaseInOut(easein),
29163 'out-in': EaseOutIn(easein),
29164 'in-quad': Quad,
29165 'out-quad': EaseOut(Quad),
29166 'in-out-quad': EaseInOut(Quad),
29167 'out-in-quad': EaseOutIn(Quad),
29168 'in-cubic': Cubic,
29169 'out-cubic': EaseOut(Cubic),
29170 'in-out-cubic': EaseInOut(Cubic),
29171 'out-in-cubic': EaseOutIn(Cubic),
29172 'in-quart': Quart,
29173 'out-quart': EaseOut(Quart),
29174 'in-out-quart': EaseInOut(Quart),
29175 'out-in-quart': EaseOutIn(Quart),
29176 'in-quint': Quint,
29177 'out-quint': EaseOut(Quint),
29178 'in-out-quint': EaseInOut(Quint),
29179 'out-in-quint': EaseOutIn(Quint),
29180 'in-expo': Expo,
29181 'out-expo': EaseOut(Expo),
29182 'in-out-expo': EaseInOut(Expo),
29183 'out-in-expo': EaseOutIn(Expo),
29184 'in-sine': Sine,
29185 'out-sine': EaseOut(Sine),
29186 'in-out-sine': EaseInOut(Sine),
29187 'out-in-sine': EaseOutIn(Sine),
29188 'in-circ': Circ,
29189 'out-circ': EaseOut(Circ),
29190 'in-out-circ': EaseInOut(Circ),
29191 'out-in-circ': EaseOutIn(Circ),
29192 'in-back': Back,
29193 'out-back': EaseOut(Back),
29194 'in-out-back': EaseInOut(Back),
29195 'out-in-back': EaseOutIn(Back),
29196 'in-bounce': Bounce,
29197 'out-bounce': EaseOut(Bounce),
29198 'in-out-bounce': EaseInOut(Bounce),
29199 'out-in-bounce': EaseOutIn(Bounce),
29200 'in-elastic': Elastic,
29201 'out-elastic': EaseOut(Elastic),
29202 'in-out-elastic': EaseInOut(Elastic),
29203 'out-in-elastic': EaseOutIn(Elastic),
29204 spring: Spring,
29205 'spring-in': Spring,
29206 'spring-out': EaseOut(Spring),
29207 'spring-in-out': EaseInOut(Spring),
29208 'spring-out-in': EaseOutIn(Spring),
29209 };
29210 /**
29211 * Convert string easing to their proper form
29212 */
29213 var complexEasingSyntax = function (ease) {
29214 return convertToDash(ease)
29215 .replace(/^ease-/, '') // Remove the "ease-" keyword
29216 .replace(/(\(|\s).+/, '') // Remove the function brackets and parameters
29217 .toLowerCase()
29218 .trim();
29219 };
29220 /** Re-maps a number from one range to another. Numbers outside the range are not clamped to 0 and 1, because out-of-range values are often intentional and useful. */
29221 var getEasingFunction = function (ease) {
29222 return EasingFunctions[complexEasingSyntax(ease)] || EasingFunctions.linear;
29223 };
29224 // /**
29225 // * Allows you to register new easing functions
29226 // */
29227 // export const registerEasingFunction = (key: string, fn: TypeEasingFunction) => {
29228 // Object.assign(EasingFunctions, {
29229 // [key]: fn,
29230 // });
29231 // };
29232 // /**
29233 // * Allows you to register multiple new easing functions
29234 // */
29235 // export const registerEasingFunctions = (...obj: typeof EasingFunctions[]) => {
29236 // Object.assign(EasingFunctions, ...obj);
29237 // };
29238
29239 var linear = function (x) {
29240 return x;
29241 };
29242 var Start = 1;
29243 var Middle = 0.5;
29244 var End = 0;
29245 function step(count, pos) {
29246 return function (x) {
29247 if (x >= 1) {
29248 return 1;
29249 }
29250 var stepSize = 1 / count;
29251 x += pos * stepSize;
29252 return x - (x % stepSize);
29253 };
29254 }
29255 var numberString = '\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*';
29256 var cubicBezierRe = new RegExp('cubic-bezier\\(' +
29257 numberString +
29258 ',' +
29259 numberString +
29260 ',' +
29261 numberString +
29262 ',' +
29263 numberString +
29264 '\\)');
29265 var step1Re = /steps\(\s*(\d+)\s*\)/;
29266 var step2Re = /steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/;
29267 function parseEasingFunction(normalizedEasing) {
29268 var cubicData = cubicBezierRe.exec(normalizedEasing);
29269 if (cubicData) {
29270 // @ts-ignore
29271 return bezier.apply(void 0, __spreadArray([], __read(cubicData.slice(1).map(Number)), false));
29272 }
29273 var step1Data = step1Re.exec(normalizedEasing);
29274 if (step1Data) {
29275 return step(Number(step1Data[1]), End);
29276 }
29277 var step2Data = step2Re.exec(normalizedEasing);
29278 if (step2Data) {
29279 // @ts-ignore
29280 return step(Number(step2Data[1]), { start: Start, middle: Middle, end: End }[step2Data[2]]);
29281 }
29282 return getEasingFunction(normalizedEasing);
29283 }
29284 function calculateActiveDuration(timing) {
29285 // @ts-ignore
29286 return Math.abs(repeatedDuration(timing) / (timing.playbackRate || 1));
29287 }
29288 function repeatedDuration(timing) {
29289 var _a;
29290 // https://drafts.csswg.org/web-animations/#calculating-the-active-duration
29291 if (timing.duration === 0 || timing.iterations === 0) {
29292 return 0;
29293 }
29294 // @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/duration#value
29295 // if (timing.duration === 'auto') {
29296 // timing.duration = 0;
29297 // }
29298 return (timing.duration === 'auto' ? 0 : Number(timing.duration)) * ((_a = timing.iterations) !== null && _a !== void 0 ? _a : 1);
29299 }
29300 var PhaseNone = 0;
29301 var PhaseBefore = 1;
29302 var PhaseAfter = 2;
29303 var PhaseActive = 3;
29304 function calculatePhase(activeDuration, localTime, timing) {
29305 // https://drafts.csswg.org/web-animations/#animation-effect-phases-and-states
29306 if (localTime === null) {
29307 return PhaseNone;
29308 }
29309 var endTime = timing.endTime;
29310 if (localTime < Math.min(timing.delay, endTime)) {
29311 return PhaseBefore;
29312 }
29313 if (localTime >= Math.min(timing.delay + activeDuration + timing.endDelay, endTime)) {
29314 return PhaseAfter;
29315 }
29316 return PhaseActive;
29317 }
29318 function calculateActiveTime(activeDuration, fillMode, localTime, phase, delay) {
29319 // https://drafts.csswg.org/web-animations/#calculating-the-active-time
29320 switch (phase) {
29321 case PhaseBefore:
29322 if (fillMode === 'backwards' || fillMode === 'both')
29323 return 0;
29324 return null;
29325 case PhaseActive:
29326 return localTime - delay;
29327 case PhaseAfter:
29328 if (fillMode === 'forwards' || fillMode === 'both')
29329 return activeDuration;
29330 return null;
29331 case PhaseNone:
29332 return null;
29333 }
29334 }
29335 function calculateOverallProgress(iterationDuration, phase, iterations, activeTime, iterationStart) {
29336 // https://drafts.csswg.org/web-animations/#calculating-the-overall-progress
29337 var overallProgress = iterationStart;
29338 if (iterationDuration === 0) {
29339 if (phase !== PhaseBefore) {
29340 overallProgress += iterations;
29341 }
29342 }
29343 else {
29344 overallProgress += activeTime / iterationDuration;
29345 }
29346 return overallProgress;
29347 }
29348 function calculateSimpleIterationProgress(overallProgress, iterationStart, phase, iterations, activeTime, iterationDuration) {
29349 // https://drafts.csswg.org/web-animations/#calculating-the-simple-iteration-progress
29350 var simpleIterationProgress = overallProgress === Infinity ? iterationStart % 1 : overallProgress % 1;
29351 if (simpleIterationProgress === 0 &&
29352 phase === PhaseAfter &&
29353 iterations !== 0 &&
29354 (activeTime !== 0 || iterationDuration === 0)) {
29355 simpleIterationProgress = 1;
29356 }
29357 return simpleIterationProgress;
29358 }
29359 function calculateCurrentIteration(phase, iterations, simpleIterationProgress, overallProgress) {
29360 // https://drafts.csswg.org/web-animations/#calculating-the-current-iteration
29361 if (phase === PhaseAfter && iterations === Infinity) {
29362 return Infinity;
29363 }
29364 if (simpleIterationProgress === 1) {
29365 return Math.floor(overallProgress) - 1;
29366 }
29367 return Math.floor(overallProgress);
29368 }
29369 function calculateDirectedProgress(playbackDirection, currentIteration, simpleIterationProgress) {
29370 // https://drafts.csswg.org/web-animations/#calculating-the-directed-progress
29371 var currentDirection = playbackDirection;
29372 if (playbackDirection !== 'normal' && playbackDirection !== 'reverse') {
29373 var d = currentIteration;
29374 if (playbackDirection === 'alternate-reverse') {
29375 d += 1;
29376 }
29377 currentDirection = 'normal';
29378 if (d !== Infinity && d % 2 !== 0) {
29379 currentDirection = 'reverse';
29380 }
29381 }
29382 if (currentDirection === 'normal') {
29383 return simpleIterationProgress;
29384 }
29385 return 1 - simpleIterationProgress;
29386 }
29387 function calculateIterationProgress(activeDuration, localTime, timing) {
29388 var phase = calculatePhase(activeDuration, localTime, timing);
29389 var activeTime = calculateActiveTime(activeDuration, timing.fill, localTime, phase, timing.delay);
29390 if (activeTime === null)
29391 return null;
29392 var duration = timing.duration === 'auto' ? 0 : timing.duration;
29393 var overallProgress = calculateOverallProgress(duration, phase, timing.iterations, activeTime, timing.iterationStart);
29394 var simpleIterationProgress = calculateSimpleIterationProgress(overallProgress, timing.iterationStart, phase, timing.iterations, activeTime, duration);
29395 var currentIteration = calculateCurrentIteration(phase, timing.iterations, simpleIterationProgress, overallProgress);
29396 var directedProgress = calculateDirectedProgress(timing.direction, currentIteration, simpleIterationProgress);
29397 timing.currentIteration = currentIteration;
29398 timing.progress = directedProgress;
29399 // https://drafts.csswg.org/web-animations/#calculating-the-transformed-progress
29400 // https://drafts.csswg.org/web-animations/#calculating-the-iteration-progress
29401 return timing.easingFunction(directedProgress);
29402 }
29403
29404 function convertEffectInput(keyframes, timing, target) {
29405 var propertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups(keyframes, timing);
29406 var interpolations = makeInterpolations(propertySpecificKeyframeGroups, target);
29407 return function (target, fraction) {
29408 if (fraction !== null) {
29409 interpolations
29410 .filter(function (interpolation) {
29411 return (fraction >= interpolation.applyFrom &&
29412 fraction < interpolation.applyTo);
29413 })
29414 .forEach(function (interpolation) {
29415 var offsetFraction = fraction - interpolation.startOffset;
29416 var localDuration = interpolation.endOffset - interpolation.startOffset;
29417 var scaledLocalTime = localDuration === 0
29418 ? 0
29419 : interpolation.easingFunction(offsetFraction / localDuration);
29420 // apply updated attribute
29421 target.setAttribute(interpolation.property, interpolation.interpolation(scaledLocalTime));
29422 // if (interpolation.property === 'visibility') {
29423 // console.log(
29424 // scaledLocalTime,
29425 // interpolation.interpolation(scaledLocalTime),
29426 // );
29427 // }
29428 });
29429 }
29430 else {
29431 for (var property in propertySpecificKeyframeGroups)
29432 if (isNotReservedWord(property)) {
29433 // clear attribute
29434 target.setAttribute(property, null);
29435 }
29436 }
29437 };
29438 }
29439 function isNotReservedWord(member) {
29440 return (member !== 'offset' &&
29441 member !== 'easing' &&
29442 member !== 'composite' &&
29443 member !== 'computedOffset');
29444 }
29445 function makePropertySpecificKeyframeGroups(keyframes, timing) {
29446 var propertySpecificKeyframeGroups = {};
29447 for (var i = 0; i < keyframes.length; i++) {
29448 for (var member in keyframes[i]) {
29449 if (isNotReservedWord(member)) {
29450 var propertySpecificKeyframe = {
29451 offset: keyframes[i].offset,
29452 computedOffset: keyframes[i].computedOffset,
29453 easing: keyframes[i].easing,
29454 easingFunction: parseEasingFunction(keyframes[i].easing) || timing.easingFunction,
29455 value: keyframes[i][member],
29456 };
29457 propertySpecificKeyframeGroups[member] =
29458 propertySpecificKeyframeGroups[member] || [];
29459 propertySpecificKeyframeGroups[member].push(propertySpecificKeyframe);
29460 }
29461 }
29462 }
29463 return propertySpecificKeyframeGroups;
29464 }
29465 function makeInterpolations(propertySpecificKeyframeGroups, target) {
29466 var interpolations = [];
29467 for (var groupName in propertySpecificKeyframeGroups) {
29468 var keyframes = propertySpecificKeyframeGroups[groupName];
29469 for (var i = 0; i < keyframes.length - 1; i++) {
29470 var startIndex = i;
29471 var endIndex = i + 1;
29472 var startOffset = keyframes[startIndex].computedOffset;
29473 var endOffset = keyframes[endIndex].computedOffset;
29474 var applyFrom = startOffset;
29475 var applyTo = endOffset;
29476 if (i === 0) {
29477 applyFrom = -Infinity;
29478 if (endOffset === 0) {
29479 endIndex = startIndex;
29480 }
29481 }
29482 if (i === keyframes.length - 2) {
29483 applyTo = Infinity;
29484 if (startOffset === 1) {
29485 startIndex = endIndex;
29486 }
29487 }
29488 interpolations.push({
29489 applyFrom: applyFrom,
29490 applyTo: applyTo,
29491 startOffset: keyframes[startIndex].computedOffset,
29492 endOffset: keyframes[endIndex].computedOffset,
29493 easingFunction: keyframes[startIndex].easingFunction,
29494 property: groupName,
29495 interpolation: propertyInterpolation(groupName, keyframes[startIndex].value, keyframes[endIndex].value, target),
29496 });
29497 }
29498 }
29499 interpolations.sort(function (leftInterpolation, rightInterpolation) {
29500 return leftInterpolation.startOffset - rightInterpolation.startOffset;
29501 });
29502 return interpolations;
29503 }
29504 var InterpolationFactory = function (from, to,
29505 // eslint-disable-next-line @typescript-eslint/ban-types
29506 convertToString) {
29507 return function (f) {
29508 var interpolated = interpolate(from, to, f);
29509 return !runtime.enableCSSParsing && isNumber(interpolated)
29510 ? interpolated
29511 : convertToString(interpolated);
29512 };
29513 };
29514 function propertyInterpolation(property, left, right, target) {
29515 var metadata = propertyMetadataCache[property];
29516 // discrete step
29517 // if (property === 'visibility') {
29518 // return function (t: number) {
29519 // if (t === 0) return left;
29520 // if (t === 1) return right;
29521 // debugger;
29522 // return t < 0.5 ? left : right;
29523 // };
29524 // }
29525 if (metadata && metadata.syntax && metadata.int) {
29526 var propertyHandler = runtime.styleValueRegistry.getPropertySyntax(metadata.syntax);
29527 if (propertyHandler) {
29528 var usedLeft = void 0;
29529 var usedRight = void 0;
29530 if (runtime.enableCSSParsing) {
29531 var computedLeft = runtime.styleValueRegistry.parseProperty(property, left, target);
29532 var computedRight = runtime.styleValueRegistry.parseProperty(property, right, target);
29533 usedLeft = runtime.styleValueRegistry.computeProperty(property, computedLeft, target);
29534 usedRight = runtime.styleValueRegistry.computeProperty(property, computedRight, target);
29535 }
29536 else {
29537 var parser = propertyHandler.parserWithCSSDisabled;
29538 usedLeft = parser ? parser(left, target) : left;
29539 usedRight = parser ? parser(right, target) : right;
29540 }
29541 // merger [left, right, n2string()]
29542 var interpolationArgs = propertyHandler.mixer(usedLeft, usedRight, target);
29543 if (interpolationArgs) {
29544 var interp_1 = InterpolationFactory.apply(void 0, __spreadArray([], __read(interpolationArgs), false));
29545 return function (t) {
29546 if (t === 0)
29547 return left;
29548 if (t === 1)
29549 return right;
29550 return interp_1(t);
29551 };
29552 }
29553 }
29554 }
29555 // eslint-disable-next-line @typescript-eslint/no-use-before-define
29556 return InterpolationFactory(false, true, function (bool) {
29557 return bool ? right : left;
29558 });
29559 }
29560 /**
29561 * interpolate with number, boolean, number[], boolean[]
29562 */
29563 function interpolate(from, to, f) {
29564 if (typeof from === 'number' && typeof to === 'number') {
29565 return from * (1 - f) + to * f;
29566 }
29567 if ((typeof from === 'boolean' && typeof to === 'boolean') ||
29568 (typeof from === 'string' && typeof to === 'string') // skip string, eg. path ['M', 10, 10]
29569 ) {
29570 return f < 0.5 ? from : to;
29571 }
29572 if (Array.isArray(from) && Array.isArray(to)) {
29573 // interpolate arrays/matrix
29574 var fromLength = from.length;
29575 var toLength = to.length;
29576 var length_1 = Math.max(fromLength, toLength);
29577 var r = [];
29578 for (var i = 0; i < length_1; i++) {
29579 r.push(interpolate(from[i < fromLength ? i : fromLength - 1], to[i < toLength ? i : toLength - 1], f));
29580 }
29581 return r;
29582 }
29583 throw new Error('Mismatched interpolation arguments ' + from + ':' + to);
29584 }
29585
29586 /**
29587 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming
29588 */
29589 var AnimationEffectTiming = /** @class */ (function () {
29590 function AnimationEffectTiming() {
29591 /**
29592 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/delay
29593 */
29594 this.delay = 0;
29595 /**
29596 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/direction
29597 */
29598 this.direction = 'normal';
29599 /**
29600 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/duration
29601 */
29602 this.duration = 'auto';
29603 /**
29604 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/easing
29605 */
29606 this._easing = 'linear';
29607 this.easingFunction = linear;
29608 /**
29609 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/endDelay
29610 */
29611 this.endDelay = 0;
29612 /**
29613 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/fill
29614 */
29615 this.fill = 'auto';
29616 /**
29617 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/iterationStart
29618 */
29619 this.iterationStart = 0;
29620 /**
29621 * @see https://developer.mozilla.org/en-US/docs/Web/API/EffectTiming/iterations
29622 */
29623 this.iterations = 1;
29624 this.currentIteration = null;
29625 this.progress = null;
29626 }
29627 Object.defineProperty(AnimationEffectTiming.prototype, "easing", {
29628 get: function () {
29629 return this._easing;
29630 },
29631 set: function (value) {
29632 this.easingFunction = parseEasingFunction(value);
29633 this._easing = value;
29634 },
29635 enumerable: false,
29636 configurable: true
29637 });
29638 return AnimationEffectTiming;
29639 }());
29640
29641 /**
29642 * @example
29643 {
29644 translateY: [200, 300],
29645 scale: [1, 10],
29646 }
29647
29648 * groups' length can be different, the following config should generate 3 frames:
29649 @example
29650 {
29651 translateY: [200, 300, 400],
29652 scale: [1, 10],
29653 }
29654 */
29655 function convertToArrayForm(effectInput) {
29656 var normalizedEffectInput = [];
29657 for (var property in effectInput) {
29658 // skip reserved props
29659 if (property in ['easing', 'offset', 'composite']) {
29660 continue;
29661 }
29662 // @ts-ignore
29663 var values = effectInput[property];
29664 if (!Array.isArray(values)) {
29665 values = [values];
29666 }
29667 var numKeyframes = values.length;
29668 for (var i = 0; i < numKeyframes; i++) {
29669 if (!normalizedEffectInput[i]) {
29670 var keyframe = {};
29671 if ('offset' in effectInput) {
29672 keyframe.offset = Number(effectInput.offset);
29673 }
29674 if ('easing' in effectInput) {
29675 // @ts-ignore
29676 keyframe.easing = effectInput.easing;
29677 }
29678 if ('composite' in effectInput) {
29679 // @ts-ignore
29680 keyframe.composite = effectInput.composite;
29681 }
29682 normalizedEffectInput[i] = keyframe;
29683 }
29684 if (values[i] !== undefined && values[i] !== null) {
29685 normalizedEffectInput[i][property] = values[i];
29686 }
29687 }
29688 }
29689 normalizedEffectInput.sort(function (a, b) {
29690 return (a.computedOffset || 0) - (b.computedOffset || 0);
29691 });
29692 return normalizedEffectInput;
29693 }
29694 function normalizeKeyframes(effectInput, timing) {
29695 if (effectInput === null) {
29696 return [];
29697 }
29698 if (!Array.isArray(effectInput)) {
29699 effectInput = convertToArrayForm(effectInput);
29700 }
29701 var keyframes = effectInput.map(function (originalKeyframe) {
29702 var keyframe = {};
29703 if (timing === null || timing === void 0 ? void 0 : timing.composite) {
29704 // This will be auto if the composite operation specified on the effect is being used.
29705 // @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats
29706 keyframe.composite = 'auto';
29707 }
29708 for (var member in originalKeyframe) {
29709 var memberValue = originalKeyframe[member];
29710 if (member === 'offset') {
29711 if (memberValue !== null) {
29712 memberValue = Number(memberValue);
29713 if (!isFinite(memberValue))
29714 throw new Error('Keyframe offsets must be numbers.');
29715 if (memberValue < 0 || memberValue > 1)
29716 throw new Error('Keyframe offsets must be between 0 and 1.');
29717 keyframe.computedOffset = memberValue;
29718 }
29719 }
29720 else if (member === 'composite') {
29721 // TODO: Support add & accumulate in KeyframeEffect.composite
29722 // @see https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect/composite
29723 if (['replace', 'add', 'accumulate', 'auto'].indexOf(memberValue) === -1) {
29724 throw new Error("".concat(memberValue, " compositing is not supported"));
29725 }
29726 }
29727 else ;
29728 // assign to keyframe, no need to parse shorthand value
29729 keyframe[member] = memberValue;
29730 }
29731 if (keyframe.offset === undefined) {
29732 keyframe.offset = null;
29733 }
29734 if (keyframe.easing === undefined) {
29735 // override with timing.easing
29736 keyframe.easing = (timing === null || timing === void 0 ? void 0 : timing.easing) || 'linear';
29737 }
29738 if (keyframe.composite === undefined) {
29739 keyframe.composite = 'auto';
29740 }
29741 return keyframe;
29742 });
29743 var everyFrameHasOffset = true;
29744 var previousOffset = -Infinity;
29745 for (var i = 0; i < keyframes.length; i++) {
29746 var offset = keyframes[i].offset;
29747 if (!isNil(offset)) {
29748 if (offset < previousOffset) {
29749 throw new TypeError('Keyframes are not loosely sorted by offset. Sort or specify offsets.');
29750 }
29751 previousOffset = offset;
29752 }
29753 else {
29754 everyFrameHasOffset = false;
29755 }
29756 }
29757 keyframes = keyframes.filter(function (keyframe) {
29758 return Number(keyframe.offset) >= 0 && Number(keyframe.offset) <= 1;
29759 });
29760 function spaceKeyframes() {
29761 var _a, _b;
29762 var length = keyframes.length;
29763 keyframes[length - 1].computedOffset = Number((_a = keyframes[length - 1].offset) !== null && _a !== void 0 ? _a : 1);
29764 if (length > 1) {
29765 keyframes[0].computedOffset = Number((_b = keyframes[0].offset) !== null && _b !== void 0 ? _b : 0);
29766 }
29767 var previousIndex = 0;
29768 var previousOffset = Number(keyframes[0].computedOffset);
29769 for (var i = 1; i < length; i++) {
29770 var offset = keyframes[i].computedOffset;
29771 if (!isNil(offset) && !isNil(previousOffset)) {
29772 for (var j = 1; j < i - previousIndex; j++)
29773 keyframes[previousIndex + j].computedOffset =
29774 previousOffset + ((Number(offset) - previousOffset) * j) / (i - previousIndex);
29775 previousIndex = i;
29776 previousOffset = Number(offset);
29777 }
29778 }
29779 }
29780 if (!everyFrameHasOffset)
29781 spaceKeyframes();
29782 return keyframes;
29783 }
29784
29785 var fills = 'backwards|forwards|both|none'.split('|');
29786 var directions = 'reverse|alternate|alternate-reverse'.split('|');
29787 function makeTiming(timingInput, forGroup) {
29788 var timing = new AnimationEffectTiming();
29789 if (forGroup) {
29790 timing.fill = 'both';
29791 timing.duration = 'auto';
29792 }
29793 if (typeof timingInput === 'number' && !isNaN(timingInput)) {
29794 timing.duration = timingInput;
29795 }
29796 else if (timingInput !== undefined) {
29797 Object.keys(timingInput).forEach(function (property) {
29798 if (timingInput[property] !== undefined &&
29799 timingInput[property] !== null &&
29800 timingInput[property] !== 'auto') {
29801 if (typeof timing[property] === 'number' || property === 'duration') {
29802 if (typeof timingInput[property] !== 'number' ||
29803 isNaN(timingInput[property])) {
29804 return;
29805 }
29806 }
29807 if (property === 'fill' &&
29808 fills.indexOf(timingInput[property]) === -1) {
29809 return;
29810 }
29811 if (property === 'direction' &&
29812 directions.indexOf(timingInput[property]) === -1) {
29813 return;
29814 }
29815 // @ts-ignore
29816 timing[property] = timingInput[property];
29817 }
29818 });
29819 }
29820 return timing;
29821 }
29822 function normalizeTimingInput(timingInput, forGroup) {
29823 timingInput = numericTimingToObject(timingInput !== null && timingInput !== void 0 ? timingInput : { duration: 'auto' });
29824 return makeTiming(timingInput, forGroup);
29825 }
29826 function numericTimingToObject(timingInput) {
29827 if (typeof timingInput === 'number') {
29828 if (isNaN(timingInput)) {
29829 timingInput = { duration: 'auto' };
29830 }
29831 else {
29832 timingInput = { duration: timingInput };
29833 }
29834 }
29835 return timingInput;
29836 }
29837 /**
29838 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyframeEffect
29839 * @example
29840 const circleDownKeyframes = new KeyframeEffect(
29841 circle, // element to animate
29842 [
29843 { transform: 'translateY(0)' }, // keyframe
29844 { transform: 'translateY(100)' } // keyframe
29845 ],
29846 { duration: 3000, fill: 'forwards' } // keyframe options
29847 );
29848 *
29849 */
29850 var KeyframeEffect = /** @class */ (function () {
29851 function KeyframeEffect(target, effectInput, timingInput) {
29852 var _this = this;
29853 this.composite = 'replace';
29854 this.iterationComposite = 'replace';
29855 this.target = target;
29856 this.timing = normalizeTimingInput(timingInput, false);
29857 this.timing.effect = this;
29858 this.timing.activeDuration = calculateActiveDuration(this.timing);
29859 this.timing.endTime = Math.max(0, this.timing.delay + this.timing.activeDuration + this.timing.endDelay);
29860 this.normalizedKeyframes = normalizeKeyframes(effectInput, this.timing);
29861 this.interpolations = convertEffectInput(this.normalizedKeyframes, this.timing, this.target);
29862 // 不支持 proxy 时降级成 this.timing
29863 var Proxy = runtime.globalThis.Proxy;
29864 this.computedTiming = Proxy
29865 ? new Proxy(this.timing, {
29866 get: function (target, prop) {
29867 if (prop === 'duration') {
29868 return target.duration === 'auto' ? 0 : target.duration;
29869 }
29870 else if (prop === 'fill') {
29871 return target.fill === 'auto' ? 'none' : target.fill;
29872 }
29873 else if (prop === 'localTime') {
29874 return (_this.animation && _this.animation.currentTime) || null;
29875 }
29876 else if (prop === 'currentIteration') {
29877 if (!_this.animation || _this.animation.playState !== 'running') {
29878 return null;
29879 }
29880 return target.currentIteration || 0;
29881 }
29882 else if (prop === 'progress') {
29883 if (!_this.animation || _this.animation.playState !== 'running') {
29884 return null;
29885 }
29886 return target.progress || 0;
29887 }
29888 return target[prop];
29889 },
29890 set: function () {
29891 return true;
29892 },
29893 })
29894 : this.timing;
29895 }
29896 KeyframeEffect.prototype.applyInterpolations = function () {
29897 this.interpolations(this.target, Number(this.timeFraction));
29898 };
29899 KeyframeEffect.prototype.update = function (localTime) {
29900 if (localTime === null) {
29901 return false;
29902 }
29903 this.timeFraction = calculateIterationProgress(this.timing.activeDuration, localTime, this.timing);
29904 return this.timeFraction !== null;
29905 };
29906 KeyframeEffect.prototype.getKeyframes = function () {
29907 return this.normalizedKeyframes;
29908 };
29909 KeyframeEffect.prototype.setKeyframes = function (keyframes) {
29910 this.normalizedKeyframes = normalizeKeyframes(keyframes);
29911 };
29912 /**
29913 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffect/getComputedTiming
29914 */
29915 KeyframeEffect.prototype.getComputedTiming = function () {
29916 return this.computedTiming;
29917 };
29918 /**
29919 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffect/getTiming
29920 */
29921 KeyframeEffect.prototype.getTiming = function () {
29922 return this.timing;
29923 };
29924 /**
29925 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEffect/updateTiming
29926 */
29927 KeyframeEffect.prototype.updateTiming = function (timing) {
29928 var _this = this;
29929 Object.keys(timing || {}).forEach(function (name) {
29930 _this.timing[name] = timing[name];
29931 });
29932 };
29933 return KeyframeEffect;
29934 }());
29935
29936 function compareAnimations(leftAnimation, rightAnimation) {
29937 return Number(leftAnimation.id) - Number(rightAnimation.id);
29938 }
29939 /**
29940 * @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/web-animations-js/index.d.ts
29941 */
29942 var AnimationTimeline = /** @class */ (function () {
29943 function AnimationTimeline(document) {
29944 var _this = this;
29945 this.document = document;
29946 /**
29947 * all active animations
29948 */
29949 this.animations = [];
29950 this.ticking = false;
29951 this.timelineTicking = false;
29952 this.hasRestartedThisFrame = false;
29953 this.animationsWithPromises = [];
29954 this.inTick = false;
29955 this.pendingEffects = [];
29956 this.currentTime = null;
29957 this.rafId = 0;
29958 this.rafCallbacks = [];
29959 this.webAnimationsNextTick = function (t) {
29960 _this.currentTime = t;
29961 _this.discardAnimations();
29962 if (_this.animations.length === 0) {
29963 _this.timelineTicking = false;
29964 }
29965 else {
29966 _this.requestAnimationFrame(_this.webAnimationsNextTick);
29967 }
29968 };
29969 this.processRafCallbacks = function (t) {
29970 var processing = _this.rafCallbacks;
29971 _this.rafCallbacks = [];
29972 if (t < Number(_this.currentTime))
29973 t = Number(_this.currentTime);
29974 _this.animations.sort(compareAnimations);
29975 _this.animations = _this.tick(t, true, _this.animations)[0];
29976 processing.forEach(function (entry) {
29977 entry[1](t);
29978 });
29979 _this.applyPendingEffects();
29980 };
29981 }
29982 AnimationTimeline.prototype.getAnimations = function () {
29983 this.discardAnimations();
29984 return this.animations.slice();
29985 };
29986 AnimationTimeline.prototype.isTicking = function () {
29987 return this.inTick;
29988 };
29989 AnimationTimeline.prototype.play = function (target, keyframes, options) {
29990 var effect = new KeyframeEffect(target, keyframes, options);
29991 var animation = new Animation(effect, this);
29992 this.animations.push(animation);
29993 this.restartWebAnimationsNextTick();
29994 animation.updatePromises();
29995 animation.play();
29996 animation.updatePromises();
29997 return animation;
29998 };
29999 // RAF is supposed to be the last script to occur before frame rendering but not
30000 // all browsers behave like this. This function is for synchonously updating an
30001 // animation's effects whenever its state is mutated by script to work around
30002 // incorrect script execution ordering by the browser.
30003 AnimationTimeline.prototype.applyDirtiedAnimation = function (animation) {
30004 var _this = this;
30005 if (this.inTick) {
30006 return;
30007 }
30008 // update active animations in displayobject
30009 animation.markTarget();
30010 var animations = animation.targetAnimations();
30011 animations.sort(compareAnimations);
30012 // clear inactive animations
30013 var inactiveAnimations = this.tick(Number(this.currentTime), false, animations.slice())[1];
30014 inactiveAnimations.forEach(function (animation) {
30015 var index = _this.animations.indexOf(animation);
30016 if (index !== -1) {
30017 _this.animations.splice(index, 1);
30018 }
30019 });
30020 this.applyPendingEffects();
30021 };
30022 AnimationTimeline.prototype.restart = function () {
30023 if (!this.ticking) {
30024 this.ticking = true;
30025 this.requestAnimationFrame(function () { });
30026 this.hasRestartedThisFrame = true;
30027 }
30028 return this.hasRestartedThisFrame;
30029 };
30030 AnimationTimeline.prototype.destroy = function () {
30031 this.document.defaultView.cancelAnimationFrame(this.frameId);
30032 };
30033 AnimationTimeline.prototype.applyPendingEffects = function () {
30034 this.pendingEffects.forEach(function (effect) {
30035 effect === null || effect === void 0 ? void 0 : effect.applyInterpolations();
30036 });
30037 this.pendingEffects = [];
30038 };
30039 AnimationTimeline.prototype.updateAnimationsPromises = function () {
30040 this.animationsWithPromises = this.animationsWithPromises.filter(function (animation) {
30041 return animation.updatePromises();
30042 });
30043 };
30044 AnimationTimeline.prototype.discardAnimations = function () {
30045 this.updateAnimationsPromises();
30046 this.animations = this.animations.filter(function (animation) {
30047 return animation.playState !== 'finished' && animation.playState !== 'idle';
30048 });
30049 };
30050 AnimationTimeline.prototype.restartWebAnimationsNextTick = function () {
30051 if (!this.timelineTicking) {
30052 this.timelineTicking = true;
30053 this.requestAnimationFrame(this.webAnimationsNextTick);
30054 }
30055 };
30056 AnimationTimeline.prototype.rAF = function (f) {
30057 var id = this.rafId++;
30058 if (this.rafCallbacks.length === 0) {
30059 this.frameId = this.document.defaultView.requestAnimationFrame(this.processRafCallbacks);
30060 }
30061 this.rafCallbacks.push([id, f]);
30062 return id;
30063 };
30064 AnimationTimeline.prototype.requestAnimationFrame = function (f) {
30065 var _this = this;
30066 return this.rAF(function (x) {
30067 _this.updateAnimationsPromises();
30068 f(x);
30069 _this.updateAnimationsPromises();
30070 });
30071 };
30072 AnimationTimeline.prototype.tick = function (t, isAnimationFrame, updatingAnimations) {
30073 var _a, _b;
30074 var _this = this;
30075 this.inTick = true;
30076 this.hasRestartedThisFrame = false;
30077 this.currentTime = t;
30078 this.ticking = false;
30079 var newPendingClears = [];
30080 var newPendingEffects = [];
30081 var activeAnimations = [];
30082 var inactiveAnimations = [];
30083 updatingAnimations.forEach(function (animation) {
30084 animation.tick(t, isAnimationFrame);
30085 if (!animation._inEffect) {
30086 newPendingClears.push(animation.effect);
30087 animation.unmarkTarget();
30088 }
30089 else {
30090 newPendingEffects.push(animation.effect);
30091 animation.markTarget();
30092 }
30093 if (animation._needsTick)
30094 _this.ticking = true;
30095 var alive = animation._inEffect || animation._needsTick;
30096 animation._inTimeline = alive;
30097 if (alive) {
30098 activeAnimations.push(animation);
30099 }
30100 else {
30101 inactiveAnimations.push(animation);
30102 }
30103 });
30104 (_a = this.pendingEffects).push.apply(_a, __spreadArray([], __read(newPendingClears), false));
30105 (_b = this.pendingEffects).push.apply(_b, __spreadArray([], __read(newPendingEffects), false));
30106 if (this.ticking)
30107 this.requestAnimationFrame(function () { });
30108 this.inTick = false;
30109 return [activeAnimations, inactiveAnimations];
30110 };
30111 return AnimationTimeline;
30112 }());
30113
30114 runtime.EasingFunction = parseEasingFunction;
30115 runtime.AnimationTimeline = AnimationTimeline;
30116
30117 function measureText(container, px2hd, theme) {
30118 return function (text, font) {
30119 var _a = font || {},
30120 _b = _a.fontSize,
30121 fontSize = _b === void 0 ? theme.fontSize : _b,
30122 _c = _a.fontFamily,
30123 fontFamily = _c === void 0 ? theme.fontFamily : _c,
30124 _d = _a.fontWeight,
30125 fontWeight = _d === void 0 ? theme.fontWeight : _d,
30126 _e = _a.fontVariant,
30127 fontVariant = _e === void 0 ? theme.fontVariant : _e,
30128 _f = _a.fontStyle,
30129 fontStyle = _f === void 0 ? theme.fontStyle : _f,
30130 _g = _a.textAlign,
30131 textAlign = _g === void 0 ? theme.textAlign : _g,
30132 _h = _a.textBaseline,
30133 textBaseline = _h === void 0 ? theme.textBaseline : _h,
30134 _j = _a.lineWidth,
30135 lineWidth = _j === void 0 ? 1 : _j;
30136 var style = {
30137 x: 0,
30138 y: 0,
30139 fontSize: px2hd(fontSize),
30140 fontFamily: fontFamily,
30141 fontStyle: fontStyle,
30142 fontWeight: fontWeight,
30143 fontVariant: fontVariant,
30144 text: text,
30145 textAlign: textAlign,
30146 textBaseline: textBaseline,
30147 lineWidth: lineWidth,
30148 visibility: 'hidden'
30149 };
30150 var result = checkCSSRule('text', style);
30151 var shape = new Text({
30152 style: result
30153 });
30154 container.appendChild(shape);
30155 var _k = shape.getBBox(),
30156 width = _k.width,
30157 height = _k.height;
30158 shape.remove();
30159 return {
30160 width: width,
30161 height: height
30162 };
30163 };
30164 }
30165 function computeLayout$2(style) {
30166 var left = style.left,
30167 top = style.top,
30168 width = style.width,
30169 height = style.height,
30170 padding = style.padding;
30171 var paddingTop = padding[0],
30172 paddingRight = padding[1],
30173 paddingBottom = padding[2],
30174 paddingLeft = padding[3];
30175 return {
30176 left: left + paddingLeft,
30177 top: top + paddingTop,
30178 width: width - paddingLeft - paddingRight,
30179 height: height - paddingTop - paddingBottom
30180 };
30181 }
30182 // 顶层Canvas标签
30183 var Canvas$1 = /** @class */function () {
30184 function Canvas$1(props) {
30185 var context = props.context,
30186 _a = props.renderer,
30187 renderer = _a === void 0 ? new Renderer() : _a,
30188 width = props.width,
30189 height = props.height,
30190 customTheme = props.theme,
30191 customPx2hd = props.px2hd,
30192 customPixelRatio = props.pixelRatio,
30193 landscape = props.landscape,
30194 rendererContainer = props.container,
30195 // style: customStyle,
30196 _b = props.animate,
30197 // style: customStyle,
30198 animate = _b === void 0 ? true : _b,
30199 createImage = props.createImage,
30200 requestAnimationFrame = props.requestAnimationFrame,
30201 cancelAnimationFrame = props.cancelAnimationFrame,
30202 offscreenCanvas = props.offscreenCanvas,
30203 isTouchEvent = props.isTouchEvent,
30204 isMouseEvent = props.isMouseEvent,
30205 _c = props.useNativeClickEvent,
30206 useNativeClickEvent = _c === void 0 ? true : _c;
30207 var px2hd$1 = isFunction(customPx2hd) ? batch2hd(customPx2hd) : px2hd;
30208 // 初始化主题
30209 var theme = px2hd$1(__assign(__assign({}, THEME), customTheme));
30210 var pixelRatio = theme.pixelRatio,
30211 fontSize = theme.fontSize,
30212 fontFamily = theme.fontFamily;
30213 var devicePixelRatio = customPixelRatio ? customPixelRatio : pixelRatio;
30214 // 组件更新器
30215 var updater = createUpdater(this);
30216 var canvasElement = createMobileCanvasElement(context);
30217 var canvas = new Canvas({
30218 container: rendererContainer,
30219 canvas: canvasElement,
30220 devicePixelRatio: devicePixelRatio,
30221 renderer: renderer,
30222 width: width,
30223 height: height,
30224 supportsTouchEvents: true,
30225 // https://caniuse.com/?search=PointerEvent ios 13 以下不支持 Pointer
30226 supportsPointerEvents: runtime.globalThis.PointerEvent ? true : false,
30227 // 允许在canvas外部触发
30228 alwaysTriggerPointerEventOnCanvas: true,
30229 createImage: createImage,
30230 requestAnimationFrame: requestAnimationFrame,
30231 cancelAnimationFrame: cancelAnimationFrame,
30232 useNativeClickEvent: useNativeClickEvent,
30233 offscreenCanvas: offscreenCanvas,
30234 isTouchEvent: isTouchEvent,
30235 isMouseEvent: isMouseEvent
30236 });
30237 var container = canvas.getRoot();
30238 var _d = canvas.getConfig(),
30239 canvasWidth = _d.width,
30240 canvasHeight = _d.height;
30241 // 设置默认的全局样式
30242 container.setAttribute('fontSize', fontSize);
30243 container.setAttribute('fontFamily', fontFamily);
30244 var gesture = new Gesture(container);
30245 // 供全局使用的一些变量
30246 var componentContext = {
30247 ctx: context,
30248 root: this,
30249 canvas: canvas,
30250 px2hd: px2hd$1,
30251 theme: theme,
30252 gesture: gesture,
30253 measureText: measureText(container, px2hd$1, theme),
30254 timeline: null
30255 };
30256 var vNode = {
30257 key: undefined,
30258 tag: ClassComponent,
30259 // style: layout,
30260 // @ts-ignore
30261 type: Canvas$1,
30262 props: props,
30263 shape: container,
30264 animate: animate,
30265 // @ts-ignore
30266 component: this,
30267 canvas: this,
30268 context: componentContext,
30269 updater: updater
30270 };
30271 this._ee = new eventemitter3$1();
30272 this.props = props;
30273 this.context = componentContext;
30274 this.updater = updater;
30275 this.gesture = gesture;
30276 this.theme = theme;
30277 this.canvas = canvas;
30278 this.container = container;
30279 this.el = canvasElement;
30280 this.vNode = vNode;
30281 // todo: 横屏事件逻辑
30282 this.landscape = landscape;
30283 this.updateLayout(__assign(__assign({}, props), {
30284 width: canvasWidth,
30285 height: canvasHeight
30286 }));
30287 }
30288 Canvas$1.prototype.updateComponents = function (components) {
30289 updateComponents(components);
30290 };
30291 Canvas$1.prototype.update = function (nextProps) {
30292 return __awaiter(this, void 0, void 0, function () {
30293 var _a, props, vNode, _b, animate;
30294 return __generator(this, function (_c) {
30295 switch (_c.label) {
30296 case 0:
30297 _a = this, props = _a.props, vNode = _a.vNode;
30298 if (equal(nextProps, props)) {
30299 return [2 /*return*/];
30300 }
30301
30302 _b = props.animate, animate = _b === void 0 ? true : _b;
30303 this.props = nextProps;
30304 vNode.props = nextProps;
30305 vNode.animate = animate;
30306 return [4 /*yield*/, this.render()];
30307 case 1:
30308 _c.sent();
30309 return [2 /*return*/];
30310 }
30311 });
30312 });
30313 };
30314
30315 Canvas$1.prototype.render = function () {
30316 return __awaiter(this, void 0, void 0, function () {
30317 var _a, canvas, vNode;
30318 return __generator(this, function (_b) {
30319 switch (_b.label) {
30320 case 0:
30321 _a = this, canvas = _a.canvas, vNode = _a.vNode;
30322 return [4 /*yield*/, canvas.ready];
30323 case 1:
30324 _b.sent();
30325 render(vNode);
30326 return [2 /*return*/];
30327 }
30328 });
30329 });
30330 };
30331
30332 Canvas$1.prototype.emit = function (type, event) {
30333 this._ee.emit(type, event);
30334 };
30335 Canvas$1.prototype.on = function (type, listener) {
30336 this._ee.on(type, listener);
30337 };
30338 Canvas$1.prototype.off = function (type, listener) {
30339 this._ee.off(type, listener);
30340 };
30341 Canvas$1.prototype.getCanvasEl = function () {
30342 return this.el;
30343 };
30344 Canvas$1.prototype.resize = function (width, height) {
30345 return __awaiter(this, void 0, void 0, function () {
30346 var canvas;
30347 return __generator(this, function (_a) {
30348 switch (_a.label) {
30349 case 0:
30350 canvas = this.canvas;
30351 canvas.resize(width, height);
30352 this.updateLayout(__assign(__assign({}, this.props), {
30353 width: width,
30354 height: height
30355 }));
30356 return [4 /*yield*/, this.render()];
30357 case 1:
30358 _a.sent();
30359 return [2 /*return*/];
30360 }
30361 });
30362 });
30363 };
30364
30365 Canvas$1.prototype.toDataURL = function (type, encoderOptions) {
30366 return __awaiter(this, void 0, void 0, function () {
30367 var canvas;
30368 return __generator(this, function (_a) {
30369 canvas = this.canvas;
30370 return [2 /*return*/, new Promise(function (resolve) {
30371 canvas.addEventListener('rerender', function () {
30372 canvas.getContextService().toDataURL({
30373 type: type,
30374 encoderOptions: encoderOptions
30375 }).then(resolve);
30376 }, {
30377 once: true
30378 });
30379 })];
30380 });
30381 });
30382 };
30383 Canvas$1.prototype.updateLayout = function (props) {
30384 var width = props.width,
30385 height = props.height;
30386 var _a = this.context,
30387 px2hd = _a.px2hd,
30388 theme = _a.theme;
30389 var style = px2hd(__assign({
30390 left: 0,
30391 top: 0,
30392 width: width,
30393 height: height,
30394 padding: theme.padding
30395 }, props.style));
30396 var layout = computeLayout$2(style);
30397 var left = layout.left,
30398 top = layout.top;
30399 // 设置 container 的位置
30400 this.container.setAttribute('x', left);
30401 this.container.setAttribute('y', top);
30402 this.context = __assign(__assign({}, this.context), {
30403 left: left,
30404 top: top,
30405 width: layout.width,
30406 height: layout.height
30407 });
30408 this.vNode = __assign(__assign({}, this.vNode), {
30409 style: layout,
30410 context: this.context
30411 });
30412 };
30413 Canvas$1.prototype.toRawChildren = function (children) {
30414 return children;
30415 };
30416 Canvas$1.prototype.destroy = function () {
30417 var _a = this,
30418 canvas = _a.canvas,
30419 children = _a.children,
30420 el = _a.el;
30421 destroyElement(children);
30422 // 需要清理 canvas 画布内容,否则会导致 spa 应用 ios 下 canvas 白屏
30423 // https://stackoverflow.com/questions/52532614/total-canvas-memory-use-exceeds-the-maximum-limit-safari-12
30424 // https://github.com/antvis/F2/issues/630
30425 el.width = 0;
30426 el.height = 0;
30427 this.props = null;
30428 this.context = null;
30429 this.updater = null;
30430 this.theme = null;
30431 this.canvas = null;
30432 this.container = null;
30433 this.el = null;
30434 this.vNode = null;
30435 // 销毁也需要等 ready
30436 canvas.ready.then(function () {
30437 canvas.destroy();
30438 });
30439 };
30440 return Canvas$1;
30441 }();
30442
30443 function createRef() {
30444 var ref = {
30445 current: null
30446 };
30447 return ref;
30448 }
30449
30450 function createContext(defaultValue) {
30451 // 创建 Context 对象
30452 var context = {
30453 _currentValue: defaultValue
30454 };
30455 // 定义 Provider 组件
30456 var Provider = function Provider(_a) {
30457 var value = _a.value,
30458 children = _a.children;
30459 context._currentValue = value;
30460 return children;
30461 };
30462 // Injecter 可以往全局的 context 注入内容
30463 var Injecter = function Injecter(_a, context) {
30464 var children = _a.children,
30465 props = __rest(_a, ["children"]);
30466 Object.assign(context, props);
30467 return children;
30468 };
30469 Injecter.contextInjecter = context;
30470 // 定义 Consumer 组件
30471 var Consumer = function Consumer(_a) {
30472 var children = _a.children;
30473 return children(context._currentValue);
30474 };
30475 context.Provider = Provider;
30476 context.Injecter = Injecter;
30477 context.Consumer = Consumer;
30478 return context;
30479 }
30480
30481 var Timeline = /** @class */function (_super) {
30482 __extends(Timeline, _super);
30483 function Timeline(props) {
30484 var _this = _super.call(this, props) || this;
30485 _this.next = function () {
30486 var _a = _this,
30487 state = _a.state,
30488 props = _a.props;
30489 var index = state.index,
30490 count = state.count,
30491 delay = state.delay;
30492 var loop = props.loop,
30493 _b = props.autoPlay,
30494 autoPlay = _b === void 0 ? true : _b;
30495 var next = loop ? (index + 1) % count : index + 1;
30496 if (next < count && autoPlay) {
30497 setTimeout(function () {
30498 _this.setState({
30499 index: next
30500 });
30501 }, delay || 0);
30502 }
30503 };
30504 var delay = props.delay,
30505 _a = props.start,
30506 start = _a === void 0 ? 0 : _a,
30507 children = props.children;
30508 var count = Children.toArray(children).length;
30509 _this.state = {
30510 delay: delay,
30511 count: count,
30512 index: start
30513 };
30514 return _this;
30515 }
30516 Timeline.prototype.didMount = function () {
30517 var _a = this.props.autoPlay,
30518 autoPlay = _a === void 0 ? true : _a;
30519 if (autoPlay) {
30520 this.animator.on('end', this.next);
30521 }
30522 };
30523 Timeline.prototype.didUnmount = function () {
30524 this.animator.off('end', this.next);
30525 };
30526 Timeline.prototype.render = function () {
30527 var _a = this,
30528 state = _a.state,
30529 props = _a.props;
30530 var children = props.children;
30531 var index = state.index;
30532 var childrenArray = Children.toArray(children);
30533 return childrenArray[index];
30534 };
30535 return Timeline;
30536 }(Component);
30537
30538 var Timeline$1 = /** @class */function () {
30539 function Timeline(playComponent) {
30540 this.frame = 0;
30541 this.playState = 'play';
30542 this.animations = [];
30543 this.play = playComponent;
30544 }
30545 Timeline.prototype.setPlayState = function (state) {
30546 this.playState = state;
30547 var animator = this.play.animator;
30548 switch (state) {
30549 case 'play':
30550 animator.play();
30551 break;
30552 case 'pause':
30553 animator.pause();
30554 break;
30555 case 'finish':
30556 animator.play();
30557 animator.finish();
30558 break;
30559 }
30560 };
30561 Timeline.prototype.getPlayState = function () {
30562 return this.playState;
30563 };
30564 Timeline.prototype.goTo = function (frame) {
30565 if (!frame) return;
30566 var animator = this.play.animator;
30567 animator.goTo(frame);
30568 };
30569 Timeline.prototype.add = function (animation) {
30570 var frame = this.frame;
30571 if (this.animations[frame]) {
30572 animation.map(function (d) {
30573 return d.cancel();
30574 });
30575 return;
30576 }
30577 this.animations[frame] = animation;
30578 };
30579 Timeline.prototype.getAnimation = function () {
30580 var frame = this.frame;
30581 return this.animations[frame];
30582 };
30583 Timeline.prototype.push = function (animation) {
30584 var frame = this.frame;
30585 if (!this.animations[frame]) return;
30586 this.animations[0] = this.animations[frame].concat(animation);
30587 };
30588 Timeline.prototype.pop = function () {
30589 var frame = this.frame;
30590 this.animations[frame].pop();
30591 };
30592 Timeline.prototype.delete = function (animation) {
30593 var frame = this.frame;
30594 if (!animation || !this.animations[frame]) return;
30595 this.animations[frame].filter(function (d) {
30596 return d !== animation;
30597 });
30598 };
30599 Timeline.prototype.replace = function (next) {
30600 var _this = this;
30601 var frame = this.frame;
30602 if (!this.animations[frame]) return;
30603 var newAnimation = next.map(function (index) {
30604 return _this.animations[frame].map(function (d) {
30605 if (index === d) {
30606 return index;
30607 }
30608 return d;
30609 });
30610 });
30611 this.animations = newAnimation;
30612 };
30613 return Timeline;
30614 }();
30615
30616 function generateFrameElement(cur, element) {
30617 if (!element) return;
30618 return Children.map(element, function (child) {
30619 var key = child.key,
30620 props = child.props;
30621 var newProps = cur[key] ? cur[key].to : {};
30622 var children = generateFrameElement(cur, props.children);
30623 return Children.cloneElement(child, __assign(__assign({}, newProps), {
30624 children: children
30625 }));
30626 });
30627 }
30628
30629 var Player = /** @class */function (_super) {
30630 __extends(Player, _super);
30631 function Player(props) {
30632 var _this = _super.call(this, props) || this;
30633 _this.next = function () {
30634 var _a = _this.state,
30635 index = _a.index,
30636 count = _a.count;
30637 var _b = _this.props,
30638 _c = _b.onend,
30639 onend = _c === void 0 ? function () {} : _c,
30640 state = _b.state;
30641 if (index < count - 1 && state === 'play') {
30642 _this.setState(function () {
30643 return {
30644 index: index + 1
30645 };
30646 });
30647 } else {
30648 onend();
30649 }
30650 };
30651 var _a = props.keyFrames,
30652 keyFrames = _a === void 0 ? [] : _a,
30653 children = props.children;
30654 _this.playerFrames = keyFrames.reduce(function (array, cur) {
30655 var frames = generateFrameElement(cur, array[array.length - 1] || children);
30656 array.push(frames);
30657 return array;
30658 }, []);
30659 var count = _this.playerFrames.length;
30660 _this.state = {
30661 count: count,
30662 index: 0
30663 };
30664 return _this;
30665 }
30666 Player.prototype.setPlayState = function () {
30667 var _a = this,
30668 props = _a.props,
30669 context = _a.context;
30670 var playState = props.state;
30671 var timeline = context.timeline;
30672 timeline.setPlayState(playState);
30673 };
30674 Player.prototype.willMount = function () {
30675 this.context.timeline = new Timeline$1(this);
30676 };
30677 Player.prototype.didMount = function () {
30678 var _a = this,
30679 animator = _a.animator,
30680 props = _a.props;
30681 var state = props.state;
30682 animator.on('end', this.next);
30683 if (state === 'finish') {
30684 this.setState(function (_a) {
30685 var count = _a.count;
30686 return {
30687 index: count - 1
30688 };
30689 });
30690 }
30691 };
30692 Player.prototype.willUpdate = function () {
30693 var _a = this,
30694 context = _a.context,
30695 props = _a.props;
30696 var state = props.state;
30697 var timeline = context.timeline;
30698 if (state === 'finish' && timeline.getPlayState() !== 'finish') {
30699 this.setState(function (_a) {
30700 var count = _a.count;
30701 return {
30702 index: count - 1
30703 };
30704 });
30705 }
30706 };
30707 Player.prototype.animationWillPlay = function () {
30708 var _a = this,
30709 animator = _a.animator,
30710 context = _a.context;
30711 // @ts-ignore
30712 var timeline = context.timeline;
30713 var animations = animator.animations;
30714 timeline.add(animations);
30715 animator.animations = timeline.getAnimation();
30716 this.setPlayState();
30717 };
30718 Player.prototype.render = function () {
30719 return this.playerFrames[this.state.index];
30720 };
30721 return Player;
30722 }(Component);
30723
30724 function transposedRect(_a) {
30725 var xMin = _a.xMin,
30726 xMax = _a.xMax,
30727 yMin = _a.yMin,
30728 yMax = _a.yMax;
30729 return {
30730 xMin: yMin,
30731 xMax: yMax,
30732 yMin: xMin,
30733 yMax: xMax
30734 };
30735 }
30736 function convertRect(_a) {
30737 var x = _a.x,
30738 y = _a.y,
30739 size = _a.size,
30740 y0 = _a.y0;
30741 var xMin;
30742 var xMax;
30743 if (isArray(x)) {
30744 xMin = x[0];
30745 xMax = x[1];
30746 } else {
30747 xMin = x - size / 2;
30748 xMax = x + size / 2;
30749 }
30750 var yMin;
30751 var yMax;
30752 if (isArray(y)) {
30753 yMin = y[0];
30754 yMax = y[1];
30755 } else {
30756 yMin = Math.min(y0, y);
30757 yMax = Math.max(y0, y);
30758 }
30759 return {
30760 xMin: xMin,
30761 xMax: xMax,
30762 yMin: yMin,
30763 yMax: yMax
30764 };
30765 }
30766 /**
30767 * 直角坐标系
30768 * convert相关的方法,涉及将标准坐标系映射到实际坐标系内
30769 * transform相关的方法,是仅将某一种关键点转换成另一种关键点 (比如将x/y/size/y0转换成yMin/yMax/..)
30770 */
30771 var Base = /** @class */function () {
30772 function Base(option) {
30773 this.left = 0;
30774 this.top = 0;
30775 this.width = 0;
30776 this.height = 0;
30777 // x y 调换
30778 this.transposed = false;
30779 // x,y 的值域,在极坐标中对应的就是弧度和半径
30780 this.x = [0, 1];
30781 this.y = [0, 1];
30782 this.update(option);
30783 }
30784 Base.prototype.update = function (option) {
30785 mix(this, option);
30786 var _a = this,
30787 left = _a.left,
30788 top = _a.top,
30789 width = _a.width,
30790 height = _a.height;
30791 this.right = left + width;
30792 this.bottom = top + height;
30793 this.center = {
30794 x: left + width / 2,
30795 y: top + height / 2
30796 };
30797 return this;
30798 };
30799 // 是循环, 比如极坐标是以 2π 循环的
30800 Base.prototype.isCyclic = function () {
30801 return false;
30802 };
30803 Base.prototype._zoomVal = function (val, func) {
30804 return isArray(val) ? val.map(function (v) {
30805 return func(v);
30806 }) : func(val);
30807 };
30808 /**
30809 * 把归一后的值映射到对应的定义域
30810 * @param point
30811 */
30812 Base.prototype.convert = function (point) {
30813 var _a = this,
30814 transposed = _a.transposed,
30815 x = _a.x,
30816 y = _a.y;
30817 var xDim = transposed ? 'y' : 'x';
30818 var yDim = transposed ? 'x' : 'y';
30819 var pointX = point[xDim];
30820 var pointY = point[yDim];
30821 // 超出边界不绘制
30822 if (pointX < 0 || pointX > 1 || pointY < 0 || pointY > 1) {
30823 return {
30824 x: NaN,
30825 y: NaN
30826 };
30827 }
30828 return {
30829 x: this._zoomVal(point[xDim], function (v) {
30830 return x[0] + (x[1] - x[0]) * v;
30831 }),
30832 y: this._zoomVal(point[yDim], function (v) {
30833 return y[0] + (y[1] - y[0]) * v;
30834 })
30835 };
30836 };
30837 /**
30838 * convert 的反处理,把定义域的值,反处理到归一的值
30839 */
30840 Base.prototype.invert = function (point) {
30841 var _a;
30842 var _b = this,
30843 transposed = _b.transposed,
30844 x = _b.x,
30845 y = _b.y;
30846 var xDim = transposed ? 'y' : 'x';
30847 var yDim = transposed ? 'x' : 'y';
30848 return _a = {}, _a[xDim] = this._zoomVal(point.x, function (v) {
30849 return (v - x[0]) / (x[1] - x[0]);
30850 }), _a[yDim] = this._zoomVal(point.y, function (v) {
30851 return (v - y[0]) / (y[1] - y[0]);
30852 }), _a;
30853 };
30854 /**
30855 * 把归一化的值映射到 canvas 的坐标点
30856 * @param point
30857 * @returns
30858 */
30859 Base.prototype.convertPoint = function (point) {
30860 return this.convert(point);
30861 };
30862 /**
30863 * 把canvas坐标的点位映射回归一的值
30864 */
30865 Base.prototype.invertPoint = function (point) {
30866 return this.invert(point);
30867 };
30868 // 将标准坐标系下的矩形绘制关键点映射成实际绘制的坐标点
30869 Base.prototype.convertRect = function (rectPoint) {
30870 var _a = this,
30871 xRange = _a.x,
30872 yRange = _a.y,
30873 transposed = _a.transposed;
30874 var xStart = xRange[0],
30875 xEnd = xRange[1];
30876 var yStart = yRange[0],
30877 yEnd = yRange[1];
30878 var rect = convertRect(rectPoint);
30879 var _b = transposed ? transposedRect(rect) : rect,
30880 xMin = _b.xMin,
30881 xMax = _b.xMax,
30882 yMin = _b.yMin,
30883 yMax = _b.yMax;
30884 var x0 = xStart + (xEnd - xStart) * xMin;
30885 var x1 = xStart + (xEnd - xStart) * xMax;
30886 var y0 = yStart + (yEnd - yStart) * yMin;
30887 var y1 = yStart + (yEnd - yStart) * yMax;
30888 return {
30889 xMin: Math.min(x0, x1),
30890 xMax: Math.max(x0, x1),
30891 yMin: Math.min(y0, y1),
30892 yMax: Math.max(y0, y1)
30893 };
30894 };
30895 // 将已经映射好的矩形绘制关键点转换成实际绘制的坐标点
30896 Base.prototype.transformToRect = function (rectPoint) {
30897 var x = rectPoint.x,
30898 y = rectPoint.y,
30899 y0 = rectPoint.y0,
30900 size = rectPoint.size;
30901 var coordOrigin = this.convertPoint({
30902 x: 0,
30903 y: y0
30904 });
30905 var transposed = this.transposed;
30906 var _rectPoint = {
30907 size: size,
30908 x: transposed ? y : x,
30909 y: transposed ? x : y,
30910 y0: transposed ? coordOrigin.x : coordOrigin.y
30911 };
30912 var rect = convertRect(_rectPoint);
30913 var _a = transposed ? transposedRect(rect) : rect,
30914 xMin = _a.xMin,
30915 xMax = _a.xMax,
30916 yMin = _a.yMin,
30917 yMax = _a.yMax;
30918 return {
30919 xMin: xMin,
30920 xMax: xMax,
30921 yMin: yMin,
30922 yMax: yMax
30923 };
30924 };
30925 return Base;
30926 }();
30927
30928 var Rect$1 = /** @class */function (_super) {
30929 __extends(Rect, _super);
30930 function Rect() {
30931 var _this = _super !== null && _super.apply(this, arguments) || this;
30932 _this.type = 'rect';
30933 return _this;
30934 }
30935 Rect.prototype.update = function (option) {
30936 _super.prototype.update.call(this, option);
30937 var _a = this,
30938 left = _a.left,
30939 top = _a.top,
30940 width = _a.width,
30941 height = _a.height;
30942 var x = [left, left + width];
30943 var y = [top + height, top];
30944 this.x = x;
30945 this.y = y;
30946 return this;
30947 };
30948 return Rect;
30949 }(Base);
30950
30951 /**
30952 * expand Vec2
30953 */
30954 var vec2Direction = function vec2Direction(v1, v2) {
30955 return v1[0] * v2[1] - v2[0] * v1[1];
30956 };
30957 var vec2Zero = function vec2Zero(v) {
30958 return v[0] === 0 && v[1] === 0;
30959 };
30960 var vec2AngleTo = function vec2AngleTo(v1, v2, direction) {
30961 var angle$1 = angle(v1, v2);
30962 var angleLargeThanPI = vec2Direction(v1, v2) >= 0;
30963 if (direction) {
30964 if (angleLargeThanPI) {
30965 return Math.PI * 2 - angle$1;
30966 }
30967 return angle$1;
30968 }
30969 if (angleLargeThanPI) {
30970 return angle$1;
30971 }
30972 return Math.PI * 2 - angle$1;
30973 };
30974
30975 var Polar = /** @class */function (_super) {
30976 __extends(Polar, _super);
30977 function Polar() {
30978 var _this = _super !== null && _super.apply(this, arguments) || this;
30979 _this.type = 'polar';
30980 _this.isPolar = true;
30981 return _this;
30982 }
30983 Polar.prototype.update = function (option) {
30984 _super.prototype.update.call(this, option);
30985 if (!this.option) {
30986 this.option = option;
30987 }
30988 var _a = this.option,
30989 _b = _a.radius,
30990 radiusRatio = _b === void 0 ? 1 : _b,
30991 _c = _a.innerRadius,
30992 innerRadiusRatio = _c === void 0 ? 0 : _c;
30993 var _d = this,
30994 width = _d.width,
30995 height = _d.height,
30996 _e = _d.startAngle,
30997 startAngle = _e === void 0 ? -Math.PI / 2 : _e,
30998 _f = _d.endAngle,
30999 endAngle = _f === void 0 ? Math.PI * 3 / 2 : _f;
31000 // 半径取宽高的最小值
31001 var radius = radiusRatio * (Math.min(width, height) / 2);
31002 // 极坐标下 x 表示弧度, y 代表 半径
31003 var x = [startAngle, endAngle];
31004 var y = [innerRadiusRatio * radius, radius];
31005 this.x = x;
31006 this.y = y;
31007 this.startAngle = startAngle;
31008 this.endAngle = endAngle;
31009 this.radius = radius;
31010 this.innnerRadius = innerRadiusRatio * radius;
31011 return this;
31012 };
31013 Polar.prototype.isCyclic = function () {
31014 var _a = this,
31015 startAngle = _a.startAngle,
31016 endAngle = _a.endAngle;
31017 if (endAngle - startAngle < Math.PI * 2) {
31018 return false;
31019 }
31020 return true;
31021 };
31022 Polar.prototype.convertPoint = function (point) {
31023 var _a = this,
31024 center = _a.center,
31025 transposed = _a.transposed,
31026 x = _a.x,
31027 y = _a.y;
31028 var xDim = transposed ? 'y' : 'x';
31029 var yDim = transposed ? 'x' : 'y';
31030 var xStart = x[0],
31031 xEnd = x[1];
31032 var yStart = y[0],
31033 yEnd = y[1];
31034 var angle = xStart + (xEnd - xStart) * point[xDim];
31035 var radius = yStart + (yEnd - yStart) * point[yDim];
31036 return {
31037 x: center.x + Math.cos(angle) * radius,
31038 y: center.y + Math.sin(angle) * radius
31039 };
31040 };
31041 Polar.prototype.invertPoint = function (point) {
31042 var _a = this,
31043 center = _a.center,
31044 transposed = _a.transposed,
31045 x = _a.x,
31046 y = _a.y;
31047 var xDim = transposed ? 'y' : 'x';
31048 var yDim = transposed ? 'x' : 'y';
31049 var xStart = x[0],
31050 xEnd = x[1];
31051 var yStart = y[0],
31052 yEnd = y[1];
31053 var m = [1, 0, 0, 1, 0, 0];
31054 rotate(m, m, xStart);
31055 var startV = [1, 0];
31056 transformMat2d(startV, startV, m);
31057 startV = [startV[0], startV[1]];
31058 var pointV = [point.x - center.x, point.y - center.y];
31059 if (vec2Zero(pointV)) {
31060 return {
31061 x: 0,
31062 y: 0
31063 };
31064 }
31065 var theta = vec2AngleTo(startV, pointV, xEnd < xStart);
31066 if (Math.abs(theta - Math.PI * 2) < 0.001) {
31067 theta = 0;
31068 }
31069 var l = length$1(pointV);
31070 var percentX = theta / (xEnd - xStart);
31071 percentX = xEnd - xStart > 0 ? percentX : -percentX;
31072 var percentY = (l - yStart) / (yEnd - yStart);
31073 var rst = {};
31074 rst[xDim] = percentX;
31075 rst[yDim] = percentY;
31076 return rst;
31077 };
31078 return Polar;
31079 }(Base);
31080
31081 var coordMap = {
31082 rect: Rect$1,
31083 polar: Polar
31084 };
31085 var coordController = /** @class */function () {
31086 function coordController() {}
31087 coordController.prototype.getOption = function (cfg) {
31088 if (isString(cfg)) {
31089 return {
31090 type: coordMap[cfg] || Rect$1
31091 };
31092 }
31093 if (isFunction(cfg)) {
31094 return {
31095 type: cfg
31096 };
31097 }
31098 var type = (cfg || {}).type;
31099 return __assign(__assign({}, cfg), {
31100 // 默认直角坐标系
31101 type: isFunction(type) ? type : coordMap[type] || Rect$1
31102 });
31103 };
31104 coordController.prototype.create = function (cfg) {
31105 var layout = this.layout;
31106 var option = this.getOption(cfg);
31107 var type = option.type;
31108 var coord = new type(__assign(__assign({}, option), layout));
31109 this.coord = coord;
31110 return coord;
31111 };
31112 coordController.prototype.updateLayout = function (style) {
31113 var coord = this.coord;
31114 var left = style.left,
31115 top = style.top,
31116 width = style.width,
31117 height = style.height,
31118 padding = style.padding;
31119 var _a = padding || [0, 0, 0, 0],
31120 paddingTop = _a[0],
31121 paddingRight = _a[1],
31122 paddingBottom = _a[2],
31123 paddingLeft = _a[3];
31124 this.layout = {
31125 left: left + paddingLeft,
31126 top: top + paddingTop,
31127 width: width - paddingLeft - paddingRight,
31128 height: height - paddingTop - paddingBottom
31129 };
31130 if (coord) {
31131 coord.update(this.layout);
31132 }
31133 };
31134 coordController.prototype.useLayout = function (positionLayout) {
31135 var coord = this.coord;
31136 var position = positionLayout.position,
31137 boxWidth = positionLayout.width,
31138 boxHeight = positionLayout.height;
31139 var left = coord.left,
31140 top = coord.top,
31141 width = coord.width,
31142 height = coord.height;
31143 switch (position) {
31144 case 'left':
31145 left += boxWidth;
31146 width = Math.max(0, width - boxWidth);
31147 break;
31148 case 'right':
31149 width = Math.max(0, width - boxWidth);
31150 break;
31151 case 'top':
31152 top += boxHeight;
31153 height = Math.max(0, height - boxHeight);
31154 break;
31155 case 'bottom':
31156 height = Math.max(0, height - boxHeight);
31157 break;
31158 }
31159 coord.update({
31160 left: left,
31161 top: top,
31162 width: width,
31163 height: height
31164 });
31165 };
31166 coordController.prototype.update = function () {};
31167 coordController.prototype.getCoord = function () {
31168 return this.coord;
31169 };
31170 return coordController;
31171 }();
31172
31173 var methodCache = {};
31174 /**
31175 * 获取计算 ticks 的方法
31176 * @param key 键值
31177 * @returns 计算 ticks 的方法
31178 */
31179 function getTickMethod(key) {
31180 return methodCache[key];
31181 }
31182 /**
31183 * 注册计算 ticks 的方法
31184 * @param key 键值
31185 * @param method 方法
31186 */
31187 function registerTickMethod(key, method) {
31188 methodCache[key] = method;
31189 }
31190
31191 var Scale = /** @class */function () {
31192 function Scale(cfg) {
31193 /**
31194 * 度量的类型
31195 */
31196 this.type = 'base';
31197 /**
31198 * 是否分类类型的度量
31199 */
31200 this.isCategory = false;
31201 /**
31202 * 是否线性度量,有linear, time 度量
31203 */
31204 this.isLinear = false;
31205 /**
31206 * 是否连续类型的度量,linear,time,log, pow, quantile, quantize 都支持
31207 */
31208 this.isContinuous = false;
31209 /**
31210 * 是否是常量的度量,传入和传出一致
31211 */
31212 this.isIdentity = false;
31213 this.values = [];
31214 this.range = [0, 1];
31215 this.ticks = [];
31216 this.__cfg__ = cfg;
31217 this.initCfg();
31218 this.init();
31219 }
31220 // 对于原始值的必要转换,如分类、时间字段需转换成数值,用transform/map命名可能更好
31221 Scale.prototype.translate = function (v) {
31222 return v;
31223 };
31224 /** 重新初始化 */
31225 Scale.prototype.change = function (cfg) {
31226 // 覆盖配置项,而不替代
31227 mix(this.__cfg__, cfg);
31228 this.init();
31229 };
31230 Scale.prototype.clone = function () {
31231 return this.constructor(this.__cfg__);
31232 };
31233 /** 获取坐标轴需要的ticks */
31234 Scale.prototype.getTicks = function () {
31235 var _this = this;
31236 return map(this.ticks, function (tick, idx) {
31237 if (isObject(tick)) {
31238 // 仅当符合Tick类型时才有意义
31239 return tick;
31240 }
31241 return {
31242 text: _this.getText(tick, idx),
31243 tickValue: tick,
31244 value: _this.scale(tick) // scaled
31245 };
31246 });
31247 };
31248 /** 获取Tick的格式化结果 */
31249 Scale.prototype.getText = function (value, key) {
31250 var formatter = this.formatter;
31251 var res = formatter ? formatter(value, key) : value;
31252 if (isNil(res) || !isFunction(res.toString)) {
31253 return '';
31254 }
31255 return res.toString();
31256 };
31257 // 获取配置项中的值,当前 scale 上的值可能会被修改
31258 Scale.prototype.getConfig = function (key) {
31259 return this.__cfg__[key];
31260 };
31261 // scale初始化
31262 Scale.prototype.init = function () {
31263 mix(this, this.__cfg__);
31264 this.setDomain();
31265 if (isEmpty(this.getConfig('ticks'))) {
31266 this.ticks = this.calculateTicks();
31267 }
31268 };
31269 // 子类上覆盖某些属性,不能直接在类上声明,否则会被覆盖
31270 Scale.prototype.initCfg = function () {};
31271 Scale.prototype.setDomain = function () {};
31272 Scale.prototype.calculateTicks = function () {
31273 var tickMethod = this.tickMethod;
31274 var ticks = [];
31275 if (isString(tickMethod)) {
31276 var method = getTickMethod(tickMethod);
31277 if (!method) {
31278 throw new Error('There is no method to to calculate ticks!');
31279 }
31280 ticks = method(this);
31281 } else if (isFunction(tickMethod)) {
31282 ticks = tickMethod(this);
31283 }
31284 return ticks;
31285 };
31286 // range 的最小值
31287 Scale.prototype.rangeMin = function () {
31288 return this.range[0];
31289 };
31290 // range 的最大值
31291 Scale.prototype.rangeMax = function () {
31292 return this.range[1];
31293 };
31294 /** 定义域转 0~1 */
31295 Scale.prototype.calcPercent = function (value, min, max) {
31296 if (isNumber(value)) {
31297 return (value - min) / (max - min);
31298 }
31299 return NaN;
31300 };
31301 /** 0~1转定义域 */
31302 Scale.prototype.calcValue = function (percent, min, max) {
31303 return min + percent * (max - min);
31304 };
31305 return Scale;
31306 }();
31307
31308 /**
31309 * 分类度量
31310 * @class
31311 */
31312 var Category = /** @class */function (_super) {
31313 __extends(Category, _super);
31314 function Category() {
31315 var _this = _super !== null && _super.apply(this, arguments) || this;
31316 _this.type = 'cat';
31317 _this.isCategory = true;
31318 return _this;
31319 }
31320 Category.prototype.buildIndexMap = function () {
31321 if (!this.translateIndexMap) {
31322 this.translateIndexMap = new Map();
31323 // 重新构建缓存
31324 for (var i = 0; i < this.values.length; i++) {
31325 this.translateIndexMap.set(this.values[i], i);
31326 }
31327 }
31328 };
31329 Category.prototype.translate = function (value) {
31330 // 按需构建 map
31331 this.buildIndexMap();
31332 // 找得到
31333 var idx = this.translateIndexMap.get(value);
31334 if (idx === undefined) {
31335 idx = isNumber(value) ? value : NaN;
31336 }
31337 return idx;
31338 };
31339 Category.prototype.scale = function (value) {
31340 var order = this.translate(value);
31341 // 分类数据允许 0.5 范围内调整
31342 // if (order < this.min - 0.5 || order > this.max + 0.5) {
31343 // return NaN;
31344 // }
31345 var percent = this.calcPercent(order, this.min, this.max);
31346 return this.calcValue(percent, this.rangeMin(), this.rangeMax());
31347 };
31348 Category.prototype.invert = function (scaledValue) {
31349 var domainRange = this.max - this.min;
31350 var percent = this.calcPercent(scaledValue, this.rangeMin(), this.rangeMax());
31351 var idx = Math.round(domainRange * percent) + this.min;
31352 if (idx < this.min || idx > this.max) {
31353 return NaN;
31354 }
31355 return this.values[idx];
31356 };
31357 Category.prototype.getText = function (value) {
31358 var args = [];
31359 for (var _i = 1; _i < arguments.length; _i++) {
31360 args[_i - 1] = arguments[_i];
31361 }
31362 var v = value;
31363 // value为index
31364 if (isNumber(value) && !this.values.includes(value)) {
31365 v = this.values[v];
31366 }
31367 return _super.prototype.getText.apply(this, __spreadArray([v], args, false));
31368 };
31369 // 复写属性
31370 Category.prototype.initCfg = function () {
31371 this.tickMethod = 'cat';
31372 };
31373 // 设置 min, max
31374 Category.prototype.setDomain = function () {
31375 // 用户有可能设置 min
31376 if (isNil(this.getConfig('min'))) {
31377 this.min = 0;
31378 }
31379 if (isNil(this.getConfig('max'))) {
31380 var size = this.values.length;
31381 this.max = size > 1 ? size - 1 : size;
31382 }
31383 // scale.init 的时候清除缓存
31384 if (this.translateIndexMap) {
31385 this.translateIndexMap = undefined;
31386 }
31387 };
31388 return Category;
31389 }(Scale);
31390
31391 var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
31392 var literal = /\[([^]*?)\]/gm;
31393 function shorten(arr, sLen) {
31394 var newArr = [];
31395 for (var i = 0, len = arr.length; i < len; i++) {
31396 newArr.push(arr[i].substr(0, sLen));
31397 }
31398 return newArr;
31399 }
31400 function assign(origObj) {
31401 var args = [];
31402 for (var _i = 1; _i < arguments.length; _i++) {
31403 args[_i - 1] = arguments[_i];
31404 }
31405 for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
31406 var obj = args_1[_a];
31407 for (var key in obj) {
31408 // @ts-ignore ex
31409 origObj[key] = obj[key];
31410 }
31411 }
31412 return origObj;
31413 }
31414 var dayNames = [
31415 "Sunday",
31416 "Monday",
31417 "Tuesday",
31418 "Wednesday",
31419 "Thursday",
31420 "Friday",
31421 "Saturday"
31422 ];
31423 var monthNames = [
31424 "January",
31425 "February",
31426 "March",
31427 "April",
31428 "May",
31429 "June",
31430 "July",
31431 "August",
31432 "September",
31433 "October",
31434 "November",
31435 "December"
31436 ];
31437 var monthNamesShort = shorten(monthNames, 3);
31438 var dayNamesShort = shorten(dayNames, 3);
31439 var defaultI18n = {
31440 dayNamesShort: dayNamesShort,
31441 dayNames: dayNames,
31442 monthNamesShort: monthNamesShort,
31443 monthNames: monthNames,
31444 amPm: ["am", "pm"],
31445 DoFn: function (dayOfMonth) {
31446 return (dayOfMonth +
31447 ["th", "st", "nd", "rd"][dayOfMonth % 10 > 3
31448 ? 0
31449 : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]);
31450 }
31451 };
31452 var globalI18n = assign({}, defaultI18n);
31453 var pad = function (val, len) {
31454 if (len === void 0) { len = 2; }
31455 val = String(val);
31456 while (val.length < len) {
31457 val = "0" + val;
31458 }
31459 return val;
31460 };
31461 var formatFlags = {
31462 D: function (dateObj) { return String(dateObj.getDate()); },
31463 DD: function (dateObj) { return pad(dateObj.getDate()); },
31464 Do: function (dateObj, i18n) {
31465 return i18n.DoFn(dateObj.getDate());
31466 },
31467 d: function (dateObj) { return String(dateObj.getDay()); },
31468 dd: function (dateObj) { return pad(dateObj.getDay()); },
31469 ddd: function (dateObj, i18n) {
31470 return i18n.dayNamesShort[dateObj.getDay()];
31471 },
31472 dddd: function (dateObj, i18n) {
31473 return i18n.dayNames[dateObj.getDay()];
31474 },
31475 M: function (dateObj) { return String(dateObj.getMonth() + 1); },
31476 MM: function (dateObj) { return pad(dateObj.getMonth() + 1); },
31477 MMM: function (dateObj, i18n) {
31478 return i18n.monthNamesShort[dateObj.getMonth()];
31479 },
31480 MMMM: function (dateObj, i18n) {
31481 return i18n.monthNames[dateObj.getMonth()];
31482 },
31483 YY: function (dateObj) {
31484 return pad(String(dateObj.getFullYear()), 4).substr(2);
31485 },
31486 YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); },
31487 h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); },
31488 hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); },
31489 H: function (dateObj) { return String(dateObj.getHours()); },
31490 HH: function (dateObj) { return pad(dateObj.getHours()); },
31491 m: function (dateObj) { return String(dateObj.getMinutes()); },
31492 mm: function (dateObj) { return pad(dateObj.getMinutes()); },
31493 s: function (dateObj) { return String(dateObj.getSeconds()); },
31494 ss: function (dateObj) { return pad(dateObj.getSeconds()); },
31495 S: function (dateObj) {
31496 return String(Math.round(dateObj.getMilliseconds() / 100));
31497 },
31498 SS: function (dateObj) {
31499 return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
31500 },
31501 SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); },
31502 a: function (dateObj, i18n) {
31503 return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
31504 },
31505 A: function (dateObj, i18n) {
31506 return dateObj.getHours() < 12
31507 ? i18n.amPm[0].toUpperCase()
31508 : i18n.amPm[1].toUpperCase();
31509 },
31510 ZZ: function (dateObj) {
31511 var offset = dateObj.getTimezoneOffset();
31512 return ((offset > 0 ? "-" : "+") +
31513 pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4));
31514 },
31515 Z: function (dateObj) {
31516 var offset = dateObj.getTimezoneOffset();
31517 return ((offset > 0 ? "-" : "+") +
31518 pad(Math.floor(Math.abs(offset) / 60), 2) +
31519 ":" +
31520 pad(Math.abs(offset) % 60, 2));
31521 }
31522 };
31523 // Some common format strings
31524 var globalMasks = {
31525 default: "ddd MMM DD YYYY HH:mm:ss",
31526 shortDate: "M/D/YY",
31527 mediumDate: "MMM D, YYYY",
31528 longDate: "MMMM D, YYYY",
31529 fullDate: "dddd, MMMM D, YYYY",
31530 isoDate: "YYYY-MM-DD",
31531 isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
31532 shortTime: "HH:mm",
31533 mediumTime: "HH:mm:ss",
31534 longTime: "HH:mm:ss.SSS"
31535 };
31536 /***
31537 * Format a date
31538 * @method format
31539 * @param {Date|number} dateObj
31540 * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
31541 * @returns {string} Formatted date string
31542 */
31543 var format = function (dateObj, mask, i18n) {
31544 if (mask === void 0) { mask = globalMasks["default"]; }
31545 if (i18n === void 0) { i18n = {}; }
31546 if (typeof dateObj === "number") {
31547 dateObj = new Date(dateObj);
31548 }
31549 if (Object.prototype.toString.call(dateObj) !== "[object Date]" ||
31550 isNaN(dateObj.getTime())) {
31551 throw new Error("Invalid Date pass to format");
31552 }
31553 mask = globalMasks[mask] || mask;
31554 var literals = [];
31555 // Make literals inactive by replacing them with @@@
31556 mask = mask.replace(literal, function ($0, $1) {
31557 literals.push($1);
31558 return "@@@";
31559 });
31560 var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
31561 // Apply formatting rules
31562 mask = mask.replace(token, function ($0) {
31563 return formatFlags[$0](dateObj, combinedI18nSettings);
31564 });
31565 // Inline literal values back into the formatted value
31566 return mask.replace(/@@@/g, function () { return literals.shift(); });
31567 };
31568
31569 function timeFormat(time, mask) {
31570 return format(time, mask);
31571 }
31572 /**
31573 * 转换成时间戳
31574 * @param value 时间值
31575 */
31576 function toTimeStamp(value) {
31577 if (isString(value)) {
31578 if (value.indexOf('T') > 0) {
31579 value = new Date(value).getTime();
31580 } else {
31581 // new Date('2010/01/10') 和 new Date('2010-01-10') 的差别在于:
31582 // 如果仅有年月日时,前者是带有时区的: Fri Jan 10 2020 02:40:13 GMT+0800 (中国标准时间)
31583 // 后者会格式化成 Sun Jan 10 2010 08:00:00 GMT+0800 (中国标准时间)
31584 value = new Date(value.replace(/-/gi, '/')).getTime();
31585 }
31586 }
31587 if (isDate(value)) {
31588 value = value.getTime();
31589 }
31590 return value;
31591 }
31592
31593 /**
31594 * 时间分类度量
31595 * @class
31596 */
31597 var TimeCat = /** @class */function (_super) {
31598 __extends(TimeCat, _super);
31599 function TimeCat() {
31600 var _this = _super !== null && _super.apply(this, arguments) || this;
31601 _this.type = 'timeCat';
31602 return _this;
31603 }
31604 /**
31605 * @override
31606 */
31607 TimeCat.prototype.translate = function (value) {
31608 value = toTimeStamp(value);
31609 var index = this.values.indexOf(value);
31610 if (index === -1) {
31611 if (isNumber(value) && value < this.values.length) {
31612 index = value;
31613 } else {
31614 index = NaN;
31615 }
31616 }
31617 return index;
31618 };
31619 /**
31620 * 由于时间类型数据需要转换一下,所以复写 getText
31621 * @override
31622 */
31623 TimeCat.prototype.getText = function (value, tickIndex) {
31624 var index = this.translate(value);
31625 if (index > -1) {
31626 var result = this.values[index];
31627 var formatter = this.formatter;
31628 result = formatter ? formatter(result, tickIndex) : timeFormat(result, this.mask);
31629 return result;
31630 }
31631 return value;
31632 };
31633 TimeCat.prototype.initCfg = function () {
31634 this.tickMethod = 'time-cat';
31635 this.mask = 'YYYY-MM-DD';
31636 this.tickCount = 7; // 一般时间数据会显示 7, 14, 30 天的数字
31637 };
31638
31639 TimeCat.prototype.setDomain = function () {
31640 var values = this.values;
31641 // 针对时间分类类型,会将时间统一转换为时间戳
31642 each(values, function (v, i) {
31643 values[i] = toTimeStamp(v);
31644 });
31645 values.sort(function (v1, v2) {
31646 return v1 - v2;
31647 });
31648 _super.prototype.setDomain.call(this);
31649 };
31650 return TimeCat;
31651 }(Category);
31652
31653 /**
31654 * 连续度量的基类
31655 * @class
31656 */
31657 var Continuous = /** @class */function (_super) {
31658 __extends(Continuous, _super);
31659 function Continuous() {
31660 var _this = _super !== null && _super.apply(this, arguments) || this;
31661 _this.isContinuous = true;
31662 return _this;
31663 }
31664 Continuous.prototype.scale = function (value) {
31665 if (isNil(value)) {
31666 return NaN;
31667 }
31668 var rangeMin = this.rangeMin();
31669 var rangeMax = this.rangeMax();
31670 var max = this.max;
31671 var min = this.min;
31672 if (max === min) {
31673 return rangeMin;
31674 }
31675 var percent = this.getScalePercent(value);
31676 return rangeMin + percent * (rangeMax - rangeMin);
31677 };
31678 Continuous.prototype.init = function () {
31679 _super.prototype.init.call(this);
31680 // init 完成后保证 min, max 包含 ticks 的范围
31681 var ticks = this.ticks;
31682 var firstTick = head(ticks);
31683 var lastTick = last(ticks);
31684 if (firstTick < this.min) {
31685 this.min = firstTick;
31686 }
31687 if (lastTick > this.max) {
31688 this.max = lastTick;
31689 }
31690 // strict-limit 方式
31691 if (!isNil(this.minLimit)) {
31692 this.min = firstTick;
31693 }
31694 if (!isNil(this.maxLimit)) {
31695 this.max = lastTick;
31696 }
31697 };
31698 Continuous.prototype.setDomain = function () {
31699 var _a = getRange(this.values),
31700 min = _a.min,
31701 max = _a.max;
31702 if (isNil(this.min)) {
31703 this.min = min;
31704 }
31705 if (isNil(this.max)) {
31706 this.max = max;
31707 }
31708 if (this.min > this.max) {
31709 this.min = min;
31710 this.max = max;
31711 }
31712 };
31713 Continuous.prototype.calculateTicks = function () {
31714 var _this = this;
31715 var ticks = _super.prototype.calculateTicks.call(this);
31716 if (!this.nice) {
31717 ticks = filter(ticks, function (tick) {
31718 return tick >= _this.min && tick <= _this.max;
31719 });
31720 }
31721 return ticks;
31722 };
31723 // 计算原始值值占的百分比
31724 Continuous.prototype.getScalePercent = function (value) {
31725 var max = this.max;
31726 var min = this.min;
31727 return (value - min) / (max - min);
31728 };
31729 Continuous.prototype.getInvertPercent = function (value) {
31730 return (value - this.rangeMin()) / (this.rangeMax() - this.rangeMin());
31731 };
31732 return Continuous;
31733 }(Scale);
31734
31735 /**
31736 * 线性度量
31737 * @class
31738 */
31739 var Linear = /** @class */function (_super) {
31740 __extends(Linear, _super);
31741 function Linear() {
31742 var _this = _super !== null && _super.apply(this, arguments) || this;
31743 _this.type = 'linear';
31744 _this.isLinear = true;
31745 return _this;
31746 }
31747 Linear.prototype.invert = function (value) {
31748 var percent = this.getInvertPercent(value);
31749 return this.min + percent * (this.max - this.min);
31750 };
31751 Linear.prototype.initCfg = function () {
31752 this.tickMethod = 'wilkinson-extended';
31753 this.nice = false;
31754 };
31755 return Linear;
31756 }(Continuous);
31757
31758 // 求以a为次幂,结果为b的基数,如 x^^a = b;求x
31759 // 虽然数学上 b 不支持负数,但是这里需要支持 负数
31760 function calBase(a, b) {
31761 var e = Math.E;
31762 var value;
31763 if (b >= 0) {
31764 value = Math.pow(e, Math.log(b) / a); // 使用换底公式求底
31765 } else {
31766 value = Math.pow(e, Math.log(-b) / a) * -1; // 使用换底公式求底
31767 }
31768
31769 return value;
31770 }
31771 function log(a, b) {
31772 if (a === 1) {
31773 return 1;
31774 }
31775 return Math.log(b) / Math.log(a);
31776 }
31777 function getLogPositiveMin(values, base, max) {
31778 if (isNil(max)) {
31779 max = Math.max.apply(null, values);
31780 }
31781 var positiveMin = max;
31782 each(values, function (value) {
31783 if (value > 0 && value < positiveMin) {
31784 positiveMin = value;
31785 }
31786 });
31787 if (positiveMin === max) {
31788 positiveMin = max / base;
31789 }
31790 if (positiveMin > 1) {
31791 positiveMin = 1;
31792 }
31793 return positiveMin;
31794 }
31795
31796 /**
31797 * Log 度量,处理非均匀分布
31798 */
31799 var Log = /** @class */function (_super) {
31800 __extends(Log, _super);
31801 function Log() {
31802 var _this = _super !== null && _super.apply(this, arguments) || this;
31803 _this.type = 'log';
31804 return _this;
31805 }
31806 /**
31807 * @override
31808 */
31809 Log.prototype.invert = function (value) {
31810 var base = this.base;
31811 var max = log(base, this.max);
31812 var rangeMin = this.rangeMin();
31813 var range = this.rangeMax() - rangeMin;
31814 var min;
31815 var positiveMin = this.positiveMin;
31816 if (positiveMin) {
31817 if (value === 0) {
31818 return 0;
31819 }
31820 min = log(base, positiveMin / base);
31821 var appendPercent = 1 / (max - min) * range; // 0 到 positiveMin的占比
31822 if (value < appendPercent) {
31823 // 落到 0 - positiveMin 之间
31824 return value / appendPercent * positiveMin;
31825 }
31826 } else {
31827 min = log(base, this.min);
31828 }
31829 var percent = (value - rangeMin) / range;
31830 var tmp = percent * (max - min) + min;
31831 return Math.pow(base, tmp);
31832 };
31833 Log.prototype.initCfg = function () {
31834 this.tickMethod = 'log';
31835 this.base = 10;
31836 this.tickCount = 6;
31837 this.nice = true;
31838 };
31839 // 设置
31840 Log.prototype.setDomain = function () {
31841 _super.prototype.setDomain.call(this);
31842 var min = this.min;
31843 if (min < 0) {
31844 throw new Error('When you use log scale, the minimum value must be greater than zero!');
31845 }
31846 if (min === 0) {
31847 this.positiveMin = getLogPositiveMin(this.values, this.base, this.max);
31848 }
31849 };
31850 // 根据当前值获取占比
31851 Log.prototype.getScalePercent = function (value) {
31852 var max = this.max;
31853 var min = this.min;
31854 if (max === min) {
31855 return 0;
31856 }
31857 // 如果值小于等于0,则按照0处理
31858 if (value <= 0) {
31859 return 0;
31860 }
31861 var base = this.base;
31862 var positiveMin = this.positiveMin;
31863 // 如果min == 0, 则根据比0大的最小值,计算比例关系。这个最小值作为坐标轴上的第二个tick,第一个是0但是不显示
31864 if (positiveMin) {
31865 min = positiveMin * 1 / base;
31866 }
31867 var percent;
31868 // 如果数值小于次小值,那么就计算 value / 次小值 占整体的比例
31869 if (value < positiveMin) {
31870 percent = value / positiveMin / (log(base, max) - log(base, min));
31871 } else {
31872 percent = (log(base, value) - log(base, min)) / (log(base, max) - log(base, min));
31873 }
31874 return percent;
31875 };
31876 return Log;
31877 }(Continuous);
31878
31879 /**
31880 * Pow 度量,处理非均匀分布
31881 */
31882 var Pow = /** @class */function (_super) {
31883 __extends(Pow, _super);
31884 function Pow() {
31885 var _this = _super !== null && _super.apply(this, arguments) || this;
31886 _this.type = 'pow';
31887 return _this;
31888 }
31889 /**
31890 * @override
31891 */
31892 Pow.prototype.invert = function (value) {
31893 var percent = this.getInvertPercent(value);
31894 var exponent = this.exponent;
31895 var max = calBase(exponent, this.max);
31896 var min = calBase(exponent, this.min);
31897 var tmp = percent * (max - min) + min;
31898 var factor = tmp >= 0 ? 1 : -1;
31899 return Math.pow(tmp, exponent) * factor;
31900 };
31901 Pow.prototype.initCfg = function () {
31902 this.tickMethod = 'pow';
31903 this.exponent = 2;
31904 this.tickCount = 5;
31905 this.nice = true;
31906 };
31907 // 获取度量计算时,value占的定义域百分比
31908 Pow.prototype.getScalePercent = function (value) {
31909 var max = this.max;
31910 var min = this.min;
31911 if (max === min) {
31912 return 0;
31913 }
31914 var exponent = this.exponent;
31915 var percent = (calBase(exponent, value) - calBase(exponent, min)) / (calBase(exponent, max) - calBase(exponent, min));
31916 return percent;
31917 };
31918 return Pow;
31919 }(Continuous);
31920
31921 /**
31922 * 时间度量
31923 * @class
31924 */
31925 var Time = /** @class */function (_super) {
31926 __extends(Time, _super);
31927 function Time() {
31928 var _this = _super !== null && _super.apply(this, arguments) || this;
31929 _this.type = 'time';
31930 return _this;
31931 }
31932 /**
31933 * @override
31934 */
31935 Time.prototype.getText = function (value, index) {
31936 var numberValue = this.translate(value);
31937 var formatter = this.formatter;
31938 return formatter ? formatter(numberValue, index) : timeFormat(numberValue, this.mask);
31939 };
31940 /**
31941 * @override
31942 */
31943 Time.prototype.scale = function (value) {
31944 var v = value;
31945 if (isString(v) || isDate(v)) {
31946 v = this.translate(v);
31947 }
31948 return _super.prototype.scale.call(this, v);
31949 };
31950 /**
31951 * 将时间转换成数字
31952 * @override
31953 */
31954 Time.prototype.translate = function (v) {
31955 return toTimeStamp(v);
31956 };
31957 Time.prototype.initCfg = function () {
31958 this.tickMethod = 'time-pretty';
31959 this.mask = 'YYYY-MM-DD';
31960 this.tickCount = 7;
31961 this.nice = false;
31962 };
31963 Time.prototype.setDomain = function () {
31964 var values = this.values;
31965 // 是否设置了 min, max,而不是直接取 this.min, this.max
31966 var minConfig = this.getConfig('min');
31967 var maxConfig = this.getConfig('max');
31968 // 如果设置了 min,max 则转换成时间戳
31969 if (!isNil(minConfig) || !isNumber(minConfig)) {
31970 this.min = this.translate(this.min);
31971 }
31972 if (!isNil(maxConfig) || !isNumber(maxConfig)) {
31973 this.max = this.translate(this.max);
31974 }
31975 // 没有设置 min, max 时
31976 if (values && values.length) {
31977 // 重新计算最大最小值
31978 var timeStamps_1 = [];
31979 var min_1 = Infinity; // 最小值
31980 var secondMin_1 = min_1; // 次小值
31981 var max_1 = 0;
31982 // 使用一个循环,计算min,max,secondMin
31983 each(values, function (v) {
31984 var timeStamp = toTimeStamp(v);
31985 if (isNaN(timeStamp)) {
31986 throw new TypeError("Invalid Time: ".concat(v, " in time scale!"));
31987 }
31988 if (min_1 > timeStamp) {
31989 secondMin_1 = min_1;
31990 min_1 = timeStamp;
31991 } else if (secondMin_1 > timeStamp) {
31992 secondMin_1 = timeStamp;
31993 }
31994 if (max_1 < timeStamp) {
31995 max_1 = timeStamp;
31996 }
31997 timeStamps_1.push(timeStamp);
31998 });
31999 // 存在多个值时,设置最小间距
32000 if (values.length > 1) {
32001 this.minTickInterval = secondMin_1 - min_1;
32002 }
32003 if (isNil(minConfig)) {
32004 this.min = min_1;
32005 }
32006 if (isNil(maxConfig)) {
32007 this.max = max_1;
32008 }
32009 }
32010 };
32011 return Time;
32012 }(Linear);
32013
32014 /**
32015 * 分段度量
32016 */
32017 var Quantize = /** @class */function (_super) {
32018 __extends(Quantize, _super);
32019 function Quantize() {
32020 var _this = _super !== null && _super.apply(this, arguments) || this;
32021 _this.type = 'quantize';
32022 return _this;
32023 }
32024 Quantize.prototype.invert = function (value) {
32025 var ticks = this.ticks;
32026 var length = ticks.length;
32027 var percent = this.getInvertPercent(value);
32028 var minIndex = Math.floor(percent * (length - 1));
32029 // 最后一个
32030 if (minIndex >= length - 1) {
32031 return last(ticks);
32032 }
32033 // 超出左边界, 则取第一个
32034 if (minIndex < 0) {
32035 return head(ticks);
32036 }
32037 var minTick = ticks[minIndex];
32038 var nextTick = ticks[minIndex + 1];
32039 // 比当前值小的 tick 在度量上的占比
32040 var minIndexPercent = minIndex / (length - 1);
32041 var maxIndexPercent = (minIndex + 1) / (length - 1);
32042 return minTick + (percent - minIndexPercent) / (maxIndexPercent - minIndexPercent) * (nextTick - minTick);
32043 };
32044 Quantize.prototype.initCfg = function () {
32045 this.tickMethod = 'r-pretty';
32046 this.tickCount = 5;
32047 this.nice = true;
32048 };
32049 Quantize.prototype.calculateTicks = function () {
32050 var ticks = _super.prototype.calculateTicks.call(this);
32051 if (!this.nice) {
32052 // 如果 nice = false ,补充 min, max
32053 if (last(ticks) !== this.max) {
32054 ticks.push(this.max);
32055 }
32056 if (head(ticks) !== this.min) {
32057 ticks.unshift(this.min);
32058 }
32059 }
32060 return ticks;
32061 };
32062 // 计算当前值在刻度中的占比
32063 Quantize.prototype.getScalePercent = function (value) {
32064 var ticks = this.ticks;
32065 // 超出左边界
32066 if (value < head(ticks)) {
32067 return 0;
32068 }
32069 // 超出右边界
32070 if (value > last(ticks)) {
32071 return 1;
32072 }
32073 var minIndex = 0;
32074 each(ticks, function (tick, index) {
32075 if (value >= tick) {
32076 minIndex = index;
32077 } else {
32078 return false;
32079 }
32080 });
32081 return minIndex / (ticks.length - 1);
32082 };
32083 return Quantize;
32084 }(Continuous);
32085
32086 var Quantile = /** @class */function (_super) {
32087 __extends(Quantile, _super);
32088 function Quantile() {
32089 var _this = _super !== null && _super.apply(this, arguments) || this;
32090 _this.type = 'quantile';
32091 return _this;
32092 }
32093 Quantile.prototype.initCfg = function () {
32094 this.tickMethod = 'quantile';
32095 this.tickCount = 5;
32096 this.nice = true;
32097 };
32098 return Quantile;
32099 }(Quantize);
32100
32101 var map$3 = {};
32102 function getClass(key) {
32103 return map$3[key];
32104 }
32105 function registerClass(key, cls) {
32106 if (getClass(key)) {
32107 throw new Error("type '".concat(key, "' existed."));
32108 }
32109 map$3[key] = cls;
32110 }
32111
32112 /**
32113 * identity scale原则上是定义域和值域一致,scale/invert方法也是一致的
32114 * 参考R的实现:https://github.com/r-lib/scales/blob/master/R/pal-identity.r
32115 * 参考d3的实现(做了下转型):https://github.com/d3/d3-scale/blob/master/src/identity.js
32116 */
32117 var Identity = /** @class */function (_super) {
32118 __extends(Identity, _super);
32119 function Identity() {
32120 var _this = _super !== null && _super.apply(this, arguments) || this;
32121 _this.type = 'identity';
32122 _this.isIdentity = true;
32123 return _this;
32124 }
32125 Identity.prototype.calculateTicks = function () {
32126 return this.values;
32127 };
32128 Identity.prototype.scale = function (value) {
32129 // 如果传入的值不等于 identity 的值,则直接返回,用于一维图时的 dodge
32130 if (this.values[0] !== value && isNumber(value)) {
32131 return value;
32132 }
32133 return this.range[0];
32134 };
32135 Identity.prototype.invert = function (value) {
32136 var range = this.range;
32137 if (value < range[0] || value > range[1]) {
32138 return NaN;
32139 }
32140 return this.values[0];
32141 };
32142 return Identity;
32143 }(Scale);
32144
32145 // cat平均算法,保头保尾
32146 var CatTick = (function (cfg) {
32147 var values = cfg.values,
32148 tickCount = cfg.tickCount;
32149 if (!tickCount) {
32150 return values;
32151 }
32152 if (values.length <= 1) {
32153 return values;
32154 }
32155 // 获取间隔步长, 最小是1
32156 var step = Math.floor(values.length / (tickCount - 1)) || 1;
32157 var ticks = [];
32158 // 按间隔数取对应节点
32159 for (var index = 0; index < values.length; index = index + step) {
32160 ticks.push(values[index]);
32161 }
32162 var last = values[values.length - 1];
32163 // 如果最后一个tick不等于原数据的最后一个
32164 if (ticks[ticks.length - 1] !== last) {
32165 if (ticks.length >= tickCount) {
32166 // 如果当前的tick个数满足要求
32167 ticks[ticks.length - 1] = last;
32168 } else {
32169 // 不满足tickCount则直接加入最后一个
32170 ticks.push(last);
32171 }
32172 }
32173 return ticks;
32174 });
32175
32176 // 认为是nice的刻度
32177 var SNAP_COUNT_ARRAY = [1, 1.2, 1.5, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10];
32178 var DEFAULT_COUNT = 5; // 默认刻度值
32179 var LinearTick = (function (cfg) {
32180 var _a = cfg || {},
32181 tickCount = _a.tickCount,
32182 tickInterval = _a.tickInterval;
32183 var _b = cfg || {},
32184 min = _b.min,
32185 max = _b.max;
32186 min = isNaN(min) ? 0 : min;
32187 max = isNaN(max) ? 0 : max;
32188 var count = tickCount && tickCount >= 2 ? tickCount : DEFAULT_COUNT;
32189 // 计算interval, 优先取tickInterval
32190 var interval = tickInterval || getBestInterval({
32191 tickCount: count,
32192 max: max,
32193 min: min
32194 });
32195 // 通过interval计算最小tick
32196 var minTick = Math.floor(min / interval) * interval;
32197 // 如果指定了tickInterval, count 需要根据指定的tickInterval来算计
32198 if (tickInterval) {
32199 var intervalCount = Math.abs(Math.ceil((max - minTick) / tickInterval)) + 1;
32200 // tickCount 作为最小 count 处理
32201 count = Math.max(count, intervalCount);
32202 }
32203 var tickLength = 0;
32204 var fixedLength = getFixedLength(interval);
32205 if (min < 0 && max > 0 && count === 2) {
32206 return [toFixed(minTick, fixedLength), toFixed(Math.ceil(max / interval) * interval, fixedLength)];
32207 }
32208 var ticks = [];
32209 while (tickLength < count) {
32210 ticks.push(toFixed(minTick + tickLength * interval, fixedLength));
32211 tickLength++;
32212 }
32213 return ticks;
32214 });
32215 var DECIMAL_LENGTH = 12;
32216 function getFactor(number) {
32217 // 取正数
32218 number = Math.abs(number);
32219 var factor = 1;
32220 if (number === 0) {
32221 return factor;
32222 }
32223 // 小于1,逐渐放大
32224 if (number < 1) {
32225 var count = 0;
32226 while (number < 1) {
32227 factor = factor / 10;
32228 number = number * 10;
32229 count++;
32230 }
32231 // 浮点数计算出现问题
32232 if (factor.toString().length > DECIMAL_LENGTH) {
32233 factor = parseFloat(factor.toFixed(count));
32234 }
32235 return factor;
32236 }
32237 // 大于10逐渐缩小
32238 while (number > 10) {
32239 factor = factor * 10;
32240 number = number / 10;
32241 }
32242 return factor;
32243 }
32244 // 获取最佳匹配刻度
32245 function getBestInterval(_a) {
32246 var tickCount = _a.tickCount,
32247 min = _a.min,
32248 max = _a.max;
32249 // 如果最大最小相等,则直接按1处理
32250 if (min === max) {
32251 return 1 * getFactor(max);
32252 }
32253 // 1.计算平均刻度间隔
32254 var avgInterval = (max - min) / (tickCount - 1);
32255 // 2.数据标准归一化 映射到[1-10]区间
32256 var factor = getFactor(avgInterval);
32257 var calInterval = avgInterval / factor;
32258 var calMax = max / factor;
32259 var calMin = min / factor;
32260 // 根据平均值推算最逼近刻度值
32261 var similarityIndex = 0;
32262 for (var index = 0; index < SNAP_COUNT_ARRAY.length; index++) {
32263 var item = SNAP_COUNT_ARRAY[index];
32264 if (calInterval <= item) {
32265 similarityIndex = index;
32266 break;
32267 }
32268 }
32269 var similarityInterval = min < 0 && max > 0 && tickCount === 2 ? SNAP_COUNT_ARRAY[similarityIndex] : getInterval(similarityIndex, tickCount, calMin, calMax);
32270 // 小数点位数还原到数据的位数, 因为similarityIndex有可能是小数,所以需要保留similarityIndex自己的小数位数
32271 var fixedLength = getFixedLength(similarityInterval) + getFixedLength(factor);
32272 return toFixed(similarityInterval * factor, fixedLength);
32273 }
32274 function getInterval(startIndex, tickCount, min, max) {
32275 var verify = false;
32276 var interval = SNAP_COUNT_ARRAY[startIndex];
32277 // 刻度值校验,如果不满足,循环下去
32278 for (var i = startIndex; i < SNAP_COUNT_ARRAY.length; i++) {
32279 if (intervalIsVerify({
32280 interval: SNAP_COUNT_ARRAY[i],
32281 tickCount: tickCount,
32282 max: max,
32283 min: min
32284 })) {
32285 // 有符合条件的interval
32286 interval = SNAP_COUNT_ARRAY[i];
32287 verify = true;
32288 break;
32289 }
32290 }
32291 // 如果不满足, 依次缩小10倍,再计算
32292 if (!verify) {
32293 return 10 * getInterval(0, tickCount, min / 10, max / 10);
32294 }
32295 return interval;
32296 }
32297 // 刻度是否满足展示需求
32298 function intervalIsVerify(_a) {
32299 var interval = _a.interval,
32300 tickCount = _a.tickCount,
32301 max = _a.max,
32302 min = _a.min;
32303 var minTick = Math.floor(min / interval) * interval;
32304 if (minTick + (tickCount - 1) * interval >= max) {
32305 return true;
32306 }
32307 return false;
32308 }
32309 // 计算小数点应该保留的位数
32310 function getFixedLength(num) {
32311 var str = num.toString();
32312 var index = str.indexOf('.');
32313 var indexOfExp = str.indexOf('e-');
32314 var length = indexOfExp >= 0 ? parseInt(str.substr(indexOfExp + 2), 10) : str.substr(index + 1).length;
32315 if (length > 20) {
32316 // 最多保留20位小数
32317 length = 20;
32318 }
32319 return length;
32320 }
32321 // @antv/util fixedbase不支持科学计数法的判断,需要提mr
32322 function toFixed(v, length) {
32323 return parseFloat(v.toFixed(length));
32324 }
32325
32326 registerClass('cat', Category);
32327 registerClass('category', Category);
32328 registerClass('identity', Identity);
32329 registerClass('linear', Linear);
32330 registerClass('log', Log);
32331 registerClass('pow', Pow);
32332 registerClass('time', Time);
32333 registerClass('timeCat', TimeCat);
32334 registerClass('quantize', Quantize);
32335 registerClass('quantile', Quantile);
32336 // 覆盖0.3.x的 cat 方法
32337 registerTickMethod('cat', CatTick);
32338 registerTickMethod('time-cat', CatTick);
32339 // 覆盖linear 度量的tick算法
32340 registerTickMethod('wilkinson-extended', LinearTick);
32341 var ScaleController = /** @class */function () {
32342 function ScaleController(data) {
32343 this.data = data;
32344 this.options = {};
32345 this.scales = {};
32346 }
32347 ScaleController.prototype._getType = function (option) {
32348 var type = option.type,
32349 values = option.values,
32350 field = option.field;
32351 if (type) {
32352 return type;
32353 }
32354 if (isNumber(field) || isNil(values[0]) && field) {
32355 return 'identity';
32356 }
32357 if (typeof values[0] === 'number') {
32358 return 'linear';
32359 }
32360 return 'cat';
32361 };
32362 ScaleController.prototype._getOption = function (option) {
32363 var values = option.values,
32364 field = option.field,
32365 justifyContent = option.justifyContent;
32366 var type = this._getType(option);
32367 option.type = type;
32368 // identity
32369 if (type === 'identity') {
32370 option.field = field.toString();
32371 option.values = [field];
32372 return option;
32373 }
32374 // linear 类型
32375 if (type === 'linear') {
32376 // 设置默认nice
32377 if (typeof option.nice !== 'boolean') {
32378 option.nice = true;
32379 }
32380 // 重置最大最小
32381 var _a = getRange(values),
32382 min = _a.min,
32383 max = _a.max;
32384 if (isNil(option.min)) {
32385 option.min = min;
32386 }
32387 if (isNil(option.max)) {
32388 option.max = max;
32389 }
32390 option.values = values.sort(function (a, b) {
32391 return a - b;
32392 });
32393 return option;
32394 }
32395 // 分类类型和 timeCat 类型,调整 range
32396 if (type === 'cat' || type === 'timeCat') {
32397 if (option.range) {
32398 return option;
32399 }
32400 var count = values.length;
32401 var range = [0, 1];
32402 // 如果只有一项,显示在中间
32403 if (count === 1) {
32404 range = [0.5, 1];
32405 } else if (justifyContent) {
32406 // 居中
32407 var offset = 1 / count * 0.5;
32408 range = [offset, 1 - offset];
32409 } else {
32410 // 最后留 1 / count
32411 var offset = 1 / count;
32412 range = [0, 1 - offset];
32413 }
32414 option.range = range;
32415 }
32416 return option;
32417 };
32418 ScaleController.prototype.createScale = function (option) {
32419 var type = option.type;
32420 if (isFunction(type)) {
32421 return new type(option);
32422 }
32423 var ScaleClass = getClass(type);
32424 return new ScaleClass(option);
32425 };
32426 // 更新或创建scale
32427 ScaleController.prototype.setScale = function (field, option) {
32428 var _a = this,
32429 options = _a.options,
32430 scales = _a.scales;
32431 options[field] = mix({}, options[field], option);
32432 // 如果scale有更新,scale 也需要重新创建
32433 if (scales[field]) {
32434 scales[field].change(options[field]);
32435 // delete scales[field];
32436 }
32437 };
32438
32439 ScaleController.prototype.create = function (options) {
32440 this.update(options);
32441 };
32442 ScaleController.prototype.update = function (options) {
32443 var _this = this;
32444 if (!options) return;
32445 each(options, function (option, field) {
32446 _this.setScale(field, option);
32447 });
32448 };
32449 ScaleController.prototype.changeData = function (data) {
32450 this.data = data;
32451 this.scales = {};
32452 };
32453 ScaleController.prototype.getData = function () {
32454 return this.data;
32455 };
32456 ScaleController.prototype.getScale = function (field) {
32457 var _a = this,
32458 scales = _a.scales,
32459 options = _a.options,
32460 data = _a.data;
32461 var scale = scales[field];
32462 if (scale) {
32463 // for adjust=dodge, 需要更新 range
32464 var option_1 = this._getOption(__assign(__assign({}, options[field]), {
32465 values: scale.values
32466 }));
32467 if (option_1.range) {
32468 scale.range = option_1.range;
32469 }
32470 return scale;
32471 }
32472 var option = options[field];
32473 if (!option) {
32474 return null;
32475 }
32476 var values = option.values ? option.values : data ? valuesOfKey(data, field) : [];
32477 var scaleOption = this._getOption(__assign(__assign({}, option), {
32478 field: field,
32479 values: values
32480 }));
32481 var newScale = this.createScale(scaleOption);
32482 scales[field] = newScale;
32483 return newScale;
32484 };
32485 ScaleController.prototype.getScales = function () {
32486 var _this = this;
32487 var _a = this,
32488 options = _a.options,
32489 scales = _a.scales;
32490 each(options, function (option, field) {
32491 _this.getScale(field);
32492 });
32493 return scales;
32494 };
32495 ScaleController.prototype.getOptions = function () {
32496 var scales = this.scales;
32497 var options = {};
32498 each(scales, function (scale, field) {
32499 options[field] = __assign({}, scale.__cfg__);
32500 });
32501 return options;
32502 };
32503 ScaleController.prototype.adjustStartZero = function (scale) {
32504 var options = this.options;
32505 var field = scale.field,
32506 min = scale.min,
32507 max = scale.max;
32508 var option = options[field];
32509 // 如果有定义,则不处理
32510 if (option && option.min) {
32511 return;
32512 }
32513 if (min > 0) {
32514 scale.change({
32515 min: 0
32516 });
32517 } else if (max < 0) {
32518 scale.change({
32519 max: 0
32520 });
32521 }
32522 };
32523 // 饼图下的scale调整
32524 ScaleController.prototype.adjustPieScale = function (scale) {
32525 var options = this.options;
32526 var field = scale.field;
32527 var option = options[field];
32528 if (option && !isNil(option.nice)) {
32529 return null;
32530 }
32531 scale.change({
32532 nice: false
32533 });
32534 };
32535 // 获取scale 在 0点对位置的值
32536 ScaleController.prototype.getZeroValue = function (scale) {
32537 var min = scale.min,
32538 max = scale.max;
32539 var value;
32540 if (min >= 0) {
32541 value = min;
32542 } else if (max <= 0) {
32543 value = max;
32544 } else {
32545 value = 0;
32546 }
32547 return scale.scale(value);
32548 };
32549 return ScaleController;
32550 }();
32551
32552 var axis = {
32553 labelOffset: '15px',
32554 line: {
32555 stroke: '#E8E8E8',
32556 lineWidth: '1px'
32557 },
32558 symbol: {
32559 fill: '#E8E8E8',
32560 radius: '10px'
32561 },
32562 tickLine: {
32563 stroke: '#E8E8E8'
32564 },
32565 label: {
32566 fill: '#808080',
32567 fontSize: '20px'
32568 },
32569 grid: {
32570 stroke: '#E8E8E8',
32571 lineWidth: '1px',
32572 lineDash: ['4px']
32573 }
32574 };
32575 var guide = {
32576 line: {
32577 style: {
32578 stroke: '#a3a3a3',
32579 lineWidth: 1
32580 },
32581 offsetX: 0,
32582 offsetY: 0
32583 },
32584 text: {
32585 style: {
32586 fill: '#787878',
32587 // textAlign: 'center',
32588 textBaseline: 'middle'
32589 },
32590 offsetX: 0,
32591 offsetY: 0
32592 },
32593 rect: {
32594 style: {
32595 fill: '#fafafa'
32596 }
32597 },
32598 arc: {
32599 style: {
32600 stroke: '#a3a3a3'
32601 }
32602 },
32603 html: {
32604 offsetX: 0,
32605 offsetY: 0,
32606 alignX: 'center',
32607 alignY: 'middle'
32608 },
32609 tag: {
32610 offsetX: 0,
32611 offsetY: 0,
32612 side: 4,
32613 background: {
32614 padding: 5,
32615 radius: 2,
32616 fill: '#1890FF'
32617 },
32618 textStyle: {
32619 fontSize: 12,
32620 fill: '#fff',
32621 textAlign: 'center',
32622 textBaseline: 'middle'
32623 }
32624 },
32625 point: {
32626 offsetX: 0,
32627 offsetY: 0,
32628 style: {
32629 fill: '#fff',
32630 r: 3,
32631 lineWidth: 2,
32632 stroke: '#1890ff'
32633 }
32634 }
32635 };
32636 var chart = {
32637 padding: ['30px', '30px', '30px', '30px']
32638 };
32639 var Theme = {
32640 chart: chart,
32641 colors: ['#1890FF', '#2FC25B', '#FACC14', '#223273', '#8543E0', '#13C2C2', '#3436C7', '#F04864'],
32642 shapes: {
32643 line: ['line', 'dash', 'smooth'],
32644 point: ['circle', 'hollowCircle', 'rect'],
32645 area: ['area', 'smooth'],
32646 interval: ['rect', 'pyramid', 'funnel']
32647 },
32648 sizes: ['4px', '6px', '8px', '10px', '12px'],
32649 shape: {
32650 line: {
32651 default: {
32652 lineWidth: '4px',
32653 lineJoin: 'round',
32654 lineCap: 'round'
32655 },
32656 smooth: {
32657 smooth: true
32658 },
32659 dash: {
32660 lineDash: ['8px', '8px']
32661 }
32662 },
32663 point: {
32664 default: {
32665 size: '6px'
32666 },
32667 hollowCircle: {
32668 lineWidth: '2px'
32669 }
32670 },
32671 area: {
32672 default: {
32673 fillOpacity: 0.1
32674 }
32675 },
32676 interval: {
32677 default: {}
32678 }
32679 },
32680 axis: axis,
32681 guide: guide
32682 };
32683
32684 // 统计图表
32685 var Chart = /** @class */function (_super) {
32686 __extends(Chart, _super);
32687 function Chart(props, context) {
32688 var _this = _super.call(this, props) || this;
32689 // 坐标系
32690 _this.componentsPosition = [];
32691 var theme = context.theme,
32692 px2hd = context.px2hd;
32693 // hack 处理,设置默认的主题样式
32694 // 目前没想到其他更合适的方式,只能先这样处理
32695 context.theme = deepMix(px2hd(Theme), theme);
32696 var data = props.data;
32697 _this.scale = new ScaleController(data);
32698 _this.coord = new coordController();
32699 _this.coordRef = createRef();
32700 // state
32701 _this.state = {
32702 filters: {}
32703 };
32704 return _this;
32705 }
32706 Chart.prototype.getStyle = function (props) {
32707 var _a = this,
32708 context = _a.context,
32709 layout = _a.layout;
32710 var theme = context.theme,
32711 px2hd = context.px2hd;
32712 var left = layout.left,
32713 top = layout.top,
32714 width = layout.width,
32715 height = layout.height;
32716 var customStyle = props.style;
32717 return px2hd(__assign(__assign({
32718 left: left,
32719 top: top,
32720 width: width,
32721 height: height
32722 }, theme.chart), customStyle));
32723 };
32724 Chart.prototype.willMount = function () {
32725 var _a = this,
32726 props = _a.props,
32727 coord = _a.coord,
32728 scale = _a.scale;
32729 var scaleOptions = props.scale,
32730 coordOption = props.coord;
32731 this.resetCoordLayout();
32732 // 初始化 scale
32733 scale.create(scaleOptions);
32734 // 初始化 coord
32735 coord.create(coordOption);
32736 };
32737 // props 更新
32738 Chart.prototype.willReceiveProps = function (nextProps, context) {
32739 var _a = this,
32740 scale = _a.scale,
32741 coord = _a.coord,
32742 lastProps = _a.props;
32743 var nextStyle = nextProps.style,
32744 nextData = nextProps.data,
32745 nextScale = nextProps.scale;
32746 var lastStyle = lastProps.style,
32747 lastData = lastProps.data,
32748 lastScale = lastProps.scale;
32749 // style 更新
32750 if (!equal(nextStyle, lastStyle) || context !== this.context) {
32751 var style = this.getStyle(nextProps);
32752 coord.updateLayout(style);
32753 }
32754 if (nextData !== lastData) {
32755 scale.changeData(nextData);
32756 }
32757 // scale
32758 if (!equal(nextScale, lastScale)) {
32759 scale.update(nextScale);
32760 }
32761 };
32762 Chart.prototype.willUpdate = function () {
32763 this.coord.create(this.props.coord);
32764 };
32765 Chart.prototype.on = function (eventName, listener) {
32766 var roolEl = this.coordRef.current;
32767 if (!roolEl || !roolEl.gesture) return;
32768 var gesture = roolEl.gesture;
32769 gesture.on(eventName, listener);
32770 };
32771 Chart.prototype.off = function (eventName, listener) {
32772 var roolEl = this.coordRef.current;
32773 if (!roolEl || !roolEl.gesture) return;
32774 var gesture = roolEl.gesture;
32775 gesture.off(eventName, listener);
32776 };
32777 // 给需要显示的组件留空
32778 Chart.prototype.layoutCoord = function (layout) {
32779 this.coord.useLayout(layout);
32780 };
32781 Chart.prototype.resetCoordLayout = function () {
32782 var _a = this,
32783 coord = _a.coord,
32784 props = _a.props;
32785 var style = this.getStyle(props);
32786 coord.updateLayout(style);
32787 };
32788 Chart.prototype.updateCoordLayout = function (layout) {
32789 var _this = this;
32790 if (isArray(layout)) {
32791 layout.forEach(function (item) {
32792 _this.layoutCoord(item);
32793 });
32794 return;
32795 }
32796 this.layoutCoord(layout);
32797 };
32798 Chart.prototype.updateCoordFor = function (component, layout) {
32799 var _this = this;
32800 if (!layout) return;
32801 var componentsPosition = this.componentsPosition;
32802 var componentPosition = {
32803 component: component,
32804 layout: layout
32805 };
32806 var existIndex = findIndex(componentsPosition, function (item) {
32807 return item.component === component;
32808 });
32809 // 说明是已经存在的组件
32810 if (existIndex > -1) {
32811 componentsPosition.splice(existIndex, 1, componentPosition);
32812 // 先重置,然后整体重新算一次
32813 this.resetCoordLayout();
32814 // 再整体计算前,需要去掉已经销毁的组件
32815 this.removeComponentsPositionCache();
32816 componentsPosition.forEach(function (componentPosition) {
32817 var layout = componentPosition.layout;
32818 _this.updateCoordLayout(layout);
32819 });
32820 return;
32821 }
32822 // 是新组件,直接添加
32823 componentsPosition.push(componentPosition);
32824 this.updateCoordLayout(layout);
32825 };
32826 Chart.prototype.removeComponentsPositionCache = function () {
32827 var _a;
32828 if (!((_a = this.componentsPosition) === null || _a === void 0 ? void 0 : _a.length)) return;
32829 for (var i = this.componentsPosition.length; i > -1; i--) {
32830 var item = this.componentsPosition[i];
32831 if (item && item.component && item.component.destroyed) {
32832 this.componentsPosition.splice(i, 1);
32833 }
32834 }
32835 };
32836 Chart.prototype.getGeometrys = function () {
32837 // @ts-ignore
32838 var children = this.children.children;
32839 var geometrys = [];
32840 Children.toArray(children).forEach(function (element) {
32841 if (!element) return false;
32842 var component = element.component;
32843 // @ts-ignore
32844 if (component && component.isGeometry) {
32845 geometrys.push(component);
32846 }
32847 });
32848 return geometrys;
32849 };
32850 /**
32851 * calculate dataset's position on canvas
32852 * @param {Object} record the dataset
32853 * @return {Object} return the position
32854 */
32855 Chart.prototype.getPosition = function (record) {
32856 var coord = this.getCoord();
32857 var xScale = this.getXScales()[0];
32858 var xField = xScale.field;
32859 var yScales = this.getYScales();
32860 // default first
32861 var yScale = yScales[0];
32862 var yField = yScale.field;
32863 for (var i = 0, len = yScales.length; i < len; i++) {
32864 var scale = yScales[i];
32865 var field = scale.field;
32866 if (record[field]) {
32867 yScale = scale;
32868 yField = field;
32869 break;
32870 }
32871 }
32872 var x = xScale.scale(record[xField]);
32873 var y = yScale.scale(record[yField]);
32874 return coord.convertPoint({
32875 x: x,
32876 y: y
32877 });
32878 };
32879 Chart.prototype.getSnapRecords = function (point, inCoordRange) {
32880 var geometrys = this.getGeometrys();
32881 if (!geometrys.length) return;
32882 // @ts-ignore
32883 return geometrys[0].getSnapRecords(point, inCoordRange);
32884 };
32885 Chart.prototype.getRecords = function (data, field) {
32886 var geometrys = this.getGeometrys();
32887 if (!geometrys.length) return;
32888 // @ts-ignore
32889 return geometrys[0].getRecords(data, field);
32890 };
32891 Chart.prototype.getLegendItems = function (point) {
32892 var geometrys = this.getGeometrys();
32893 if (!geometrys.length) return;
32894 // @ts-ignore
32895 return geometrys[0].getLegendItems(point);
32896 };
32897 Chart.prototype.setScale = function (field, option) {
32898 this.scale.setScale(field, option);
32899 };
32900 Chart.prototype.getScale = function (field) {
32901 return this.scale.getScale(field);
32902 };
32903 Chart.prototype.getScales = function () {
32904 return this.scale.getScales();
32905 };
32906 Chart.prototype.getXScales = function () {
32907 var geometrys = this.getGeometrys();
32908 return geometrys.map(function (component) {
32909 // @ts-ignore
32910 return component.getXScale();
32911 });
32912 };
32913 Chart.prototype.getYScales = function () {
32914 var geometrys = this.getGeometrys();
32915 return geometrys.map(function (component) {
32916 // @ts-ignore
32917 return component.getYScale();
32918 });
32919 };
32920 Chart.prototype.getLayout = function () {
32921 return this.coord.layout;
32922 };
32923 Chart.prototype.getCoord = function () {
32924 return this.coord.coord;
32925 };
32926 Chart.prototype.filter = function (field, condition) {
32927 var _a;
32928 var filters = this.state.filters;
32929 this.setState({
32930 filters: __assign(__assign({}, filters), (_a = {}, _a[field] = condition, _a))
32931 });
32932 };
32933 Chart.prototype._getRenderData = function () {
32934 var _a = this,
32935 props = _a.props,
32936 state = _a.state;
32937 var data = props.data;
32938 var filters = state.filters;
32939 if (!filters || !Object.keys(filters).length) {
32940 return data;
32941 }
32942 var filteredData = data;
32943 each(filters, function (condition, field) {
32944 if (!condition) return;
32945 filteredData = filteredData.filter(function (record) {
32946 return condition(record[field], record);
32947 });
32948 });
32949 return filteredData;
32950 };
32951 Chart.prototype.render = function () {
32952 var _this = this;
32953 var _a = this,
32954 props = _a.props,
32955 scale = _a.scale,
32956 chartLayout = _a.layout;
32957 var children = props.children,
32958 originData = props.data;
32959 if (!originData) return null;
32960 var data = this._getRenderData();
32961 var layout = this.getLayout();
32962 var coord = this.getCoord();
32963 var scaleOptions = scale.getOptions();
32964 var width = chartLayout.width,
32965 height = chartLayout.height;
32966 return jsx("group", {
32967 ref: this.coordRef,
32968 style: {
32969 width: width,
32970 height: height,
32971 fill: 'transparent'
32972 }
32973 }, Children.map(children, function (child) {
32974 return Children.cloneElement(child, {
32975 data: data,
32976 chart: _this,
32977 layout: layout,
32978 coord: coord,
32979 // 传 scaleOptions 是为了让 child 感知到 props 的的变化,合理的做法的应该是传递 scale,但是现在无法感知到 scale 的变化, 所以暂时只能先这么处理,scaleOptions 子组件目前是使用不到的。
32980 scaleOptions: scaleOptions
32981 });
32982 }));
32983 };
32984 return Chart;
32985 }(Component);
32986
32987 function isEqual$1(origin1, origin2, fields) {
32988 if (origin1 === origin2) {
32989 return true;
32990 }
32991 for (var i = 0, len = fields.length; i < len; i++) {
32992 var field = fields[i];
32993 if (origin1[field] !== origin2[field]) {
32994 return false;
32995 }
32996 }
32997 return true;
32998 }
32999 var Selection = /** @class */function (_super) {
33000 __extends(Selection, _super);
33001 function Selection(props, context) {
33002 var _this = _super.call(this, props, context) || this;
33003 var selection = props.selection;
33004 if (!selection) return _this;
33005 var defaultSelected = selection.defaultSelected;
33006 _this.state.selected = defaultSelected;
33007 return _this;
33008 }
33009 Selection.prototype.didMount = function () {
33010 var _this = this;
33011 var _a = this,
33012 props = _a.props,
33013 state = _a.state;
33014 var selection = props.selection,
33015 chart = props.chart;
33016 if (!selection) return;
33017 // 默认为 click
33018 var _b = selection.triggerOn,
33019 triggerOn = _b === void 0 ? 'click' : _b;
33020 chart.on(triggerOn, function (ev) {
33021 var points = ev.points,
33022 x = ev.canvasX,
33023 y = ev.canvasY;
33024 var point = triggerOn === 'click' ? {
33025 x: x,
33026 y: y
33027 } : points[0];
33028 var records = _this.getSnapRecords(point);
33029 var _a = selection.type,
33030 type = _a === void 0 ? 'single' : _a,
33031 _b = selection.cancelable,
33032 cancelable = _b === void 0 ? true : _b;
33033 if (!records || !records.length) {
33034 if (cancelable) {
33035 _this.setState({
33036 selected: null
33037 });
33038 }
33039 return;
33040 }
33041 var selected = state.selected;
33042 var origins = records.map(function (record) {
33043 return record.origin;
33044 });
33045 if (!selected || !selected.length) {
33046 _this.setState({
33047 selected: origins
33048 });
33049 }
33050 if (type === 'single') {
33051 if (!cancelable) {
33052 _this.setState({
33053 selected: origins
33054 });
33055 return;
33056 }
33057 var newSelected_1 = [];
33058 records.forEach(function (record) {
33059 if (!_this.isSelected(record)) {
33060 newSelected_1.push(record.origin);
33061 }
33062 });
33063 _this.setState({
33064 selected: newSelected_1
33065 });
33066 return;
33067 }
33068 // 多选
33069 var scales = chart.getScales();
33070 var fields = Object.keys(scales);
33071 var selectedMap = {};
33072 selected.forEach(function (item) {
33073 var key = fields.map(function (field) {
33074 return item[field];
33075 }).join('-');
33076 selectedMap[key] = item;
33077 });
33078 records.forEach(function (record) {
33079 var origin = record.origin;
33080 var key = fields.map(function (field) {
33081 return origin[field];
33082 }).join('-');
33083 selectedMap[key] = selectedMap[key] ? null : origin;
33084 });
33085 var newSelected = Object.keys(selectedMap).map(function (key) {
33086 return selectedMap[key];
33087 }).filter(Boolean);
33088 _this.setState({
33089 selected: newSelected
33090 });
33091 });
33092 };
33093 Selection.prototype.willReceiveProps = function (nextProps) {
33094 var nextSelection = nextProps.selection;
33095 var lastSelection = this.props.selection;
33096 if (!nextSelection || !lastSelection) {
33097 return;
33098 }
33099 var nextDefaultSelected = nextSelection.defaultSelected;
33100 var lastDefaultSelected = lastSelection.defaultSelected;
33101 if (!equal(nextDefaultSelected, lastDefaultSelected)) {
33102 this.state.selected = nextDefaultSelected;
33103 }
33104 };
33105 Selection.prototype.getSnapRecords = function (_point) {
33106 return null;
33107 };
33108 Selection.prototype.isSelected = function (record) {
33109 var _a = this,
33110 state = _a.state,
33111 props = _a.props;
33112 var selected = state.selected;
33113 if (!selected || !selected.length) {
33114 return false;
33115 }
33116 var chart = props.chart;
33117 var scales = chart.getScales();
33118 var fields = Object.keys(scales);
33119 for (var i = 0, len = selected.length; i < len; i++) {
33120 var item = selected[i];
33121 if (isEqual$1(record.origin, item, fields)) {
33122 return true;
33123 }
33124 }
33125 return false;
33126 };
33127 Selection.prototype.getSelectionStyle = function (record) {
33128 var _a = this,
33129 state = _a.state,
33130 props = _a.props;
33131 var selected = state.selected;
33132 if (!selected || !selected.length) {
33133 return null;
33134 }
33135 var selection = props.selection;
33136 var selectedStyle = selection.selectedStyle,
33137 unSelectedStyle = selection.unSelectedStyle;
33138 var isSelected = this.isSelected(record);
33139 if (isSelected) {
33140 return isFunction(selectedStyle) ? selectedStyle(record) : selectedStyle;
33141 }
33142 return isFunction(unSelectedStyle) ? unSelectedStyle(record) : unSelectedStyle;
33143 };
33144 return Selection;
33145 }(Component);
33146
33147 var DEFAULT_Y = 0; // 默认的 y 的值
33148 // 偏移之后,间距
33149 var MARGIN_RATIO = 1 / 2;
33150 var DODGE_RATIO = 1 / 2;
33151 // 散点分开之后,距离边界的距离
33152 var GAP = 0.05;
33153
33154 var Adjust = /** @class */function () {
33155 function Adjust(cfg) {
33156 var xField = cfg.xField,
33157 yField = cfg.yField,
33158 _a = cfg.adjustNames,
33159 adjustNames = _a === void 0 ? ['x', 'y'] : _a,
33160 dimValuesMap = cfg.dimValuesMap;
33161 this.adjustNames = adjustNames;
33162 this.xField = xField;
33163 this.yField = yField;
33164 this.dimValuesMap = dimValuesMap;
33165 }
33166 /**
33167 * 查看维度是否是 adjust 字段
33168 * @param dim
33169 */
33170 Adjust.prototype.isAdjust = function (dim) {
33171 return this.adjustNames.indexOf(dim) >= 0;
33172 };
33173 Adjust.prototype.getAdjustRange = function (dim, dimValue, values) {
33174 var yField = this.yField;
33175 var index = values.indexOf(dimValue);
33176 var length = values.length;
33177 var pre;
33178 var next;
33179 // 没有 y 字段,但是需要根据 y 调整
33180 if (!yField && this.isAdjust('y')) {
33181 pre = 0;
33182 next = 1;
33183 } else if (length > 1) {
33184 // 如果以其开头,则取之,否则取他前面一个
33185 pre = values[index === 0 ? 0 : index - 1];
33186 // 如果以其结尾,则取之,否则取他后面一个
33187 next = values[index === length - 1 ? length - 1 : index + 1];
33188 if (index !== 0) {
33189 pre += (dimValue - pre) / 2;
33190 } else {
33191 pre -= (next - dimValue) / 2;
33192 }
33193 if (index !== length - 1) {
33194 next -= (next - dimValue) / 2;
33195 } else {
33196 next += (dimValue - values[length - 2]) / 2;
33197 }
33198 } else {
33199 pre = dimValue === 0 ? 0 : dimValue - 0.5;
33200 next = dimValue === 0 ? 1 : dimValue + 0.5;
33201 }
33202 return {
33203 pre: pre,
33204 next: next
33205 };
33206 };
33207 Adjust.prototype.adjustData = function (groupedDataArray, mergedData) {
33208 var _this = this;
33209 // 所有调整维度的值数组
33210 var dimValuesMap = this.getDimValues(mergedData);
33211 // 按照每一个分组来进行调整
33212 each(groupedDataArray, function (dataArray, index) {
33213 // 遍历所有数据集合
33214 // 每个分组中,分别按照不同的 dim 进行调整
33215 each(dimValuesMap, function (values, dim) {
33216 // 根据不同的度量分别调整位置
33217 _this.adjustDim(dim, values, dataArray, index);
33218 });
33219 });
33220 };
33221 /**
33222 * 对数据进行分组adjustData
33223 * @param data 数据
33224 * @param dim 分组的字段
33225 * @return 分组结果
33226 */
33227 Adjust.prototype.groupData = function (data, dim) {
33228 // 补齐数据空数据为默认值
33229 each(data, function (record) {
33230 if (record[dim] === undefined) {
33231 record[dim] = DEFAULT_Y;
33232 }
33233 });
33234 // 按照 dim 维度分组
33235 return groupBy(data, dim);
33236 };
33237 /** @override */
33238 Adjust.prototype.adjustDim = function (_dim, _values, _data, _index) {};
33239 /**
33240 * 获取可调整度量对应的值
33241 * @param mergedData 数据
33242 * @return 值的映射
33243 */
33244 Adjust.prototype.getDimValues = function (mergedData) {
33245 var _a = this,
33246 xField = _a.xField,
33247 yField = _a.yField;
33248 var dimValuesMap = mix({}, this.dimValuesMap);
33249 // 所有的维度
33250 var dims = [];
33251 if (xField && this.isAdjust('x')) {
33252 dims.push(xField);
33253 }
33254 if (yField && this.isAdjust('y')) {
33255 dims.push(yField);
33256 }
33257 dims.forEach(function (dim) {
33258 if (dimValuesMap && dimValuesMap[dim]) {
33259 return;
33260 }
33261 // 在每个维度上,所有的值
33262 dimValuesMap[dim] = valuesOfKey(mergedData, dim).sort(function (v1, v2) {
33263 return v1 - v2;
33264 }).filter(function (v) {
33265 return !isNaN(v);
33266 });
33267 });
33268 // 只有一维的情况下,同时调整 y,赋予默认值
33269 if (!yField && this.isAdjust('y')) {
33270 var dim = 'y';
33271 dimValuesMap[dim] = [DEFAULT_Y, 1]; // 默认分布在 y 轴的 0 与 1 之间
33272 }
33273
33274 return dimValuesMap;
33275 };
33276 return Adjust;
33277 }();
33278
33279 var Dodge = /** @class */function (_super) {
33280 __extends(Dodge, _super);
33281 function Dodge(cfg) {
33282 var _this = _super.call(this, cfg) || this;
33283 _this.cacheMap = {};
33284 _this.adjustDataArray = [];
33285 _this.mergeData = [];
33286 var _a = cfg.marginRatio,
33287 marginRatio = _a === void 0 ? MARGIN_RATIO : _a,
33288 _b = cfg.dodgeRatio,
33289 dodgeRatio = _b === void 0 ? DODGE_RATIO : _b,
33290 dodgeBy = cfg.dodgeBy,
33291 intervalPadding = cfg.intervalPadding,
33292 dodgePadding = cfg.dodgePadding,
33293 xDimensionLength = cfg.xDimensionLength,
33294 groupNum = cfg.groupNum,
33295 defaultSize = cfg.defaultSize,
33296 maxColumnWidth = cfg.maxColumnWidth,
33297 minColumnWidth = cfg.minColumnWidth,
33298 columnWidthRatio = cfg.columnWidthRatio,
33299 customOffset = cfg.customOffset;
33300 _this.marginRatio = marginRatio;
33301 _this.dodgeRatio = dodgeRatio;
33302 _this.dodgeBy = dodgeBy;
33303 _this.intervalPadding = intervalPadding;
33304 _this.dodgePadding = dodgePadding;
33305 _this.xDimensionLegenth = xDimensionLength;
33306 _this.groupNum = groupNum;
33307 _this.defaultSize = defaultSize;
33308 _this.maxColumnWidth = maxColumnWidth;
33309 _this.minColumnWidth = minColumnWidth;
33310 _this.columnWidthRatio = columnWidthRatio;
33311 _this.customOffset = customOffset;
33312 return _this;
33313 }
33314 Dodge.prototype.process = function (groupDataArray) {
33315 var groupedDataArray = clone(groupDataArray);
33316 // 将数据数组展开一层
33317 var mergeData = flatten(groupedDataArray);
33318 var dodgeBy = this.dodgeBy;
33319 // 如果指定了分组 dim 的字段
33320 var adjustDataArray = dodgeBy ? group(mergeData, dodgeBy) : groupedDataArray;
33321 this.cacheMap = {};
33322 this.adjustDataArray = adjustDataArray;
33323 this.mergeData = mergeData;
33324 this.adjustData(adjustDataArray, mergeData);
33325 this.adjustDataArray = [];
33326 this.mergeData = [];
33327 return groupedDataArray;
33328 };
33329 Dodge.prototype.adjustDim = function (dim, values, data, frameIndex) {
33330 var _this = this;
33331 var customOffset = this.customOffset;
33332 var map = this.getDistribution(dim);
33333 var groupData = this.groupData(data, dim); // 根据值分组
33334 each(groupData, function (group, key) {
33335 var range;
33336 // xField 中只有一个值,不需要做 dodge
33337 if (values.length === 1) {
33338 range = {
33339 pre: values[0] - 1,
33340 next: values[0] + 1
33341 };
33342 } else {
33343 // 如果有多个,则需要获取调整的范围
33344 range = _this.getAdjustRange(dim, parseFloat(key), values);
33345 }
33346 each(group, function (d) {
33347 var value = d[dim];
33348 var valueArr = map[value];
33349 var valIndex = valueArr.indexOf(frameIndex);
33350 if (!isNil(customOffset)) {
33351 var pre = range.pre,
33352 next = range.next;
33353 d[dim] = isFunction(customOffset) ? customOffset(d, range) : (pre + next) / 2 + customOffset;
33354 } else {
33355 d[dim] = _this.getDodgeOffset(range, valIndex, valueArr.length);
33356 }
33357 });
33358 });
33359 return [];
33360 };
33361 Dodge.prototype.getDodgeOffset = function (range, idx, len) {
33362 var _a = this,
33363 dodgeRatio = _a.dodgeRatio,
33364 marginRatio = _a.marginRatio,
33365 intervalPadding = _a.intervalPadding,
33366 dodgePadding = _a.dodgePadding;
33367 var pre = range.pre,
33368 next = range.next;
33369 var tickLength = next - pre;
33370 var position;
33371 // 分多种输入情况
33372 if (!isNil(intervalPadding) && isNil(dodgePadding) && intervalPadding >= 0) {
33373 // 仅配置intervalPadding
33374 var offset = this.getIntervalOnlyOffset(len, idx);
33375 position = pre + offset;
33376 } else if (!isNil(dodgePadding) && isNil(intervalPadding) && dodgePadding >= 0) {
33377 // 仅配置dodgePadding
33378 var offset = this.getDodgeOnlyOffset(len, idx);
33379 position = pre + offset;
33380 } else if (!isNil(intervalPadding) && !isNil(dodgePadding) && intervalPadding >= 0 && dodgePadding >= 0) {
33381 // 同时配置intervalPadding和dodgePadding
33382 var offset = this.getIntervalAndDodgeOffset(len, idx);
33383 position = pre + offset;
33384 } else {
33385 // 默认情况
33386 var width = tickLength * dodgeRatio / len;
33387 var margin = marginRatio * width;
33388 var offset = 1 / 2 * (tickLength - len * width - (len - 1) * margin) + ((idx + 1) * width + idx * margin) - 1 / 2 * width - 1 / 2 * tickLength;
33389 position = (pre + next) / 2 + offset;
33390 }
33391 return position;
33392 };
33393 Dodge.prototype.getIntervalOnlyOffset = function (len, idx) {
33394 var _a = this,
33395 defaultSize = _a.defaultSize,
33396 intervalPadding = _a.intervalPadding,
33397 xDimensionLegenth = _a.xDimensionLegenth,
33398 groupNum = _a.groupNum,
33399 dodgeRatio = _a.dodgeRatio,
33400 maxColumnWidth = _a.maxColumnWidth,
33401 minColumnWidth = _a.minColumnWidth,
33402 columnWidthRatio = _a.columnWidthRatio;
33403 var normalizedIntervalPadding = intervalPadding / xDimensionLegenth;
33404 var normalizedDodgePadding = (1 - (groupNum - 1) * normalizedIntervalPadding) / groupNum * dodgeRatio / (len - 1);
33405 var geomWidth = ((1 - normalizedIntervalPadding * (groupNum - 1)) / groupNum - normalizedDodgePadding * (len - 1)) / len;
33406 // 根据columnWidthRatio/defaultSize/maxColumnWidth/minColumnWidth调整宽度
33407 geomWidth = !isNil(columnWidthRatio) ? 1 / groupNum / len * columnWidthRatio : geomWidth;
33408 if (!isNil(maxColumnWidth)) {
33409 var normalizedMaxWidht = maxColumnWidth / xDimensionLegenth;
33410 geomWidth = Math.min(geomWidth, normalizedMaxWidht);
33411 }
33412 if (!isNil(minColumnWidth)) {
33413 var normalizedMinWidht = minColumnWidth / xDimensionLegenth;
33414 geomWidth = Math.max(geomWidth, normalizedMinWidht);
33415 }
33416 geomWidth = defaultSize ? defaultSize / xDimensionLegenth : geomWidth;
33417 // 调整组内间隔
33418 normalizedDodgePadding = ((1 - (groupNum - 1) * normalizedIntervalPadding) / groupNum - len * geomWidth) / (len - 1);
33419 var offset = ((1 / 2 + idx) * geomWidth + idx * normalizedDodgePadding + 1 / 2 * normalizedIntervalPadding) * groupNum - normalizedIntervalPadding / 2;
33420 return offset;
33421 };
33422 Dodge.prototype.getDodgeOnlyOffset = function (len, idx) {
33423 var _a = this,
33424 defaultSize = _a.defaultSize,
33425 dodgePadding = _a.dodgePadding,
33426 xDimensionLegenth = _a.xDimensionLegenth,
33427 groupNum = _a.groupNum,
33428 marginRatio = _a.marginRatio,
33429 maxColumnWidth = _a.maxColumnWidth,
33430 minColumnWidth = _a.minColumnWidth,
33431 columnWidthRatio = _a.columnWidthRatio;
33432 var normalizedDodgePadding = dodgePadding / xDimensionLegenth;
33433 var normalizedIntervalPadding = 1 * marginRatio / (groupNum - 1);
33434 var geomWidth = ((1 - normalizedIntervalPadding * (groupNum - 1)) / groupNum - normalizedDodgePadding * (len - 1)) / len;
33435 // 根据columnWidthRatio/defaultSize/maxColumnWidth/minColumnWidth调整宽度
33436 geomWidth = columnWidthRatio ? 1 / groupNum / len * columnWidthRatio : geomWidth;
33437 if (!isNil(maxColumnWidth)) {
33438 var normalizedMaxWidht = maxColumnWidth / xDimensionLegenth;
33439 geomWidth = Math.min(geomWidth, normalizedMaxWidht);
33440 }
33441 if (!isNil(minColumnWidth)) {
33442 var normalizedMinWidht = minColumnWidth / xDimensionLegenth;
33443 geomWidth = Math.max(geomWidth, normalizedMinWidht);
33444 }
33445 geomWidth = defaultSize ? defaultSize / xDimensionLegenth : geomWidth;
33446 // 调整组间距
33447 normalizedIntervalPadding = (1 - (geomWidth * len + normalizedDodgePadding * (len - 1)) * groupNum) / (groupNum - 1);
33448 var offset = ((1 / 2 + idx) * geomWidth + idx * normalizedDodgePadding + 1 / 2 * normalizedIntervalPadding) * groupNum - normalizedIntervalPadding / 2;
33449 return offset;
33450 };
33451 Dodge.prototype.getIntervalAndDodgeOffset = function (len, idx) {
33452 var _a = this,
33453 intervalPadding = _a.intervalPadding,
33454 dodgePadding = _a.dodgePadding,
33455 xDimensionLegenth = _a.xDimensionLegenth,
33456 groupNum = _a.groupNum;
33457 var normalizedIntervalPadding = intervalPadding / xDimensionLegenth;
33458 var normalizedDodgePadding = dodgePadding / xDimensionLegenth;
33459 var geomWidth = ((1 - normalizedIntervalPadding * (groupNum - 1)) / groupNum - normalizedDodgePadding * (len - 1)) / len;
33460 var offset = ((1 / 2 + idx) * geomWidth + idx * normalizedDodgePadding + 1 / 2 * normalizedIntervalPadding) * groupNum - normalizedIntervalPadding / 2;
33461 return offset;
33462 };
33463 Dodge.prototype.getDistribution = function (dim) {
33464 var groupedDataArray = this.adjustDataArray;
33465 var cacheMap = this.cacheMap;
33466 var map = cacheMap[dim];
33467 if (!map) {
33468 map = {};
33469 each(groupedDataArray, function (data, index) {
33470 var values = valuesOfKey(data, dim);
33471 if (!values.length) {
33472 values.push(0);
33473 }
33474 each(values, function (val) {
33475 if (!map[val]) {
33476 map[val] = [];
33477 }
33478 map[val].push(index);
33479 });
33480 });
33481 cacheMap[dim] = map;
33482 }
33483 return map;
33484 };
33485 return Dodge;
33486 }(Adjust);
33487
33488 function randomNumber(min, max) {
33489 return (max - min) * Math.random() + min;
33490 }
33491 var Jitter = /** @class */function (_super) {
33492 __extends(Jitter, _super);
33493 function Jitter() {
33494 return _super !== null && _super.apply(this, arguments) || this;
33495 }
33496 Jitter.prototype.process = function (groupDataArray) {
33497 var groupedDataArray = clone(groupDataArray);
33498 // 之前分组之后的数据,然后有合并回去(和分组前可以理解成是一样的)
33499 var mergeData = flatten(groupedDataArray);
33500 // 返回值
33501 this.adjustData(groupedDataArray, mergeData);
33502 return groupedDataArray;
33503 };
33504 /**
33505 * 当前数据分组(index)中,按照维度 dim 进行 jitter 调整
33506 * @param dim
33507 * @param values
33508 * @param dataArray
33509 */
33510 Jitter.prototype.adjustDim = function (dim, values, dataArray) {
33511 var _this = this;
33512 // 在每一个分组中,将数据再按照 dim 分组,用于散列
33513 var groupDataArray = this.groupData(dataArray, dim);
33514 return each(groupDataArray, function (data, dimValue) {
33515 return _this.adjustGroup(data, dim, parseFloat(dimValue), values);
33516 });
33517 };
33518 // 随机出来的字段值
33519 Jitter.prototype.getAdjustOffset = function (range) {
33520 var pre = range.pre,
33521 next = range.next;
33522 // 随机的范围
33523 var margin = (next - pre) * GAP;
33524 return randomNumber(pre + margin, next - margin);
33525 };
33526 // adjust group data
33527 Jitter.prototype.adjustGroup = function (group, dim, dimValue, values) {
33528 var _this = this;
33529 // 调整范围
33530 var range = this.getAdjustRange(dim, dimValue, values);
33531 each(group, function (data) {
33532 data[dim] = _this.getAdjustOffset(range); // 获取调整的位置
33533 });
33534
33535 return group;
33536 };
33537 return Jitter;
33538 }(Adjust);
33539
33540 var Stack = /** @class */function (_super) {
33541 __extends(Stack, _super);
33542 function Stack(cfg) {
33543 var _this = _super.call(this, cfg) || this;
33544 var _a = cfg.adjustNames,
33545 adjustNames = _a === void 0 ? ['y'] : _a,
33546 _b = cfg.height,
33547 height = _b === void 0 ? NaN : _b,
33548 _c = cfg.size,
33549 size = _c === void 0 ? 10 : _c,
33550 _d = cfg.reverseOrder,
33551 reverseOrder = _d === void 0 ? false : _d;
33552 _this.adjustNames = adjustNames;
33553 _this.height = height;
33554 _this.size = size;
33555 _this.reverseOrder = reverseOrder;
33556 return _this;
33557 }
33558 /**
33559 * 方法入参是经过数据分组、数据数字化之后的二维数组
33560 * @param groupDataArray 分组之后的数据
33561 */
33562 Stack.prototype.process = function (groupDataArray) {
33563 var _a = this,
33564 yField = _a.yField,
33565 reverseOrder = _a.reverseOrder;
33566 // 如果有指定 y 字段,那么按照 y 字段来 stack
33567 // 否则,按照高度均分
33568 var d = yField ? this.processStack(groupDataArray) : this.processOneDimStack(groupDataArray);
33569 return reverseOrder ? this.reverse(d) : d;
33570 };
33571 Stack.prototype.reverse = function (groupedDataArray) {
33572 return groupedDataArray.slice(0).reverse();
33573 };
33574 Stack.prototype.processStack = function (groupDataArray) {
33575 var _a = this,
33576 xField = _a.xField,
33577 yField = _a.yField,
33578 reverseOrder = _a.reverseOrder;
33579 // 层叠顺序翻转
33580 var groupedDataArray = reverseOrder ? this.reverse(groupDataArray) : groupDataArray;
33581 // 用来缓存,正数和负数的堆叠问题
33582 var positive = new default_1();
33583 var negative = new default_1();
33584 return groupedDataArray.map(function (dataArray) {
33585 return dataArray.map(function (data) {
33586 var _a;
33587 var x = get(data, xField, 0);
33588 var y = get(data, [yField]);
33589 var xKey = x.toString();
33590 // todo 是否应该取 _origin?因为 y 可能取到的值不正确,比如先 symmetric,再 stack!
33591 y = isArray(y) ? y[1] : y;
33592 if (!isNil(y)) {
33593 var cache = y >= 0 ? positive : negative;
33594 if (!cache.has(xKey)) {
33595 cache.set(xKey, 0);
33596 }
33597 var xValue = cache.get(xKey);
33598 var newXValue = y + xValue;
33599 // 存起来
33600 cache.set(xKey, newXValue);
33601 return __assign(__assign({}, data), (_a = {}, _a[yField] = [xValue, newXValue], _a));
33602 }
33603 // 没有修改,则直接返回
33604 return data;
33605 });
33606 });
33607 };
33608 Stack.prototype.processOneDimStack = function (groupDataArray) {
33609 var _this = this;
33610 var _a = this,
33611 xField = _a.xField,
33612 height = _a.height,
33613 reverseOrder = _a.reverseOrder;
33614 var yField = 'y';
33615 // 如果层叠的顺序翻转
33616 var groupedDataArray = reverseOrder ? this.reverse(groupDataArray) : groupDataArray;
33617 // 缓存累加数据
33618 var cache = new default_1();
33619 return groupedDataArray.map(function (dataArray) {
33620 return dataArray.map(function (data) {
33621 var _a;
33622 var size = _this.size;
33623 var xValue = data[xField];
33624 // todo 没有看到这个 stack 计算原理
33625 var stackHeight = size * 2 / height;
33626 if (!cache.has(xValue)) {
33627 cache.set(xValue, stackHeight / 2); // 初始值大小
33628 }
33629
33630 var stackValue = cache.get(xValue);
33631 // 增加一层 stackHeight
33632 cache.set(xValue, stackValue + stackHeight);
33633 return __assign(__assign({}, data), (_a = {}, _a[yField] = stackValue, _a));
33634 });
33635 });
33636 };
33637 return Stack;
33638 }(Adjust);
33639
33640 var Symmetric = /** @class */function (_super) {
33641 __extends(Symmetric, _super);
33642 function Symmetric() {
33643 return _super !== null && _super.apply(this, arguments) || this;
33644 }
33645 Symmetric.prototype.process = function (groupDataArray) {
33646 var mergeData = flatten(groupDataArray);
33647 var _a = this,
33648 xField = _a.xField,
33649 yField = _a.yField;
33650 // 每个 x 值对应的 最大值
33651 var cache = this.getXValuesMaxMap(mergeData);
33652 // 所有数据的最大的值
33653 var max = Math.max.apply(Math, Object.keys(cache).map(function (key) {
33654 return cache[key];
33655 }));
33656 return map(groupDataArray, function (dataArray) {
33657 return map(dataArray, function (data) {
33658 var _a, _b;
33659 var yValue = data[yField];
33660 var xValue = data[xField];
33661 // 数组处理逻辑
33662 if (isArray(yValue)) {
33663 var off_1 = (max - cache[xValue]) / 2;
33664 return __assign(__assign({}, data), (_a = {}, _a[yField] = map(yValue, function (y) {
33665 return off_1 + y;
33666 }), _a));
33667 }
33668 // 非数组处理逻辑
33669 var offset = (max - yValue) / 2;
33670 return __assign(__assign({}, data), (_b = {}, _b[yField] = [offset, yValue + offset], _b));
33671 });
33672 });
33673 };
33674 // 获取每个 x 对应的最大的值
33675 Symmetric.prototype.getXValuesMaxMap = function (mergeData) {
33676 var _this = this;
33677 var _a = this,
33678 xField = _a.xField,
33679 yField = _a.yField;
33680 // 根据 xField 的值进行分组
33681 var groupDataArray = groupBy(mergeData, function (data) {
33682 return data[xField];
33683 });
33684 // 获取每个 xField 值中的最大值
33685 return mapValues(groupDataArray, function (dataArray) {
33686 return _this.getDimMaxValue(dataArray, yField);
33687 });
33688 };
33689 Symmetric.prototype.getDimMaxValue = function (mergeData, dim) {
33690 // 所有的 value 值
33691 var dimValues = map(mergeData, function (data) {
33692 return get(data, dim, []);
33693 });
33694 // 将数组打平(dim value 有可能是数组,比如 stack 之后的)
33695 var flattenValues = flatten(dimValues);
33696 // 求出数组的最大值
33697 return Math.max.apply(Math, flattenValues);
33698 };
33699 return Symmetric;
33700 }(Adjust);
33701
33702 function toTimeStamp$1(value) {
33703 if (isString(value)) {
33704 if (value.indexOf('T') > 0) {
33705 value = new Date(value).getTime();
33706 } else {
33707 // new Date('2010/01/10') 和 new Date('2010-01-10') 的差别在于:
33708 // 如果仅有年月日时,前者是带有时区的: Fri Jan 10 2020 02:40:13 GMT+0800 (中国标准时间)
33709 // 后者会格式化成 Sun Jan 10 2010 08:00:00 GMT+0800 (中国标准时间)
33710 value = new Date(value.replace(/-/gi, '/')).getTime();
33711 }
33712 }
33713 if (isDate(value)) {
33714 value = value.getTime();
33715 }
33716 return value;
33717 }
33718
33719 var Base$1 = /** @class */function () {
33720 function Base(options) {
33721 mix(this, options);
33722 var _a = this,
33723 scale = _a.scale,
33724 field = _a.field,
33725 data = _a.data;
33726 if (!scale && data) {
33727 var values = valuesOfKey(data, field);
33728 this.scale = this.createScale({
33729 values: values,
33730 field: field
33731 });
33732 }
33733 }
33734 Base.prototype.createScale = function (_scaleConfig) {
33735 return null;
33736 };
33737 // 数据映射方法
33738 Base.prototype._mapping = function (value) {
33739 return value;
33740 };
33741 Base.prototype.update = function (options) {
33742 mix(this, options);
33743 };
33744 Base.prototype.setRange = function (range) {
33745 this.range = range;
33746 };
33747 // 归一化,参数是原始数据,返回是归一化的数据
33748 Base.prototype.normalize = function (value) {
33749 var scale = this.scale;
33750 if (isArray(value)) {
33751 return value.map(function (v) {
33752 return scale.scale(v);
33753 });
33754 }
33755 return scale.scale(value);
33756 };
33757 // convert 参数是归一化的数据,返回定义域的值
33758 Base.prototype.convert = function (value) {
33759 return value;
33760 };
33761 // 等于 normalize + convert, 参数是原始数据,返回是定义域的值
33762 Base.prototype.mapping = function (value, child) {
33763 if (child === void 0) {
33764 child = null;
33765 }
33766 var rst = isFunction(this.callback) ? this.callback(value, child) : null;
33767 if (!isNil(rst)) {
33768 return rst;
33769 }
33770 return this._mapping(value);
33771 };
33772 return Base;
33773 }();
33774
33775 var _typeof_1 = createCommonjsModule(function (module) {
33776 function _typeof(o) {
33777 "@babel/helpers - typeof";
33778
33779 return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
33780 return typeof o;
33781 } : function (o) {
33782 return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
33783 }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(o);
33784 }
33785 module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports;
33786 });
33787
33788 function define$1 (constructor, factory, prototype) {
33789 constructor.prototype = factory.prototype = prototype;
33790 prototype.constructor = constructor;
33791 }
33792 function extend$1(parent, definition) {
33793 var prototype = Object.create(parent.prototype);
33794 for (var key in definition) prototype[key] = definition[key];
33795 return prototype;
33796 }
33797
33798 function Color$1() {}
33799 var _darker = 0.7;
33800 var _brighter = 1 / _darker;
33801 var reI$1 = "\\s*([+-]?\\d+)\\s*",
33802 reN$1 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
33803 reP$1 = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
33804 reHex$1 = /^#([0-9a-f]{3,8})$/,
33805 reRgbInteger$1 = new RegExp("^rgb\\(" + [reI$1, reI$1, reI$1] + "\\)$"),
33806 reRgbPercent$1 = new RegExp("^rgb\\(" + [reP$1, reP$1, reP$1] + "\\)$"),
33807 reRgbaInteger$1 = new RegExp("^rgba\\(" + [reI$1, reI$1, reI$1, reN$1] + "\\)$"),
33808 reRgbaPercent$1 = new RegExp("^rgba\\(" + [reP$1, reP$1, reP$1, reN$1] + "\\)$"),
33809 reHslPercent$1 = new RegExp("^hsl\\(" + [reN$1, reP$1, reP$1] + "\\)$"),
33810 reHslaPercent$1 = new RegExp("^hsla\\(" + [reN$1, reP$1, reP$1, reN$1] + "\\)$");
33811 var named$1 = {
33812 aliceblue: 0xf0f8ff,
33813 antiquewhite: 0xfaebd7,
33814 aqua: 0x00ffff,
33815 aquamarine: 0x7fffd4,
33816 azure: 0xf0ffff,
33817 beige: 0xf5f5dc,
33818 bisque: 0xffe4c4,
33819 black: 0x000000,
33820 blanchedalmond: 0xffebcd,
33821 blue: 0x0000ff,
33822 blueviolet: 0x8a2be2,
33823 brown: 0xa52a2a,
33824 burlywood: 0xdeb887,
33825 cadetblue: 0x5f9ea0,
33826 chartreuse: 0x7fff00,
33827 chocolate: 0xd2691e,
33828 coral: 0xff7f50,
33829 cornflowerblue: 0x6495ed,
33830 cornsilk: 0xfff8dc,
33831 crimson: 0xdc143c,
33832 cyan: 0x00ffff,
33833 darkblue: 0x00008b,
33834 darkcyan: 0x008b8b,
33835 darkgoldenrod: 0xb8860b,
33836 darkgray: 0xa9a9a9,
33837 darkgreen: 0x006400,
33838 darkgrey: 0xa9a9a9,
33839 darkkhaki: 0xbdb76b,
33840 darkmagenta: 0x8b008b,
33841 darkolivegreen: 0x556b2f,
33842 darkorange: 0xff8c00,
33843 darkorchid: 0x9932cc,
33844 darkred: 0x8b0000,
33845 darksalmon: 0xe9967a,
33846 darkseagreen: 0x8fbc8f,
33847 darkslateblue: 0x483d8b,
33848 darkslategray: 0x2f4f4f,
33849 darkslategrey: 0x2f4f4f,
33850 darkturquoise: 0x00ced1,
33851 darkviolet: 0x9400d3,
33852 deeppink: 0xff1493,
33853 deepskyblue: 0x00bfff,
33854 dimgray: 0x696969,
33855 dimgrey: 0x696969,
33856 dodgerblue: 0x1e90ff,
33857 firebrick: 0xb22222,
33858 floralwhite: 0xfffaf0,
33859 forestgreen: 0x228b22,
33860 fuchsia: 0xff00ff,
33861 gainsboro: 0xdcdcdc,
33862 ghostwhite: 0xf8f8ff,
33863 gold: 0xffd700,
33864 goldenrod: 0xdaa520,
33865 gray: 0x808080,
33866 green: 0x008000,
33867 greenyellow: 0xadff2f,
33868 grey: 0x808080,
33869 honeydew: 0xf0fff0,
33870 hotpink: 0xff69b4,
33871 indianred: 0xcd5c5c,
33872 indigo: 0x4b0082,
33873 ivory: 0xfffff0,
33874 khaki: 0xf0e68c,
33875 lavender: 0xe6e6fa,
33876 lavenderblush: 0xfff0f5,
33877 lawngreen: 0x7cfc00,
33878 lemonchiffon: 0xfffacd,
33879 lightblue: 0xadd8e6,
33880 lightcoral: 0xf08080,
33881 lightcyan: 0xe0ffff,
33882 lightgoldenrodyellow: 0xfafad2,
33883 lightgray: 0xd3d3d3,
33884 lightgreen: 0x90ee90,
33885 lightgrey: 0xd3d3d3,
33886 lightpink: 0xffb6c1,
33887 lightsalmon: 0xffa07a,
33888 lightseagreen: 0x20b2aa,
33889 lightskyblue: 0x87cefa,
33890 lightslategray: 0x778899,
33891 lightslategrey: 0x778899,
33892 lightsteelblue: 0xb0c4de,
33893 lightyellow: 0xffffe0,
33894 lime: 0x00ff00,
33895 limegreen: 0x32cd32,
33896 linen: 0xfaf0e6,
33897 magenta: 0xff00ff,
33898 maroon: 0x800000,
33899 mediumaquamarine: 0x66cdaa,
33900 mediumblue: 0x0000cd,
33901 mediumorchid: 0xba55d3,
33902 mediumpurple: 0x9370db,
33903 mediumseagreen: 0x3cb371,
33904 mediumslateblue: 0x7b68ee,
33905 mediumspringgreen: 0x00fa9a,
33906 mediumturquoise: 0x48d1cc,
33907 mediumvioletred: 0xc71585,
33908 midnightblue: 0x191970,
33909 mintcream: 0xf5fffa,
33910 mistyrose: 0xffe4e1,
33911 moccasin: 0xffe4b5,
33912 navajowhite: 0xffdead,
33913 navy: 0x000080,
33914 oldlace: 0xfdf5e6,
33915 olive: 0x808000,
33916 olivedrab: 0x6b8e23,
33917 orange: 0xffa500,
33918 orangered: 0xff4500,
33919 orchid: 0xda70d6,
33920 palegoldenrod: 0xeee8aa,
33921 palegreen: 0x98fb98,
33922 paleturquoise: 0xafeeee,
33923 palevioletred: 0xdb7093,
33924 papayawhip: 0xffefd5,
33925 peachpuff: 0xffdab9,
33926 peru: 0xcd853f,
33927 pink: 0xffc0cb,
33928 plum: 0xdda0dd,
33929 powderblue: 0xb0e0e6,
33930 purple: 0x800080,
33931 rebeccapurple: 0x663399,
33932 red: 0xff0000,
33933 rosybrown: 0xbc8f8f,
33934 royalblue: 0x4169e1,
33935 saddlebrown: 0x8b4513,
33936 salmon: 0xfa8072,
33937 sandybrown: 0xf4a460,
33938 seagreen: 0x2e8b57,
33939 seashell: 0xfff5ee,
33940 sienna: 0xa0522d,
33941 silver: 0xc0c0c0,
33942 skyblue: 0x87ceeb,
33943 slateblue: 0x6a5acd,
33944 slategray: 0x708090,
33945 slategrey: 0x708090,
33946 snow: 0xfffafa,
33947 springgreen: 0x00ff7f,
33948 steelblue: 0x4682b4,
33949 tan: 0xd2b48c,
33950 teal: 0x008080,
33951 thistle: 0xd8bfd8,
33952 tomato: 0xff6347,
33953 turquoise: 0x40e0d0,
33954 violet: 0xee82ee,
33955 wheat: 0xf5deb3,
33956 white: 0xffffff,
33957 whitesmoke: 0xf5f5f5,
33958 yellow: 0xffff00,
33959 yellowgreen: 0x9acd32
33960 };
33961 define$1(Color$1, color$1, {
33962 copy: function copy(channels) {
33963 return Object.assign(new this.constructor(), this, channels);
33964 },
33965 displayable: function displayable() {
33966 return this.rgb().displayable();
33967 },
33968 hex: color_formatHex$1,
33969 // Deprecated! Use color.formatHex.
33970 formatHex: color_formatHex$1,
33971 formatHsl: color_formatHsl$1,
33972 formatRgb: color_formatRgb$1,
33973 toString: color_formatRgb$1
33974 });
33975 function color_formatHex$1() {
33976 return this.rgb().formatHex();
33977 }
33978 function color_formatHsl$1() {
33979 return hslConvert$1(this).formatHsl();
33980 }
33981 function color_formatRgb$1() {
33982 return this.rgb().formatRgb();
33983 }
33984 function color$1(format) {
33985 var m, l;
33986 format = (format + "").trim().toLowerCase();
33987 return (m = reHex$1.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn$1(m) // #ff0000
33988 : l === 3 ? new Rgb$1(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
33989 : l === 8 ? rgba$1(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
33990 : l === 4 ? rgba$1(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
33991 : null // invalid hex
33992 ) : (m = reRgbInteger$1.exec(format)) ? new Rgb$1(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
33993 : (m = reRgbPercent$1.exec(format)) ? new Rgb$1(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
33994 : (m = reRgbaInteger$1.exec(format)) ? rgba$1(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
33995 : (m = reRgbaPercent$1.exec(format)) ? rgba$1(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
33996 : (m = reHslPercent$1.exec(format)) ? hsla$1(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
33997 : (m = reHslaPercent$1.exec(format)) ? hsla$1(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
33998 : named$1.hasOwnProperty(format) ? rgbn$1(named$1[format]) // eslint-disable-line no-prototype-builtins
33999 : format === "transparent" ? new Rgb$1(NaN, NaN, NaN, 0) : null;
34000 }
34001 function rgbn$1(n) {
34002 return new Rgb$1(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
34003 }
34004 function rgba$1(r, g, b, a) {
34005 if (a <= 0) r = g = b = NaN;
34006 return new Rgb$1(r, g, b, a);
34007 }
34008 function rgbConvert$1(o) {
34009 if (!(o instanceof Color$1)) o = color$1(o);
34010 if (!o) return new Rgb$1();
34011 o = o.rgb();
34012 return new Rgb$1(o.r, o.g, o.b, o.opacity);
34013 }
34014 function rgb$1(r, g, b, opacity) {
34015 return arguments.length === 1 ? rgbConvert$1(r) : new Rgb$1(r, g, b, opacity == null ? 1 : opacity);
34016 }
34017 function Rgb$1(r, g, b, opacity) {
34018 this.r = +r;
34019 this.g = +g;
34020 this.b = +b;
34021 this.opacity = +opacity;
34022 }
34023 define$1(Rgb$1, rgb$1, extend$1(Color$1, {
34024 brighter: function brighter(k) {
34025 k = k == null ? _brighter : Math.pow(_brighter, k);
34026 return new Rgb$1(this.r * k, this.g * k, this.b * k, this.opacity);
34027 },
34028 darker: function darker(k) {
34029 k = k == null ? _darker : Math.pow(_darker, k);
34030 return new Rgb$1(this.r * k, this.g * k, this.b * k, this.opacity);
34031 },
34032 rgb: function rgb() {
34033 return this;
34034 },
34035 displayable: function displayable() {
34036 return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
34037 },
34038 hex: rgb_formatHex$1,
34039 // Deprecated! Use color.formatHex.
34040 formatHex: rgb_formatHex$1,
34041 formatRgb: rgb_formatRgb$1,
34042 toString: rgb_formatRgb$1
34043 }));
34044 function rgb_formatHex$1() {
34045 return "#" + hex$1(this.r) + hex$1(this.g) + hex$1(this.b);
34046 }
34047 function rgb_formatRgb$1() {
34048 var a = this.opacity;
34049 a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
34050 return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
34051 }
34052 function hex$1(value) {
34053 value = Math.max(0, Math.min(255, Math.round(value) || 0));
34054 return (value < 16 ? "0" : "") + value.toString(16);
34055 }
34056 function hsla$1(h, s, l, a) {
34057 if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
34058 return new Hsl$1(h, s, l, a);
34059 }
34060 function hslConvert$1(o) {
34061 if (o instanceof Hsl$1) return new Hsl$1(o.h, o.s, o.l, o.opacity);
34062 if (!(o instanceof Color$1)) o = color$1(o);
34063 if (!o) return new Hsl$1();
34064 if (o instanceof Hsl$1) return o;
34065 o = o.rgb();
34066 var r = o.r / 255,
34067 g = o.g / 255,
34068 b = o.b / 255,
34069 min = Math.min(r, g, b),
34070 max = Math.max(r, g, b),
34071 h = NaN,
34072 s = max - min,
34073 l = (max + min) / 2;
34074 if (s) {
34075 if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
34076 s /= l < 0.5 ? max + min : 2 - max - min;
34077 h *= 60;
34078 } else {
34079 s = l > 0 && l < 1 ? 0 : h;
34080 }
34081 return new Hsl$1(h, s, l, o.opacity);
34082 }
34083 function hsl$1(h, s, l, opacity) {
34084 return arguments.length === 1 ? hslConvert$1(h) : new Hsl$1(h, s, l, opacity == null ? 1 : opacity);
34085 }
34086 function Hsl$1(h, s, l, opacity) {
34087 this.h = +h;
34088 this.s = +s;
34089 this.l = +l;
34090 this.opacity = +opacity;
34091 }
34092 define$1(Hsl$1, hsl$1, extend$1(Color$1, {
34093 brighter: function brighter(k) {
34094 k = k == null ? _brighter : Math.pow(_brighter, k);
34095 return new Hsl$1(this.h, this.s, this.l * k, this.opacity);
34096 },
34097 darker: function darker(k) {
34098 k = k == null ? _darker : Math.pow(_darker, k);
34099 return new Hsl$1(this.h, this.s, this.l * k, this.opacity);
34100 },
34101 rgb: function rgb() {
34102 var h = this.h % 360 + (this.h < 0) * 360,
34103 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
34104 l = this.l,
34105 m2 = l + (l < 0.5 ? l : 1 - l) * s,
34106 m1 = 2 * l - m2;
34107 return new Rgb$1(hsl2rgb$1(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb$1(h, m1, m2), hsl2rgb$1(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
34108 },
34109 displayable: function displayable() {
34110 return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
34111 },
34112 formatHsl: function formatHsl() {
34113 var a = this.opacity;
34114 a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
34115 return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
34116 }
34117 }));
34118
34119 /* From FvD 13.37, CSS Color Module Level 3 */
34120 function hsl2rgb$1(h, m1, m2) {
34121 return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
34122 }
34123
34124 var constant = (function (x) {
34125 return function () {
34126 return x;
34127 };
34128 });
34129
34130 function linear$1(a, d) {
34131 return function (t) {
34132 return a + t * d;
34133 };
34134 }
34135 function exponential(a, b, y) {
34136 return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) {
34137 return Math.pow(a + t * b, y);
34138 };
34139 }
34140 function gamma(y) {
34141 return (y = +y) === 1 ? nogamma : function (a, b) {
34142 return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a);
34143 };
34144 }
34145 function nogamma(a, b) {
34146 var d = b - a;
34147 return d ? linear$1(a, d) : constant(isNaN(a) ? b : a);
34148 }
34149
34150 var interpolateRgb = (function rgbGamma(y) {
34151 var color = gamma(y);
34152 function rgb(start, end) {
34153 var r = color((start = rgb$1(start)).r, (end = rgb$1(end)).r),
34154 g = color(start.g, end.g),
34155 b = color(start.b, end.b),
34156 opacity = nogamma(start.opacity, end.opacity);
34157 return function (t) {
34158 start.r = r(t);
34159 start.g = g(t);
34160 start.b = b(t);
34161 start.opacity = opacity(t);
34162 return start + '';
34163 };
34164 }
34165 rgb.gamma = rgbGamma;
34166 return rgb;
34167 })(1);
34168
34169 function interpolateNumber (a, b) {
34170 return a = +a, b = +b, function (t) {
34171 return a * (1 - t) + b * t;
34172 };
34173 }
34174
34175 // 只处理 number 和 color
34176 var interpolate$1 = function interpolate(a, b) {
34177 if (isNumber(b)) {
34178 return interpolateNumber(a, b);
34179 }
34180 return interpolateRgb(a, b);
34181 };
34182 var Linear$1 = /** @class */function (_super) {
34183 __extends(Linear$1, _super);
34184 function Linear$1(options) {
34185 var _this = _super.call(this, options) || this;
34186 _this._updateInterpolate();
34187 return _this;
34188 }
34189 Linear$1.prototype.createScale = function (scaleConfig) {
34190 return new Linear(scaleConfig);
34191 };
34192 Linear$1.prototype._updateInterpolate = function () {
34193 var _a = this.range,
34194 min = _a[0],
34195 max = _a[1];
34196 this.interpolate = interpolate$1(min, max);
34197 };
34198 Linear$1.prototype.update = function (options) {
34199 _super.prototype.update.call(this, options);
34200 this._updateInterpolate();
34201 };
34202 Linear$1.prototype._mapping = function (value) {
34203 var _a = this,
34204 scale = _a.scale,
34205 interpolate = _a.interpolate;
34206 if (isArray(value)) {
34207 return value.map(function (v) {
34208 return interpolate(scale.scale(v));
34209 });
34210 }
34211 return interpolate(scale.scale(value));
34212 };
34213 Linear$1.prototype.normalize = function (value) {
34214 var scale = this.scale;
34215 if (isArray(value)) {
34216 return value.map(function (v) {
34217 return scale.scale(v);
34218 });
34219 }
34220 return scale.scale(value);
34221 };
34222 Linear$1.prototype.convert = function (value) {
34223 var range = this.range;
34224 var min = range[0],
34225 max = range[1];
34226 if (isArray(value)) {
34227 return value.map(function (v) {
34228 return min + (max - min) * v;
34229 });
34230 }
34231 return min + (max - min) * value;
34232 };
34233 return Linear$1;
34234 }(Base$1);
34235
34236 var Category$1 = /** @class */function (_super) {
34237 __extends(Category$1, _super);
34238 function Category$1() {
34239 return _super !== null && _super.apply(this, arguments) || this;
34240 }
34241 Category$1.prototype.createScale = function (scaleConfig) {
34242 return new Category(scaleConfig);
34243 };
34244 Category$1.prototype._mapping = function (value) {
34245 var _a = this,
34246 scale = _a.scale,
34247 range = _a.range;
34248 if (scale.type === 'cat') {
34249 var index_1 = scale.translate(value);
34250 return range[index_1 % range.length];
34251 }
34252 var normalizeValue = scale.scale(value);
34253 var index = Math.round(normalizeValue * (range.length - 1));
34254 return range[index];
34255 };
34256 return Category$1;
34257 }(Base$1);
34258
34259 var Identity$1 = /** @class */function (_super) {
34260 __extends(Identity$1, _super);
34261 function Identity$1() {
34262 return _super !== null && _super.apply(this, arguments) || this;
34263 }
34264 Identity$1.prototype.createScale = function (scaleConfig) {
34265 return new Identity(scaleConfig);
34266 };
34267 Identity$1.prototype._mapping = function () {
34268 var _a = this,
34269 field = _a.field,
34270 range = _a.range;
34271 return field || range && range[0];
34272 };
34273 return Identity$1;
34274 }(Base$1);
34275
34276 var Attrs = /*#__PURE__*/Object.freeze({
34277 __proto__: null,
34278 Attr: Base$1,
34279 Linear: Linear$1,
34280 Category: Category$1,
34281 Identity: Identity$1
34282 });
34283
34284 var Identity$2 = Identity$1,
34285 Linear$2 = Linear$1,
34286 Category$2 = Category$1;
34287 // 需要映射的属性名
34288 var ATTRS = ['x', 'y', 'color', 'size', 'shape'];
34289 // 分组处理的属性
34290 var GROUP_ATTRS = ['color', 'size', 'shape'];
34291 function cloneScale(scale, scaleConfig) {
34292 // @ts-ignore
34293 return new scale.constructor(__assign(__assign({}, scale.__cfg__), scaleConfig));
34294 }
34295 var AttrController = /** @class */function () {
34296 function AttrController(scaleController, attrsRange) {
34297 this.scaleController = scaleController;
34298 this.attrsRange = attrsRange;
34299 this.options = {};
34300 this.attrs = {};
34301 }
34302 AttrController.prototype.parseOption = function (option, attrName) {
34303 if (!option) {
34304 return {
34305 type: 'identity'
34306 };
34307 }
34308 if (isString(option)) {
34309 return {
34310 field: option,
34311 type: 'category'
34312 };
34313 }
34314 if (isNumber(option)) {
34315 if (attrName === 'size') {
34316 return {
34317 type: 'identity',
34318 field: option
34319 };
34320 }
34321 }
34322 if (isArray(option)) {
34323 return {
34324 field: option[0],
34325 range: option[1]
34326 };
34327 }
34328 return option;
34329 };
34330 AttrController.prototype.getAttrOptions = function (props, justifyContentCenter) {
34331 var _this = this;
34332 if (!props.x || !props.y) {
34333 throw new Error('x, y are required !');
34334 }
34335 var options = {};
34336 var ranges = this.attrsRange;
34337 ATTRS.forEach(function (attrName) {
34338 if (!props[attrName]) return;
34339 var option = _this.parseOption(props[attrName], attrName);
34340 if (!option.range) {
34341 option.range = ranges[attrName];
34342 }
34343 options[attrName] = option;
34344 });
34345 // @ts-ignore
34346 var x = options.x,
34347 y = options.y;
34348 x.justifyContent = justifyContentCenter;
34349 // x, y 都是固定Linear 映射
34350 x.type = Linear$2;
34351 y.type = Linear$2;
34352 return options;
34353 };
34354 AttrController.prototype.getDefaultAttrValues = function () {
34355 var _a = this.attrsRange,
34356 color = _a.color,
34357 shape = _a.shape;
34358 return {
34359 color: color[0],
34360 shape: shape && shape[0]
34361 };
34362 };
34363 AttrController.prototype.getGroupScales = function () {
34364 var attrs = this.attrs;
34365 var scales = [];
34366 each(GROUP_ATTRS, function (attrName) {
34367 var attr = attrs[attrName];
34368 if (!attr) {
34369 return;
34370 }
34371 var scale = attr.scale;
34372 if (scale && scale.isCategory && scales.indexOf(scale) === -1) {
34373 scales.push(scale);
34374 }
34375 });
34376 return scales;
34377 };
34378 AttrController.prototype.createAttr = function (option) {
34379 var type = option.type,
34380 field = option.field,
34381 scaleConfig = option.scale;
34382 if (isNil(field) || type === Identity$2) {
34383 return new Identity$2(option);
34384 }
34385 var scale = this.scaleController.getScale(field);
34386 var attrOption = __assign(__assign({}, option), {
34387 data: this.scaleController.getData(),
34388 // scaleConfig 只在属性映射中生效
34389 scale: scaleConfig ? cloneScale(scale, scaleConfig) : scale
34390 });
34391 // identity
34392 if (scale && scale.type === 'identity') {
34393 return new Identity$2(attrOption);
34394 }
34395 // Attr的默认类型和scale类型保持一致
34396 var AttrConstructor = scale.isLinear ? Linear$2 : Category$2;
34397 // custom Attr Constructor
34398 if (isFunction(type)) {
34399 AttrConstructor = type;
34400 }
34401 if (isString(type) && Attrs[upperFirst(type)]) {
34402 AttrConstructor = Attrs[upperFirst(type)];
34403 }
34404 return new AttrConstructor(attrOption);
34405 };
34406 AttrController.prototype.create = function (options) {
34407 this.update(options);
34408 };
34409 AttrController.prototype.update = function (nextOptions) {
34410 var _a = this,
34411 scaleController = _a.scaleController,
34412 lastOptions = _a.options,
34413 lastAttrs = _a.attrs;
34414 var nextAttrs = {};
34415 each(nextOptions, function (nextOption, attrName) {
34416 var lastOption = lastOptions[attrName];
34417 if (equal(nextOption, lastOption)) {
34418 nextAttrs[attrName] = lastAttrs[attrName];
34419 }
34420 var field = nextOption.field,
34421 justifyContent = nextOption.justifyContent;
34422 if (field) {
34423 scaleController.setScale(field, {
34424 justifyContent: justifyContent
34425 });
34426 }
34427 });
34428 this.options = nextOptions;
34429 this.attrs = nextAttrs;
34430 };
34431 AttrController.prototype.getAttr = function (attrName) {
34432 var _a = this,
34433 attrs = _a.attrs,
34434 options = _a.options;
34435 var attr = attrs[attrName];
34436 if (attr) {
34437 return attr;
34438 }
34439 var option = options[attrName];
34440 if (!option) {
34441 return null;
34442 }
34443 var newAttr = this.createAttr(option);
34444 attrs[attrName] = newAttr;
34445 return newAttr;
34446 };
34447 AttrController.prototype.getAttrs = function () {
34448 var _this = this;
34449 var _a = this,
34450 options = _a.options,
34451 attrs = _a.attrs;
34452 each(options, function (option, attrName) {
34453 _this.getAttr(attrName);
34454 });
34455 return attrs;
34456 };
34457 AttrController.prototype.isGroupAttr = function (attrName) {
34458 return GROUP_ATTRS.indexOf(attrName) !== -1;
34459 };
34460 AttrController.prototype.getAttrsByLinear = function () {
34461 var attrs = this.attrs;
34462 var attrNames = Object.keys(attrs);
34463 var linearAttrs = [];
34464 var nonlinearAttrs = [];
34465 attrNames.forEach(function (attrName) {
34466 if (attrName === 'x' || attrName === 'y') {
34467 linearAttrs.push(attrName);
34468 return;
34469 }
34470 var scale = attrs[attrName].scale;
34471 if (scale && scale.type === 'linear') {
34472 linearAttrs.push(attrName);
34473 } else {
34474 nonlinearAttrs.push(attrName);
34475 }
34476 });
34477 return {
34478 linearAttrs: linearAttrs,
34479 nonlinearAttrs: nonlinearAttrs
34480 };
34481 };
34482 return AttrController;
34483 }();
34484
34485 var AdjustMap = {
34486 Stack: Stack,
34487 Dodge: Dodge,
34488 Jitter: Jitter,
34489 Symmetric: Symmetric
34490 };
34491 // 保留原始数据的字段
34492 var FIELD_ORIGIN = 'origin';
34493 var Geometry = /** @class */function (_super) {
34494 __extends(Geometry, _super);
34495 function Geometry(props, context) {
34496 var _this = _super.call(this, props, context) || this;
34497 _this.isGeometry = true;
34498 // x 轴居中
34499 _this.justifyContent = false;
34500 // y 轴是否从0开始
34501 _this.startOnZero = false;
34502 // 是否连接空值
34503 _this.connectNulls = false;
34504 // 是否需要排序
34505 _this.sortable = false;
34506 mix(_this, _this.getDefaultCfg());
34507 var chart = props.chart,
34508 coord = props.coord;
34509 var attrsRange = _this._getThemeAttrsRange();
34510 _this.attrController = new AttrController(chart.scale, attrsRange);
34511 var _a = _this,
34512 attrController = _a.attrController,
34513 justifyContent = _a.justifyContent;
34514 var attrOptions = attrController.getAttrOptions(props, !coord.isCyclic() || justifyContent);
34515 attrController.create(attrOptions);
34516 return _this;
34517 }
34518 Geometry.prototype.getDefaultCfg = function () {
34519 return {};
34520 };
34521 Geometry.prototype.willReceiveProps = function (nextProps) {
34522 var _a = this,
34523 lastProps = _a.props,
34524 attrController = _a.attrController,
34525 justifyContent = _a.justifyContent;
34526 var nextData = nextProps.data,
34527 nextAdjust = nextProps.adjust,
34528 coord = nextProps.coord,
34529 selection = nextProps.selection;
34530 var lastData = lastProps.data,
34531 lastAdjust = lastProps.adjust,
34532 lastSelection = lastProps.selection;
34533 var justifyContentCenter = !coord.isCyclic() || justifyContent;
34534 var lastAttrOptions = attrController.getAttrOptions(lastProps, justifyContentCenter);
34535 attrController.attrsRange = this._getThemeAttrsRange();
34536 var nextAttrOptions = attrController.getAttrOptions(nextProps, justifyContentCenter);
34537 if (!equal(nextAttrOptions, lastAttrOptions)) {
34538 attrController.update(nextAttrOptions);
34539 this.dataRecords = null;
34540 }
34541 // 重新处理数据
34542 if (nextData !== lastData) {
34543 this.dataRecords = null;
34544 }
34545 // 重新处理数据
34546 if (nextAdjust !== lastAdjust) {
34547 this.dataRecords = null;
34548 }
34549 // selection 发生变化
34550 if (!equal(selection, lastSelection)) {
34551 _super.prototype.willReceiveProps.call(this, nextProps);
34552 }
34553 };
34554 Geometry.prototype.willMount = function () {
34555 this._createAttrs();
34556 if (!this.dataRecords) {
34557 this._processData();
34558 }
34559 };
34560 Geometry.prototype.willUpdate = function () {
34561 this._createAttrs();
34562 if (!this.dataRecords) {
34563 this._processData();
34564 } else {
34565 this._readjustData(this.dataRecords);
34566 }
34567 };
34568 Geometry.prototype.didMount = function () {
34569 this._initEvent();
34570 _super.prototype.didMount.call(this);
34571 // 更新 attrController
34572 this.attrController.attrsRange = this._getThemeAttrsRange();
34573 };
34574 Geometry.prototype._initEvent = function () {
34575 var _this = this;
34576 var props = this.props;
34577 var chart = props.chart;
34578 ['onPressStart', 'onPress', 'onPressEnd', 'onPan', 'onPanStart', 'onPanEnd'].forEach(function (eventName) {
34579 if (props[eventName]) {
34580 chart.on(eventName.substr(2).toLowerCase(), function (ev) {
34581 ev.geometry = _this;
34582 props[eventName](ev);
34583 });
34584 }
34585 });
34586 };
34587 Geometry.prototype._createAttrs = function () {
34588 var attrController = this.attrController;
34589 attrController.attrs = {};
34590 this.attrs = attrController.getAttrs();
34591 };
34592 Geometry.prototype._getThemeAttrsRange = function () {
34593 var _a = this,
34594 context = _a.context,
34595 props = _a.props,
34596 geomType = _a.geomType;
34597 var coord = props.coord;
34598 var theme = context.theme;
34599 var colors = theme.colors,
34600 sizes = theme.sizes,
34601 shapes = theme.shapes;
34602 return {
34603 x: coord.x,
34604 y: coord.y,
34605 color: colors,
34606 size: sizes,
34607 shape: shapes[geomType]
34608 };
34609 };
34610 Geometry.prototype._createAdjust = function () {
34611 var _a = this,
34612 attrs = _a.attrs,
34613 props = _a.props;
34614 var adjust = props.adjust;
34615 if (!adjust) {
34616 return null;
34617 }
34618 var adjustCfg = typeof adjust === 'string' ? {
34619 type: adjust
34620 } : adjust;
34621 var adjustType = upperFirst(adjustCfg.type);
34622 var AdjustConstructor = AdjustMap[adjustType];
34623 if (!AdjustConstructor) {
34624 throw new Error('not support such adjust : ' + adjust);
34625 }
34626 if (adjustType === 'Dodge') {
34627 // @ts-ignore
34628 adjustCfg.adjustNames = ['x'];
34629 }
34630 var x = attrs.x,
34631 y = attrs.y;
34632 // @ts-ignore
34633 adjustCfg.xField = x.field;
34634 // @ts-ignore
34635 adjustCfg.yField = y.field;
34636 var adjustInstance = new AdjustConstructor(adjustCfg);
34637 this.adjust = {
34638 type: adjustCfg.type,
34639 adjust: adjustInstance
34640 };
34641 return this.adjust;
34642 };
34643 Geometry.prototype._adjustScales = function () {
34644 var _a = this,
34645 attrs = _a.attrs,
34646 props = _a.props,
34647 defaultStartOnZero = _a.startOnZero;
34648 var chart = props.chart,
34649 _b = props.startOnZero,
34650 startOnZero = _b === void 0 ? defaultStartOnZero : _b,
34651 coord = props.coord,
34652 adjust = props.adjust;
34653 var isPolar = coord.isPolar,
34654 transposed = coord.transposed;
34655 var y = attrs.y;
34656 var yField = y.field;
34657 // 如果从 0 开始,只调整 y 轴 scale
34658 if (startOnZero) {
34659 var y_1 = attrs.y;
34660 chart.scale.adjustStartZero(y_1.scale);
34661 }
34662 // 饼图的scale调整,关闭nice
34663 if (isPolar && transposed && (adjust === 'stack' || (adjust === null || adjust === void 0 ? void 0 : adjust.type) === 'stack')) {
34664 var y_2 = attrs.y;
34665 chart.scale.adjustPieScale(y_2.scale);
34666 }
34667 if (adjust === 'stack' || (adjust === null || adjust === void 0 ? void 0 : adjust.type) === 'stack') {
34668 this._updateStackRange(yField, y.scale, this.dataArray);
34669 }
34670 };
34671 Geometry.prototype._groupData = function (data) {
34672 var attrController = this.attrController;
34673 var groupScales = attrController.getGroupScales();
34674 if (!groupScales.length) {
34675 return [{
34676 children: data
34677 }];
34678 }
34679 var names = [];
34680 groupScales.forEach(function (scale) {
34681 var field = scale.field;
34682 names.push(field);
34683 });
34684 var groups = groupToMap(data, names);
34685 var records = [];
34686 for (var key in groups) {
34687 records.push({
34688 key: key.replace(/^_/, ''),
34689 children: groups[key]
34690 });
34691 }
34692 return records;
34693 };
34694 Geometry.prototype._saveOrigin = function (originData) {
34695 var _a;
34696 var len = originData.length;
34697 var data = new Array(len);
34698 for (var i = 0; i < len; i++) {
34699 var record = originData[i];
34700 data[i] = __assign(__assign({}, record), (_a = {}, _a[FIELD_ORIGIN] = record, _a));
34701 }
34702 return data;
34703 };
34704 Geometry.prototype._numberic = function (data) {
34705 var attrs = this.attrs;
34706 var scales = [attrs.x.scale, attrs.y.scale];
34707 for (var j = 0, len = data.length; j < len; j++) {
34708 var obj = data[j];
34709 var count = scales.length;
34710 for (var i = 0; i < count; i++) {
34711 var scale = scales[i];
34712 if (scale.isCategory) {
34713 var field = scale.field;
34714 var value = scale.translate(obj.origin[field]);
34715 obj[field] = value;
34716 }
34717 }
34718 }
34719 };
34720 Geometry.prototype._adjustData = function (records) {
34721 var adjust = this.adjust;
34722 // groupedArray 是二维数组
34723 var groupedArray = records.map(function (record) {
34724 return record.children;
34725 });
34726 if (!adjust) {
34727 return groupedArray;
34728 }
34729 var attrs = this.attrs;
34730 var scales = [attrs.x.scale, attrs.y.scale];
34731 for (var i = 0, len = groupedArray.length; i < len; i++) {
34732 var records_1 = groupedArray[i];
34733 for (var j = 0, len_1 = records_1.length; j < len_1; j++) {
34734 var record = records_1[j];
34735 var count = scales.length;
34736 for (var i_1 = 0; i_1 < count; i_1++) {
34737 var scale = scales[i_1];
34738 var field = scale.field;
34739 record[field] = record.origin[field];
34740 }
34741 }
34742 }
34743 if (adjust.type === 'dodge') {
34744 for (var i = 0, len = groupedArray.length; i < len; i++) {
34745 // 如果是dodge, 需要处理数字再处理
34746 this._numberic(groupedArray[i]);
34747 }
34748 }
34749 var adjustData = adjust.adjust.process(groupedArray);
34750 // process 返回的是新数组,所以要修改 records
34751 records.forEach(function (record, index) {
34752 record.children = adjustData[index];
34753 });
34754 return adjustData;
34755 };
34756 Geometry.prototype._updateStackRange = function (field, scale, dataArray) {
34757 var flattenArray = flatten(dataArray);
34758 var min = Infinity;
34759 var max = -Infinity;
34760 for (var i = 0, len = flattenArray.length; i < len; i++) {
34761 var obj = flattenArray[i];
34762 var tmpMin = Math.min.apply(null, obj[field]);
34763 var tmpMax = Math.max.apply(null, obj[field]);
34764 if (tmpMin < min) {
34765 min = tmpMin;
34766 }
34767 if (tmpMax > max) {
34768 max = tmpMax;
34769 }
34770 }
34771 if (min !== scale.min || max !== scale.max) {
34772 scale.change({
34773 min: min,
34774 max: max
34775 });
34776 }
34777 };
34778 Geometry.prototype._processData = function () {
34779 var props = this.props;
34780 var originData = props.data;
34781 var data = this._saveOrigin(originData);
34782 // 根据分类度量进行数据分组
34783 var records = this._groupData(data);
34784 this._createAdjust();
34785 // 根据adjust分组
34786 var dataArray = this._adjustData(records);
34787 this.dataArray = dataArray;
34788 // scale适配调整,主要是调整 y 轴是否从 0 开始 以及 饼图
34789 this._adjustScales();
34790 // 数据排序(非必须)
34791 if (this.sortable) {
34792 this._sortData(records);
34793 }
34794 this.dataRecords = records;
34795 };
34796 Geometry.prototype._readjustData = function (records) {
34797 var adjust = this.adjust;
34798 if (!adjust) return;
34799 // 根据adjust分组
34800 var dataArray = this._adjustData(records);
34801 this.dataArray = dataArray;
34802 };
34803 Geometry.prototype._sortData = function (records) {
34804 var xScale = this.getXScale();
34805 var field = xScale.field,
34806 type = xScale.type;
34807 if (type !== 'identity' && xScale.values.length > 1) {
34808 each(records, function (_a) {
34809 var children = _a.children;
34810 children.sort(function (record1, record2) {
34811 if (type === 'timeCat') {
34812 return toTimeStamp$1(record1[FIELD_ORIGIN][field]) - toTimeStamp$1(record2[FIELD_ORIGIN][field]);
34813 }
34814 var normalized1 = xScale.translate(record1[FIELD_ORIGIN][field]);
34815 var normalized2 = xScale.translate(record2[FIELD_ORIGIN][field]);
34816 if (isNaN(normalized1)) {
34817 return 1;
34818 }
34819 if (isNaN(normalized2)) {
34820 return -1;
34821 }
34822 return normalized1 - normalized2;
34823 });
34824 });
34825 }
34826 };
34827 Geometry.prototype.getY0Value = function () {
34828 var _a = this,
34829 attrs = _a.attrs,
34830 props = _a.props;
34831 var chart = props.chart;
34832 var field = attrs.y.field;
34833 var scale = chart.getScale(field);
34834 return chart.scale.getZeroValue(scale);
34835 };
34836 // 根据各属性映射的值域来获取真正的绘图属性
34837 Geometry.prototype._getShapeStyle = function (shape, origin) {
34838 var _a = this,
34839 context = _a.context,
34840 props = _a.props,
34841 geomType = _a.geomType;
34842 var theme = context.theme;
34843 var shapeTheme = theme.shape[geomType] || {};
34844 var defaultShapeStyle = shapeTheme.default;
34845 var shapeThemeStyle = shapeTheme[shape];
34846 var style = props.style;
34847 var shapeStyle = __assign(__assign({}, defaultShapeStyle), shapeThemeStyle);
34848 if (!style || !isObject(style)) {
34849 return shapeStyle;
34850 }
34851 // @ts-ignore
34852 var field = style.field,
34853 styles = __rest(style, ["field"]);
34854 var value = field ? origin[field] : origin;
34855 each(styles, function (attr, key) {
34856 if (isFunction(attr)) {
34857 var attrValue = attr(value);
34858 if (!attrValue) {
34859 return;
34860 }
34861 shapeStyle[key] = attrValue;
34862 return;
34863 }
34864 shapeStyle[key] = attr;
34865 });
34866 return shapeStyle;
34867 };
34868 /**
34869 * 数据映射到视图属性核心逻辑
34870 * x、y 每个元素走 normalize 然后 convertPoint
34871 * color、size、shape
34872 * 如果是Linear,则每个元素 走 mapping
34873 * 如果是Category/Identity 则第一个元素走 mapping
34874 */
34875 Geometry.prototype._mapping = function (records) {
34876 var _a = this,
34877 attrs = _a.attrs,
34878 props = _a.props,
34879 attrController = _a.attrController;
34880 var coord = props.coord;
34881 var _b = attrController.getAttrsByLinear(),
34882 linearAttrs = _b.linearAttrs,
34883 nonlinearAttrs = _b.nonlinearAttrs;
34884 var defaultAttrValues = attrController.getDefaultAttrValues();
34885 var mappedRecords = [];
34886 for (var i = 0, len = records.length; i < len; i++) {
34887 var record = records[i];
34888 var children = record.children;
34889 var attrValues = __assign({}, defaultAttrValues);
34890 var firstChild = children[0];
34891 if (children.length === 0) {
34892 mappedRecords.push(__assign({}, record));
34893 continue;
34894 }
34895 // 非线性映射
34896 for (var k = 0, len_2 = nonlinearAttrs.length; k < len_2; k++) {
34897 var attrName = nonlinearAttrs[k];
34898 var attr = attrs[attrName];
34899 // 非线性映射只用映射第一项就可以了
34900 attrValues[attrName] = attr.mapping(firstChild[attr.field], firstChild.origin);
34901 }
34902 // 线性属性映射
34903 var mappedChildren = [];
34904 for (var j = 0, childrenLen = children.length; j < childrenLen; j++) {
34905 var child = children[j];
34906 var normalized = {};
34907 for (var k = 0; k < linearAttrs.length; k++) {
34908 var attrName = linearAttrs[k];
34909 var attr = attrs[attrName];
34910 var value = child[attr.field];
34911 // 分类属性的线性映射
34912 if (attrController.isGroupAttr(attrName)) {
34913 attrValues[attrName] = attr.mapping(value, child);
34914 } else {
34915 normalized[attrName] = attr.normalize(value);
34916 }
34917 }
34918 var _c = coord.convertPoint({
34919 x: normalized.x,
34920 y: normalized.y
34921 }),
34922 x = _c.x,
34923 y = _c.y;
34924 // 获取 shape 的 style
34925 var origin_1 = child.origin;
34926 var shapeName = attrValues.shape;
34927 var shape = this._getShapeStyle(shapeName, origin_1);
34928 var selected = this.isSelected(child);
34929 mappedChildren.push(__assign(__assign(__assign({}, child), attrValues), {
34930 normalized: normalized,
34931 x: x,
34932 y: y,
34933 shapeName: shapeName,
34934 shape: shape,
34935 selected: selected
34936 }));
34937 }
34938 mappedRecords.push(__assign(__assign({}, record), {
34939 children: mappedChildren
34940 }));
34941 }
34942 return mappedRecords;
34943 };
34944 // 数据映射
34945 Geometry.prototype.mapping = function () {
34946 var dataRecords = this.dataRecords;
34947 // 数据映射
34948 this.records = this._mapping(dataRecords);
34949 return this.records;
34950 };
34951 Geometry.prototype.getClip = function () {
34952 var _a = this.props,
34953 coord = _a.coord,
34954 viewClip = _a.viewClip;
34955 var contentWidth = coord.width,
34956 contentHeight = coord.height,
34957 left = coord.left,
34958 top = coord.top;
34959 if (viewClip) {
34960 return {
34961 type: 'rect',
34962 style: {
34963 x: left,
34964 y: top,
34965 width: contentWidth,
34966 height: contentHeight
34967 }
34968 };
34969 }
34970 return null;
34971 };
34972 Geometry.prototype.getAttr = function (attrName) {
34973 return this.attrController.getAttr(attrName);
34974 };
34975 Geometry.prototype.getXScale = function () {
34976 return this.getAttr('x').scale;
34977 };
34978 Geometry.prototype.getYScale = function () {
34979 return this.getAttr('y').scale;
34980 };
34981 Geometry.prototype._getXSnap = function (invertPointX) {
34982 var xScale = this.getXScale();
34983 if (xScale.isCategory) {
34984 return xScale.invert(invertPointX);
34985 }
34986 // linear 类型
34987 var invertValue = xScale.invert(invertPointX);
34988 var values = xScale.values;
34989 var len = values.length;
34990 // 如果只有1个点直接返回第1个点
34991 if (len === 1) {
34992 return values[0];
34993 }
34994 // 第1个点和第2个点之间
34995 if ((values[0] + values[1]) / 2 > invertValue) {
34996 return values[0];
34997 }
34998 // 最后2个点
34999 if ((values[len - 2] + values[len - 1]) / 2 <= invertValue) {
35000 return values[len - 1];
35001 }
35002 for (var i = 1; i < len; i++) {
35003 // 中间的点
35004 if ((values[i - 1] + values[i]) / 2 <= invertValue && (values[i + 1] + values[i]) / 2 > invertValue) {
35005 return values[i];
35006 }
35007 }
35008 return null;
35009 };
35010 Geometry.prototype._getYSnapRecords = function (invertPointY, records) {
35011 var yScale = this.getYScale();
35012 var yField = yScale.field;
35013 var yValue = yScale.invert(invertPointY);
35014 // category
35015 if (yScale.isCategory) {
35016 return records.filter(function (record) {
35017 return record[FIELD_ORIGIN][yField] === yValue;
35018 });
35019 }
35020 // linear
35021 return records.filter(function (record) {
35022 var rangeY = record[yField];
35023 if (rangeY[0] <= yValue && rangeY[1] >= yValue) {
35024 return true;
35025 }
35026 return false;
35027 });
35028 };
35029 // 把 records 拍平
35030 Geometry.prototype.flatRecords = function () {
35031 var records = this.records;
35032 return records.reduce(function (prevRecords, record) {
35033 return prevRecords.concat(record.children);
35034 }, []);
35035 };
35036 Geometry.prototype.getSnapRecords = function (point, inCoordRange) {
35037 var props = this.props;
35038 var coord = props.coord,
35039 adjust = props.adjust;
35040 var invertPoint = coord.invertPoint(point);
35041 var xScale = this.getXScale();
35042 var yScale = this.getYScale();
35043 // 如果不在coord坐标范围内,直接返回空
35044 // if (invertPoint.x < 0 || invertPoint.y < 0) {
35045 // return [];
35046 // }
35047 // 是否调整 point,默认为不调整
35048 if (inCoordRange) {
35049 var xRange = xScale.range;
35050 var yRange = yScale.range;
35051 // 如果 inCoordRange=true,当 point 不在 coord 坐标范围内时,调整到 range 内
35052 invertPoint.x = Math.min(Math.max(invertPoint.x, xRange[0]), xRange[1]);
35053 invertPoint.y = Math.min(Math.max(invertPoint.y, yRange[0]), yRange[1]);
35054 }
35055 var records = this.flatRecords();
35056 var xValue = xScale.invert(invertPoint.x);
35057 var yValue = yScale.invert(invertPoint.y);
35058 var coordPoint = coord.convertPoint(invertPoint);
35059 var coordRecord = {
35060 // 坐标点
35061 x: coordPoint.x,
35062 y: coordPoint.y,
35063 xValue: xValue,
35064 yValue: yValue,
35065 xText: xScale.getText(xValue),
35066 yText: yScale.getText(yValue)
35067 };
35068 // 处理饼图
35069 if (adjust === 'stack' && coord.isPolar && coord.transposed) {
35070 // 弧度在半径范围内
35071 if (invertPoint.x >= 0 && invertPoint.x <= 1) {
35072 var snapRecords = this._getYSnapRecords(invertPoint.y, records);
35073 return snapRecords;
35074 }
35075 }
35076 var rst = [];
35077 var value = this._getXSnap(invertPoint.x);
35078 if (isNull(value)) {
35079 return rst;
35080 }
35081 var xField = xScale.field;
35082 var yField = yScale.field;
35083 for (var i = 0, len = records.length; i < len; i++) {
35084 var record = __assign(__assign({}, records[i]), {
35085 xField: xField,
35086 yField: yField,
35087 coord: coordRecord
35088 });
35089 var originValue = record[FIELD_ORIGIN][xField];
35090 if (xScale.type === 'timeCat' && toTimeStamp$1(originValue) === value) {
35091 rst.push(record);
35092 } else if (originValue === value) {
35093 rst.push(record);
35094 }
35095 }
35096 return rst;
35097 };
35098 Geometry.prototype.getRecords = function (data, field) {
35099 if (field === void 0) {
35100 field = 'xfield';
35101 }
35102 var records = this.flatRecords();
35103 var xScale = this.getXScale();
35104 var yScale = this.getYScale();
35105 var xField = xScale.field;
35106 var yField = yScale.field;
35107 var value = data[xField];
35108 var rst = [];
35109 for (var i = 0, len = records.length; i < len; i++) {
35110 var record = __assign(__assign({}, records[i]), {
35111 xField: xField,
35112 yField: yField
35113 });
35114 var originValue = record[FIELD_ORIGIN][field === 'xfield' ? xField : yField];
35115 if (originValue === value) {
35116 rst.push(record);
35117 }
35118 }
35119 return rst;
35120 };
35121 Geometry.prototype.getLegendItems = function () {
35122 var _a = this,
35123 attrController = _a.attrController,
35124 records = _a.records;
35125 var colorAttr = attrController.getAttr('color');
35126 if (!colorAttr) return null;
35127 var scale = colorAttr.scale;
35128 var isCategory = scale.isCategory,
35129 field = scale.field;
35130 if (!isCategory) return null;
35131 var flatRecords = records ? this.flatRecords() : [];
35132 var ticks = scale.getTicks();
35133 var items = ticks.map(function (tick) {
35134 var text = tick.text,
35135 tickValue = tick.tickValue;
35136 var record = find(flatRecords, function (item) {
35137 if (!item) return false;
35138 var origin = item.origin;
35139 return origin[field] === tickValue;
35140 });
35141 // @ts-ignore
35142 var color = record ? record.color : colorAttr.mapping(tickValue);
35143 return {
35144 field: scale.field,
35145 color: color,
35146 name: text,
35147 tickValue: tickValue
35148 };
35149 });
35150 return items;
35151 };
35152 return Geometry;
35153 }(Selection);
35154
35155 var withLine = (function (View) {
35156 return /** @class */function (_super) {
35157 __extends(Line, _super);
35158 function Line() {
35159 return _super !== null && _super.apply(this, arguments) || this;
35160 }
35161 Line.prototype.getDefaultCfg = function () {
35162 return {
35163 geomType: 'line',
35164 sortable: true
35165 };
35166 };
35167 Line.prototype.splitPoints = function (points) {
35168 var topPoints = [];
35169 var bottomPoints = [];
35170 for (var i = 0, len = points.length; i < len; i++) {
35171 var point = points[i];
35172 var x = point.x,
35173 y = point.y;
35174 topPoints.push(__assign(__assign({}, point), {
35175 x: x,
35176 y: y[1]
35177 }));
35178 bottomPoints.push(__assign(__assign({}, point), {
35179 x: x,
35180 y: y[0]
35181 }));
35182 }
35183 return [topPoints, bottomPoints];
35184 };
35185 Line.prototype.splitNulls = function (points, connectNulls) {
35186 if (connectNulls) {
35187 var tmpPoints_1 = [];
35188 for (var i = 0, len = points.length; i < len; i++) {
35189 var point = points[i];
35190 var x = point.x,
35191 y = point.y;
35192 // 过滤 x 为 NaN 的点
35193 if (isNaN(x)) {
35194 continue;
35195 }
35196 if (isArray(y)) {
35197 if (isNaN(y[0])) {
35198 continue;
35199 }
35200 tmpPoints_1.push(point);
35201 continue;
35202 }
35203 if (isNaN(y)) {
35204 continue;
35205 }
35206 tmpPoints_1.push(point);
35207 }
35208 if (tmpPoints_1.length) {
35209 return [tmpPoints_1];
35210 }
35211 return [];
35212 }
35213 var result = [];
35214 var tmpPoints = [];
35215 for (var i = 0, len = points.length; i < len; i++) {
35216 var point = points[i];
35217 var x = point.x,
35218 y = point.y;
35219 // 过滤 x 为 NaN 的点
35220 if (isNaN(x)) {
35221 continue;
35222 }
35223 if (isArray(y)) {
35224 if (isNaN(y[0])) {
35225 if (tmpPoints.length) {
35226 result.push(tmpPoints);
35227 tmpPoints = [];
35228 }
35229 continue;
35230 }
35231 tmpPoints.push(point);
35232 continue;
35233 }
35234 if (isNaN(y)) {
35235 if (tmpPoints.length) {
35236 result.push(tmpPoints);
35237 tmpPoints = [];
35238 }
35239 continue;
35240 }
35241 tmpPoints.push(point);
35242 }
35243 if (tmpPoints.length) {
35244 result.push(tmpPoints);
35245 }
35246 return result;
35247 };
35248 Line.prototype.mapping = function () {
35249 var _this = this;
35250 var records = _super.prototype.mapping.call(this);
35251 var _a = this,
35252 props = _a.props,
35253 defaultConnectNulls = _a.connectNulls,
35254 context = _a.context;
35255 var coord = props.coord,
35256 _b = props.connectNulls,
35257 connectNulls = _b === void 0 ? defaultConnectNulls : _b,
35258 sizeZoom = props.sizeZoom;
35259 return records.map(function (record) {
35260 var _a;
35261 var children = record.children;
35262 // children 有可能为空
35263 var _b = children[0] || {},
35264 size = _b.size,
35265 color = _b.color,
35266 shape = _b.shape,
35267 y = _b.y,
35268 origin = _b.origin;
35269 // 极坐标时,需加入起点,从而闭合所绘图形
35270 var points = coord.isPolar ? __spreadArray(__spreadArray([], children, true), [children[0]], false) : children;
35271 var sizeZoomRatio = (_a = isFunction(sizeZoom) ? sizeZoom(origin) : sizeZoom) !== null && _a !== void 0 ? _a : 1;
35272 var splitPoints = _this.splitNulls(points, connectNulls);
35273 var newChildren = splitPoints.map(function (points) {
35274 var _a = isArray(y) ? _this.splitPoints(points) : [points, undefined],
35275 topPoints = _a[0],
35276 bottomPoints = _a[1];
35277 return {
35278 size: context.px2hd(size || shape.lineWidth) * sizeZoomRatio,
35279 color: color,
35280 shape: shape,
35281 points: [].concat(topPoints),
35282 topPoints: topPoints,
35283 bottomPoints: bottomPoints
35284 };
35285 });
35286 return __assign(__assign({}, record), {
35287 children: newChildren
35288 });
35289 });
35290 };
35291 Line.prototype.concatPoints = function (topPoints, bottomPoints) {
35292 if (!bottomPoints || !bottomPoints.length) {
35293 return topPoints;
35294 }
35295 var adjust = this.adjust;
35296 // 堆叠产生的 bottomPoints 不绘制
35297 if (adjust && adjust.type === 'stack') {
35298 return topPoints;
35299 }
35300 // 说明是 y 轴对应字段为数组, 这种情况下首尾默认相连,如果想画 2 根线,在数据里对数组分拆
35301 var points = topPoints.concat(bottomPoints.reverse());
35302 points.push(topPoints[0]);
35303 return points;
35304 };
35305 Line.prototype.render = function () {
35306 var props = this.props;
35307 var coord = props.coord;
35308 var records = this.mapping();
35309 var clip = this.getClip();
35310 for (var i = 0, len = records.length; i < len; i++) {
35311 var record = records[i];
35312 var children = record.children;
35313 for (var j = 0, len_1 = children.length; j < len_1; j++) {
35314 var child = children[j];
35315 var points = child.points,
35316 bottomPoints = child.bottomPoints;
35317 child.points = this.concatPoints(points, bottomPoints);
35318 }
35319 }
35320 return jsx(View, __assign({}, props, {
35321 coord: coord,
35322 records: records,
35323 clip: clip
35324 }));
35325 };
35326 return Line;
35327 }(Geometry);
35328 });
35329
35330 function concatPoints(children) {
35331 var result = [];
35332 for (var i = 0; i < children.length; i++) {
35333 var child = children[i];
35334 result = result.concat(child.points);
35335 }
35336 return result;
35337 }
35338 var LineView = (function (props) {
35339 var records = props.records,
35340 coord = props.coord,
35341 animation = props.animation,
35342 EndView = props.endView,
35343 clip = props.clip;
35344 var _a = coord,
35345 left = _a.left,
35346 top = _a.top,
35347 width = _a.width,
35348 height = _a.height,
35349 center = _a.center,
35350 startAngle = _a.startAngle,
35351 endAngle = _a.endAngle,
35352 radius = _a.radius;
35353 var appear = coord.isPolar ? {
35354 easing: 'quadraticOut',
35355 duration: 450,
35356 clip: {
35357 type: 'sector',
35358 property: ['endAngle'],
35359 style: {
35360 cx: center.x,
35361 cy: center.y,
35362 startAngle: "".concat(startAngle, "rad"),
35363 r: radius
35364 },
35365 start: {
35366 endAngle: "".concat(startAngle, "rad")
35367 },
35368 end: {
35369 endAngle: "".concat(endAngle, "rad")
35370 }
35371 }
35372 } : {
35373 easing: 'quadraticOut',
35374 duration: 450,
35375 clip: {
35376 type: 'rect',
35377 property: ['width'],
35378 style: {
35379 x: left,
35380 y: top,
35381 height: height
35382 },
35383 start: {
35384 width: 0
35385 },
35386 end: {
35387 width: width
35388 }
35389 }
35390 };
35391 return jsx("group", {
35392 style: {
35393 clip: clip
35394 }
35395 }, records.map(function (record) {
35396 var _a;
35397 var key = record.key,
35398 children = record.children;
35399 var points = concatPoints(children);
35400 var ref = createRef();
35401 return jsx("group", {
35402 key: key
35403 }, children.map(function (child) {
35404 var points = child.points,
35405 color = child.color,
35406 size = child.size,
35407 shape = child.shape;
35408 var fliterPoints = points.filter(function (point) {
35409 return !isNaN(point.x) && !isNaN(point.y);
35410 });
35411 if (fliterPoints.length === 0) return;
35412 return jsx("polyline", {
35413 key: key,
35414 ref: ref,
35415 style: __assign(__assign({
35416 points: fliterPoints.map(function (point) {
35417 return [point.x, point.y];
35418 }),
35419 stroke: color
35420 }, shape), {
35421 lineWidth: size || shape.lineWidth
35422 }),
35423 animation: deepMix({
35424 update: {
35425 easing: 'linear',
35426 duration: 450,
35427 property: ['points']
35428 },
35429 appear: appear
35430 }, animation)
35431 });
35432 }), EndView ? jsx("group", {
35433 style: {
35434 offset: ref
35435 },
35436 animation: deepMix({
35437 appear: {
35438 easing: 'quadraticOut',
35439 duration: 450,
35440 property: ['offsetDistance'],
35441 start: {
35442 offsetDistance: 0
35443 },
35444 end: {
35445 offsetDistance: 1
35446 }
35447 }
35448 }, animation)
35449 }, jsx(EndView, {
35450 origin: (_a = points[0]) === null || _a === void 0 ? void 0 : _a.origin
35451 })) : null);
35452 }));
35453 });
35454
35455 var index = withLine(LineView);
35456
35457 var withArea = (function (View) {
35458 return /** @class */function (_super) {
35459 __extends(Area, _super);
35460 function Area() {
35461 return _super !== null && _super.apply(this, arguments) || this;
35462 }
35463 Area.prototype.getDefaultCfg = function () {
35464 return {
35465 geomType: 'area',
35466 // 面积图默认设为从0开始
35467 startOnZero: true,
35468 // 点需要排序
35469 sortable: true
35470 };
35471 };
35472 Area.prototype.getBaseY = function () {
35473 // 坐标轴 y0
35474 var y0 = this.getY0Value();
35475 var _a = this,
35476 props = _a.props,
35477 defaultStartOnZero = _a.startOnZero;
35478 var coord = props.coord,
35479 _b = props.startOnZero,
35480 startOnZero = _b === void 0 ? defaultStartOnZero : _b;
35481 if (startOnZero) {
35482 // 零点映射到绝对坐标
35483 var originCoord = coord.convertPoint({
35484 x: 0,
35485 y: y0
35486 });
35487 return originCoord.y;
35488 }
35489 return coord.y[0];
35490 };
35491 Area.prototype.mapping = function () {
35492 var records = _super.prototype.mapping.call(this);
35493 var baseY = this.getBaseY();
35494 for (var i = 0, len = records.length; i < len; i++) {
35495 var record = records[i];
35496 var children = record.children;
35497 for (var j = 0, len_1 = children.length; j < len_1; j++) {
35498 var child = children[j];
35499 var points = child.points,
35500 bottomPoints = child.bottomPoints;
35501 if (bottomPoints && bottomPoints.length) {
35502 bottomPoints.reverse();
35503 child.points = points.concat(bottomPoints);
35504 } else {
35505 points.push({
35506 x: points[points.length - 1].x,
35507 y: baseY
35508 });
35509 points.push({
35510 x: points[0].x,
35511 y: baseY
35512 });
35513 }
35514 }
35515 }
35516 return records;
35517 };
35518 Area.prototype.render = function () {
35519 var props = this.props;
35520 var coord = props.coord;
35521 var records = this.mapping();
35522 var clip = this.getClip();
35523 var baseY = this.getBaseY();
35524 return jsx(View, __assign({}, props, {
35525 baseY: baseY,
35526 coord: coord,
35527 records: records,
35528 clip: clip
35529 }));
35530 };
35531 return Area;
35532 }(withLine(View));
35533 });
35534
35535 var AreaView = (function (props) {
35536 var coord = props.coord,
35537 records = props.records,
35538 baseY = props.baseY,
35539 shape = props.shape,
35540 animation = props.animation;
35541 var isSmooth = shape === 'smooth';
35542 var _a = coord,
35543 left = _a.left,
35544 top = _a.top,
35545 width = _a.width,
35546 height = _a.height,
35547 center = _a.center,
35548 startAngle = _a.startAngle,
35549 endAngle = _a.endAngle,
35550 radius = _a.radius;
35551 var appear = coord.isPolar ? {
35552 easing: 'quadraticOut',
35553 duration: 450,
35554 clip: {
35555 type: 'sector',
35556 property: ['endAngle'],
35557 style: {
35558 cx: center.x,
35559 cy: center.y,
35560 startAngle: "".concat(startAngle, "rad"),
35561 r: radius
35562 },
35563 start: {
35564 endAngle: "".concat(startAngle, "rad")
35565 },
35566 end: {
35567 endAngle: "".concat(endAngle, "rad")
35568 }
35569 }
35570 } : {
35571 easing: 'quadraticOut',
35572 duration: 450,
35573 clip: {
35574 type: 'rect',
35575 property: ['width'],
35576 style: {
35577 x: left,
35578 y: top,
35579 height: height
35580 },
35581 start: {
35582 width: 0
35583 },
35584 end: {
35585 width: width
35586 }
35587 }
35588 };
35589 return jsx("group", null, records.map(function (record) {
35590 var key = record.key,
35591 children = record.children;
35592 return jsx("group", {
35593 key: key
35594 }, children.map(function (child) {
35595 var points = child.points,
35596 topPoints = child.topPoints,
35597 bottomPoints = child.bottomPoints,
35598 color = child.color,
35599 shape = child.shape;
35600 if (isSmooth) {
35601 var generatePath = function generatePath() {
35602 var d = [];
35603 var constaint = [[0, 0], [1, 1]];
35604 var topSps = catmullRom2bezier(topPoints, false, constaint);
35605 d.push(['M', topPoints[0].x, topPoints[0].y]);
35606 for (var i = 0, n = topSps.length; i < n; i++) {
35607 var sp = topSps[i];
35608 d.push(['C', sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
35609 }
35610 if (bottomPoints && bottomPoints.length) {
35611 var bottomSps = catmullRom2bezier(bottomPoints, false, constaint);
35612 d.push(['L', bottomPoints[0].x, bottomPoints[0].y]);
35613 for (var i = 0, n = bottomSps.length; i < n; i++) {
35614 var sp = bottomSps[i];
35615 d.push(['C', sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
35616 }
35617 } else {
35618 d.push(['L', topPoints[topPoints.length - 1].x, baseY]);
35619 d.push(['L', topPoints[0].x, baseY]);
35620 }
35621 return d;
35622 };
35623 return jsx("path", {
35624 style: __assign({
35625 path: generatePath(),
35626 lineWidth: '2px',
35627 fill: color
35628 }, shape)
35629 });
35630 }
35631 return jsx("polygon", {
35632 style: __assign({
35633 points: points.map(function (point) {
35634 return [point.x, point.y];
35635 }),
35636 lineWidth: '2px',
35637 fill: color
35638 }, shape),
35639 animation: deepMix({
35640 appear: appear,
35641 update: {
35642 easing: 'linear',
35643 duration: 450,
35644 property: ['points']
35645 }
35646 }, animation)
35647 });
35648 }));
35649 }));
35650 });
35651
35652 var index$1 = withArea(AreaView);
35653
35654 /**
35655 * 计算两个坐标的中点坐标
35656 * @param start 起始点{x:number, y:number}
35657 * @param end 结束点{x:number, y:number}
35658 * @returns 中点坐标{x:number, y:number}
35659 */
35660 function getMiddlePoint(start, end) {
35661 var x = (end.x - start.x) / 2 + start.x;
35662 var y = (end.y - start.y) / 2 + start.y;
35663 return {
35664 x: x,
35665 y: y
35666 };
35667 }
35668
35669 var DEFAULT_LABEL_CFG = {
35670 textBaseline: 'middle',
35671 fill: '#808080'
35672 };
35673 function LabelView(props) {
35674 var _a;
35675 var record = props.record,
35676 offsetX = props.offsetX,
35677 offsetY = props.offsetY,
35678 points = props.points,
35679 label = props.label,
35680 guide = props.guide;
35681 var origin = record.origin,
35682 color = record.color;
35683 var labelAttrs, guideAttrs;
35684 if (isFunction(label)) {
35685 var point = points.length === 4 // 如果是金字塔图,顶部只有 3 个点
35686 ? getMiddlePoint(points[1], points[2]) : getMiddlePoint(points[0], points[1]);
35687 labelAttrs = mix({
35688 x: point.x + offsetX,
35689 y: point.y + offsetY
35690 }, DEFAULT_LABEL_CFG, label(origin, color));
35691 }
35692 if (isFunction(guide)) {
35693 var point = getMiddlePoint(points.length === 4 ? getMiddlePoint(points[0], points[1]) : points[0], getMiddlePoint(points[2], (_a = points[3]) !== null && _a !== void 0 ? _a : points[1]));
35694 guideAttrs = mix({
35695 x: point.x,
35696 y: point.y,
35697 textBaseline: 'middle',
35698 textAlign: 'center'
35699 }, DEFAULT_LABEL_CFG, guide(origin, color));
35700 }
35701 return jsx("group", null, labelAttrs && jsx("text", {
35702 attrs: labelAttrs
35703 }), guideAttrs && jsx("text", {
35704 attrs: guideAttrs
35705 }));
35706 }
35707
35708 var LabelViews = /*#__PURE__*/Object.freeze({
35709 __proto__: null,
35710 pyramid: LabelView,
35711 funnel: LabelView
35712 });
35713
35714 var withInterval = (function (Views) {
35715 return /** @class */function (_super) {
35716 __extends(Interval, _super);
35717 function Interval() {
35718 return _super !== null && _super.apply(this, arguments) || this;
35719 }
35720 Interval.prototype.getDefaultCfg = function () {
35721 return {
35722 geomType: 'interval',
35723 justifyContent: true,
35724 startOnZero: true
35725 };
35726 };
35727 Interval.prototype.getDefaultSize = function () {
35728 var _a = this,
35729 attrs = _a.attrs,
35730 props = _a.props,
35731 adjust = _a.adjust,
35732 records = _a.records;
35733 var coord = props.coord,
35734 sizeRatio = props.sizeRatio;
35735 var x = attrs.x;
35736 var scale = x.scale;
35737 var values = scale.values;
35738 if (sizeRatio) {
35739 return 1 / values.length * sizeRatio;
35740 }
35741 var defaultWithRatio = {
35742 column: 1 / 2,
35743 rose: 0.999999,
35744 multiplePie: 3 / 4 // 多饼图
35745 };
35746
35747 var count = values.length;
35748 var ratio;
35749 if (coord.isPolar) {
35750 if (coord.transposed && count > 1) {
35751 ratio = defaultWithRatio.multiplePie;
35752 } else {
35753 ratio = defaultWithRatio.rose;
35754 }
35755 } else {
35756 ratio = defaultWithRatio.column;
35757 }
35758 var size = 1 / values.length * ratio;
35759 // 分组时size要除以类别个数
35760 if (adjust && adjust.type === 'dodge') {
35761 return size / records.length;
35762 }
35763 return size;
35764 };
35765 Interval.prototype.mapping = function () {
35766 var _a;
35767 var records = _super.prototype.mapping.call(this);
35768 var props = this.props;
35769 var coord = props.coord,
35770 sizeZoom = props.sizeZoom;
35771 var y0 = this.getY0Value();
35772 var defaultSize = this.getDefaultSize();
35773 for (var i = 0, len = records.length; i < len; i++) {
35774 var record = records[i];
35775 var children = record.children;
35776 for (var j = 0, len_1 = children.length; j < len_1; j++) {
35777 var child = children[j];
35778 var normalized = child.normalized,
35779 mappedSize = child.size,
35780 origin_1 = child.origin;
35781 // 没有指定size,则根据数据来计算默认size
35782 if (isNil(mappedSize)) {
35783 var x = normalized.x,
35784 y = normalized.y,
35785 _b = normalized.size,
35786 size = _b === void 0 ? defaultSize : _b;
35787 var zoomRatio = (_a = isFunction(sizeZoom) ? sizeZoom(origin_1) : sizeZoom) !== null && _a !== void 0 ? _a : 1;
35788 mix(child, coord.convertRect({
35789 x: x,
35790 y: y,
35791 y0: y0,
35792 size: size * zoomRatio
35793 }));
35794 } else {
35795 var x = child.x,
35796 y = child.y;
35797 var rect = {
35798 size: mappedSize,
35799 x: x,
35800 y: y,
35801 y0: y0
35802 };
35803 mix(child, coord.transformToRect(rect));
35804 }
35805 mix(child.shape, this.getSelectionStyle(child));
35806 }
35807 }
35808 return records;
35809 };
35810 // 获取Y轴坐标零点的画布位置
35811 Interval.prototype.getPointY0 = function () {
35812 var props = this.props;
35813 var coord = props.coord;
35814 var y0 = this.getY0Value();
35815 var y0Point = coord.convertPoint({
35816 y: y0,
35817 x: 0
35818 });
35819 return y0Point === null || y0Point === void 0 ? void 0 : y0Point.y;
35820 };
35821 Interval.prototype.render = function () {
35822 var _a = this,
35823 props = _a.props,
35824 state = _a.state;
35825 var coord = props.coord,
35826 _b = props.shape,
35827 shape = _b === void 0 ? 'rect' : _b,
35828 animation = props.animation,
35829 showLabel = props.showLabel,
35830 customLabelCfg = props.labelCfg;
35831 var View = isFunction(Views) ? Views : Views[shape];
35832 var LabelView = LabelViews[shape];
35833 var labelCfg = deepMix({
35834 label: null,
35835 offsetX: 0,
35836 offsetY: 0
35837 }, customLabelCfg);
35838 if (!View) return null;
35839 var selected = state.selected;
35840 var records = this.mapping();
35841 var pointY0 = this.getPointY0();
35842 var clip = this.getClip();
35843 return jsx(View, {
35844 coord: coord,
35845 records: records,
35846 selected: selected,
35847 shape: shape,
35848 animation: animation,
35849 showLabel: showLabel,
35850 labelCfg: labelCfg,
35851 LabelView: LabelView,
35852 y0: pointY0,
35853 clip: clip
35854 });
35855 };
35856 return Interval;
35857 }(Geometry);
35858 });
35859
35860 var Rect$2 = (function (props) {
35861 var records = props.records,
35862 animation = props.animation,
35863 y0 = props.y0,
35864 clip = props.clip,
35865 onClick = props.onClick;
35866 return jsx("group", {
35867 attrs: {
35868 clip: clip
35869 }
35870 }, records.map(function (record) {
35871 var key = record.key,
35872 children = record.children;
35873 return jsx("group", {
35874 key: key
35875 }, children.map(function (item) {
35876 var key = item.key,
35877 xMin = item.xMin,
35878 xMax = item.xMax,
35879 yMin = item.yMin,
35880 yMax = item.yMax,
35881 color = item.color,
35882 shape = item.shape;
35883 if (isNaN(xMin) || isNaN(xMax) || isNaN(yMin) || isNaN(yMax)) {
35884 return null;
35885 }
35886 return jsx("rect", {
35887 key: key,
35888 attrs: __assign({
35889 x: xMin,
35890 y: yMin,
35891 width: xMax - xMin,
35892 height: yMax - yMin,
35893 fill: color
35894 }, shape),
35895 onClick: onClick,
35896 animation: deepMix({
35897 appear: {
35898 easing: 'linear',
35899 duration: 450,
35900 property: ['y', 'height'],
35901 start: {
35902 y: y0,
35903 height: 0
35904 }
35905 },
35906 update: {
35907 easing: 'linear',
35908 duration: 450,
35909 property: ['x', 'y', 'width', 'height']
35910 }
35911 }, animation)
35912 });
35913 }));
35914 }));
35915 });
35916
35917 var Polar$1 = (function (props) {
35918 var coord = props.coord,
35919 records = props.records,
35920 animation = props.animation,
35921 onClick = props.onClick;
35922 var center = coord.center,
35923 startAngle = coord.startAngle,
35924 endAngle = coord.endAngle,
35925 radius = coord.radius;
35926 return jsx("group", {
35927 animation: {
35928 appear: __assign({
35929 easing: 'quadraticOut',
35930 duration: 450,
35931 clip: {
35932 type: 'sector',
35933 property: ['endAngle'],
35934 style: {
35935 cx: center.x,
35936 cy: center.y,
35937 startAngle: "".concat(startAngle, "rad"),
35938 r: radius
35939 },
35940 start: {
35941 endAngle: "".concat(startAngle, "rad")
35942 },
35943 end: {
35944 endAngle: "".concat(endAngle, "rad")
35945 }
35946 }
35947 }, animation && animation.appear)
35948 }
35949 }, records.map(function (record) {
35950 var key = record.key,
35951 children = record.children;
35952 return jsx("group", {
35953 key: key
35954 }, children.map(function (item) {
35955 var key = item.key,
35956 xMin = item.xMin,
35957 xMax = item.xMax,
35958 yMin = item.yMin,
35959 yMax = item.yMax,
35960 color = item.color,
35961 shape = item.shape;
35962 return jsx("sector", {
35963 key: key,
35964 attrs: __assign({
35965 cx: center.x,
35966 cy: center.y,
35967 fill: color,
35968 lineWidth: 1,
35969 startAngle: "".concat(xMin, "rad"),
35970 endAngle: "".concat(xMax, "rad"),
35971 r0: yMin,
35972 r: yMax
35973 }, shape),
35974 onClick: onClick,
35975 animation: deepMix({
35976 update: {
35977 easing: 'linear',
35978 duration: 450,
35979 property: ['x', 'y', 'startAngle', 'endAngle', 'r0', 'r']
35980 }
35981 }, animation)
35982 });
35983 }));
35984 }));
35985 });
35986
35987 var intervalView = (function (props) {
35988 var coord = props.coord;
35989 var coordType = coord.type;
35990 // 直角坐标系
35991 if (coordType === 'rect') {
35992 return jsx(Rect$2, __assign({}, props));
35993 }
35994 // 极坐标系
35995 return jsx(Polar$1, __assign({}, props));
35996 });
35997
35998 function convertToPoints(_a) {
35999 var xMin = _a.xMin,
36000 xMax = _a.xMax,
36001 yMin = _a.yMin,
36002 yMax = _a.yMax;
36003 return [{
36004 x: xMin,
36005 y: yMin
36006 }, {
36007 x: xMax,
36008 y: yMin
36009 }, {
36010 x: xMax,
36011 y: yMax
36012 }, {
36013 x: xMin,
36014 y: yMax
36015 } // bl
36016 ];
36017 }
36018
36019 // 金字塔图和漏斗图的View
36020 var polygonView = (function (props) {
36021 var records = props.records,
36022 shape = props.shape,
36023 showLabel = props.showLabel,
36024 labelCfg = props.labelCfg,
36025 LabelView = props.LabelView;
36026 // 是否倒置
36027 var overturn = false;
36028 return jsx("group", null, records.map(function (record, index) {
36029 var key = record.key,
36030 children = record.children;
36031 var isLastRecord = index === records.length - 1;
36032 var nextRecord = isLastRecord ? record : records[index + 1];
36033 var nextChildren = nextRecord.children;
36034 var nextFirstPoint = convertToPoints(nextChildren[0]);
36035 var nextLastPoints = convertToPoints(nextChildren[nextChildren.length - 1]);
36036 if (!overturn) {
36037 overturn = nextChildren[0].yMax > children[0].yMax;
36038 }
36039 if (overturn) {
36040 nextFirstPoint.reverse();
36041 nextLastPoints.reverse();
36042 }
36043 var polygonPoints = children.map(function (child, childIndex) {
36044 var points = convertToPoints(child);
36045 if (overturn) {
36046 points.reverse();
36047 }
36048 if (isLastRecord) {
36049 if (shape === 'pyramid') {
36050 points = [getMiddlePoint(points[0], points[1]), points[2], points[3]];
36051 }
36052 } else {
36053 if (childIndex === 0) {
36054 points[0] = nextFirstPoint[3];
36055 }
36056 if (childIndex === children.length - 1) {
36057 points[1] = nextLastPoints[2];
36058 }
36059 }
36060 return __assign(__assign({}, child), {
36061 points: points
36062 });
36063 });
36064 return jsx("group", {
36065 key: key
36066 }, polygonPoints.map(function (child) {
36067 var points = child.points,
36068 color = child.color,
36069 shape = child.shape;
36070 return jsx("group", null, jsx("polygon", {
36071 attrs: __assign({
36072 points: points.map(function (d) {
36073 return [d.x, d.y];
36074 }),
36075 fill: color
36076 }, shape)
36077 }), showLabel && LabelView ? jsx(LabelView, __assign({
36078 record: child,
36079 points: points
36080 }, labelCfg)) : null);
36081 }));
36082 }));
36083 });
36084
36085 // 柱图/条图
36086
36087 var Views = /*#__PURE__*/Object.freeze({
36088 __proto__: null,
36089 rect: intervalView,
36090 pyramid: polygonView,
36091 funnel: polygonView
36092 });
36093
36094 var index$2 = withInterval(Views);
36095
36096 var withPoint = (function (View) {
36097 return /** @class */function (_super) {
36098 __extends(Point, _super);
36099 function Point() {
36100 return _super !== null && _super.apply(this, arguments) || this;
36101 }
36102 Point.prototype.getDefaultCfg = function () {
36103 return {
36104 geomType: 'point'
36105 };
36106 };
36107 Point.prototype.render = function () {
36108 var props = this.props;
36109 var coord = props.coord;
36110 var records = this.mapping();
36111 var clip = this.getClip();
36112 return jsx(View, __assign({}, props, {
36113 coord: coord,
36114 records: records,
36115 clip: clip
36116 }));
36117 };
36118 return Point;
36119 }(Geometry);
36120 });
36121
36122 var PointView = (function (props) {
36123 var records = props.records,
36124 animation = props.animation,
36125 clip = props.clip;
36126 return jsx("group", {
36127 attrs: {
36128 clip: clip
36129 }
36130 }, records.map(function (record) {
36131 var key = record.key,
36132 children = record.children;
36133 return jsx("group", {
36134 key: key
36135 }, children.map(function (item) {
36136 var x = item.x,
36137 y = item.y,
36138 size = item.size,
36139 color = item.color,
36140 shapeName = item.shapeName,
36141 shape = item.shape;
36142 if (isNaN(x) || isNaN(y)) {
36143 return null;
36144 }
36145 if (shapeName === 'rect') {
36146 var rectSize = isNil(size) ? shape.size : size;
36147 return jsx("rect", {
36148 key: key,
36149 attrs: __assign(__assign({
36150 x: x - rectSize,
36151 y: y - rectSize,
36152 fill: color,
36153 stroke: color
36154 }, shape), {
36155 width: rectSize * 2,
36156 height: rectSize * 2
36157 }),
36158 animation: deepMix({
36159 appear: {
36160 easing: 'linear',
36161 duration: 450
36162 },
36163 update: {
36164 easing: 'linear',
36165 duration: 450,
36166 property: ['x', 'y', 'width', 'height', 'fill']
36167 }
36168 }, animation)
36169 });
36170 }
36171 return jsx("circle", {
36172 key: key,
36173 style: __assign(__assign({
36174 cx: x,
36175 cy: y,
36176 fill: shapeName === 'circle' ? color : null,
36177 stroke: shapeName === 'hollowCircle' ? color : null
36178 }, shape), {
36179 r: isNil(size) ? shape.size : size
36180 }),
36181 animation: deepMix({
36182 appear: {
36183 easing: 'linear',
36184 duration: 450
36185 },
36186 update: {
36187 easing: 'linear',
36188 duration: 450,
36189 property: ['cx', 'cy', 'r', 'fill']
36190 }
36191 }, animation)
36192 });
36193 }));
36194 }));
36195 });
36196
36197 var index$3 = withPoint(PointView);
36198
36199 var withAxis = (function (View) {
36200 return /** @class */function (_super) {
36201 __extends(Axis, _super);
36202 function Axis(props) {
36203 var _this = _super.call(this, props) || this;
36204 _this.axisStyle = {};
36205 var chart = props.chart,
36206 field = props.field;
36207 var scaleOption = _this.getScaleOption(props);
36208 chart.setScale(field, scaleOption);
36209 return _this;
36210 }
36211 Axis.prototype.willReceiveProps = function (nextProps) {
36212 var lastProps = this.props;
36213 var chart = nextProps.chart,
36214 field = nextProps.field;
36215 var nextScaleOption = this.getScaleOption(nextProps);
36216 var lastScaleOption = this.getScaleOption(lastProps);
36217 if (!equal(nextScaleOption, lastScaleOption)) {
36218 chart.setScale(field, nextScaleOption);
36219 }
36220 };
36221 Axis.prototype.willMount = function () {
36222 this.updateCoord();
36223 };
36224 Axis.prototype.willUpdate = function () {
36225 this.updateCoord();
36226 };
36227 Axis.prototype.getScaleOption = function (props) {
36228 var type = props.type,
36229 tickCount = props.tickCount,
36230 range = props.range,
36231 mask = props.mask,
36232 formatter = props.formatter,
36233 ticks = props.ticks,
36234 min = props.min,
36235 max = props.max,
36236 nice = props.nice;
36237 return {
36238 type: type,
36239 tickCount: tickCount,
36240 range: range,
36241 mask: mask,
36242 formatter: formatter,
36243 min: min,
36244 max: max,
36245 nice: nice,
36246 ticks: ticks
36247 };
36248 };
36249 Axis.prototype._getDimType = function () {
36250 var props = this.props;
36251 var field = props.field,
36252 chart = props.chart;
36253 var xScales = chart.getXScales();
36254 var scales = xScales.filter(function (scale) {
36255 return scale.field === field;
36256 });
36257 return scales.length > 0 ? 'x' : 'y';
36258 };
36259 // 获取ticks最大的宽高
36260 Axis.prototype.getMaxBBox = function (ticks, style) {
36261 var context = this.context;
36262 var measureText = context.measureText;
36263 var label = style.label,
36264 labelOffset = style.labelOffset;
36265 var width = 0;
36266 var height = 0;
36267 ticks.forEach(function (tick) {
36268 if (!label) return;
36269 var _a = tick.labelStyle,
36270 labelStyle = _a === void 0 ? {} : _a,
36271 text = tick.text;
36272 var bbox = measureText(labelStyle.text || text, __assign(__assign({}, label), labelStyle));
36273 width = Math.max(width, bbox.width);
36274 height = Math.max(height, bbox.height);
36275 });
36276 if (!width && !height) {
36277 return {
36278 width: width,
36279 height: height
36280 };
36281 }
36282 var bbox = {
36283 width: width + labelOffset,
36284 height: height + labelOffset
36285 };
36286 return bbox;
36287 };
36288 Axis.prototype._getPosition = function () {
36289 var props = this.props;
36290 var position = props.position,
36291 coord = props.coord;
36292 if (position) {
36293 return position;
36294 }
36295 var dimType = this._getDimType();
36296 if (coord.transposed) {
36297 return dimType === 'x' ? 'left' : 'bottom';
36298 }
36299 return dimType === 'x' ? 'bottom' : 'left';
36300 };
36301 Axis.prototype.getTicks = function () {
36302 var props = this.props;
36303 var field = props.field,
36304 chart = props.chart;
36305 var scale = chart.getScale(field);
36306 var ticks = scale.getTicks();
36307 // 设置tick的样式
36308 ticks = this._setTicksStyle(ticks);
36309 ticks = this._generateGridPoints(ticks);
36310 return ticks;
36311 };
36312 /**
36313 * 生成极坐标下网格线的交叉点
36314 * @param ticks
36315 * @returns
36316 */
36317 Axis.prototype._generateGridPoints = function (ticks) {
36318 var props = this.props;
36319 var chart = props.chart,
36320 coord = props.coord;
36321 if (!coord.isPolar) {
36322 return ticks;
36323 }
36324 var dimType = this._getDimType();
36325 // 只需要在 y 的时候生成
36326 if (dimType !== 'y') {
36327 return ticks;
36328 }
36329 var xScale = chart.getXScales()[0];
36330 var xTicks = xScale.getTicks();
36331 ticks.forEach(function (tick) {
36332 var gridPoints = xTicks.map(function (xTick) {
36333 return coord.convertPoint({
36334 x: xTick.value,
36335 y: tick.value
36336 });
36337 });
36338 // 添加第 1 个点,形成环状
36339 gridPoints.push(gridPoints[0]);
36340 tick.gridPoints = gridPoints;
36341 });
36342 return ticks;
36343 };
36344 Axis.prototype._setTicksStyle = function (ticks) {
36345 var _this = this;
36346 var _a = this,
36347 props = _a.props,
36348 context = _a.context;
36349 var theme = context.theme,
36350 px2hd = context.px2hd;
36351 var _b = props.style,
36352 style = _b === void 0 ? {} : _b;
36353 var themeAxis = theme.axis;
36354 each(themeAxis, function (value, key) {
36355 // 关闭tick的样式
36356 if (style[key] === null) {
36357 return;
36358 }
36359 var styleValue = isFunction(style[key]) ? undefined : style[key];
36360 if (isString(value) || isNumber(value)) {
36361 _this.axisStyle[key] = px2hd(styleValue) || value;
36362 } else if (isArray(styleValue)) {
36363 _this.axisStyle[key] = styleValue.map(function (d) {
36364 return px2hd(deepMix(clone(value), d));
36365 });
36366 } else {
36367 _this.axisStyle[key] = px2hd(deepMix(clone(value), styleValue));
36368 }
36369 });
36370 return ticks.map(function (tick, index) {
36371 var label = style.label,
36372 grid = style.grid;
36373 var defaultLabelStyle = themeAxis.label,
36374 defaultGridStyle = themeAxis.grid;
36375 if (isFunction(label)) {
36376 tick.labelStyle = px2hd(mix({}, defaultLabelStyle, label(tick.text, index, ticks)));
36377 }
36378 if (isFunction(grid)) {
36379 tick.gridStyle = px2hd(mix({}, defaultGridStyle, grid(tick.text, index, ticks.length)));
36380 }
36381 return tick;
36382 });
36383 };
36384 Axis.prototype.convertTicks = function (ticks) {
36385 var props = this.props;
36386 var coord = props.coord;
36387 var dimType = this._getDimType();
36388 var otherDim = dimType === 'x' ? 'y' : 'x';
36389 return ticks.map(function (tick) {
36390 var _a, _b;
36391 var start = coord.convertPoint((_a = {}, _a[dimType] = tick.value, _a[otherDim] = 0, _a));
36392 var end = coord.convertPoint((_b = {}, _b[dimType] = tick.value, _b[otherDim] = 1, _b));
36393 return __assign(__assign({}, tick), {
36394 points: [start, end]
36395 });
36396 });
36397 };
36398 Axis.prototype.measureLayout = function () {
36399 var props = this.props;
36400 var visible = props.visible,
36401 coord = props.coord;
36402 if (visible === false) {
36403 return null;
36404 }
36405 var ticks = this.getTicks();
36406 var bbox = this.getMaxBBox(ticks, this.axisStyle);
36407 var isPolar = coord.isPolar;
36408 var dimType = this._getDimType();
36409 var width = bbox.width,
36410 height = bbox.height;
36411 if (isPolar) {
36412 // 机坐标系的 y 不占位置
36413 if (dimType === 'y') {
36414 return null;
36415 }
36416 // 4 个方向都需要留空
36417 return ['top', 'right', 'bottom', 'left'].map(function (position) {
36418 return {
36419 position: position,
36420 width: width,
36421 height: height
36422 };
36423 });
36424 }
36425 // 直角坐标系下
36426 var position = this._getPosition();
36427 return {
36428 position: position,
36429 width: width,
36430 height: height
36431 };
36432 };
36433 // 主要是计算coord的布局
36434 Axis.prototype.updateCoord = function () {
36435 var props = this.props;
36436 var chart = props.chart;
36437 var layout = this.measureLayout();
36438 chart.updateCoordFor(this, layout);
36439 };
36440 Axis.prototype.render = function () {
36441 var _a = this,
36442 props = _a.props,
36443 axisStyle = _a.axisStyle;
36444 var visible = props.visible,
36445 coord = props.coord;
36446 if (visible === false) {
36447 return null;
36448 }
36449 var ticks = this.getTicks();
36450 var position = this._getPosition();
36451 var dimType = this._getDimType();
36452 return jsx(View, __assign({}, props, {
36453 style: axisStyle,
36454 ticks: this.convertTicks(ticks),
36455 coord: coord,
36456 position: position,
36457 dimType: dimType
36458 }));
36459 };
36460 return Axis;
36461 }(Component);
36462 });
36463
36464 // 相对圆心偏移量的点
36465 function getOffsetPoint(center, point, offset) {
36466 var vectorX = point.x - center.x;
36467 var vectorY = point.y - center.y;
36468 var vectorLength = length$1([vectorX, vectorY]);
36469 var offsetLength = vectorLength + offset;
36470 var x = vectorX / vectorLength * offsetLength;
36471 var y = vectorY / vectorLength * offsetLength;
36472 return {
36473 x: center.x + x,
36474 y: center.y + y
36475 };
36476 }
36477 // 获取文本的对齐方式
36478 function getTextAlignInfo(center, point) {
36479 // 文本点向量
36480 var vector = [point.x - center.x, point.y - center.y];
36481 var align;
36482 var baseLine;
36483 // 水平对齐
36484 if (vector[0] > 0) {
36485 align = 'left';
36486 } else if (vector[0] < 0) {
36487 align = 'right';
36488 } else {
36489 align = 'center';
36490 }
36491 // 垂直对齐
36492 if (vector[1] > 0) {
36493 baseLine = 'top';
36494 } else if (vector[1] < 0) {
36495 baseLine = 'bottom';
36496 } else {
36497 baseLine = 'middle';
36498 }
36499 return {
36500 textAlign: align,
36501 textBaseline: baseLine
36502 };
36503 }
36504 var Line$1 = function Line(props) {
36505 var line = props.line,
36506 gridType = props.gridType,
36507 center = props.center,
36508 radius = props.radius,
36509 ticks = props.ticks;
36510 if (!line) return null;
36511 if (gridType !== 'line') {
36512 return jsx("arc", {
36513 attrs: __assign({
36514 cx: center.x,
36515 cy: center.y,
36516 r: radius,
36517 startAngle: 0,
36518 endAngle: 360
36519 }, line)
36520 });
36521 }
36522 var points = ticks.map(function (tick) {
36523 var points = tick.points;
36524 return points[points.length - 1];
36525 });
36526 // 头尾相连
36527 points.push(points[0]);
36528 return jsx("polyline", {
36529 attrs: __assign({
36530 points: points.map(function (d) {
36531 return [d.x, d.y];
36532 })
36533 }, line)
36534 });
36535 };
36536 var PolarX = (function (props) {
36537 var originTicks = props.ticks,
36538 coord = props.coord,
36539 style = props.style,
36540 gridType = props.grid;
36541 var center = coord.center;
36542 var grid = style.grid,
36543 tickLine = style.tickLine,
36544 line = style.line,
36545 labelOffset = style.labelOffset,
36546 label = style.label;
36547 var ticks = originTicks.filter(function (d) {
36548 return !isNaN(d.value);
36549 });
36550 var firstTicks = ticks[0];
36551 var points = firstTicks.points;
36552 var end = points[points.length - 1];
36553 var radius = length$1([end.x - center.x, end.y - center.y]);
36554 return jsx("group", null, grid ? ticks.map(function (tick) {
36555 var points = tick.points,
36556 gridStyle = tick.gridStyle;
36557 var end = points[points.length - 1];
36558 return jsx("line", {
36559 attrs: __assign(__assign({
36560 x1: center.x,
36561 y1: center.y,
36562 x2: end.x,
36563 y2: end.y
36564 }, grid), gridStyle)
36565 });
36566 }) : null, tickLine && tickLine.length ? ticks.map(function (tick) {
36567 var points = tick.points;
36568 var end = points[points.length - 1];
36569 var offsetPoint = getOffsetPoint(center, end, tickLine.length);
36570 return jsx("line", {
36571 attrs: __assign({
36572 x1: end.x,
36573 y1: end.y,
36574 x2: offsetPoint.x,
36575 y2: offsetPoint.y
36576 }, tickLine)
36577 });
36578 }) : null, jsx(Line$1, {
36579 line: line,
36580 gridType: gridType,
36581 center: center,
36582 radius: radius,
36583 ticks: ticks
36584 }), label ? ticks.map(function (tick) {
36585 var points = tick.points,
36586 text = tick.text,
36587 labelStyle = tick.labelStyle;
36588 var end = points[points.length - 1];
36589 var offsetPoint = getOffsetPoint(center, end, labelOffset);
36590 return jsx("text", {
36591 attrs: __assign(__assign(__assign({
36592 x: offsetPoint.x,
36593 y: offsetPoint.y,
36594 text: text
36595 }, getTextAlignInfo(center, end)), label), labelStyle)
36596 });
36597 }) : null);
36598 });
36599
36600 var PolarY = (function (props) {
36601 var originTicks = props.ticks,
36602 coord = props.coord,
36603 style = props.style,
36604 gridType = props.grid;
36605 var center = coord.center;
36606 var grid = style.grid,
36607 tickLine = style.tickLine,
36608 line = style.line,
36609 labelOffset = style.labelOffset,
36610 label = style.label;
36611 var ticks = originTicks.filter(function (d) {
36612 return !isNaN(d.value);
36613 });
36614 return jsx("group", null, grid ? ticks.map(function (tick) {
36615 var points = tick.points,
36616 gridStyle = tick.gridStyle,
36617 gridPoints = tick.gridPoints;
36618 var end = points[points.length - 1];
36619 if (gridType !== 'line') {
36620 return jsx("arc", {
36621 style: __assign(__assign({
36622 cx: center.x,
36623 cy: center.y,
36624 startAngle: 0,
36625 endAngle: 360,
36626 r: length$1([end.x - center.x, end.y - center.y])
36627 }, grid), gridStyle)
36628 });
36629 }
36630 return jsx("polyline", {
36631 attrs: __assign(__assign({
36632 points: gridPoints.map(function (d) {
36633 return [d.x, d.y];
36634 })
36635 }, grid), gridStyle)
36636 });
36637 }) : null, tickLine && tickLine.length ? ticks.map(function (tick) {
36638 var points = tick.points;
36639 var end = points[points.length - 1];
36640 return jsx("line", {
36641 attrs: __assign({
36642 x1: end.x,
36643 y1: end.y,
36644 x2: end.x - tickLine.length,
36645 y2: end.y
36646 }, tickLine)
36647 });
36648 }) : null, line ? jsx("line", {
36649 attrs: __assign({
36650 x1: ticks[0].points[0].x,
36651 y1: ticks[0].points[0].y,
36652 x2: ticks[ticks.length - 1].points[0].x,
36653 y2: ticks[ticks.length - 1].points[0].y
36654 }, line)
36655 }) : null, label ? ticks.map(function (tick) {
36656 var points = tick.points,
36657 text = tick.text,
36658 labelStyle = tick.labelStyle;
36659 var end = points[points.length - 1];
36660 return jsx("text", {
36661 attrs: __assign(__assign({
36662 x: end.x - labelOffset,
36663 y: end.y,
36664 text: text,
36665 textAlign: 'right',
36666 textBaseline: 'middle'
36667 }, label), labelStyle)
36668 });
36669 }) : null);
36670 });
36671
36672 var Top = (function (props, context) {
36673 var originTicks = props.ticks,
36674 coord = props.coord,
36675 style = props.style;
36676 var px2hd = context.px2hd;
36677 var left = coord.left,
36678 top = coord.top,
36679 right = coord.right;
36680 var grid = style.grid,
36681 tickLine = style.tickLine,
36682 line = style.line,
36683 labelOffset = style.labelOffset,
36684 label = style.label,
36685 symbol = style.symbol;
36686 var ticks = originTicks.filter(function (d) {
36687 return !isNaN(d.value);
36688 });
36689 var symbols = isArray(symbol) ? symbol : [symbol];
36690 var _a = tickLine || {},
36691 tickLineLength = _a.length,
36692 tickLineStyle = __rest(_a, ["length"]);
36693 return jsx("group", null, grid ? ticks.map(function (tick) {
36694 var points = tick.points,
36695 tickValue = tick.tickValue,
36696 gridStyle = tick.gridStyle;
36697 var start = points[0];
36698 var end = points[points.length - 1];
36699 return jsx("line", {
36700 key: "grid-".concat(tickValue),
36701 style: __assign(__assign({
36702 x1: start.x,
36703 y1: start.y,
36704 x2: end.x,
36705 y2: end.y
36706 }, grid), gridStyle)
36707 });
36708 }) : null, tickLine && tickLine.length ? ticks.map(function (tick) {
36709 var points = tick.points,
36710 tickValue = tick.tickValue;
36711 var end = points[points.length - 1];
36712 return jsx("line", {
36713 key: "tickLine-".concat(tickValue),
36714 style: __assign({
36715 x1: end.x,
36716 y1: end.y,
36717 x2: end.x,
36718 y2: end.y - px2hd(tickLineLength)
36719 }, tickLineStyle)
36720 });
36721 }) : null, symbols[0] ? jsx("marker", {
36722 style: __assign(__assign({
36723 x: right,
36724 y: top,
36725 transform: 'rotate(90deg)',
36726 transformOrigin: '50% 50%'
36727 }, symbols[0]), {
36728 symbol: symbols[0].type
36729 })
36730 }) : null, line ? jsx("line", {
36731 style: __assign({
36732 x1: left,
36733 y1: top,
36734 x2: right,
36735 y2: top
36736 }, line)
36737 }) : null, symbols[1] ? jsx("marker", {
36738 style: __assign(__assign({
36739 x: left,
36740 y: top,
36741 transform: 'rotate(-90deg)',
36742 transformOrigin: '50% 50%'
36743 }, symbols[0]), {
36744 symbol: symbols[1].type
36745 })
36746 }) : null, label ? ticks.map(function (tick, _index) {
36747 var tickValue = tick.tickValue,
36748 points = tick.points,
36749 text = tick.text,
36750 labelStyle = tick.labelStyle;
36751 var end = points[points.length - 1];
36752 return jsx("text", {
36753 key: "text-".concat(tickValue),
36754 style: __assign(__assign({
36755 x: end.x,
36756 y: end.y - labelOffset,
36757 textAlign: 'center',
36758 textBaseline: 'bottom',
36759 text: text
36760 }, label), labelStyle)
36761 });
36762 }) : null);
36763 });
36764
36765 var Bottom = (function (props, context) {
36766 var ticks = props.ticks,
36767 coord = props.coord,
36768 style = props.style,
36769 animation = props.animation;
36770 var px2hd = context.px2hd;
36771 var left = coord.left,
36772 right = coord.right,
36773 bottom = coord.bottom;
36774 var grid = style.grid,
36775 tickLine = style.tickLine,
36776 line = style.line,
36777 labelOffset = style.labelOffset,
36778 label = style.label,
36779 symbol = style.symbol;
36780 var filterTicks = ticks.filter(function (d) {
36781 return !isNaN(d.value);
36782 });
36783 var symbols = isArray(symbol) ? symbol : [symbol];
36784 var _a = tickLine || {},
36785 tickLineLength = _a.length,
36786 tickLineStyle = __rest(_a, ["length"]);
36787 return jsx("group", null, grid ? filterTicks.map(function (tick) {
36788 var points = tick.points,
36789 tickValue = tick.tickValue,
36790 gridStyle = tick.gridStyle;
36791 var start = points[0];
36792 var end = points[points.length - 1];
36793 return jsx("line", {
36794 key: "grid-".concat(tickValue),
36795 style: __assign(__assign({
36796 x1: start.x,
36797 y1: start.y,
36798 x2: end.x,
36799 y2: end.y
36800 }, grid), gridStyle)
36801 });
36802 }) : null, tickLineLength ? filterTicks.map(function (tick) {
36803 var points = tick.points,
36804 tickValue = tick.tickValue;
36805 var start = points[0];
36806 return jsx("line", {
36807 key: "tickLine-".concat(tickValue),
36808 style: __assign({
36809 x1: start.x,
36810 y1: start.y,
36811 x2: start.x,
36812 y2: start.y + px2hd(tickLineLength)
36813 }, tickLineStyle)
36814 });
36815 }) : null, symbols[0] ? jsx("marker", {
36816 style: __assign(__assign({
36817 x: right,
36818 y: bottom,
36819 transform: 'rotate(90deg)',
36820 transformOrigin: '50% 50%'
36821 }, symbols[0]), {
36822 symbol: symbols[0].type
36823 })
36824 }) : null, line ? jsx("line", {
36825 style: __assign({
36826 x1: left,
36827 y1: bottom,
36828 x2: right,
36829 y2: bottom
36830 }, line)
36831 }) : null, symbols[1] ? jsx("marker", {
36832 style: __assign(__assign({
36833 x: left,
36834 y: bottom,
36835 transform: 'rotate(-90deg)',
36836 transformOrigin: '50% 50%'
36837 }, symbols[0]), {
36838 symbol: symbols[1].type
36839 })
36840 }) : null, label ? filterTicks.map(function (tick, index) {
36841 var points = tick.points,
36842 text = tick.text,
36843 tickValue = tick.tickValue,
36844 labelStyle = tick.labelStyle;
36845 var start = points[0];
36846 var _a = (labelStyle || label || {}).align,
36847 align = _a === void 0 ? 'center' : _a;
36848 var textAttrs = __assign(__assign({
36849 x: start.x,
36850 y: start.y + labelOffset,
36851 textBaseline: 'top',
36852 text: text
36853 }, label), labelStyle);
36854 if (align === 'between') {
36855 if (index === 0) {
36856 textAttrs.textAlign = 'start';
36857 } else if (index === ticks.length - 1) {
36858 textAttrs.textAlign = 'end';
36859 } else {
36860 textAttrs.textAlign = 'center';
36861 }
36862 } else {
36863 textAttrs.textAlign = align;
36864 }
36865 return jsx("text", {
36866 key: "text-".concat(tickValue),
36867 style: textAttrs,
36868 animation: animation || {
36869 appear: {
36870 easing: 'linear',
36871 duration: 300,
36872 delay: 0,
36873 property: ['fillOpacity'],
36874 start: {
36875 fillOpacity: 0
36876 },
36877 end: {
36878 fillOpacity: 1
36879 }
36880 },
36881 update: {
36882 easing: 'linear',
36883 duration: 450,
36884 delay: 0,
36885 property: ['x', 'y']
36886 },
36887 leave: {
36888 easing: 'linear',
36889 duration: 450,
36890 delay: 0,
36891 property: ['fillOpacity'],
36892 start: {
36893 fillOpacity: 1
36894 },
36895 end: {
36896 fillOpacity: 0
36897 }
36898 }
36899 }
36900 });
36901 }) : null);
36902 });
36903
36904 var Right = (function (props, context) {
36905 var originTicks = props.ticks,
36906 coord = props.coord,
36907 style = props.style;
36908 var px2hd = context.px2hd;
36909 var top = coord.top,
36910 right = coord.right,
36911 bottom = coord.bottom;
36912 var grid = style.grid,
36913 tickLine = style.tickLine,
36914 line = style.line,
36915 labelOffset = style.labelOffset,
36916 label = style.label,
36917 symbol = style.symbol;
36918 var ticks = originTicks.filter(function (d) {
36919 return !isNaN(d.value);
36920 });
36921 var symbols = isArray(symbol) ? symbol : [symbol];
36922 var _a = tickLine || {},
36923 tickLineLength = _a.length,
36924 tickLineStyle = __rest(_a, ["length"]);
36925 return jsx("group", null, grid ? ticks.map(function (tick) {
36926 var points = tick.points,
36927 tickValue = tick.tickValue,
36928 gridStyle = tick.gridStyle;
36929 var start = points[0];
36930 var end = points[points.length - 1];
36931 return jsx("line", {
36932 key: "grid-".concat(tickValue),
36933 style: __assign(__assign({
36934 x1: start.x,
36935 y1: start.y,
36936 x2: end.x,
36937 y2: end.y
36938 }, grid), gridStyle)
36939 });
36940 }) : null, tickLineLength ? ticks.map(function (tick) {
36941 var points = tick.points,
36942 tickValue = tick.tickValue;
36943 var end = points[points.length - 1];
36944 return jsx("line", {
36945 key: "tickLine-".concat(tickValue),
36946 style: __assign({
36947 x1: end.x,
36948 y1: end.y,
36949 x2: end.x + px2hd(tickLineLength),
36950 y2: end.y
36951 }, tickLineStyle)
36952 });
36953 }) : null, symbols[0] ? jsx("marker", {
36954 style: __assign(__assign({
36955 x: right,
36956 y: top
36957 }, symbols[0]), {
36958 symbol: symbols[0].type
36959 })
36960 }) : null, line ? jsx("line", {
36961 style: __assign({
36962 x1: right,
36963 y1: top,
36964 x2: right,
36965 y2: bottom
36966 }, line)
36967 }) : null, symbols[1] ? jsx("marker", {
36968 style: __assign(__assign({
36969 x: right,
36970 y: bottom,
36971 transform: 'rotate(180deg)',
36972 transformOrigin: '50% 50%'
36973 }, symbols[1]), {
36974 symbol: symbols[1].type
36975 })
36976 }) : null, label ? ticks.map(function (tick, _index) {
36977 var tickValue = tick.tickValue,
36978 points = tick.points,
36979 text = tick.text,
36980 labelStyle = tick.labelStyle;
36981 var end = points[points.length - 1];
36982 return jsx("text", {
36983 key: "text-".concat(tickValue),
36984 style: __assign(__assign({
36985 x: end.x + labelOffset,
36986 y: end.y,
36987 textAlign: 'left',
36988 textBaseline: 'middle',
36989 text: text
36990 }, label), labelStyle)
36991 });
36992 }) : null);
36993 });
36994
36995 var Left = (function (props, context) {
36996 var originTicks = props.ticks,
36997 coord = props.coord,
36998 style = props.style,
36999 animation = props.animation;
37000 var px2hd = context.px2hd;
37001 var left = coord.left,
37002 top = coord.top,
37003 bottom = coord.bottom;
37004 var grid = style.grid,
37005 tickLine = style.tickLine,
37006 line = style.line,
37007 labelOffset = style.labelOffset,
37008 label = style.label,
37009 symbol = style.symbol;
37010 var ticks = originTicks.filter(function (d) {
37011 return !isNaN(d.value);
37012 });
37013 var symbols = isArray(symbol) ? symbol : [symbol];
37014 var _a = tickLine || {},
37015 tickLineLength = _a.length,
37016 tickLineStyle = __rest(_a, ["length"]);
37017 return jsx("group", null, grid ? ticks.map(function (tick) {
37018 var points = tick.points,
37019 tickValue = tick.tickValue,
37020 gridStyle = tick.gridStyle;
37021 var start = points[0];
37022 var end = points[points.length - 1];
37023 return jsx("line", {
37024 key: "grid-".concat(tickValue),
37025 style: __assign(__assign({
37026 x1: start.x,
37027 y1: start.y,
37028 x2: end.x,
37029 y2: end.y
37030 }, grid), gridStyle)
37031 });
37032 }) : null, tickLineLength ? ticks.map(function (tick) {
37033 var points = tick.points,
37034 tickValue = tick.tickValue;
37035 var start = points[0];
37036 return jsx("line", {
37037 key: "tickLine-".concat(tickValue),
37038 style: __assign({
37039 x1: start.x,
37040 y1: start.y,
37041 x2: start.x - px2hd(tickLineLength),
37042 y2: start.y
37043 }, tickLineStyle)
37044 });
37045 }) : null, symbols[0] ? jsx("marker", {
37046 style: __assign(__assign({
37047 x: left,
37048 y: top
37049 }, symbols[0]), {
37050 symbol: symbols[0].type
37051 })
37052 }) : null, line ? jsx("line", {
37053 style: __assign({
37054 x1: left,
37055 y1: top,
37056 x2: left,
37057 y2: bottom
37058 }, line)
37059 }) : null, symbols[1] ? jsx("marker", {
37060 style: __assign(__assign({
37061 x: left,
37062 y: bottom,
37063 transform: 'rotate(180deg)',
37064 transformOrigin: '50% 50%'
37065 }, symbols[1]), {
37066 symbol: symbols[1].type
37067 })
37068 }) : null, label ? ticks.map(function (tick, _index) {
37069 var tickValue = tick.tickValue,
37070 points = tick.points,
37071 text = tick.text,
37072 labelStyle = tick.labelStyle;
37073 var start = points[0];
37074 return jsx("text", {
37075 key: "text-".concat(tickValue),
37076 style: __assign(__assign({
37077 x: start.x - labelOffset,
37078 y: start.y,
37079 textAlign: 'right',
37080 textBaseline: 'middle',
37081 text: text
37082 }, label), labelStyle),
37083 animation: animation || {
37084 appear: {
37085 easing: 'linear',
37086 duration: 300,
37087 delay: 0,
37088 property: ['fillOpacity'],
37089 start: {
37090 fillOpacity: 0
37091 },
37092 end: {
37093 fillOpacity: 1
37094 }
37095 },
37096 update: {
37097 easing: 'linear',
37098 duration: 450,
37099 delay: 0,
37100 property: ['x', 'y']
37101 },
37102 leave: {
37103 easing: 'linear',
37104 duration: 450,
37105 delay: 0,
37106 property: ['fillOpacity'],
37107 start: {
37108 fillOpacity: 1
37109 },
37110 end: {
37111 fillOpacity: 0
37112 }
37113 }
37114 }
37115 });
37116 }) : null);
37117 });
37118
37119 function isPolar(props) {
37120 return props.coord.isPolar;
37121 }
37122 var AxisView = (function (props) {
37123 // 极坐标
37124 if (isPolar(props)) {
37125 var dimType = props.dimType;
37126 if (dimType === 'x') {
37127 return jsx(PolarX, __assign({}, props));
37128 }
37129 return jsx(PolarY, __assign({}, props));
37130 }
37131 var position = props.position;
37132 // 直角坐标
37133 if (position === 'right') {
37134 return jsx(Right, __assign({}, props));
37135 }
37136 if (position === 'left') {
37137 return jsx(Left, __assign({}, props));
37138 }
37139 if (position === 'top') {
37140 return jsx(Top, __assign({}, props));
37141 }
37142 return jsx(Bottom, __assign({}, props));
37143 });
37144
37145 var index$4 = withAxis(AxisView);
37146
37147 var withLegend = (function (View) {
37148 return /** @class */function (_super) {
37149 __extends(Legend, _super);
37150 function Legend(props) {
37151 var _this = _super.call(this, props) || this;
37152 _this._onclick = function (item) {
37153 var _a;
37154 var props = _this.props;
37155 var chart = props.chart,
37156 _b = props.clickable,
37157 clickable = _b === void 0 ? true : _b,
37158 onClick = props.onClick;
37159 if (!clickable) return;
37160 var clickItem = item.currentTarget;
37161 if (!clickItem) {
37162 return;
37163 }
37164 // @ts-ignore
37165 var dataItem = clickItem.config['data-item'];
37166 if (!dataItem) {
37167 return;
37168 }
37169 if (isFunction(onClick)) {
37170 onClick(dataItem);
37171 }
37172 var field = dataItem.field,
37173 tickValue = dataItem.tickValue;
37174 var prevFiltered = _this.state.filtered;
37175 var filtered = __assign(__assign({}, prevFiltered), (_a = {}, _a[tickValue] = !prevFiltered[tickValue], _a));
37176 _this.setState({
37177 filtered: filtered
37178 });
37179 chart.filter(field, function (value) {
37180 return !filtered[value];
37181 });
37182 };
37183 _this.state = {
37184 filtered: {},
37185 items: []
37186 };
37187 return _this;
37188 }
37189 Legend.prototype.getOriginItems = function () {
37190 var chart = this.props.chart;
37191 return chart.getLegendItems();
37192 };
37193 Legend.prototype.getItems = function () {
37194 var _a;
37195 var _b = this,
37196 props = _b.props,
37197 state = _b.state;
37198 var filtered = state.filtered;
37199 var renderItems = ((_a = props.items) === null || _a === void 0 ? void 0 : _a.length) ? props.items : this.getOriginItems();
37200 if (!renderItems) return null;
37201 return renderItems.map(function (item) {
37202 var tickValue = item.tickValue;
37203 return __assign(__assign({}, item), {
37204 filtered: filtered[tickValue]
37205 });
37206 });
37207 };
37208 Legend.prototype.setItems = function (items) {
37209 this.setState({
37210 items: items
37211 });
37212 };
37213 Legend.prototype.getMaxItemBox = function (node) {
37214 var maxItemWidth = 0;
37215 var maxItemHeight = 0;
37216 (node.children || []).forEach(function (child) {
37217 var layout = child.layout;
37218 var width = layout.width,
37219 height = layout.height;
37220 maxItemWidth = Math.max(maxItemWidth, width);
37221 maxItemHeight = Math.max(maxItemHeight, height);
37222 });
37223 return {
37224 width: maxItemWidth,
37225 height: maxItemHeight
37226 };
37227 };
37228 // 计算 legend 的位置
37229 Legend.prototype._init = function () {
37230 var _a = this,
37231 props = _a.props,
37232 context = _a.context;
37233 var
37234 // @ts-ignore
37235 parentLayout = props.layout,
37236 customWidth = props.width,
37237 customHeight = props.height,
37238 _b = props.position,
37239 position = _b === void 0 ? 'top' : _b;
37240 var items = this.getItems();
37241 if (!items || !items.length) return;
37242 var left = parentLayout.left,
37243 top = parentLayout.top,
37244 layoutWidth = parentLayout.width,
37245 layoutHeight = parentLayout.height;
37246 var width = context.px2hd(customWidth) || layoutWidth;
37247 var node = computeLayout$1(this, this.render());
37248 var _c = this.getMaxItemBox(node),
37249 itemMaxWidth = _c.width,
37250 itemMaxHeight = _c.height;
37251 // 每行最多的个数
37252 var lineMaxCount = Math.max(1, Math.floor(width / itemMaxWidth));
37253 var itemCount = items.length;
37254 // legend item 的行数
37255 var lineCount = Math.ceil(itemCount / lineMaxCount);
37256 var itemWidth = width / lineMaxCount;
37257 var autoHeight = itemMaxHeight * lineCount;
37258 var style = {
37259 left: left,
37260 top: top,
37261 width: width,
37262 // height 默认自适应
37263 height: undefined,
37264 flexDirection: 'row',
37265 flexWrap: 'wrap',
37266 alignItems: 'center',
37267 justifyContent: 'flex-start'
37268 };
37269 // 如果只有一行,2端对齐
37270 if (lineCount === 1) {
37271 style.justifyContent = 'space-between';
37272 }
37273 if (position === 'top') {
37274 style.height = customHeight ? customHeight : autoHeight;
37275 }
37276 if (position === 'left') {
37277 style.flexDirection = 'column';
37278 style.justifyContent = 'center';
37279 style.width = itemMaxWidth;
37280 style.height = customHeight ? customHeight : layoutHeight;
37281 }
37282 if (position === 'right') {
37283 style.flexDirection = 'column';
37284 style.alignItems = 'flex-start';
37285 style.justifyContent = 'center';
37286 style.width = itemMaxWidth;
37287 style.height = customHeight ? customHeight : layoutHeight;
37288 style.left = left + (width - itemMaxWidth);
37289 }
37290 if (position === 'bottom') {
37291 style.top = top + (layoutHeight - autoHeight);
37292 style.height = customHeight ? customHeight : autoHeight;
37293 }
37294 this.itemWidth = itemWidth;
37295 this.legendStyle = style;
37296 };
37297 Legend.prototype.updateCoord = function () {
37298 var _a = this,
37299 context = _a.context,
37300 props = _a.props,
37301 legendStyle = _a.legendStyle;
37302 var _b = props.position,
37303 position = _b === void 0 ? 'top' : _b,
37304 _c = props.margin,
37305 margin = _c === void 0 ? '30px' : _c,
37306 chart = props.chart;
37307 var width = legendStyle.width,
37308 height = legendStyle.height;
37309 var marginNumber = context.px2hd(margin);
37310 chart.updateCoordFor(this, {
37311 position: position,
37312 width: width + marginNumber,
37313 height: height + marginNumber
37314 });
37315 };
37316 Legend.prototype.willMount = function () {
37317 var items = this.getItems();
37318 if (!items || !items.length) return;
37319 this._init();
37320 this.updateCoord();
37321 };
37322 Legend.prototype.didMount = function () {
37323 // this._initEvent();
37324 };
37325 Legend.prototype.willUpdate = function () {
37326 var items = this.getItems();
37327 if (!items || !items.length) return;
37328 this.updateCoord();
37329 };
37330 Legend.prototype.render = function () {
37331 var _a = this,
37332 props = _a.props,
37333 itemWidth = _a.itemWidth,
37334 legendStyle = _a.legendStyle;
37335 var items = this.getItems();
37336 if (!items || !items.length) {
37337 return null;
37338 }
37339 return jsx(View, __assign({}, props, {
37340 items: items,
37341 itemWidth: itemWidth,
37342 style: __assign(__assign({}, legendStyle), props.style),
37343 onClick: this._onclick
37344 }));
37345 };
37346 return Legend;
37347 }(Component);
37348 });
37349
37350 var Marker$1 = function Marker(_a) {
37351 var type = _a.type,
37352 color = _a.color;
37353 if (type === 'square') {
37354 return jsx("rect", {
37355 style: {
37356 width: '12px',
37357 height: '12px',
37358 marginRight: '10px'
37359 },
37360 attrs: {
37361 fill: color
37362 }
37363 });
37364 }
37365 if (type === 'line') {
37366 return jsx("line", {
37367 style: {
37368 width: '19px',
37369 marginRight: '10px'
37370 },
37371 attrs: {
37372 stroke: color,
37373 lineCap: 'round',
37374 lineWidth: '4px'
37375 }
37376 });
37377 }
37378 return jsx("circle", {
37379 style: {
37380 width: '12px',
37381 height: '12px',
37382 marginRight: '10px',
37383 fill: color
37384 }
37385 });
37386 };
37387 var LegendView = (function (props) {
37388 var items = props.items,
37389 itemWidth = props.itemWidth,
37390 itemFormatter = props.itemFormatter,
37391 style = props.style,
37392 _a = props.marker,
37393 marker = _a === void 0 ? 'circle' : _a,
37394 // 图例标记默认为 circle
37395 itemStyle = props.itemStyle,
37396 nameStyle = props.nameStyle,
37397 valueStyle = props.valueStyle,
37398 valuePrefix = props.valuePrefix,
37399 onClick = props.onClick;
37400 var formatValue = function formatValue(value, valuePrefix) {
37401 if (valuePrefix === void 0) {
37402 valuePrefix = ': ';
37403 }
37404 return "".concat(valuePrefix).concat(value);
37405 };
37406 return jsx("group", {
37407 style: __assign({
37408 display: 'flex'
37409 }, style)
37410 }, items.map(function (item) {
37411 var color = item.color,
37412 name = item.name,
37413 value = item.value,
37414 filtered = item.filtered,
37415 tickValue = item.tickValue;
37416 var valueText = isFunction(itemFormatter) ? itemFormatter(value, tickValue) : value;
37417 return jsx("group", {
37418 className: "legend-item",
37419 style: __assign({
37420 width: itemWidth,
37421 display: 'flex',
37422 flexDirection: 'row',
37423 alignItems: 'center',
37424 justifyContent: 'flex-start',
37425 //TODO: padding改为’12px‘ 就和原来一致了
37426 padding: ['6px', '6px', '6px', 0]
37427 }, itemStyle),
37428 "data-item": item,
37429 onClick: onClick
37430 }, Marker$1({
37431 color: filtered ? '#bfbfbf' : color,
37432 type: marker
37433 }), jsx("text", {
37434 attrs: __assign({
37435 fill: filtered ? '#bfbfbf' : '#808080',
37436 text: name
37437 }, nameStyle)
37438 }), valueText ? jsx("text", {
37439 attrs: __assign({
37440 fill: '#808080',
37441 text: formatValue(valueText, valuePrefix)
37442 }, valueStyle)
37443 }) : null);
37444 }));
37445 });
37446
37447 var index$5 = withLegend(LegendView);
37448
37449 var withGuide = (function (View) {
37450 return /** @class */function (_super) {
37451 __extends(Guide, _super);
37452 function Guide(props) {
37453 return _super.call(this, props) || this;
37454 }
37455 Guide.prototype.getGuideBBox = function () {
37456 var node = computeLayout$1(this, this.render());
37457 var layout = node.layout;
37458 if (!layout) return;
37459 return layout;
37460 };
37461 // 解析record里的模板字符串,如min、max、50%...
37462 Guide.prototype.parseReplaceStr = function (value, scale) {
37463 var replaceMap = {
37464 min: 0,
37465 max: 1,
37466 median: 0.5
37467 };
37468 // 传入的是 min、max、median 的
37469 if (!isNil(replaceMap[value])) {
37470 return replaceMap[value];
37471 }
37472 // 传入的是 xx%
37473 if (isString(value) && value.indexOf('%') != -1 && !isNaN(Number(value.slice(0, -1)))) {
37474 var rateValue = Number(value.slice(0, -1));
37475 var percent = rateValue / 100;
37476 return percent;
37477 }
37478 return scale.scale(value);
37479 };
37480 Guide.prototype.parsePoint = function (record) {
37481 var props = this.props;
37482 var chart = props.chart,
37483 coord = props.coord;
37484 var xScale = chart.getXScales()[0];
37485 // 只取第一个yScale
37486 var yScale = chart.getYScales()[0];
37487 // 解析 record 为归一化后的坐标
37488 var x = this.parseReplaceStr(record[xScale.field], xScale);
37489 var y = this.parseReplaceStr(record[yScale.field], yScale);
37490 return coord.convertPoint({
37491 x: x,
37492 y: y
37493 });
37494 };
37495 Guide.prototype.convertPoints = function (records) {
37496 var _this = this;
37497 return records.map(function (record) {
37498 return _this.parsePoint(record);
37499 });
37500 };
37501 Guide.prototype.getGuideTheme = function () {
37502 var context = this.context;
37503 var theme = context.theme;
37504 return theme.guide;
37505 };
37506 Guide.prototype.render = function () {
37507 var _a = this,
37508 props = _a.props,
37509 context = _a.context;
37510 var coord = props.coord,
37511 _b = props.records,
37512 records = _b === void 0 ? [] : _b,
37513 animation = props.animation,
37514 chart = props.chart,
37515 style = props.style,
37516 _onClick = props.onClick;
37517 var width = context.width,
37518 height = context.height;
37519 var points = this.convertPoints(records);
37520 var theme = this.getGuideTheme();
37521 return jsx("group", {
37522 onClick: function onClick(ev) {
37523 _onClick && _onClick(ev);
37524 }
37525 }, jsx(View, __assign({
37526 points: points,
37527 theme: theme,
37528 coord: coord
37529 }, props, {
37530 canvasWidth: width,
37531 canvasHeight: height,
37532 style: isFunction(style) ? style(points, chart) : style,
37533 animation: isFunction(animation) ? animation(points, chart) : animation
37534 })));
37535 };
37536 return Guide;
37537 }(Component);
37538 });
37539
37540 var TextGuideView = (function (props, context) {
37541 var _a = props.theme,
37542 theme = _a === void 0 ? {} : _a;
37543 var _b = deepMix(__assign({}, theme.text), props),
37544 points = _b.points,
37545 style = _b.style,
37546 offsetX = _b.offsetX,
37547 offsetY = _b.offsetY,
37548 content = _b.content,
37549 animation = _b.animation;
37550 var _c = points[0] || {},
37551 x = _c.x,
37552 y = _c.y;
37553 var offsetXNum = context.px2hd(offsetX);
37554 var offsetYNum = context.px2hd(offsetY);
37555 var posX = x + (offsetXNum || 0);
37556 var posY = y + (offsetYNum || 0);
37557 return jsx("text", {
37558 attrs: __assign({
37559 text: "".concat(content),
37560 x: posX,
37561 y: posY
37562 }, style),
37563 animation: deepMix({
37564 update: {
37565 easing: 'linear',
37566 duration: 450,
37567 property: ['x', 'y']
37568 }
37569 }, animation)
37570 });
37571 });
37572
37573 var PointGuideView = (function (props, context) {
37574 var theme = props.theme;
37575 var _a = deepMix(__assign({}, theme.point), props),
37576 points = _a.points,
37577 style = _a.style,
37578 offsetX = _a.offsetX,
37579 offsetY = _a.offsetY,
37580 animation = _a.animation;
37581 var _b = points[0] || {},
37582 x = _b.x,
37583 y = _b.y;
37584 var offsetXNum = context.px2hd(offsetX);
37585 var offsetYNum = context.px2hd(offsetY);
37586 var posX = x + (offsetXNum || 0);
37587 var posY = y + (offsetYNum || 0);
37588 return jsx("group", null, jsx("circle", {
37589 style: __assign({
37590 cx: posX,
37591 cy: posY
37592 }, style),
37593 animation: animation
37594 }));
37595 });
37596
37597 var LineGuideView = (function (props, context) {
37598 var _a = props.theme,
37599 theme = _a === void 0 ? {} : _a;
37600 var _b = deepMix(__assign({}, theme.line), props),
37601 points = _b.points,
37602 style = _b.style,
37603 offsetX = _b.offsetX,
37604 offsetY = _b.offsetY,
37605 animation = _b.animation;
37606 var _c = points[0] || {},
37607 x1 = _c.x,
37608 y1 = _c.y;
37609 var _d = points[1] || {},
37610 x2 = _d.x,
37611 y2 = _d.y;
37612 var offsetXNum = context.px2hd(offsetX);
37613 var offsetYNum = context.px2hd(offsetY);
37614 var posX1 = x1 + (isArray(offsetXNum) ? offsetXNum[0] || 0 : offsetXNum || 0);
37615 var posY1 = y1 + (isArray(offsetYNum) ? offsetYNum[0] || 0 : offsetYNum || 0);
37616 var posX2 = x2 + (isArray(offsetXNum) ? offsetXNum[1] || 0 : offsetXNum || 0);
37617 var posY2 = y2 + (isArray(offsetYNum) ? offsetYNum[1] || 0 : offsetYNum || 0);
37618 return jsx("group", null, jsx("line", {
37619 style: __assign({
37620 x1: posX1,
37621 y1: posY1,
37622 x2: posX2,
37623 y2: posY2
37624 }, style),
37625 animation: animation
37626 }));
37627 });
37628
37629 var ArcGuideView = (function (props) {
37630 var _a = props.theme,
37631 theme = _a === void 0 ? {} : _a;
37632 var _b = deepMix(__assign({}, theme.line), props),
37633 coord = _b.coord,
37634 points = _b.points,
37635 style = _b.style,
37636 animation = _b.animation;
37637 var start = points[0] || {};
37638 var end = points[1] || {};
37639 var coordCenter = coord.center;
37640 var radius = Math.sqrt((start.x - coordCenter.x) * (start.x - coordCenter.x) + (start.y - coordCenter.y) * (start.y - coordCenter.y));
37641 var startAngle = Math.atan2(start.y - coordCenter.y, start.x - coordCenter.x);
37642 var endAngle = Math.atan2(end.y - coordCenter.y, end.x - coordCenter.x);
37643 return jsx("group", null, jsx("arc", {
37644 style: __assign({
37645 cx: coordCenter.x,
37646 cy: coordCenter.y,
37647 r: radius,
37648 startAngle: "".concat(startAngle, "rad"),
37649 endAngle: "".concat(endAngle, "rad")
37650 }, style),
37651 animation: animation
37652 }));
37653 });
37654
37655 var RectGuideView = (function (props) {
37656 var _a = props.theme,
37657 theme = _a === void 0 ? {} : _a;
37658 var _b = deepMix(__assign({}, theme.rect), props),
37659 points = _b.points,
37660 style = _b.style,
37661 animation = _b.animation;
37662 var start = points[0] || {};
37663 var end = points[1] || {};
37664 return jsx("group", null, jsx("rect", {
37665 style: __assign({
37666 x: Math.min(start.x, end.x),
37667 y: Math.min(start.y, end.y),
37668 width: Math.abs(end.x - start.x),
37669 height: Math.abs(start.y - end.y)
37670 }, style),
37671 animation: animation
37672 }));
37673 });
37674
37675 var defaultProps = {
37676 offsetX: 0,
37677 offsetY: 0,
37678 points: [],
37679 src: ''
37680 };
37681 var ImageGuideView = (function (props, context) {
37682 var cfg = deepMix({}, defaultProps, props);
37683 var points = cfg.points,
37684 style = cfg.style,
37685 attrs = cfg.attrs,
37686 offsetX = cfg.offsetX,
37687 offsetY = cfg.offsetY,
37688 src = cfg.src,
37689 animation = cfg.animation;
37690 var _a = points[0] || {},
37691 x = _a.x,
37692 y = _a.y;
37693 var _b = __assign(__assign({}, attrs), style),
37694 _c = _b.height,
37695 height = _c === void 0 ? 0 : _c,
37696 _d = _b.width,
37697 width = _d === void 0 ? 0 : _d;
37698 var heightNum = context.px2hd(height + 'px');
37699 var widthNum = context.px2hd(width + 'px');
37700 var offsetXNum = context.px2hd(offsetX);
37701 var offsetYNum = context.px2hd(offsetY);
37702 var posX = x + (offsetXNum || 0) - widthNum / 2;
37703 var posY = y + (offsetYNum || 0) - heightNum / 2;
37704 return jsx("group", null, jsx("image", {
37705 style: __assign(__assign(__assign({}, attrs), style), {
37706 height: heightNum,
37707 width: widthNum,
37708 x: posX,
37709 y: posY,
37710 src: src
37711 }),
37712 animation: deepMix({
37713 update: {
37714 easing: 'linear',
37715 duration: 450,
37716 property: ['x', 'y']
37717 }
37718 }, animation)
37719 }));
37720 });
37721
37722 var defaultProps$1 = {
37723 offsetX: 0,
37724 offsetY: 0,
37725 points: [],
37726 direct: 'tl',
37727 side: '8px',
37728 autoAdjust: true
37729 };
37730 var defaultStyle = {
37731 container: {
37732 fill: '#1677FF',
37733 radius: '4px',
37734 padding: ['4px', '8px']
37735 },
37736 text: {
37737 fontSize: '22px',
37738 fill: '#fff'
37739 },
37740 arrow: {
37741 fill: '#1677FF'
37742 }
37743 };
37744 var Label = function Label(_a) {
37745 var content = _a.content,
37746 background = _a.background,
37747 textStyle = _a.textStyle;
37748 return jsx("rect", {
37749 style: __assign({
37750 display: 'flex',
37751 fill: defaultStyle.container.fill,
37752 padding: defaultStyle.container.padding,
37753 radius: defaultStyle.container.radius
37754 }, background)
37755 }, jsx("text", {
37756 style: __assign({
37757 text: content,
37758 fontSize: defaultStyle.text.fontSize,
37759 fill: defaultStyle.text.fill
37760 }, textStyle)
37761 }));
37762 };
37763 var Tag = /** @class */function (_super) {
37764 __extends(Tag, _super);
37765 function Tag() {
37766 return _super !== null && _super.apply(this, arguments) || this;
37767 }
37768 Tag.prototype.render = function () {
37769 var _a = this,
37770 props = _a.props,
37771 context = _a.context;
37772 var px2hd = context.px2hd;
37773 var cfg = __assign(__assign({}, defaultProps$1), props);
37774 var _b = px2hd(cfg),
37775 points = _b.points,
37776 content = _b.content,
37777 offsetX = _b.offsetX,
37778 offsetY = _b.offsetY,
37779 direct = _b.direct,
37780 side = _b.side,
37781 autoAdjust = _b.autoAdjust,
37782 canvasWidth = _b.canvasWidth,
37783 canvasHeight = _b.canvasHeight,
37784 background = _b.background,
37785 textStyle = _b.textStyle;
37786 var _c = points[0] || {},
37787 x = _c.x,
37788 y = _c.y;
37789 var offsetXNum = context.px2hd(offsetX);
37790 var offsetYNum = context.px2hd(offsetY);
37791 var posX = x + (offsetXNum || 0);
37792 var posY = y + (offsetYNum || 0);
37793 var layout = computeLayout$1(this, jsx(Label, {
37794 content: content,
37795 background: background,
37796 textStyle: textStyle
37797 })).layout;
37798 var guideWidth = layout.width,
37799 guideHeight = layout.height;
37800 var _getDirect = function _getDirect(point) {
37801 var newDirect = direct;
37802 var x = point.x,
37803 y = point.y;
37804 var vertical = newDirect[0];
37805 var horizontal = newDirect[1];
37806 // adjust for vertical direction
37807 if (vertical === 't' && y - side - guideHeight < 0) {
37808 vertical = 'b';
37809 } else if (vertical === 'b' && y + side + guideHeight > canvasHeight) {
37810 vertical = 't';
37811 }
37812 // adjust for horizontal direction
37813 var diff = vertical === 'c' ? side : 0;
37814 if (horizontal === 'l' && x - diff - guideWidth < 0) {
37815 horizontal = 'r';
37816 } else if (horizontal === 'r' && x + diff + guideWidth > canvasWidth) {
37817 horizontal = 'l';
37818 } else if (horizontal === 'c') {
37819 if (guideWidth / 2 + x + diff > canvasWidth) {
37820 horizontal = 'l';
37821 } else if (x - guideWidth / 2 - diff < 0) {
37822 horizontal = 'r';
37823 }
37824 }
37825 newDirect = vertical + horizontal;
37826 return newDirect;
37827 };
37828 var _getArrowPoints = function _getArrowPoints(direct) {
37829 var arrowPoints = [];
37830 if (direct === 'tl') {
37831 arrowPoints = [{
37832 x: guideWidth,
37833 y: guideHeight - 1
37834 }, {
37835 x: guideWidth,
37836 y: guideHeight + side
37837 }, {
37838 x: guideWidth - side,
37839 y: guideHeight - 1
37840 }];
37841 posX -= guideWidth || 0;
37842 posY = posY - (guideHeight || 0) - side;
37843 } else if (direct === 'cl') {
37844 arrowPoints = [{
37845 x: guideWidth,
37846 y: guideHeight / 2 - side
37847 }, {
37848 x: guideWidth,
37849 y: guideHeight / 2 + side
37850 }, {
37851 x: guideWidth + side,
37852 y: guideHeight / 2
37853 }];
37854 posX = posX - (guideWidth || 0) - side;
37855 posY -= guideHeight / 2 || 0;
37856 } else if (direct === 'bl') {
37857 arrowPoints = [{
37858 x: guideWidth,
37859 y: -side
37860 }, {
37861 x: guideWidth,
37862 y: 1
37863 }, {
37864 x: guideWidth - side,
37865 y: 1
37866 }];
37867 posX = posX - (guideWidth || 0);
37868 posY += side;
37869 } else if (direct === 'bc') {
37870 arrowPoints = [{
37871 x: guideWidth / 2,
37872 y: -side
37873 }, {
37874 x: guideWidth / 2 - side,
37875 y: 1
37876 }, {
37877 x: guideWidth / 2 + side,
37878 y: 1
37879 }];
37880 posX = posX - (guideWidth / 2 || 0);
37881 posY = posY + side;
37882 } else if (direct === 'br') {
37883 arrowPoints = [{
37884 x: 0,
37885 y: -side
37886 }, {
37887 x: 0,
37888 y: 1
37889 }, {
37890 x: +side,
37891 y: 1
37892 }];
37893 posY += side;
37894 } else if (direct === 'cr') {
37895 arrowPoints = [{
37896 x: -side,
37897 y: guideHeight / 2
37898 }, {
37899 x: 0,
37900 y: guideHeight / 2 - side
37901 }, {
37902 x: 0,
37903 y: guideHeight / 2 + side
37904 }];
37905 posX += side;
37906 posY -= guideHeight / 2 || 0;
37907 } else if (direct === 'tr') {
37908 arrowPoints = [{
37909 x: 0,
37910 y: guideHeight + side
37911 }, {
37912 x: 0,
37913 y: guideHeight - 1
37914 }, {
37915 x: side,
37916 y: guideHeight - 1
37917 }];
37918 posY = posY - (guideHeight || 0) - side;
37919 } else if (direct === 'tc') {
37920 arrowPoints = [{
37921 x: guideWidth / 2,
37922 y: guideHeight + side
37923 }, {
37924 x: guideWidth / 2 - side,
37925 y: guideHeight - 1
37926 }, {
37927 x: guideWidth / 2 + side,
37928 y: guideHeight - 1
37929 }];
37930 posX -= guideWidth / 2 || 0;
37931 posY = posY - guideHeight - side;
37932 }
37933 return arrowPoints;
37934 };
37935 var dr = autoAdjust ? _getDirect(points[0]) : direct;
37936 var arrowPoints = _getArrowPoints(dr);
37937 return jsx("group", {
37938 style: {
37939 x: posX,
37940 y: posY
37941 }
37942 }, jsx(Label, {
37943 content: content,
37944 background: background,
37945 textStyle: textStyle
37946 }), jsx("polygon", {
37947 style: {
37948 points: arrowPoints.map(function (d) {
37949 return [d.x, d.y];
37950 }),
37951 fill: (background === null || background === void 0 ? void 0 : background.fill) || defaultStyle.arrow.fill
37952 }
37953 }));
37954 };
37955 return Tag;
37956 }(Component);
37957
37958 var eps = 0.0001;
37959 /**
37960 * Provides some control methods like:
37961 * - play
37962 * - pause
37963 * - stop
37964 * - goToAndStop
37965 * - goToAndPlay
37966 * @see https://github.com/airbnb/lottie-web/blob/master/player/js/animation/AnimationItem.js
37967 */
37968 var LottieAnimation = /** @class */ (function () {
37969 function LottieAnimation(width, height, elements, context) {
37970 var _this = this;
37971 this.width = width;
37972 this.height = height;
37973 this.elements = elements;
37974 this.context = context;
37975 this.keyframeAnimationMap = new WeakMap();
37976 this.displayObjectElementMap = new WeakMap();
37977 this.animations = [];
37978 this.isPaused = false;
37979 this.direction = 1;
37980 this.displayObjects = elements.map(function (element) {
37981 return _this.buildHierachy(element);
37982 });
37983 // TODO: preload images
37984 // TODO: preload fonts
37985 }
37986 LottieAnimation.prototype.generateTransform = function (tx, ty, scaleX, scaleY, rotation) {
37987 var transformStr = '';
37988 if (tx !== 0 || ty !== 0) {
37989 transformStr += "translate(".concat(tx, ", ").concat(ty, ")");
37990 }
37991 if (scaleX !== 1 || scaleY !== 1) {
37992 transformStr += " scale(".concat(scaleX === 0 ? eps : scaleX, ", ").concat(scaleY === 0 ? eps : scaleY, ")");
37993 }
37994 if (rotation !== 0) {
37995 transformStr += " rotate(".concat(rotation, "deg)");
37996 }
37997 return transformStr;
37998 };
37999 LottieAnimation.prototype.buildHierachy = function (element) {
38000 var _this = this;
38001 var type = element.type, name = element.name, _a = element.anchorX, anchorX = _a === void 0 ? 0 : _a, _b = element.anchorY, anchorY = _b === void 0 ? 0 : _b, _c = element.rotation, rotation = _c === void 0 ? 0 : _c, _d = element.scaleX, scaleX = _d === void 0 ? 1 : _d, _e = element.scaleY, scaleY = _e === void 0 ? 1 : _e, _f = element.x, x = _f === void 0 ? 0 : _f, _g = element.y, y = _g === void 0 ? 0 : _g,
38002 // skew = 0,
38003 // skewAxis = 0,
38004 children = element.children, shape = element.shape, style = element.style, keyframeAnimation = element.keyframeAnimation;
38005 var displayObject;
38006 var transform = this.generateTransform(x - anchorX, y - anchorY, scaleX, scaleY, rotation);
38007 // const transformMat = mat4.fromRotationTranslationScaleOrigin(
38008 // mat4.create(),
38009 // quat.fromEuler(quat.create(), 0, 0, rotation),
38010 // [x - anchorX, y - anchorY, 0],
38011 // [scaleX, scaleY, 1],
38012 // [anchorX, anchorY, 0],
38013 // );
38014 // TODO: repeater @see https://lottiefiles.github.io/lottie-docs/shapes/#repeater
38015 // @see https://lottiefiles.github.io/lottie-docs/shapes/#shape
38016 // TODO: polystar, convert to Bezier @see https://lottiefiles.github.io/lottie-docs/rendering/#polystar
38017 if (type === Shape.GROUP) {
38018 displayObject = new Group({
38019 style: {
38020 transformOrigin: "".concat(anchorX, "px ").concat(anchorY, "px"),
38021 transform: transform,
38022 },
38023 });
38024 }
38025 else if (type === Shape.ELLIPSE) {
38026 var cx = shape.cx, cy = shape.cy, rx = shape.rx, ry = shape.ry;
38027 // const center = vec3.fromValues(cx, cy, 0);
38028 // vec3.transformMat4(center, center, transformMat);
38029 displayObject = new Ellipse({
38030 style: {
38031 // cx: center[0],
38032 // cy: center[1],
38033 cx: cx,
38034 cy: cy,
38035 rx: rx,
38036 ry: ry,
38037 // reset transform-origin based on anchor & center
38038 transformOrigin: "".concat(anchorX - cx + rx, "px ").concat(anchorY - cy + ry, "px"),
38039 transform: transform,
38040 },
38041 });
38042 }
38043 else if (type === Shape.PATH) {
38044 var d = this.generatePathFromShape(shape);
38045 displayObject = new Path({
38046 style: {
38047 d: d,
38048 transformOrigin: "".concat(anchorX, "px ").concat(anchorY, "px"),
38049 transform: transform,
38050 },
38051 });
38052 }
38053 else if (type === Shape.RECT) {
38054 // @see https://lottiefiles.github.io/lottie-docs/shapes/#rectangle
38055 var cx = shape.x, cy = shape.y, width = shape.width, height = shape.height, r = shape.r;
38056 displayObject = new Rect({
38057 style: {
38058 x: cx,
38059 y: cy,
38060 width: width,
38061 height: height,
38062 anchor: [0.5, 0.5],
38063 radius: r,
38064 transformOrigin: "".concat(anchorX - cx + width / 2, "px ").concat(anchorY - cy + height / 2, "px"),
38065 transform: transform,
38066 },
38067 });
38068 }
38069 else if (type === Shape.IMAGE) {
38070 var width = shape.width, height = shape.height, src = shape.src;
38071 displayObject = new Image({
38072 style: {
38073 x: 0,
38074 y: 0,
38075 width: width,
38076 height: height,
38077 src: src,
38078 transformOrigin: "".concat(anchorX, "px ").concat(anchorY, "px"),
38079 transform: transform,
38080 },
38081 });
38082 }
38083 if (name) {
38084 displayObject.name = name;
38085 }
38086 // TODO: match name `mn`, used in expressions
38087 if (style) {
38088 // { fill, fillOpacity, fillRule, opacity, lineDash, lineDashOffset }
38089 displayObject.attr(style);
38090 }
38091 if (keyframeAnimation) {
38092 this.keyframeAnimationMap.set(displayObject, keyframeAnimation);
38093 }
38094 if (children) {
38095 var childNodes = children.map(function (child) { return _this.buildHierachy(child); });
38096 displayObject.append.apply(displayObject, __spreadArray([], __read(childNodes), false));
38097 }
38098 this.displayObjectElementMap.set(displayObject, element);
38099 return displayObject;
38100 };
38101 LottieAnimation.prototype.getAnimations = function () {
38102 return this.animations;
38103 };
38104 /**
38105 * Returns the animation duration in seconds or frames.
38106 * @see https://github.com/airbnb/lottie-web#getdurationinframes
38107 */
38108 LottieAnimation.prototype.getDuration = function (inFrames) {
38109 if (inFrames === void 0) { inFrames = false; }
38110 return (((inFrames ? this.fps() : 1) *
38111 (this.context.endFrame - this.context.startFrame) *
38112 this.context.frameTime) /
38113 1000);
38114 };
38115 /**
38116 * Returns the animation frame rate (frames / second).
38117 */
38118 LottieAnimation.prototype.fps = function () {
38119 return this.context.fps;
38120 };
38121 LottieAnimation.prototype.isSameKeyframeOptions = function (options1, options2) {
38122 return (options1.delay === options2.delay &&
38123 options1.duration === options2.duration &&
38124 options1.easing === options2.easing);
38125 };
38126 LottieAnimation.prototype.isSameKeyframes = function (keyframe1, keyframe2) {
38127 // const { offset: o1, easing: e1, ...rest1 } = keyframe1;
38128 // const { offset: o2, easing: e2, ...rest2 } = keyframe2;
38129 // const isAllApplyToTransform =
38130 // Object.keys(rest1).every((key) =>
38131 // ['x', 'y', 'scaleX', 'scaleY', 'rotation'].includes(key),
38132 // ) &&
38133 // Object.keys(rest2).every((key) =>
38134 // ['x', 'y', 'scaleX', 'scaleY', 'rotation'].includes(key),
38135 // );
38136 return (keyframe1.offset === keyframe2.offset &&
38137 keyframe1.easing === keyframe2.easing
38138 // (keyframe1.easing === keyframe2.easing || isAllApplyToTransform)
38139 );
38140 };
38141 LottieAnimation.prototype.generatePathFromShape = function (shape) {
38142 // @see https://lottiefiles.github.io/lottie-docs/shapes/#path
38143 var close = shape.close, v = shape.v, i = shape.in, out = shape.out;
38144 var d = [];
38145 d.push(['M', v[0][0], v[0][1]]);
38146 for (var n = 1; n < v.length; n++) {
38147 // @see https://lottiefiles.github.io/lottie-docs/concepts/#bezier
38148 // The nth bezier segment is defined as:
38149 // v[n], v[n]+o[n], v[n+1]+i[n+1], v[n+1]
38150 d.push([
38151 'C',
38152 out[n - 1][0],
38153 out[n - 1][1],
38154 i[n][0],
38155 i[n][1],
38156 v[n][0],
38157 v[n][1],
38158 ]);
38159 }
38160 if (close) {
38161 d.push([
38162 'C',
38163 out[v.length - 1][0],
38164 out[v.length - 1][1],
38165 i[0][0],
38166 i[0][1],
38167 v[0][0],
38168 v[0][1],
38169 ]);
38170 d.push(['Z']);
38171 }
38172 return d;
38173 };
38174 /**
38175 * render Lottie Group to canvas or a mounted display object
38176 */
38177 LottieAnimation.prototype.render = function (canvasOrDisplayObject) {
38178 var _this = this;
38179 var wrapper = new Group();
38180 wrapper.append.apply(wrapper, __spreadArray([], __read(this.displayObjects), false));
38181 if (isCanvas(canvasOrDisplayObject)) {
38182 canvasOrDisplayObject.appendChild(wrapper);
38183 }
38184 else if (isDisplayObject(canvasOrDisplayObject)) {
38185 if (!canvasOrDisplayObject.isConnected) {
38186 throw new Error('[g-lottie-player]: Cannot render Lottie to an unmounted DisplayObject.');
38187 }
38188 else {
38189 canvasOrDisplayObject.appendChild(wrapper);
38190 }
38191 }
38192 else {
38193 throw new Error('[g-lottie-player]: We should render Lottie to a mounted DisplayObject or Canvas.');
38194 }
38195 this.displayObjects.forEach(function (parent) {
38196 parent.forEach(function (child) {
38197 var _a;
38198 var keyframeAnimation = _this.keyframeAnimationMap.get(child);
38199 // console.log('keyframeAnimation', keyframeAnimation);
38200 var element = _this.displayObjectElementMap.get(child);
38201 if (element && element.clipPath) {
38202 var _b = element.clipPath, shape = _b.shape, keyframeAnimation_1 = _b.keyframeAnimation;
38203 var clipPath = new Path();
38204 // use clipPath as target's siblings
38205 child.parentElement.appendChild(clipPath);
38206 child.style.clipPath = clipPath;
38207 if (shape) {
38208 clipPath.style.d = _this.generatePathFromShape(shape);
38209 }
38210 // TODO: only support one clipPath now
38211 if (keyframeAnimation_1 && keyframeAnimation_1.length) {
38212 var _c = keyframeAnimation_1[0], delay = _c.delay, duration = _c.duration, easing = _c.easing, keyframes = _c.keyframes;
38213 // animate clipPath with its `d` property
38214 var clipPathAnimation = clipPath.animate(keyframes.map(function (_a) {
38215 var offset = _a.offset, shape = _a.shape, easing = _a.easing;
38216 return {
38217 offset: offset,
38218 d: path2String(_this.generatePathFromShape(shape)),
38219 easing: easing,
38220 };
38221 }), {
38222 delay: delay,
38223 duration: duration,
38224 easing: easing,
38225 iterations: _this.context.iterations,
38226 });
38227 _this.animations.push(clipPathAnimation);
38228 }
38229 }
38230 // account for animation only apply to visibility, e.g. spring
38231 var visibilityStartOffset = element.visibilityStartOffset, visibilityEndOffset = element.visibilityEndOffset, visibilityFrame = element.visibilityFrame;
38232 if (visibilityFrame &&
38233 (!keyframeAnimation || !keyframeAnimation.length)) {
38234 keyframeAnimation = [
38235 {
38236 duration: _this.context.frameTime * visibilityFrame,
38237 keyframes: [
38238 { offset: 0, style: { opacity: 1 } },
38239 { offset: 1, style: { opacity: 1 } },
38240 ],
38241 },
38242 ];
38243 }
38244 if (keyframeAnimation && keyframeAnimation.length) {
38245 var keyframesOptions_1 = [];
38246 keyframeAnimation.map(function (_a) {
38247 var _b = _a.delay, delay = _b === void 0 ? 0 : _b, duration = _a.duration, easing = _a.easing, keyframes = _a.keyframes;
38248 var formattedKeyframes = keyframes.map(function (keyframe) {
38249 return definedProps(keyframe);
38250 });
38251 var options = definedProps({
38252 delay: delay,
38253 duration: duration,
38254 easing: easing,
38255 iterations: _this.context.iterations,
38256 fill: _this.context.fill,
38257 });
38258 keyframesOptions_1.push([formattedKeyframes, options]);
38259 });
38260 var mergedKeyframesOptions = [keyframesOptions_1[0]];
38261 var _loop_1 = function (i) {
38262 var _d = __read(keyframesOptions_1[i], 2), currentKeyframes = _d[0], currentOptions = _d[1];
38263 // can merge options?
38264 var existedKeyframeOptions = mergedKeyframesOptions.find(function (_a) {
38265 var _b = __read(_a, 2), keyframes = _b[0], options = _b[1];
38266 return keyframes.length === currentKeyframes.length &&
38267 _this.isSameKeyframeOptions(currentOptions, options);
38268 });
38269 if (existedKeyframeOptions) {
38270 currentKeyframes.forEach(function (currentKeyframe) {
38271 var existedKeyframe = existedKeyframeOptions[0].find(function (keyframe) { return _this.isSameKeyframes(currentKeyframe, keyframe); });
38272 if (existedKeyframe) {
38273 currentKeyframe.offset;
38274 // eslint-disable-next-line @typescript-eslint/no-unused-vars
38275 currentKeyframe.easing;
38276 var rest = __rest(currentKeyframe, ["offset", "easing"]);
38277 // merge interpolated properties
38278 Object.assign(existedKeyframe, rest);
38279 }
38280 else {
38281 // append if cannot be merged
38282 existedKeyframeOptions[0].push(currentKeyframe);
38283 }
38284 });
38285 }
38286 else {
38287 // cannot be merged since options are different
38288 mergedKeyframesOptions.push(keyframesOptions_1[i]);
38289 }
38290 };
38291 // merge [{ offset: 0, cx: 1 }, { offset: 0, cy: 1 }] into { offset: 0, cx: 1, cy: 1 }
38292 for (var i = 1; i < keyframesOptions_1.length; i++) {
38293 _loop_1(i);
38294 }
38295 // restore animations for later use
38296 (_a = _this.animations).push.apply(_a, __spreadArray([], __read(mergedKeyframesOptions
38297 .map(function (_a) {
38298 var _b = __read(_a, 2), merged = _b[0], options = _b[1];
38299 // format interpolated properties, e.g. scaleX -> transform
38300 var formatted = _this.formatKeyframes(merged, child);
38301 if (formatted.length) {
38302 // console.log(child, formatted);
38303 var animation_1 = child.animate(formatted, options);
38304 if (!isNil(visibilityStartOffset) &&
38305 !isNil(visibilityEndOffset)) {
38306 child.style.visibility = 'hidden';
38307 animation_1.onframe = function () {
38308 var progress = animation_1.effect.getComputedTiming().progress;
38309 if (progress >= visibilityStartOffset &&
38310 progress < visibilityEndOffset) {
38311 child.style.visibility = 'visible';
38312 }
38313 else {
38314 child.style.visibility = 'hidden';
38315 }
38316 };
38317 }
38318 if (!_this.context.autoplay) {
38319 animation_1.pause();
38320 }
38321 return animation_1;
38322 }
38323 })
38324 .filter(function (animation) { return !!animation; })), false));
38325 }
38326 });
38327 });
38328 return wrapper;
38329 };
38330 LottieAnimation.prototype.formatKeyframes = function (keyframes, object) {
38331 keyframes.forEach(function (keyframe) {
38332 // if ('offsetPath' in keyframe) {
38333 // if (!object.style.offsetPath) {
38334 // const [ox, oy] = object.getOrigin();
38335 // (keyframe.offsetPath as AbsoluteArray).forEach((segment) => {
38336 // if (segment[0] === 'M') {
38337 // segment[1] -= ox;
38338 // segment[2] -= oy;
38339 // } else if (segment[0] === 'C') {
38340 // segment[1] -= ox;
38341 // segment[2] -= oy;
38342 // segment[3] -= ox;
38343 // segment[4] -= oy;
38344 // segment[5] -= ox;
38345 // segment[6] -= oy;
38346 // }
38347 // });
38348 // const offsetPath = new Path({
38349 // style: {
38350 // d: keyframe.offsetPath,
38351 // },
38352 // });
38353 // object.style.offsetPath = offsetPath;
38354 // console.log(offsetPath);
38355 // }
38356 // delete keyframe.offsetPath;
38357 // // offsetPath should override x/y
38358 // delete keyframe.x;
38359 // delete keyframe.y;
38360 // }
38361 // should keep transform during initialization
38362 // if (!object.style.offsetPath) {
38363 // keyframe.transform = object.style.transform || '';
38364 // }
38365 keyframe.transform = object.style.transform || '';
38366 // TODO: transforms with different easing functions will conflict
38367 if ('scaleX' in keyframe) {
38368 keyframe.transform =
38369 (keyframe.transform || '') +
38370 " scaleX(".concat(keyframe.scaleX === 0 ? eps : keyframe.scaleX, ")");
38371 delete keyframe.scaleX;
38372 }
38373 if ('scaleY' in keyframe) {
38374 keyframe.transform =
38375 (keyframe.transform || '') +
38376 " scaleY(".concat(keyframe.scaleY === 0 ? eps : keyframe.scaleY, ")");
38377 delete keyframe.scaleY;
38378 }
38379 if ('rotation' in keyframe) {
38380 keyframe.transform =
38381 (keyframe.transform || '') + " rotate(".concat(keyframe.rotation, "deg)");
38382 delete keyframe.rotation;
38383 }
38384 // TODO: skew & skewAxis
38385 // if ('skew' in keyframe) {
38386 // keyframe.transform = (keyframe.transform || '') + ` skew(${keyframe.skew}deg)`;
38387 // delete keyframe.skew;
38388 // }
38389 if ('x' in keyframe) {
38390 keyframe.transform =
38391 (keyframe.transform || '') + " translateX(".concat(keyframe.x, "px)");
38392 delete keyframe.x;
38393 }
38394 if ('y' in keyframe) {
38395 keyframe.transform =
38396 (keyframe.transform || '') + " translateY(".concat(keyframe.y, "px)");
38397 delete keyframe.y;
38398 }
38399 // { style: { opacity: 1 } }
38400 if ('style' in keyframe) {
38401 Object.keys(keyframe.style).forEach(function (name) {
38402 keyframe[name] = keyframe.style[name];
38403 });
38404 delete keyframe.style;
38405 }
38406 });
38407 // ignore empty interpolable attributes
38408 keyframes = keyframes.filter(function (keyframe) {
38409 // TODO: support negative offset
38410 keyframe.ignore; keyframe.easing; var offset = keyframe.offset, rest = __rest(keyframe, ["ignore", "easing", "offset"]);
38411 return offset >= 0 && Object.keys(rest).length > 0;
38412 // return Object.keys(rest).length > 0;
38413 });
38414 if (keyframes.length) {
38415 // padding offset = 1
38416 if (keyframes[keyframes.length - 1].offset !== 1) {
38417 keyframes.push(__assign(__assign({}, keyframes[keyframes.length - 1]), { offset: 1 }));
38418 }
38419 }
38420 // sort by offset
38421 keyframes.sort(function (a, b) { return a.offset - b.offset; });
38422 // remove empty attributes
38423 keyframes.forEach(function (keyframe) {
38424 Object.keys(keyframe).forEach(function (name) {
38425 if (keyframe[name] === '') {
38426 delete keyframe[name];
38427 }
38428 });
38429 });
38430 return keyframes;
38431 };
38432 /**
38433 * Destroy all internal displayobjects.
38434 */
38435 LottieAnimation.prototype.destroy = function () {
38436 this.displayObjects.forEach(function (object) {
38437 object.destroy();
38438 });
38439 };
38440 /**
38441 * Return the size of this animation.
38442 * @param outputSize - If provided, the size will be copied into here as width, height.
38443 */
38444 LottieAnimation.prototype.size = function (outputSize) {
38445 return { width: this.width, height: this.height };
38446 };
38447 /**
38448 * Bodymovin version
38449 */
38450 LottieAnimation.prototype.version = function () {
38451 return this.context.version;
38452 };
38453 LottieAnimation.prototype.play = function () {
38454 this.isPaused = false;
38455 this.animations.forEach(function (animation) {
38456 animation.play();
38457 });
38458 };
38459 /**
38460 * Can contain 2 numeric values that will be used as first and last frame of the animation.
38461 * @see https://github.com/airbnb/lottie-web#playsegmentssegments-forceflag
38462 */
38463 LottieAnimation.prototype.playSegments = function (segments) {
38464 var _this = this;
38465 var _a = __read(segments, 2), firstFrame = _a[0], lastFrame = _a[1];
38466 this.isPaused = false;
38467 this.animations.forEach(function (animation) {
38468 animation.currentTime = (firstFrame / _this.fps()) * 1000;
38469 var originOnFrame = animation.onframe;
38470 animation.onframe = function (e) {
38471 if (originOnFrame) {
38472 // @ts-ignore
38473 originOnFrame(e);
38474 }
38475 if (animation.currentTime >= (lastFrame / _this.fps()) * 1000) {
38476 animation.finish();
38477 if (originOnFrame) {
38478 animation.onframe = originOnFrame;
38479 }
38480 else {
38481 animation.onframe = null;
38482 }
38483 }
38484 };
38485 animation.play();
38486 });
38487 };
38488 LottieAnimation.prototype.pause = function () {
38489 this.isPaused = true;
38490 this.animations.forEach(function (animation) {
38491 animation.pause();
38492 });
38493 };
38494 /**
38495 *
38496 */
38497 LottieAnimation.prototype.togglePause = function () {
38498 if (this.isPaused) {
38499 this.play();
38500 }
38501 else {
38502 this.pause();
38503 }
38504 };
38505 /**
38506 * Goto and stop at a specific time(in seconds) or frame.
38507 * Split goToAndStop/Play into goTo & stop/play
38508 * @see https://github.com/airbnb/lottie-web
38509 */
38510 LottieAnimation.prototype.goTo = function (value, isFrame) {
38511 var _this = this;
38512 if (isFrame === void 0) { isFrame = false; }
38513 if (isFrame) {
38514 this.animations.forEach(function (animation) {
38515 animation.currentTime = (value / _this.fps()) * 1000;
38516 });
38517 }
38518 else {
38519 this.animations.forEach(function (animation) {
38520 animation.currentTime = value * 1000;
38521 });
38522 }
38523 };
38524 /**
38525 * @see https://github.com/airbnb/lottie-web#stop
38526 */
38527 LottieAnimation.prototype.stop = function () {
38528 this.animations.forEach(function (animation) {
38529 animation.finish();
38530 });
38531 };
38532 /**
38533 * 1 is normal speed.
38534 * @see https://github.com/airbnb/lottie-web#setspeedspeed
38535 */
38536 LottieAnimation.prototype.setSpeed = function (speed) {
38537 var _this = this;
38538 this.animations.forEach(function (animation) {
38539 animation.playbackRate = speed * _this.direction;
38540 });
38541 };
38542 /**
38543 * 1 is forward, -1 is reverse.
38544 * @see https://github.com/airbnb/lottie-web#setdirectiondirection
38545 */
38546 LottieAnimation.prototype.setDirection = function (direction) {
38547 this.direction = direction;
38548 this.animations.forEach(function (animation) {
38549 animation.playbackRate *= direction;
38550 });
38551 };
38552 return LottieAnimation;
38553 }());
38554
38555 /**
38556 * borrow from https://github.com/airbnb/lottie-web/blob/master/player/js/utils/DataManager.js#L40-L493
38557 */
38558 function completeLayers(layers, comps) {
38559 var layerData;
38560 var i;
38561 var len = layers.length;
38562 var j;
38563 var jLen;
38564 var k;
38565 var kLen;
38566 for (i = 0; i < len; i += 1) {
38567 layerData = layers[i];
38568 if ('ks' in layerData && !layerData.completed) {
38569 layerData.completed = true;
38570 if (layerData.tt) {
38571 layers[i - 1].td = layerData.tt;
38572 }
38573 if (layerData.hasMask) {
38574 var maskProps = layerData.masksProperties;
38575 jLen = maskProps.length;
38576 for (j = 0; j < jLen; j += 1) {
38577 if (maskProps[j].pt.k.i) {
38578 convertPathsToAbsoluteValues(maskProps[j].pt.k);
38579 }
38580 else {
38581 kLen = maskProps[j].pt.k.length;
38582 for (k = 0; k < kLen; k += 1) {
38583 if (maskProps[j].pt.k[k].s) {
38584 convertPathsToAbsoluteValues(maskProps[j].pt.k[k].s[0]);
38585 }
38586 if (maskProps[j].pt.k[k].e) {
38587 convertPathsToAbsoluteValues(maskProps[j].pt.k[k].e[0]);
38588 }
38589 }
38590 }
38591 }
38592 }
38593 if (layerData.ty === 0) {
38594 layerData.layers = findCompLayers(layerData.refId, comps);
38595 completeLayers(layerData.layers, comps);
38596 }
38597 else if (layerData.ty === 4) {
38598 completeShapes(layerData.shapes);
38599 }
38600 else if (layerData.ty === 5) {
38601 completeText(layerData);
38602 }
38603 }
38604 }
38605 }
38606 function completeChars(chars, assets) {
38607 if (chars) {
38608 var i = 0;
38609 var len = chars.length;
38610 for (i = 0; i < len; i += 1) {
38611 if (chars[i].t === 1) {
38612 // var compData = findComp(chars[i].data.refId, assets);
38613 chars[i].data.layers = findCompLayers(chars[i].data.refId, assets);
38614 // chars[i].data.ip = 0;
38615 // chars[i].data.op = 99999;
38616 // chars[i].data.st = 0;
38617 // chars[i].data.sr = 1;
38618 // chars[i].w = compData.w;
38619 // chars[i].data.ks = {
38620 // a: { k: [0, 0, 0], a: 0 },
38621 // p: { k: [0, -compData.h, 0], a: 0 },
38622 // r: { k: 0, a: 0 },
38623 // s: { k: [100, 100], a: 0 },
38624 // o: { k: 100, a: 0 },
38625 // };
38626 completeLayers(chars[i].data.layers, assets);
38627 }
38628 }
38629 }
38630 }
38631 function findComp(id, comps) {
38632 var i = 0;
38633 var len = comps.length;
38634 while (i < len) {
38635 if (comps[i].id === id) {
38636 return comps[i];
38637 }
38638 i += 1;
38639 }
38640 return null;
38641 }
38642 function findCompLayers(id, comps) {
38643 var comp = findComp(id, comps);
38644 if (comp) {
38645 if (!comp.layers.__used) {
38646 comp.layers.__used = true;
38647 return comp.layers;
38648 }
38649 return JSON.parse(JSON.stringify(comp.layers));
38650 }
38651 return null;
38652 }
38653 function completeShapes(arr) {
38654 var i;
38655 var len = arr.length;
38656 var j;
38657 var jLen;
38658 for (i = len - 1; i >= 0; i -= 1) {
38659 if (arr[i].ty === 'sh') {
38660 if (arr[i].ks.k.i) {
38661 convertPathsToAbsoluteValues(arr[i].ks.k);
38662 }
38663 else {
38664 jLen = arr[i].ks.k.length;
38665 for (j = 0; j < jLen; j += 1) {
38666 if (arr[i].ks.k[j].s) {
38667 convertPathsToAbsoluteValues(arr[i].ks.k[j].s[0]);
38668 }
38669 if (arr[i].ks.k[j].e) {
38670 convertPathsToAbsoluteValues(arr[i].ks.k[j].e[0]);
38671 }
38672 }
38673 }
38674 }
38675 else if (arr[i].ty === 'gr') {
38676 completeShapes(arr[i].it);
38677 }
38678 }
38679 }
38680 function convertPathsToAbsoluteValues(path) {
38681 var i;
38682 var len = path.i.length;
38683 for (i = 0; i < len; i += 1) {
38684 path.i[i][0] += path.v[i][0];
38685 path.i[i][1] += path.v[i][1];
38686 path.o[i][0] += path.v[i][0];
38687 path.o[i][1] += path.v[i][1];
38688 }
38689 }
38690 function checkVersion(minimum, animVersionString) {
38691 var animVersion = animVersionString ? animVersionString.split('.') : [100, 100, 100];
38692 if (minimum[0] > animVersion[0]) {
38693 return true;
38694 }
38695 if (animVersion[0] > minimum[0]) {
38696 return false;
38697 }
38698 if (minimum[1] > animVersion[1]) {
38699 return true;
38700 }
38701 if (animVersion[1] > minimum[1]) {
38702 return false;
38703 }
38704 if (minimum[2] > animVersion[2]) {
38705 return true;
38706 }
38707 if (animVersion[2] > minimum[2]) {
38708 return false;
38709 }
38710 return null;
38711 }
38712 var checkText = (function () {
38713 var minimumVersion = [4, 4, 14];
38714 function updateTextLayer(textLayer) {
38715 var documentData = textLayer.t.d;
38716 textLayer.t.d = {
38717 k: [
38718 {
38719 s: documentData,
38720 t: 0,
38721 },
38722 ],
38723 };
38724 }
38725 function iterateLayers(layers) {
38726 var i;
38727 var len = layers.length;
38728 for (i = 0; i < len; i += 1) {
38729 if (layers[i].ty === 5) {
38730 updateTextLayer(layers[i]);
38731 }
38732 }
38733 }
38734 return function (animationData) {
38735 if (checkVersion(minimumVersion, animationData.v)) {
38736 iterateLayers(animationData.layers);
38737 if (animationData.assets) {
38738 var i = void 0;
38739 var len = animationData.assets.length;
38740 for (i = 0; i < len; i += 1) {
38741 if (animationData.assets[i].layers) {
38742 iterateLayers(animationData.assets[i].layers);
38743 }
38744 }
38745 }
38746 }
38747 };
38748 })();
38749 var checkChars = (function () {
38750 var minimumVersion = [4, 7, 99];
38751 return function (animationData) {
38752 if (animationData.chars && !checkVersion(minimumVersion, animationData.v)) {
38753 var i = void 0;
38754 var len = animationData.chars.length;
38755 for (i = 0; i < len; i += 1) {
38756 var charData = animationData.chars[i];
38757 if (charData.data && charData.data.shapes) {
38758 completeShapes(charData.data.shapes);
38759 charData.data.ip = 0;
38760 charData.data.op = 99999;
38761 charData.data.st = 0;
38762 charData.data.sr = 1;
38763 charData.data.ks = {
38764 p: { k: [0, 0], a: 0 },
38765 s: { k: [100, 100], a: 0 },
38766 a: { k: [0, 0], a: 0 },
38767 r: { k: 0, a: 0 },
38768 o: { k: 100, a: 0 },
38769 };
38770 if (!animationData.chars[i].t) {
38771 charData.data.shapes.push({
38772 ty: 'no',
38773 });
38774 charData.data.shapes[0].it.push({
38775 p: { k: [0, 0], a: 0 },
38776 s: { k: [100, 100], a: 0 },
38777 a: { k: [0, 0], a: 0 },
38778 r: { k: 0, a: 0 },
38779 o: { k: 100, a: 0 },
38780 sk: { k: 0, a: 0 },
38781 sa: { k: 0, a: 0 },
38782 ty: 'tr',
38783 });
38784 }
38785 }
38786 }
38787 }
38788 };
38789 })();
38790 var checkPathProperties = (function () {
38791 var minimumVersion = [5, 7, 15];
38792 function updateTextLayer(textLayer) {
38793 var pathData = textLayer.t.p;
38794 if (typeof pathData.a === 'number') {
38795 pathData.a = {
38796 a: 0,
38797 k: pathData.a,
38798 };
38799 }
38800 if (typeof pathData.p === 'number') {
38801 pathData.p = {
38802 a: 0,
38803 k: pathData.p,
38804 };
38805 }
38806 if (typeof pathData.r === 'number') {
38807 pathData.r = {
38808 a: 0,
38809 k: pathData.r,
38810 };
38811 }
38812 }
38813 function iterateLayers(layers) {
38814 var i;
38815 var len = layers.length;
38816 for (i = 0; i < len; i += 1) {
38817 if (layers[i].ty === 5) {
38818 updateTextLayer(layers[i]);
38819 }
38820 }
38821 }
38822 return function (animationData) {
38823 if (checkVersion(minimumVersion, animationData.v)) {
38824 iterateLayers(animationData.layers);
38825 if (animationData.assets) {
38826 var i = void 0;
38827 var len = animationData.assets.length;
38828 for (i = 0; i < len; i += 1) {
38829 if (animationData.assets[i].layers) {
38830 iterateLayers(animationData.assets[i].layers);
38831 }
38832 }
38833 }
38834 }
38835 };
38836 })();
38837 var checkColors = (function () {
38838 var minimumVersion = [4, 1, 9];
38839 function iterateShapes(shapes) {
38840 var i;
38841 var len = shapes.length;
38842 var j;
38843 var jLen;
38844 for (i = 0; i < len; i += 1) {
38845 if (shapes[i].ty === 'gr') {
38846 iterateShapes(shapes[i].it);
38847 }
38848 else if (shapes[i].ty === 'fl' || shapes[i].ty === 'st') {
38849 if (shapes[i].c.k && shapes[i].c.k[0].i) {
38850 jLen = shapes[i].c.k.length;
38851 for (j = 0; j < jLen; j += 1) {
38852 if (shapes[i].c.k[j].s) {
38853 shapes[i].c.k[j].s[0] /= 255;
38854 shapes[i].c.k[j].s[1] /= 255;
38855 shapes[i].c.k[j].s[2] /= 255;
38856 shapes[i].c.k[j].s[3] /= 255;
38857 }
38858 if (shapes[i].c.k[j].e) {
38859 shapes[i].c.k[j].e[0] /= 255;
38860 shapes[i].c.k[j].e[1] /= 255;
38861 shapes[i].c.k[j].e[2] /= 255;
38862 shapes[i].c.k[j].e[3] /= 255;
38863 }
38864 }
38865 }
38866 else {
38867 shapes[i].c.k[0] /= 255;
38868 shapes[i].c.k[1] /= 255;
38869 shapes[i].c.k[2] /= 255;
38870 shapes[i].c.k[3] /= 255;
38871 }
38872 }
38873 }
38874 }
38875 function iterateLayers(layers) {
38876 var i;
38877 var len = layers.length;
38878 for (i = 0; i < len; i += 1) {
38879 if (layers[i].ty === 4) {
38880 iterateShapes(layers[i].shapes);
38881 }
38882 }
38883 }
38884 return function (animationData) {
38885 if (checkVersion(minimumVersion, animationData.v)) {
38886 iterateLayers(animationData.layers);
38887 if (animationData.assets) {
38888 var i = void 0;
38889 var len = animationData.assets.length;
38890 for (i = 0; i < len; i += 1) {
38891 if (animationData.assets[i].layers) {
38892 iterateLayers(animationData.assets[i].layers);
38893 }
38894 }
38895 }
38896 }
38897 };
38898 })();
38899 var checkShapes = (function () {
38900 var minimumVersion = [4, 4, 18];
38901 function completeClosingShapes(arr) {
38902 var i;
38903 var len = arr.length;
38904 var j;
38905 var jLen;
38906 for (i = len - 1; i >= 0; i -= 1) {
38907 if (arr[i].ty === 'sh') {
38908 if (arr[i].ks.k.i) {
38909 arr[i].ks.k.c = arr[i].closed;
38910 }
38911 else {
38912 jLen = arr[i].ks.k.length;
38913 for (j = 0; j < jLen; j += 1) {
38914 if (arr[i].ks.k[j].s) {
38915 arr[i].ks.k[j].s[0].c = arr[i].closed;
38916 }
38917 if (arr[i].ks.k[j].e) {
38918 arr[i].ks.k[j].e[0].c = arr[i].closed;
38919 }
38920 }
38921 }
38922 }
38923 else if (arr[i].ty === 'gr') {
38924 completeClosingShapes(arr[i].it);
38925 }
38926 }
38927 }
38928 function iterateLayers(layers) {
38929 var layerData;
38930 var i;
38931 var len = layers.length;
38932 var j;
38933 var jLen;
38934 var k;
38935 var kLen;
38936 for (i = 0; i < len; i += 1) {
38937 layerData = layers[i];
38938 if (layerData.hasMask) {
38939 var maskProps = layerData.masksProperties;
38940 jLen = maskProps.length;
38941 for (j = 0; j < jLen; j += 1) {
38942 if (maskProps[j].pt.k.i) {
38943 maskProps[j].pt.k.c = maskProps[j].cl;
38944 }
38945 else {
38946 kLen = maskProps[j].pt.k.length;
38947 for (k = 0; k < kLen; k += 1) {
38948 if (maskProps[j].pt.k[k].s) {
38949 maskProps[j].pt.k[k].s[0].c = maskProps[j].cl;
38950 }
38951 if (maskProps[j].pt.k[k].e) {
38952 maskProps[j].pt.k[k].e[0].c = maskProps[j].cl;
38953 }
38954 }
38955 }
38956 }
38957 }
38958 if (layerData.ty === 4) {
38959 completeClosingShapes(layerData.shapes);
38960 }
38961 }
38962 }
38963 return function (animationData) {
38964 if (checkVersion(minimumVersion, animationData.v)) {
38965 iterateLayers(animationData.layers);
38966 if (animationData.assets) {
38967 var i = void 0;
38968 var len = animationData.assets.length;
38969 for (i = 0; i < len; i += 1) {
38970 if (animationData.assets[i].layers) {
38971 iterateLayers(animationData.assets[i].layers);
38972 }
38973 }
38974 }
38975 }
38976 };
38977 })();
38978 function completeData(animationData) {
38979 if (animationData.__complete) {
38980 return;
38981 }
38982 checkColors(animationData);
38983 checkText(animationData);
38984 checkChars(animationData);
38985 checkPathProperties(animationData);
38986 checkShapes(animationData);
38987 completeLayers(animationData.layers, animationData.assets);
38988 completeChars(animationData.chars, animationData.assets);
38989 animationData.__complete = true;
38990 }
38991 function completeText(data) {
38992 if (data.t.a.length === 0 && !('m' in data.t.p)) ;
38993 }
38994
38995 /**
38996 * https://lottiefiles.github.io/lottie-docs/constants/
38997 */
38998 var BlendMode;
38999 (function (BlendMode) {
39000 BlendMode[BlendMode["Normal"] = 0] = "Normal";
39001 BlendMode[BlendMode["Multiply"] = 1] = "Multiply";
39002 BlendMode[BlendMode["Screen"] = 2] = "Screen";
39003 BlendMode[BlendMode["Overlay"] = 3] = "Overlay";
39004 BlendMode[BlendMode["Darken"] = 4] = "Darken";
39005 BlendMode[BlendMode["Lighten"] = 5] = "Lighten";
39006 BlendMode[BlendMode["ColorDodge"] = 6] = "ColorDodge";
39007 BlendMode[BlendMode["ColorBurn"] = 7] = "ColorBurn";
39008 BlendMode[BlendMode["HardLight"] = 8] = "HardLight";
39009 BlendMode[BlendMode["SoftLight"] = 9] = "SoftLight";
39010 BlendMode[BlendMode["Difference"] = 10] = "Difference";
39011 BlendMode[BlendMode["Exclusion"] = 11] = "Exclusion";
39012 BlendMode[BlendMode["Hue"] = 12] = "Hue";
39013 BlendMode[BlendMode["Saturation"] = 13] = "Saturation";
39014 BlendMode[BlendMode["Color"] = 14] = "Color";
39015 BlendMode[BlendMode["Luminosity"] = 15] = "Luminosity";
39016 BlendMode[BlendMode["Add"] = 16] = "Add";
39017 BlendMode[BlendMode["HardMix"] = 17] = "HardMix";
39018 })(BlendMode || (BlendMode = {}));
39019 /**
39020 * @see https://lottiefiles.github.io/lottie-docs/constants/#mattemode
39021 */
39022 var MatteMode;
39023 (function (MatteMode) {
39024 MatteMode[MatteMode["Normal"] = 0] = "Normal";
39025 MatteMode[MatteMode["Alpha"] = 1] = "Alpha";
39026 MatteMode[MatteMode["InvertedAlpha"] = 2] = "InvertedAlpha";
39027 MatteMode[MatteMode["Luma"] = 3] = "Luma";
39028 MatteMode[MatteMode["InvertedLuma"] = 4] = "InvertedLuma";
39029 })(MatteMode || (MatteMode = {}));
39030 var Layer3DMode;
39031 (function (Layer3DMode) {
39032 Layer3DMode[Layer3DMode["Off"] = 0] = "Off";
39033 Layer3DMode[Layer3DMode["On"] = 1] = "On";
39034 })(Layer3DMode || (Layer3DMode = {}));
39035 var AutoOrientMode;
39036 (function (AutoOrientMode) {
39037 AutoOrientMode[AutoOrientMode["Off"] = 0] = "Off";
39038 AutoOrientMode[AutoOrientMode["On"] = 1] = "On";
39039 })(AutoOrientMode || (AutoOrientMode = {}));
39040 var EffectValueType;
39041 (function (EffectValueType) {
39042 EffectValueType[EffectValueType["Number"] = 0] = "Number";
39043 EffectValueType[EffectValueType["Color"] = 2] = "Color";
39044 EffectValueType[EffectValueType["MultiDimensional"] = 3] = "MultiDimensional";
39045 EffectValueType[EffectValueType["Boolean"] = 7] = "Boolean";
39046 })(EffectValueType || (EffectValueType = {}));
39047 var EffectType;
39048 (function (EffectType) {
39049 EffectType[EffectType["Transform"] = 5] = "Transform";
39050 EffectType[EffectType["DropShadow"] = 25] = "DropShadow";
39051 })(EffectType || (EffectType = {}));
39052 var MaskMode;
39053 (function (MaskMode) {
39054 MaskMode["No"] = "n";
39055 MaskMode["Add"] = "a";
39056 MaskMode["Subtract"] = "s";
39057 MaskMode["Intersect"] = "i";
39058 MaskMode["Lighten"] = "l";
39059 MaskMode["Darken"] = "d";
39060 MaskMode["Difference"] = "f";
39061 })(MaskMode || (MaskMode = {}));
39062 var LayerType;
39063 (function (LayerType) {
39064 LayerType[LayerType["precomp"] = 0] = "precomp";
39065 LayerType[LayerType["solid"] = 1] = "solid";
39066 LayerType[LayerType["image"] = 2] = "image";
39067 LayerType[LayerType["null"] = 3] = "null";
39068 LayerType[LayerType["shape"] = 4] = "shape";
39069 LayerType[LayerType["text"] = 5] = "text";
39070 LayerType[LayerType["audio"] = 6] = "audio";
39071 LayerType[LayerType["pholderVideo"] = 7] = "pholderVideo";
39072 LayerType[LayerType["imageSeq"] = 8] = "imageSeq";
39073 LayerType[LayerType["video"] = 9] = "video";
39074 LayerType[LayerType["pholderStill"] = 10] = "pholderStill";
39075 LayerType[LayerType["guide"] = 11] = "guide";
39076 LayerType[LayerType["adjustment"] = 12] = "adjustment";
39077 LayerType[LayerType["camera"] = 13] = "camera";
39078 LayerType[LayerType["light"] = 14] = "light";
39079 LayerType[LayerType["data"] = 15] = "data";
39080 })(LayerType || (LayerType = {}));
39081 var TextJustify;
39082 (function (TextJustify) {
39083 TextJustify[TextJustify["Left"] = 0] = "Left";
39084 TextJustify[TextJustify["Right"] = 1] = "Right";
39085 TextJustify[TextJustify["Center"] = 2] = "Center";
39086 })(TextJustify || (TextJustify = {}));
39087 var VerticalJustify;
39088 (function (VerticalJustify) {
39089 VerticalJustify[VerticalJustify["Top"] = 0] = "Top";
39090 VerticalJustify[VerticalJustify["Center"] = 1] = "Center";
39091 VerticalJustify[VerticalJustify["Bottom"] = 2] = "Bottom";
39092 })(VerticalJustify || (VerticalJustify = {}));
39093 var RangeSelectorDomain;
39094 (function (RangeSelectorDomain) {
39095 RangeSelectorDomain[RangeSelectorDomain["Characters"] = 1] = "Characters";
39096 RangeSelectorDomain[RangeSelectorDomain["CharactersExcludingSpaces"] = 2] = "CharactersExcludingSpaces";
39097 RangeSelectorDomain[RangeSelectorDomain["Words"] = 3] = "Words";
39098 RangeSelectorDomain[RangeSelectorDomain["Lines"] = 4] = "Lines";
39099 })(RangeSelectorDomain || (RangeSelectorDomain = {}));
39100 var RangeSelectorShape;
39101 (function (RangeSelectorShape) {
39102 RangeSelectorShape[RangeSelectorShape["Square"] = 1] = "Square";
39103 RangeSelectorShape[RangeSelectorShape["RampUp"] = 2] = "RampUp";
39104 RangeSelectorShape[RangeSelectorShape["RampDown"] = 3] = "RampDown";
39105 RangeSelectorShape[RangeSelectorShape["Triangle"] = 4] = "Triangle";
39106 RangeSelectorShape[RangeSelectorShape["Round"] = 5] = "Round";
39107 RangeSelectorShape[RangeSelectorShape["Smooth"] = 6] = "Smooth";
39108 })(RangeSelectorShape || (RangeSelectorShape = {}));
39109 var RangeSelectorUnits;
39110 (function (RangeSelectorUnits) {
39111 RangeSelectorUnits[RangeSelectorUnits["Percentage"] = 1] = "Percentage";
39112 RangeSelectorUnits[RangeSelectorUnits["Index"] = 2] = "Index";
39113 })(RangeSelectorUnits || (RangeSelectorUnits = {}));
39114 var RangeSelectorMode;
39115 (function (RangeSelectorMode) {
39116 RangeSelectorMode[RangeSelectorMode["Add"] = 1] = "Add";
39117 RangeSelectorMode[RangeSelectorMode["Subtract"] = 2] = "Subtract";
39118 RangeSelectorMode[RangeSelectorMode["Intersect"] = 3] = "Intersect";
39119 RangeSelectorMode[RangeSelectorMode["Min"] = 4] = "Min";
39120 RangeSelectorMode[RangeSelectorMode["Max"] = 5] = "Max";
39121 RangeSelectorMode[RangeSelectorMode["Difference"] = 6] = "Difference";
39122 })(RangeSelectorMode || (RangeSelectorMode = {}));
39123 /**
39124 * @see https://lottiefiles.github.io/lottie-docs/shapes/#shape-types
39125 */
39126 var ShapeType;
39127 (function (ShapeType) {
39128 ShapeType["Rectangle"] = "rc";
39129 ShapeType["Ellipse"] = "el";
39130 ShapeType["PolyStar"] = "sr";
39131 ShapeType["Path"] = "sh";
39132 ShapeType["Fill"] = "fl";
39133 ShapeType["Stroke"] = "st";
39134 ShapeType["GradientFill"] = "gf";
39135 ShapeType["GradientStroke"] = "gs";
39136 ShapeType["NoStyle"] = "no";
39137 ShapeType["Group"] = "gr";
39138 ShapeType["Transform"] = "tr";
39139 ShapeType["Repeater"] = "rp";
39140 ShapeType["Trim"] = "tm";
39141 ShapeType["RoundedCorners"] = "rd";
39142 ShapeType["PuckerOrBloat"] = "pb";
39143 ShapeType["Merge"] = "mm";
39144 ShapeType["Twist"] = "tw";
39145 ShapeType["OffsetPath"] = "op";
39146 ShapeType["ZigZag"] = "zz";
39147 })(ShapeType || (ShapeType = {}));
39148 /**
39149 * @see https://lottiefiles.github.io/lottie-docs/constants/#fillrule
39150 */
39151 var FillRule;
39152 (function (FillRule) {
39153 FillRule[FillRule["NonZero"] = 1] = "NonZero";
39154 FillRule[FillRule["EvenOdd"] = 2] = "EvenOdd";
39155 })(FillRule || (FillRule = {}));
39156 /**
39157 * @see https://lottiefiles.github.io/lottie-docs/constants/#linejoin
39158 */
39159 var LineJoin;
39160 (function (LineJoin) {
39161 LineJoin[LineJoin["Miter"] = 1] = "Miter";
39162 LineJoin[LineJoin["Round"] = 2] = "Round";
39163 LineJoin[LineJoin["Bevel"] = 3] = "Bevel";
39164 })(LineJoin || (LineJoin = {}));
39165 /**
39166 * @see https://lottiefiles.github.io/lottie-docs/constants/#linecap
39167 */
39168 var LineCap;
39169 (function (LineCap) {
39170 LineCap[LineCap["Butt"] = 1] = "Butt";
39171 LineCap[LineCap["Round"] = 2] = "Round";
39172 LineCap[LineCap["Square"] = 3] = "Square";
39173 })(LineCap || (LineCap = {}));
39174 /**
39175 * @see https://lottiefiles.github.io/lottie-docs/constants/#gradienttype
39176 */
39177 var GradientType$1;
39178 (function (GradientType) {
39179 GradientType[GradientType["Linear"] = 1] = "Linear";
39180 GradientType[GradientType["Radial"] = 2] = "Radial";
39181 })(GradientType$1 || (GradientType$1 = {}));
39182 var FontPathOrigin;
39183 (function (FontPathOrigin) {
39184 FontPathOrigin[FontPathOrigin["CssUrl"] = 1] = "CssUrl";
39185 FontPathOrigin[FontPathOrigin["ScriptUrl"] = 2] = "ScriptUrl";
39186 FontPathOrigin[FontPathOrigin["FontUrl"] = 3] = "FontUrl";
39187 })(FontPathOrigin || (FontPathOrigin = {}));
39188
39189 var ParseContext = /** @class */ (function () {
39190 function ParseContext() {
39191 this.frameTime = 1000 / 30;
39192 this.startFrame = 0;
39193 this.autoplay = false;
39194 this.fill = 'auto';
39195 this.iterations = 0;
39196 this.assetsMap = new Map();
39197 }
39198 return ParseContext;
39199 }());
39200 function isNumberArray(val) {
39201 return Array.isArray(val) && typeof val[0] === 'number';
39202 }
39203 function isMultiDimensionalValue(val) {
39204 return isNumberArray(val === null || val === void 0 ? void 0 : val.k);
39205 }
39206 function isMultiDimensionalKeyframedValue(val) {
39207 var k = val === null || val === void 0 ? void 0 : val.k;
39208 return Array.isArray(k) && k[0].t !== undefined && isNumberArray(k[0].s);
39209 }
39210 function isValue(val) {
39211 // TODO is [100] sort of value?
39212 return typeof (val === null || val === void 0 ? void 0 : val.k) === 'number';
39213 }
39214 function isKeyframedValue(val) {
39215 var k = val === null || val === void 0 ? void 0 : val.k;
39216 return Array.isArray(k) && k[0].t !== undefined && typeof k[0].s === 'number';
39217 }
39218 function toColorString(val) {
39219 var opacity = getMultiDimensionValue(val, 3);
39220 return "rgba(".concat([
39221 Math.round(getMultiDimensionValue(val, 0) * 255),
39222 Math.round(getMultiDimensionValue(val, 1) * 255),
39223 Math.round(getMultiDimensionValue(val, 2) * 255),
39224 !isNil(opacity) ? opacity : 1,
39225 ].join(','), ")");
39226 }
39227 function getMultiDimensionValue(val, dimIndex) {
39228 return val != null
39229 ? typeof val === 'number'
39230 ? val
39231 : val[dimIndex || 0]
39232 : NaN;
39233 }
39234 /**
39235 * @see https://lottiefiles.github.io/lottie-docs/concepts/#easing-handles
39236 */
39237 function getMultiDimensionEasingBezierString(kf, nextKf, dimIndex) {
39238 var _a, _b, _c, _d;
39239 var bezierEasing = [];
39240 bezierEasing.push((((_a = kf.o) === null || _a === void 0 ? void 0 : _a.x) &&
39241 (getMultiDimensionValue(kf.o.x, dimIndex) ||
39242 getMultiDimensionValue(kf.o.x, 0))) ||
39243 0, (((_b = kf.o) === null || _b === void 0 ? void 0 : _b.y) &&
39244 (getMultiDimensionValue(kf.o.y, dimIndex) ||
39245 getMultiDimensionValue(kf.o.y, 0))) ||
39246 0, (((_c = kf.i) === null || _c === void 0 ? void 0 : _c.x) &&
39247 (getMultiDimensionValue(kf.i.x, dimIndex) ||
39248 getMultiDimensionValue(kf.i.x, 0))) ||
39249 1, (((_d = kf.i) === null || _d === void 0 ? void 0 : _d.y) &&
39250 (getMultiDimensionValue(kf.i.y, dimIndex) ||
39251 getMultiDimensionValue(kf.i.y, 0))) ||
39252 1);
39253 // linear by default
39254 if (!(bezierEasing[0] === 0 &&
39255 bezierEasing[1] === 0 &&
39256 bezierEasing[2] === 1 &&
39257 bezierEasing[3] === 1)) {
39258 return "cubic-bezier(".concat(bezierEasing.join(','), ")");
39259 }
39260 return;
39261 }
39262 /**
39263 * @see https://lottiefiles.github.io/lottie-docs/concepts/#keyframe
39264 */
39265 function parseKeyframe(kfs, bezierEasingDimIndex, context, setVal) {
39266 var kfsLen = kfs.length;
39267 // const offset = context.layerStartTime;
39268 var duration = context.endFrame - context.startFrame;
39269 var out = {
39270 duration: 0,
39271 delay: 0,
39272 keyframes: [],
39273 };
39274 var prevKf;
39275 for (var i = 0; i < kfsLen; i++) {
39276 var kf = kfs[i];
39277 var nextKf = kfs[i + 1];
39278 // If h is present and it's 1, you don't need i and o,
39279 // as the property will keep the same value until the next keyframe.
39280 var isDiscrete = kf.h === 1;
39281 var offset = (kf.t + context.layerOffsetTime - context.startFrame) / duration;
39282 var outKeyframe = {
39283 offset: offset,
39284 };
39285 if (!isDiscrete) {
39286 outKeyframe.easing = getMultiDimensionEasingBezierString(kf, nextKf, bezierEasingDimIndex);
39287 }
39288 // Use end state of later frame if start state not exits.
39289 // @see https://lottiefiles.github.io/lottie-docs/concepts/#old-lottie-keyframes
39290 var startVal = kf.s || (prevKf === null || prevKf === void 0 ? void 0 : prevKf.e);
39291 if (startVal) {
39292 setVal(outKeyframe, startVal);
39293 }
39294 if (outKeyframe.offset > 0 && i === 0) {
39295 // Set initial
39296 var initialKeyframe = {
39297 offset: 0,
39298 };
39299 if (startVal) {
39300 setVal(initialKeyframe, startVal);
39301 }
39302 out.keyframes.push(initialKeyframe);
39303 }
39304 out.keyframes.push(outKeyframe);
39305 if (isDiscrete && nextKf) {
39306 // Use two keyframe to simulate the discrete animation.
39307 var extraKeyframe = {
39308 offset: Math.max((nextKf.t + context.layerOffsetTime - context.startFrame) / duration, 0),
39309 };
39310 setVal(extraKeyframe, startVal);
39311 out.keyframes.push(extraKeyframe);
39312 }
39313 prevKf = kf;
39314 }
39315 if (kfsLen) {
39316 out.duration = context.frameTime * duration;
39317 }
39318 return out;
39319 }
39320 function parseOffsetKeyframe(kfs, targetPropName, propNames, keyframeAnimations, context, convertVal) {
39321 var _loop_1 = function (dimIndex) {
39322 var propName = propNames[dimIndex];
39323 var keyframeAnim = parseKeyframe(kfs, dimIndex, context, function (outKeyframe, startVal) {
39324 var val = getMultiDimensionValue(startVal, dimIndex);
39325 if (convertVal) {
39326 val = convertVal(val);
39327 }
39328 (targetPropName
39329 ? (outKeyframe[targetPropName] = {})
39330 : outKeyframe)[propName] = val;
39331 });
39332 // moving position around a curved path
39333 var needOffsetPath = kfs.some(function (kf) { return kf.ti && kf.to; });
39334 if (needOffsetPath) {
39335 var offsetPath_1 = [];
39336 kfs.forEach(function (kf, i) {
39337 keyframeAnim.keyframes[i].offsetPath = offsetPath_1;
39338 // convert to & ti(Tangent for values (eg: moving position around a curved path)) to offsetPath & offsetDistance
39339 // @see https://lottiefiles.github.io/lottie-docs/concepts/#animated-position
39340 if (kf.ti && kf.to) {
39341 if (i === 0) {
39342 offsetPath_1.push(['M', kf.s[0], kf.s[1]]);
39343 }
39344 keyframeAnim.keyframes[i].segmentLength = getTotalLength(offsetPath_1);
39345 // @see https://lottiefiles.github.io/lottie-docs/concepts/#bezier
39346 // The nth bezier segment is defined as:
39347 // v[n], v[n]+o[n], v[n+1]+i[n+1], v[n+1]
39348 offsetPath_1.push([
39349 'C',
39350 kf.s[0] + kf.to[0],
39351 kf.s[1] + kf.to[1],
39352 kf.s[0] + kf.ti[0],
39353 kf.s[1] + kf.ti[1],
39354 kf.e[0],
39355 kf.e[1],
39356 ]);
39357 }
39358 });
39359 // calculate offsetDistance: segmentLength / totalLength
39360 var totalLength_1 = getTotalLength(offsetPath_1);
39361 keyframeAnim.keyframes.forEach(function (kf) {
39362 kf.offsetDistance = isNil(kf.segmentLength)
39363 ? 1
39364 : kf.segmentLength / totalLength_1;
39365 delete kf.segmentLength;
39366 });
39367 }
39368 if (keyframeAnim.keyframes.length) {
39369 keyframeAnimations.push(keyframeAnim);
39370 }
39371 };
39372 for (var dimIndex = 0; dimIndex < propNames.length; dimIndex++) {
39373 _loop_1(dimIndex);
39374 }
39375 }
39376 function parseColorOffsetKeyframe(kfs, targetPropName, propName, keyframeAnimations, context) {
39377 var keyframeAnim = parseKeyframe(kfs, 0, context, function (outKeyframe, startVal) {
39378 (targetPropName
39379 ? (outKeyframe[targetPropName] = {})
39380 : outKeyframe)[propName] = toColorString(startVal);
39381 });
39382 if (keyframeAnim.keyframes.length) {
39383 keyframeAnimations.push(keyframeAnim);
39384 }
39385 }
39386 function parseValue(lottieVal, attrs, targetPropName, propNames, animations, context, convertVal) {
39387 if (targetPropName) {
39388 attrs[targetPropName] = attrs[targetPropName] || {};
39389 }
39390 var target = targetPropName ? attrs[targetPropName] : attrs;
39391 if (isValue(lottieVal)) {
39392 var val = lottieVal.k;
39393 target[propNames[0]] = convertVal ? convertVal(val) : val;
39394 }
39395 else if (isKeyframedValue(lottieVal)) {
39396 parseOffsetKeyframe(lottieVal.k, targetPropName, propNames, animations, context, convertVal);
39397 }
39398 else if (isMultiDimensionalValue(lottieVal)) {
39399 for (var i = 0; i < propNames.length; i++) {
39400 var val = getMultiDimensionValue(lottieVal.k, i);
39401 target[propNames[i]] = convertVal ? convertVal(val) : val;
39402 }
39403 }
39404 else if (isMultiDimensionalKeyframedValue(lottieVal)) {
39405 // TODO Merge dimensions
39406 parseOffsetKeyframe(lottieVal.k, targetPropName, propNames, animations, context, convertVal);
39407 }
39408 }
39409 /**
39410 * @see https://lottiefiles.github.io/lottie-docs/concepts/#transform
39411 */
39412 function parseTransforms(ks, attrs, animations, context, targetProp, transformProps) {
39413 if (targetProp === void 0) { targetProp = ''; }
39414 if (transformProps === void 0) { transformProps = {
39415 x: 'x',
39416 y: 'y',
39417 rotation: 'rotation',
39418 scaleX: 'scaleX',
39419 scaleY: 'scaleY',
39420 anchorX: 'anchorX',
39421 anchorY: 'anchorY',
39422 skew: 'skew',
39423 skewAxis: 'skewAxis',
39424 }; }
39425 // @see https://lottiefiles.github.io/lottie-docs/concepts/#split-vector
39426 if (ks.p.s) {
39427 parseValue(ks.p.x, attrs, targetProp, [transformProps.x], animations, context);
39428 parseValue(ks.p.y, attrs, targetProp, [transformProps.y], animations, context);
39429 }
39430 else {
39431 parseValue(ks.p, attrs, targetProp, [transformProps.x, transformProps.y], animations, context);
39432 }
39433 parseValue(ks.s, attrs, targetProp, [transformProps.scaleX, transformProps.scaleY], animations, context, function (val) { return val / 100; });
39434 parseValue(ks.r, attrs, targetProp, [transformProps.rotation], animations, context);
39435 parseValue(ks.a, attrs, targetProp, [transformProps.anchorX, transformProps.anchorY], animations, context);
39436 parseValue(ks.sk, attrs, targetProp, [transformProps.skew], animations, context);
39437 parseValue(ks.sa, attrs, targetProp, [transformProps.skewAxis], animations, context);
39438 }
39439 function isGradientFillOrStroke(fl) {
39440 return fl.g && fl.s && fl.e;
39441 }
39442 function convertColorStops(arr, count) {
39443 var colorStops = [];
39444 for (var i = 0; i < count * 4;) {
39445 var offset = arr[i++];
39446 var r = Math.round(arr[i++] * 255);
39447 var g = Math.round(arr[i++] * 255);
39448 var b = Math.round(arr[i++] * 255);
39449 colorStops.push({
39450 offset: offset,
39451 color: "rgb(".concat(r, ", ").concat(g, ", ").concat(b, ")"),
39452 });
39453 }
39454 return colorStops;
39455 }
39456 function joinColorStops(colorStops) {
39457 return "".concat(colorStops
39458 .map(function (_a) {
39459 var offset = _a.offset, color = _a.color;
39460 return "".concat(color, " ").concat(offset * 100, "%");
39461 })
39462 .join(', '));
39463 }
39464 /**
39465 * TODO:
39466 * * Transition
39467 * * Highlight length & angle in Radial Gradient
39468 *
39469 * @see https://lottiefiles.github.io/lottie-docs/concepts/#gradients
39470 * @see https://lottiefiles.github.io/lottie-docs/shapes/#gradients
39471 */
39472 function parseGradient$2(shape) {
39473 var colorArr = shape.g.k.k;
39474 var colorStops = convertColorStops(colorArr, shape.g.p);
39475 // @see https://lottiefiles.github.io/lottie-docs/constants/#gradienttype
39476 if (shape.t === GradientType$1.Linear) {
39477 var angle = rad2deg(Math.atan2(shape.e.k[1] - shape.s.k[1], shape.e.k[0] - shape.s.k[0]));
39478 // @see https://g-next.antv.vision/zh/docs/api/css/css-properties-values-api#linear-gradient
39479 return "linear-gradient(".concat(angle, "deg, ").concat(joinColorStops(colorStops), ")");
39480 }
39481 else if (shape.t === GradientType$1.Radial) {
39482 // TODO: highlight length & angle (h & a)
39483 // Highlight Length, as a percentage between s and e
39484 // Highlight Angle, relative to the direction from s to e
39485 var size = distanceSquareRoot(shape.e.k, shape.s.k);
39486 // @see https://g-next.antv.vision/zh/docs/api/css/css-properties-values-api#radial-gradient
39487 return "radial-gradient(circle ".concat(size, "px at ").concat(shape.s.k[0], "px ").concat(shape.s.k[1], "px, ").concat(joinColorStops(colorStops), ")");
39488 }
39489 else {
39490 // Invalid gradient
39491 return '#000';
39492 }
39493 }
39494 function parseFill(fl, attrs, animations, context) {
39495 attrs.style = attrs.style || {};
39496 // Color
39497 if (isGradientFillOrStroke(fl)) {
39498 attrs.style.fill = parseGradient$2(fl);
39499 }
39500 else {
39501 if (isMultiDimensionalValue(fl.c)) {
39502 attrs.style.fill = toColorString(fl.c.k);
39503 }
39504 else if (isMultiDimensionalKeyframedValue(fl.c)) {
39505 parseColorOffsetKeyframe(fl.c.k, 'style', 'fill', animations, context);
39506 }
39507 }
39508 // FillRule @see https://lottiefiles.github.io/lottie-docs/constants/#fillrule
39509 attrs.style.fillRule =
39510 fl.r === FillRule.EvenOdd ? 'evenodd' : 'nonzero';
39511 // Opacity
39512 parseValue(fl.o, attrs, 'style', ['fillOpacity'], animations, context, function (opacity) { return opacity / 100; });
39513 }
39514 function parseStroke(st, attrs, animations, context) {
39515 attrs.style = attrs.style || {};
39516 // Color
39517 if (isGradientFillOrStroke(st)) {
39518 attrs.style.stroke = parseGradient$2(st);
39519 }
39520 else {
39521 if (isMultiDimensionalValue(st.c)) {
39522 attrs.style.stroke = toColorString(st.c.k);
39523 }
39524 else if (isMultiDimensionalKeyframedValue(st.c)) {
39525 parseColorOffsetKeyframe(st.c.k, 'style', 'stroke', animations, context);
39526 }
39527 }
39528 // Opacity
39529 parseValue(st.o, attrs, 'style', ['strokeOpacity'], animations, context, function (opacity) { return opacity / 100; });
39530 // Line width
39531 parseValue(st.w, attrs, 'style', ['lineWidth'], animations, context);
39532 switch (st.lj) {
39533 case LineJoin.Bevel:
39534 attrs.style.lineJoin = 'bevel';
39535 break;
39536 case LineJoin.Round:
39537 attrs.style.lineJoin = 'round';
39538 break;
39539 case LineJoin.Miter:
39540 attrs.style.lineJoin = 'miter';
39541 break;
39542 }
39543 switch (st.lc) {
39544 case LineCap.Butt:
39545 attrs.style.lineCap = 'butt';
39546 break;
39547 case LineCap.Round:
39548 attrs.style.lineCap = 'round';
39549 break;
39550 case LineCap.Square:
39551 attrs.style.lineCap = 'square';
39552 break;
39553 }
39554 // Line dash
39555 var dashArray = [];
39556 var dashOffset = 0;
39557 if (st.d) {
39558 st.d.forEach(function (item) {
39559 if (item.n !== 'o') {
39560 dashArray.push(item.v.k);
39561 }
39562 else {
39563 dashOffset = item.v.k;
39564 }
39565 });
39566 attrs.style.lineDash = dashArray;
39567 attrs.style.lineDashOffset = dashOffset;
39568 }
39569 }
39570 function isBezier(k) {
39571 return k && k.i && k.o && k.v;
39572 }
39573 /**
39574 * @see https://lottiefiles.github.io/lottie-docs/shapes/#path
39575 */
39576 function parseShapePaths(shape, animations, context) {
39577 var attrs = {
39578 type: Shape.PATH,
39579 // Should have no fill and stroke by default
39580 style: {
39581 fill: 'none',
39582 stroke: 'none',
39583 },
39584 };
39585 // @see https://lottiefiles.github.io/lottie-docs/concepts/#bezier
39586 if (isBezier(shape.ks.k)) {
39587 attrs.shape = {
39588 in: shape.ks.k.i,
39589 out: shape.ks.k.o,
39590 v: shape.ks.k.v,
39591 close: shape.ks.k.c,
39592 };
39593 }
39594 else if (Array.isArray(shape.ks.k)) {
39595 var keyframeAnim = parseKeyframe(shape.ks.k, 0, context, function (outKeyframe, startVal) {
39596 outKeyframe.shape = {
39597 in: startVal[0].i,
39598 out: startVal[0].o,
39599 v: startVal[0].v,
39600 close: startVal[0].c,
39601 };
39602 });
39603 if (keyframeAnim.keyframes.length) {
39604 animations.push(keyframeAnim);
39605 }
39606 }
39607 return attrs;
39608 }
39609 /**
39610 * @see https://lottiefiles.github.io/lottie-docs/shapes/#rectangle
39611 */
39612 function parseShapeRect(shape, animations, context) {
39613 var attrs = {
39614 type: Shape.RECT,
39615 // Should have no fill and stroke by default
39616 style: {
39617 fill: 'none',
39618 stroke: 'none',
39619 },
39620 shape: {},
39621 };
39622 parseValue(shape.p, attrs, 'shape', ['x', 'y'], animations, context);
39623 parseValue(shape.s, attrs, 'shape', ['width', 'height'], animations, context);
39624 parseValue(shape.r, attrs, 'shape', ['r'], animations, context);
39625 return attrs;
39626 }
39627 /**
39628 * @see https://lottiefiles.github.io/lottie-docs/layers/#image-layer
39629 */
39630 function parseImageLayer(layer, context) {
39631 var attrs = {
39632 type: Shape.IMAGE,
39633 style: {},
39634 shape: {
39635 width: 0,
39636 height: 0,
39637 src: '',
39638 },
39639 };
39640 var asset = context.assetsMap.get(layer.refId);
39641 if (asset) {
39642 attrs.shape.width = asset.w;
39643 attrs.shape.height = asset.h;
39644 // TODO: url to fetch
39645 attrs.shape.src = asset.p;
39646 }
39647 return attrs;
39648 }
39649 /**
39650 * @see https://lottiefiles.github.io/lottie-docs/shapes/#ellipse
39651 */
39652 function parseShapeEllipse(shape, animations, context) {
39653 var attrs = {
39654 type: Shape.ELLIPSE,
39655 // Should have no fill and stroke by default
39656 style: {
39657 fill: 'none',
39658 stroke: 'none',
39659 },
39660 shape: {},
39661 };
39662 parseValue(shape.p, attrs, 'shape', ['cx', 'cy'], animations, context);
39663 parseValue(shape.s, attrs, 'shape', ['rx', 'ry'], animations, context, function (val) { return val / 2; });
39664 return attrs;
39665 }
39666 function parseShapeLayer(layer, context) {
39667 function tryCreateShape(shape, keyframeAnimations) {
39668 var ecEl;
39669 // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
39670 switch (shape.ty) {
39671 case ShapeType.Path:
39672 ecEl = parseShapePaths(shape, keyframeAnimations, context);
39673 break;
39674 case ShapeType.Ellipse:
39675 ecEl = parseShapeEllipse(shape, keyframeAnimations, context);
39676 break;
39677 case ShapeType.Rectangle:
39678 ecEl = parseShapeRect(shape, keyframeAnimations, context);
39679 break;
39680 case ShapeType.PolyStar:
39681 // TODO: parseShapePolyStar
39682 break;
39683 }
39684 return ecEl;
39685 }
39686 function parseModifiers(shapes, modifiers) {
39687 shapes.forEach(function (shape) {
39688 if (shape.hd) {
39689 return;
39690 }
39691 // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
39692 switch (shape.ty) {
39693 case ShapeType.Repeater:
39694 parseValue(shape.c, modifiers.attrs, 'shape', ['repeat'], modifiers.keyframeAnimations, context);
39695 parseTransforms(shape.tr, modifiers.attrs, modifiers.keyframeAnimations, context, 'shape', {
39696 x: 'repeatX',
39697 y: 'repeatY',
39698 rotation: 'repeatRot',
39699 scaleX: 'repeatScaleX',
39700 scaleY: 'repeatScaleY',
39701 anchorX: 'repeatAnchorX',
39702 anchorY: 'repeatAnchorY',
39703 skew: 'repeatSkew',
39704 skewAxis: 'repeatSkewAxis',
39705 });
39706 break;
39707 case ShapeType.Trim:
39708 parseValue(shape.s, modifiers.attrs, 'shape', ['trimStart'], modifiers.keyframeAnimations, context);
39709 parseValue(shape.e, modifiers.attrs, 'shape', ['trimEnd'], modifiers.keyframeAnimations, context);
39710 break;
39711 }
39712 });
39713 }
39714 function parseIterations(shapes, modifiers) {
39715 var ecEls = [];
39716 var attrs = {};
39717 var keyframeAnimations = [];
39718 // Order is reversed
39719 shapes = shapes.slice().reverse();
39720 // Modifiers first:
39721 parseModifiers(shapes, modifiers);
39722 shapes.forEach(function (shape) {
39723 if (shape.hd) {
39724 return;
39725 }
39726 var ecEl;
39727 switch (shape.ty) {
39728 case ShapeType.Group:
39729 ecEl = {
39730 type: Shape.GROUP,
39731 children: parseIterations(shape.it,
39732 // Modifiers will be applied to all childrens.
39733 modifiers),
39734 };
39735 break;
39736 // TODO Multiple fill and stroke
39737 case ShapeType.Fill:
39738 case ShapeType.GradientFill:
39739 parseFill(shape, attrs, keyframeAnimations, context);
39740 break;
39741 case ShapeType.Stroke:
39742 case ShapeType.GradientStroke:
39743 parseStroke(shape, attrs, keyframeAnimations, context);
39744 break;
39745 case ShapeType.Transform:
39746 parseTransforms(shape, attrs, keyframeAnimations, context);
39747 break;
39748 // TODO Multiple shapes.
39749 default:
39750 ecEl = tryCreateShape(shape, keyframeAnimations);
39751 }
39752 if (ecEl) {
39753 ecEl.name = shape.nm;
39754 ecEls.push(ecEl);
39755 }
39756 });
39757 ecEls.forEach(function (el, idx) {
39758 // Apply modifiers first
39759 el = __assign(__assign(__assign({}, el), definedProps(modifiers.attrs)), attrs);
39760 if (keyframeAnimations.length || modifiers.keyframeAnimations.length) {
39761 el.keyframeAnimation = __spreadArray(__spreadArray([], __read(modifiers.keyframeAnimations), false), __read(keyframeAnimations), false);
39762 }
39763 ecEls[idx] = el;
39764 });
39765 return ecEls;
39766 }
39767 return {
39768 type: Shape.GROUP,
39769 children: parseIterations(layer.shapes, {
39770 attrs: {},
39771 keyframeAnimations: [],
39772 }),
39773 };
39774 }
39775 function traverse(el, cb) {
39776 var _a;
39777 cb(el);
39778 if (el.type === Shape.GROUP) {
39779 (_a = el.children) === null || _a === void 0 ? void 0 : _a.forEach(function (child) {
39780 traverse(child, cb);
39781 });
39782 }
39783 }
39784 function addLayerOpacity(layer, layerGroup, context) {
39785 var _a, _b;
39786 var opacityAttrs = {};
39787 var opacityAnimations = [];
39788 if ((_a = layer.ks) === null || _a === void 0 ? void 0 : _a.o) {
39789 parseValue(layer.ks.o, opacityAttrs, 'style', ['opacity'], opacityAnimations, context, function (val) { return val / 100; });
39790 if (((_b = opacityAttrs.style) === null || _b === void 0 ? void 0 : _b.opacity) || opacityAnimations.length) {
39791 // apply opacity to group's children
39792 traverse(layerGroup, function (el) {
39793 if (el.type !== Shape.GROUP && el.style) {
39794 Object.assign(el.style, opacityAttrs.style);
39795 if (opacityAnimations.length) {
39796 el.keyframeAnimation = (el.keyframeAnimation || []).concat(opacityAnimations);
39797 }
39798 }
39799 });
39800 }
39801 }
39802 }
39803 function parseSolidShape(layer) {
39804 return {
39805 type: Shape.RECT,
39806 shape: {
39807 x: 0,
39808 y: 0,
39809 width: layer.sw,
39810 height: layer.sh,
39811 },
39812 style: {
39813 fill: layer.sc,
39814 },
39815 };
39816 }
39817 function parseLayers(layers, context, precompLayerTl) {
39818 var elements = [];
39819 // Order is reversed
39820 layers = layers.slice().reverse();
39821 var layerIndexMap = new Map();
39822 var offsetTime = (precompLayerTl === null || precompLayerTl === void 0 ? void 0 : precompLayerTl.st) || 0;
39823 layers === null || layers === void 0 ? void 0 : layers.forEach(function (layer) {
39824 // Layer time is offseted by the precomp layer.
39825 var _a, _b;
39826 // Use the ip, op, st of ref from.
39827 var layerIp = offsetTime + layer.ip;
39828 var layerOp = offsetTime + layer.op;
39829 var layerSt = offsetTime + layer.st;
39830 context.layerOffsetTime = offsetTime;
39831 var layerGroup;
39832 // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
39833 switch (layer.ty) {
39834 case LayerType.shape:
39835 // @see https://lottiefiles.github.io/lottie-docs/layers/#shape-layer
39836 layerGroup = parseShapeLayer(layer, context);
39837 break;
39838 case LayerType.null:
39839 // @see https://lottiefiles.github.io/lottie-docs/layers/#null-layer
39840 layerGroup = {
39841 type: Shape.GROUP,
39842 children: [],
39843 };
39844 break;
39845 case LayerType.solid:
39846 // @see https://lottiefiles.github.io/lottie-docs/layers/#solid-color-layer
39847 layerGroup = {
39848 type: Shape.GROUP,
39849 children: [],
39850 };
39851 // Anything you can do with solid layers, you can do better with a shape layer and a rectangle shape
39852 // since none of this layer's own properties can be animated.
39853 if (layer.sc) {
39854 layerGroup.children.push(parseSolidShape(layer));
39855 }
39856 break;
39857 case LayerType.precomp:
39858 // @see https://lottiefiles.github.io/lottie-docs/layers/#precomposition-layer
39859 layerGroup = {
39860 type: Shape.GROUP,
39861 children: parseLayers(((_a = context.assetsMap.get(layer.refId)) === null || _a === void 0 ? void 0 : _a.layers) || [], context, {
39862 st: layerSt,
39863 }),
39864 };
39865 break;
39866 case LayerType.text:
39867 // TODO: https://lottiefiles.github.io/lottie-docs/layers/#text-layer
39868 break;
39869 case LayerType.image:
39870 // TODO: https://lottiefiles.github.io/lottie-docs/layers/#image-layer
39871 layerGroup = layerGroup = {
39872 type: Shape.GROUP,
39873 children: [parseImageLayer(layer, context)],
39874 };
39875 break;
39876 }
39877 if (layerGroup) {
39878 var keyframeAnimations = [];
39879 var attrs = {
39880 name: layer.nm,
39881 };
39882 if (layer.ks) {
39883 parseTransforms(layer.ks, attrs, keyframeAnimations, context);
39884 }
39885 Object.assign(layerGroup, attrs);
39886 if (layer.ind != null) {
39887 layerIndexMap.set(layer.ind, layerGroup);
39888 }
39889 layerGroup.extra = {
39890 layerParent: layer.parent,
39891 };
39892 // Masks @see https://lottiefiles.github.io/lottie-docs/layers/#masks
39893 // @see https://lottie-animation-community.github.io/docs/specs/layers/common/#clipping-masks
39894 // TODO: not support alpha and other modes.
39895 // @see https://lottie-animation-community.github.io/docs/specs/properties/mask-mode-types/
39896 if (layer.hasMask && ((_b = layer.masksProperties) === null || _b === void 0 ? void 0 : _b.length)) {
39897 var maskKeyframeAnimations = [];
39898 // TODO: Only support one mask now.
39899 var attrs_1 = parseShapePaths({
39900 ks: layer.masksProperties[0].pt,
39901 }, maskKeyframeAnimations, context);
39902 layerGroup.clipPath = __assign({ type: Shape.PATH }, attrs_1);
39903 if (maskKeyframeAnimations.length) {
39904 layerGroup.clipPath.keyframeAnimation = maskKeyframeAnimations;
39905 }
39906 }
39907 addLayerOpacity(layer, layerGroup, context);
39908 // Update in and out animation.
39909 if (layerIp != null &&
39910 layerOp != null &&
39911 (layerIp > context.startFrame || layerOp < context.endFrame)) {
39912 var duration = context.endFrame - context.startFrame;
39913 var visibilityStartOffset = (layerIp - context.startFrame) / duration;
39914 var visibilityEndOffset = (layerOp - context.startFrame) / duration;
39915 layerGroup.visibilityStartOffset = visibilityStartOffset;
39916 layerGroup.visibilityEndOffset = visibilityEndOffset;
39917 layerGroup.visibilityFrame = duration;
39918 }
39919 if (keyframeAnimations.length) {
39920 layerGroup.keyframeAnimation = keyframeAnimations;
39921 }
39922 elements.push(layerGroup);
39923 }
39924 });
39925 // Build hierarchy
39926 return elements.filter(function (el) {
39927 var _a, _b;
39928 var parentLayer = layerIndexMap.get((_a = el.extra) === null || _a === void 0 ? void 0 : _a.layerParent);
39929 if (parentLayer) {
39930 (_b = parentLayer.children) === null || _b === void 0 ? void 0 : _b.push(el);
39931 return false;
39932 }
39933 return true;
39934 });
39935 }
39936 var DEFAULT_LOAD_ANIMATION_OPTIONS = {
39937 loop: true,
39938 autoplay: false,
39939 fill: 'both',
39940 };
39941 function parse(data, options) {
39942 var _a;
39943 completeData(data);
39944 var _b = __assign(__assign({}, DEFAULT_LOAD_ANIMATION_OPTIONS), options), loop = _b.loop, autoplay = _b.autoplay, fill = _b.fill;
39945 var context = new ParseContext();
39946 context.fps = data.fr || 30;
39947 context.frameTime = 1000 / context.fps;
39948 context.startFrame = data.ip;
39949 context.endFrame = data.op;
39950 context.version = data.v;
39951 context.autoplay = !!autoplay;
39952 context.fill = fill;
39953 context.iterations = isNumber(loop) ? loop : loop ? Infinity : 1;
39954 // @see https://lottiefiles.github.io/lottie-docs/assets/
39955 (_a = data.assets) === null || _a === void 0 ? void 0 : _a.forEach(function (asset) {
39956 context.assetsMap.set(asset.id, asset);
39957 });
39958 var elements = parseLayers(data.layers || [], context);
39959 return {
39960 width: data.w,
39961 height: data.h,
39962 elements: elements,
39963 context: context,
39964 };
39965 }
39966
39967 /**
39968 * @see https://github.com/airbnb/lottie-web/wiki/loadAnimation-options
39969 * @see https://github.com/airbnb/lottie-web#other-loading-options
39970 */
39971 function loadAnimation(data, options) {
39972 var _a = parse(data, options), width = _a.width, height = _a.height, elements = _a.elements, context = _a.context;
39973 return new LottieAnimation(width, height, elements, context);
39974 }
39975
39976 var Lottie = /** @class */function (_super) {
39977 __extends(Lottie, _super);
39978 function Lottie(props) {
39979 var _this = _super.call(this, props) || this;
39980 _this.addLottie = function () {
39981 var _a = _this,
39982 props = _a.props,
39983 context = _a.context;
39984 var data = props.data,
39985 options = props.options,
39986 play = props.play;
39987 var canvas = context.canvas;
39988 if (!data) return;
39989 // 文档流后挂载lottie
39990 canvas.ready.then(function () {
39991 _this.animation = _this.animation ? _this.animation : loadAnimation(data, options);
39992 _this.animation.render(_this.ref.current);
39993 _this.size = _this.animation.size();
39994 _this.updateSize();
39995 // 播放控制
39996 if (play) {
39997 var _a = play.speed,
39998 speed = _a === void 0 ? 1 : _a,
39999 _b = play.start,
40000 start = _b === void 0 ? 0 : _b,
40001 _c = play.end,
40002 end = _c === void 0 ? _this.animation.getDuration(true) : _c;
40003 _this.animation.setSpeed(speed);
40004 _this.animation.playSegments([start, end]);
40005 }
40006 });
40007 };
40008 _this.updateSize = function () {
40009 var _a = _this.size,
40010 currentWidth = _a.width,
40011 currentHeight = _a.height;
40012 var style = _this.props.style;
40013 if (!style) return;
40014 var _b = style.width,
40015 width = _b === void 0 ? currentWidth : _b,
40016 _c = style.height,
40017 height = _c === void 0 ? currentHeight : _c;
40018 _this.ref.current.scale(width / currentWidth, height / currentHeight);
40019 _this.size = {
40020 width: width,
40021 height: height
40022 };
40023 };
40024 _this.ref = createRef();
40025 return _this;
40026 }
40027 Lottie.prototype.didMount = function () {
40028 this.addLottie();
40029 };
40030 Lottie.prototype.willUpdate = function () {
40031 this.addLottie();
40032 };
40033 Lottie.prototype.render = function () {
40034 var _a = this.props,
40035 style = _a.style,
40036 animation = _a.animation;
40037 return jsx("group", {
40038 ref: this.ref,
40039 style: style,
40040 animation: animation
40041 });
40042 };
40043 return Lottie;
40044 }(Component);
40045
40046 var defaultProps$2 = {
40047 offsetX: 0,
40048 offsetY: 0,
40049 points: [],
40050 data: '',
40051 animation: null,
40052 options: {
40053 loop: true,
40054 autoplay: true
40055 }
40056 };
40057 var LottieGuideView = (function (props, context) {
40058 var cfg = deepMix({}, defaultProps$2, props);
40059 var points = cfg.points,
40060 style = cfg.style,
40061 offsetX = cfg.offsetX,
40062 offsetY = cfg.offsetY,
40063 lottieJson = cfg.lottieJson,
40064 animation = cfg.animation,
40065 options = cfg.options;
40066 var _a = points[0] || {},
40067 x = _a.x,
40068 y = _a.y;
40069 var _b = style.height,
40070 height = _b === void 0 ? 0 : _b,
40071 _c = style.width,
40072 width = _c === void 0 ? 0 : _c;
40073 var offsetXNum = context.px2hd(offsetX);
40074 var offsetYNum = context.px2hd(offsetY);
40075 var posX = x + (offsetXNum || 0) - width / 2;
40076 var posY = y + (offsetYNum || 0) - height / 2;
40077 return jsx(Lottie, {
40078 data: lottieJson,
40079 options: options,
40080 style: {
40081 x: posX,
40082 y: posY,
40083 width: width,
40084 height: height
40085 },
40086 animation: deepMix({
40087 update: {
40088 easing: 'linear',
40089 duration: 450,
40090 property: ['x', 'y']
40091 }
40092 }, animation)
40093 });
40094 });
40095
40096 var DefaultGuideView = function DefaultGuideView() {
40097 return null;
40098 };
40099 var TextGuide = withGuide(TextGuideView);
40100 var PointGuide = withGuide(PointGuideView);
40101 var LineGuide = withGuide(LineGuideView);
40102 var ArcGuide = withGuide(ArcGuideView);
40103 var RectGuide = withGuide(RectGuideView);
40104 var ImageGuide = withGuide(ImageGuideView);
40105 var TagGuide = withGuide(Tag);
40106 var LottieGuide = withGuide(LottieGuideView);
40107 var index$6 = withGuide(DefaultGuideView);
40108
40109 var withTooltip = (function (View) {
40110 return /** @class */function (_super) {
40111 __extends(Tooltip, _super);
40112 function Tooltip(props) {
40113 var _this = _super.call(this, props) || this;
40114 _this._triggerOn = function (ev) {
40115 var x = ev.x,
40116 y = ev.y;
40117 _this.show({
40118 x: x,
40119 y: y
40120 }, ev);
40121 };
40122 _this._triggerOff = function () {
40123 var _a = _this.props.alwaysShow,
40124 alwaysShow = _a === void 0 ? false : _a;
40125 if (!alwaysShow) {
40126 _this.hide();
40127 }
40128 };
40129 _this.state = {
40130 records: null
40131 };
40132 return _this;
40133 }
40134 Tooltip.prototype.updateCoord = function () {
40135 var _a = this,
40136 props = _a.props,
40137 context = _a.context;
40138 var _b = props.padding,
40139 padding = _b === void 0 ? '10px' : _b,
40140 chart = props.chart;
40141 chart.updateCoordFor(this, {
40142 position: 'top',
40143 width: 0,
40144 height: context.px2hd(padding)
40145 });
40146 };
40147 Tooltip.prototype.willMount = function () {
40148 this.updateCoord();
40149 };
40150 Tooltip.prototype.didMount = function () {
40151 this._initShow();
40152 this._initEvent();
40153 };
40154 Tooltip.prototype._initEvent = function () {
40155 var _a = this.props,
40156 chart = _a.chart,
40157 _b = _a.triggerOn,
40158 triggerOn = _b === void 0 ? 'press' : _b,
40159 _c = _a.triggerOff,
40160 triggerOff = _c === void 0 ? 'pressend' : _c;
40161 chart.on(triggerOn, this._triggerOn);
40162 chart.on(triggerOff, this._triggerOff);
40163 };
40164 Tooltip.prototype.willReceiveProps = function (nextProps) {
40165 var nextDefaultItem = nextProps.defaultItem,
40166 nextCoord = nextProps.coord;
40167 var _a = this.props,
40168 lastDefaultItem = _a.defaultItem,
40169 lastCoord = _a.coord;
40170 // 默认元素或坐标有变动,均需重新渲染
40171 if (!equal(nextDefaultItem, lastDefaultItem) || !equal(nextCoord, lastCoord)) {
40172 this._showByData(nextDefaultItem);
40173 }
40174 };
40175 Tooltip.prototype._initShow = function () {
40176 var props = this.props;
40177 var defaultItem = props.defaultItem;
40178 this._showByData(defaultItem);
40179 };
40180 Tooltip.prototype._showByData = function (dataItem) {
40181 var _this = this;
40182 if (!dataItem) return;
40183 var props = this.props;
40184 var chart = props.chart;
40185 // 因为 tooltip 有可能在 geometry 之前,所以需要等 geometry render 完后再执行
40186 setTimeout(function () {
40187 var snapRecords = chart.getRecords(dataItem, 'xfield');
40188 _this.showSnapRecords(snapRecords);
40189 }, 0);
40190 };
40191 Tooltip.prototype.show = function (point, _ev) {
40192 var props = this.props;
40193 var chart = props.chart;
40194 var snapRecords = chart.getSnapRecords(point, true); // 超出边界会自动调整
40195 if (!snapRecords || !snapRecords.length) return;
40196 this.showSnapRecords(snapRecords);
40197 };
40198 Tooltip.prototype.showSnapRecords = function (snapRecords) {
40199 var _a = this.props,
40200 chart = _a.chart,
40201 onChange = _a.onChange;
40202 var legendItems = chart.getLegendItems();
40203 var _b = snapRecords[0],
40204 xField = _b.xField,
40205 yField = _b.yField;
40206 var xScale = chart.getScale(xField);
40207 var yScale = chart.getScale(yField);
40208 var records = snapRecords.map(function (record) {
40209 var origin = record.origin,
40210 xField = record.xField,
40211 yField = record.yField;
40212 var value = isArray(origin[yField]) ? origin[yField].map(function (v) {
40213 return yScale.getText(v);
40214 }) : yScale.getText(origin[yField]);
40215 // 默认取 alias 的配置
40216 var name = yScale.alias;
40217 if (!name) {
40218 name = xScale.getText(origin[xField]);
40219 if (legendItems && legendItems.length) {
40220 var item = find(legendItems, function (item) {
40221 var field = item.field,
40222 tickValue = item.tickValue;
40223 return origin[field] === tickValue;
40224 });
40225 if (item && item.name) {
40226 name = item.name;
40227 }
40228 }
40229 }
40230 return __assign(__assign({}, record), {
40231 name: name,
40232 value: "".concat(value)
40233 });
40234 });
40235 if (!isArray(records) || !records.length) {
40236 return;
40237 }
40238 this.setState({
40239 records: records
40240 });
40241 if (isFunction(onChange)) {
40242 onChange(records);
40243 }
40244 };
40245 Tooltip.prototype.hide = function () {
40246 this.setState({
40247 records: null
40248 });
40249 };
40250 Tooltip.prototype.render = function () {
40251 var _a = this,
40252 props = _a.props,
40253 state = _a.state;
40254 var visible = props.visible;
40255 if (visible === false) {
40256 return null;
40257 }
40258 var records = state.records;
40259 return records && records.length && jsx(View, __assign({}, props, {
40260 records: records
40261 }));
40262 };
40263 return Tooltip;
40264 }(Component);
40265 });
40266
40267 // view 的默认配置
40268 var defaultStyle$1 = {
40269 showTitle: false,
40270 showCrosshairs: false,
40271 crosshairsType: 'y',
40272 crosshairsStyle: {
40273 stroke: 'rgba(0, 0, 0, 0.25)',
40274 lineWidth: '2px'
40275 },
40276 showTooltipMarker: false,
40277 markerBackgroundStyle: {
40278 fill: '#CCD6EC',
40279 opacity: 0.3,
40280 padding: '6px'
40281 },
40282 tooltipMarkerStyle: {
40283 fill: '#fff',
40284 lineWidth: '3px'
40285 },
40286 background: {
40287 radius: '4px',
40288 fill: 'rgba(0, 0, 0, 0.65)',
40289 padding: ['6px', '10px']
40290 },
40291 titleStyle: {
40292 fontSize: '24px',
40293 fill: '#fff',
40294 textAlign: 'start',
40295 textBaseline: 'top'
40296 },
40297 nameStyle: {
40298 fontSize: '24px',
40299 fill: 'rgba(255, 255, 255, 0.65)',
40300 textAlign: 'start',
40301 textBaseline: 'middle'
40302 },
40303 valueStyle: {
40304 fontSize: '24px',
40305 fill: '#fff',
40306 textAlign: 'start',
40307 textBaseline: 'middle'
40308 },
40309 joinString: ': ',
40310 showItemMarker: true,
40311 itemMarkerStyle: {
40312 width: '12px',
40313 radius: '6px',
40314 symbol: 'circle',
40315 lineWidth: '2px',
40316 stroke: '#fff'
40317 },
40318 layout: 'horizontal',
40319 snap: false,
40320 xTipTextStyle: {
40321 fontSize: '24px',
40322 fill: '#fff'
40323 },
40324 yTipTextStyle: {
40325 fontSize: '24px',
40326 fill: '#fff'
40327 },
40328 xTipBackground: {
40329 radius: '4px',
40330 fill: 'rgba(0, 0, 0, 0.65)',
40331 padding: ['6px', '10px'],
40332 marginLeft: '-50%',
40333 marginTop: '6px'
40334 },
40335 yTipBackground: {
40336 radius: '4px',
40337 fill: 'rgba(0, 0, 0, 0.65)',
40338 padding: ['6px', '10px'],
40339 marginLeft: '-100%',
40340 marginTop: '-50%'
40341 }
40342 };
40343 function directionEnabled(mode, dir) {
40344 if (mode === undefined) {
40345 return true;
40346 } else if (typeof mode === 'string') {
40347 return mode.indexOf(dir) !== -1;
40348 }
40349 return false;
40350 }
40351 var RenderItemMarker = function RenderItemMarker(props) {
40352 var records = props.records,
40353 coord = props.coord,
40354 context = props.context,
40355 markerBackgroundStyle = props.markerBackgroundStyle;
40356 var point = coord.convertPoint({
40357 x: 1,
40358 y: 1
40359 });
40360 var padding = context.px2hd(markerBackgroundStyle.padding || '6px');
40361 var xPoints = __spreadArray(__spreadArray([], records.map(function (record) {
40362 return record.xMin;
40363 }), true), records.map(function (record) {
40364 return record.xMax;
40365 }), true);
40366 var yPoints = __spreadArray(__spreadArray([], records.map(function (record) {
40367 return record.yMin;
40368 }), true), records.map(function (record) {
40369 return record.yMax;
40370 }), true);
40371 if (coord.transposed) {
40372 xPoints.push(point.x);
40373 } else {
40374 yPoints.push(point.y);
40375 }
40376 var xMin = Math.min.apply(null, xPoints);
40377 var xMax = Math.max.apply(null, xPoints);
40378 var yMin = Math.min.apply(null, yPoints);
40379 var yMax = Math.max.apply(null, yPoints);
40380 var x = coord.transposed ? xMin : xMin - padding;
40381 var y = coord.transposed ? yMin - padding : yMin;
40382 var width = coord.transposed ? xMax - xMin : xMax - xMin + 2 * padding;
40383 var height = coord.transposed ? yMax - yMin + 2 * padding : yMax - yMin;
40384 return jsx("rect", {
40385 style: __assign({
40386 x: x,
40387 y: y,
40388 width: width,
40389 height: height
40390 }, markerBackgroundStyle)
40391 });
40392 };
40393 var RenderCrosshairs = function RenderCrosshairs(props) {
40394 var records = props.records,
40395 coord = props.coord,
40396 chart = props.chart,
40397 crosshairsType = props.crosshairsType,
40398 crosshairsStyle = props.crosshairsStyle,
40399 xPositionType = props.xPositionType,
40400 yPositionType = props.yPositionType;
40401 var coordLeft = coord.left,
40402 coordTop = coord.top,
40403 coordRight = coord.right,
40404 coordBottom = coord.bottom,
40405 center = coord.center;
40406 var firstRecord = records[0];
40407 var x = firstRecord.x,
40408 y = firstRecord.y,
40409 origin = firstRecord.origin,
40410 xField = firstRecord.xField,
40411 coordData = firstRecord.coord;
40412 if (coord.isPolar) {
40413 // 极坐标下的辅助线
40414 var xScale = chart.getScale(xField);
40415 var ticks = xScale.getTicks();
40416 var tick = find(ticks, function (tick) {
40417 return origin[xField] === tick.tickValue;
40418 });
40419 var end = coord.convertPoint({
40420 x: tick.value,
40421 y: 1
40422 });
40423 return jsx("line", {
40424 style: __assign({
40425 x1: center.x,
40426 y1: center.y,
40427 x2: end.x,
40428 y2: end.y
40429 }, crosshairsStyle)
40430 });
40431 }
40432 return jsx("group", null, directionEnabled(crosshairsType, 'x') ? jsx("line", {
40433 style: __assign({
40434 x1: coordLeft,
40435 y1: yPositionType === 'coord' ? coordData.y : y,
40436 x2: coordRight,
40437 y2: yPositionType === 'coord' ? coordData.y : y
40438 }, crosshairsStyle)
40439 }) : null, directionEnabled(crosshairsType, 'y') ? jsx("line", {
40440 style: __assign({
40441 x1: xPositionType === 'coord' ? coordData.x : x,
40442 y1: coordTop,
40443 x2: xPositionType === 'coord' ? coordData.x : x,
40444 y2: coordBottom
40445 }, crosshairsStyle)
40446 }) : null);
40447 };
40448 var RenderXTip = function RenderXTip(props) {
40449 var records = props.records,
40450 coord = props.coord,
40451 xTip = props.xTip,
40452 xPositionType = props.xPositionType,
40453 xTipTextStyle = props.xTipTextStyle,
40454 xTipBackground = props.xTipBackground;
40455 var coordBottom = coord.bottom;
40456 var firstRecord = records[0];
40457 var x = firstRecord.x,
40458 coordData = firstRecord.coord;
40459 var xFirstText = firstRecord.name;
40460 return jsx("rect", {
40461 style: __assign({
40462 display: 'flex',
40463 left: xPositionType === 'coord' ? coordData.x : x,
40464 top: coordBottom
40465 }, xTipBackground)
40466 }, jsx("text", {
40467 style: __assign(__assign({}, xTipTextStyle), {
40468 text: xPositionType === 'coord' ? coordData.xText : isFunction(xTip) ? xTip(xFirstText) : xFirstText
40469 })
40470 }));
40471 };
40472 var RenderYTip = function RenderYTip(props) {
40473 var records = props.records,
40474 coord = props.coord,
40475 yTip = props.yTip,
40476 yPositionType = props.yPositionType,
40477 yTipTextStyle = props.yTipTextStyle,
40478 yTipBackground = props.yTipBackground;
40479 var coordLeft = coord.left;
40480 var firstRecord = records[0];
40481 var y = firstRecord.y,
40482 coordData = firstRecord.coord;
40483 var yFirstText = firstRecord.value;
40484 return jsx("rect", {
40485 style: __assign({
40486 display: 'flex',
40487 left: coordLeft,
40488 top: yPositionType === 'coord' ? coordData.y : y
40489 }, yTipBackground)
40490 }, jsx("text", {
40491 style: __assign(__assign({}, yTipTextStyle), {
40492 text: yPositionType === 'coord' ? coordData.yText : isFunction(yTip) ? yTip(yFirstText) : yFirstText
40493 })
40494 }));
40495 };
40496 // tooltip 内容框
40497 var RenderLabel = /** @class */function (_super) {
40498 __extends(RenderLabel, _super);
40499 function RenderLabel() {
40500 return _super !== null && _super.apply(this, arguments) || this;
40501 }
40502 RenderLabel.prototype.render = function () {
40503 var _a = this.props,
40504 records = _a.records,
40505 background = _a.background,
40506 showItemMarker = _a.showItemMarker,
40507 itemMarkerStyle = _a.itemMarkerStyle,
40508 customText = _a.customText,
40509 nameStyle = _a.nameStyle,
40510 valueStyle = _a.valueStyle,
40511 joinString = _a.joinString,
40512 arrowWidth = _a.arrowWidth,
40513 x = _a.x,
40514 coord = _a.coord;
40515 // 显示内容
40516 var labelView = function labelView(left, top) {
40517 return jsx("group", {
40518 style: {
40519 display: 'flex'
40520 }
40521 }, jsx("group", {
40522 style: __assign({
40523 display: 'flex',
40524 flexDirection: 'row',
40525 flexWrap: 'wrap',
40526 padding: [0, 0, 0, '6px'],
40527 left: left,
40528 top: top
40529 }, background)
40530 }, records.map(function (record) {
40531 var name = record.name,
40532 value = record.value;
40533 return jsx("group", {
40534 style: {
40535 display: 'flex',
40536 flexDirection: 'row',
40537 alignItems: 'center',
40538 padding: [0, '6px', 0, 0]
40539 }
40540 }, showItemMarker ? jsx("marker", {
40541 style: __assign(__assign({
40542 width: itemMarkerStyle.width,
40543 marginRight: '6px'
40544 }, itemMarkerStyle), {
40545 fill: record.color
40546 })
40547 }) : null, customText && isFunction(customText) ? customText(record) : jsx("group", {
40548 style: {
40549 display: 'flex',
40550 flexDirection: 'row'
40551 }
40552 }, jsx("text", {
40553 style: __assign(__assign({}, nameStyle), {
40554 text: value ? "".concat(name).concat(joinString) : name
40555 })
40556 }), jsx("text", {
40557 style: __assign(__assign({}, valueStyle), {
40558 text: value
40559 })
40560 })));
40561 })), jsx("group", null, jsx("polygon", {
40562 style: {
40563 points: [[x - arrowWidth, top], [x + arrowWidth, top], [x, top + arrowWidth]],
40564 fill: background.fill
40565 }
40566 })));
40567 };
40568 // 计算显示位置
40569 var layout = computeLayout$1(this, labelView(0, 0)).layout; // 获取内容区大小
40570 var coordLeft = coord.left,
40571 coordTop = coord.top,
40572 coordRight = coord.right;
40573 var width = layout.width,
40574 height = layout.height;
40575 var halfWidth = width / 2;
40576 // 让 tooltip 限制在 coord 的显示范围内
40577 var advanceLeft = x - halfWidth;
40578 var advanceTop = coordTop - height;
40579 var left = advanceLeft < coordLeft ? coordLeft : advanceLeft > coordRight - width ? coordRight - width : advanceLeft;
40580 var top = advanceTop < 0 ? 0 : advanceTop;
40581 return labelView(left, top);
40582 };
40583 return RenderLabel;
40584 }(Component);
40585 var TooltipView = /** @class */function (_super) {
40586 __extends(TooltipView, _super);
40587 function TooltipView() {
40588 return _super !== null && _super.apply(this, arguments) || this;
40589 }
40590 TooltipView.prototype.render = function () {
40591 var _a = this,
40592 props = _a.props,
40593 context = _a.context;
40594 var records = props.records,
40595 coord = props.coord;
40596 var firstRecord = records[0];
40597 var x = firstRecord.x,
40598 coordData = firstRecord.coord;
40599 var chart = props.chart,
40600 customBackground = props.background,
40601 _b = props.showTooltipMarker,
40602 showTooltipMarker = _b === void 0 ? defaultStyle$1.showTooltipMarker : _b,
40603 _c = props.markerBackgroundStyle,
40604 markerBackgroundStyle = _c === void 0 ? defaultStyle$1.markerBackgroundStyle : _c,
40605 _d = props.showItemMarker,
40606 showItemMarker = _d === void 0 ? defaultStyle$1.showItemMarker : _d,
40607 customItemMarkerStyle = props.itemMarkerStyle,
40608 nameStyle = props.nameStyle,
40609 valueStyle = props.valueStyle,
40610 _e = props.joinString,
40611 joinString = _e === void 0 ? defaultStyle$1.joinString : _e,
40612 _f = props.showCrosshairs,
40613 showCrosshairs = _f === void 0 ? defaultStyle$1.showCrosshairs : _f,
40614 crosshairsStyle = props.crosshairsStyle,
40615 _g = props.crosshairsType,
40616 crosshairsType = _g === void 0 ? defaultStyle$1.crosshairsType : _g,
40617 _h = props.snap,
40618 snap = _h === void 0 ? defaultStyle$1.snap : _h,
40619 _j = props.tooltipMarkerStyle,
40620 tooltipMarkerStyle = _j === void 0 ? defaultStyle$1.tooltipMarkerStyle : _j,
40621 showXTip = props.showXTip,
40622 xPositionType = props.xPositionType,
40623 showYTip = props.showYTip,
40624 yPositionType = props.yPositionType,
40625 xTip = props.xTip,
40626 yTip = props.yTip,
40627 _k = props.xTipTextStyle,
40628 xTipTextStyle = _k === void 0 ? defaultStyle$1.xTipTextStyle : _k,
40629 _l = props.yTipTextStyle,
40630 yTipTextStyle = _l === void 0 ? defaultStyle$1.yTipTextStyle : _l,
40631 _m = props.xTipBackground,
40632 xTipBackground = _m === void 0 ? defaultStyle$1.xTipBackground : _m,
40633 _o = props.yTipBackground,
40634 yTipBackground = _o === void 0 ? defaultStyle$1.yTipBackground : _o,
40635 _p = props.custom,
40636 custom = _p === void 0 ? false : _p,
40637 customText = props.customText;
40638 var itemMarkerStyle = __assign(__assign({}, customItemMarkerStyle), defaultStyle$1.itemMarkerStyle);
40639 var background = __assign(__assign({}, defaultStyle$1.background), customBackground);
40640 var arrowWidth = context.px2hd('6px');
40641 return jsx("group", null, showTooltipMarker ? jsx(RenderItemMarker, {
40642 coord: coord,
40643 context: context,
40644 records: records,
40645 markerBackgroundStyle: markerBackgroundStyle
40646 }) : null, showCrosshairs ? jsx(RenderCrosshairs, {
40647 chart: chart,
40648 coord: coord,
40649 records: records,
40650 xPositionType: xPositionType,
40651 yPositionType: yPositionType,
40652 crosshairsType: crosshairsType,
40653 crosshairsStyle: __assign(__assign({}, defaultStyle$1.crosshairsStyle), crosshairsStyle)
40654 }) : null, snap ? records.map(function (item) {
40655 var x = item.x,
40656 y = item.y,
40657 color = item.color,
40658 shape = item.shape;
40659 return jsx("circle", {
40660 style: __assign(__assign({
40661 cx: xPositionType === 'coord' ? coordData.x : x,
40662 cy: yPositionType === 'coord' ? coordData.y : y,
40663 r: '6px',
40664 stroke: color,
40665 fill: color
40666 }, shape), tooltipMarkerStyle)
40667 });
40668 }) : null, showXTip && jsx(RenderXTip, {
40669 records: records,
40670 coord: coord,
40671 xTip: xTip,
40672 xPositionType: xPositionType,
40673 xTipTextStyle: __assign(__assign({}, defaultStyle$1.xTipTextStyle), xTipTextStyle),
40674 xTipBackground: __assign(__assign({}, defaultStyle$1.xTipBackground), xTipBackground)
40675 }), showYTip && jsx(RenderYTip, {
40676 records: records,
40677 coord: coord,
40678 yTip: yTip,
40679 yPositionType: yPositionType,
40680 yTipTextStyle: __assign(__assign({}, defaultStyle$1.yTipTextStyle), yTipTextStyle),
40681 yTipBackground: __assign(__assign({}, defaultStyle$1.yTipBackground), yTipBackground)
40682 }), !custom && jsx(RenderLabel, {
40683 records: records,
40684 coord: coord,
40685 itemMarkerStyle: itemMarkerStyle,
40686 customText: customText,
40687 showItemMarker: showItemMarker,
40688 x: x,
40689 arrowWidth: arrowWidth,
40690 background: background,
40691 nameStyle: __assign(__assign({}, defaultStyle$1.nameStyle), nameStyle),
40692 valueStyle: __assign(__assign({}, defaultStyle$1.valueStyle), valueStyle),
40693 joinString: joinString
40694 }));
40695 };
40696 return TooltipView;
40697 }(Component);
40698
40699 var index$7 = withTooltip(TooltipView);
40700
40701 var toPrimitive = createCommonjsModule(function (module) {
40702 var _typeof = _typeof_1["default"];
40703 function _toPrimitive(input, hint) {
40704 if (_typeof(input) !== "object" || input === null) return input;
40705 var prim = input[Symbol.toPrimitive];
40706 if (prim !== undefined) {
40707 var res = prim.call(input, hint || "default");
40708 if (_typeof(res) !== "object") return res;
40709 throw new TypeError("@@toPrimitive must return a primitive value.");
40710 }
40711 return (hint === "string" ? String : Number)(input);
40712 }
40713 module.exports = _toPrimitive, module.exports.__esModule = true, module.exports["default"] = module.exports;
40714 });
40715
40716 var toPropertyKey = createCommonjsModule(function (module) {
40717 var _typeof = _typeof_1["default"];
40718
40719 function _toPropertyKey(arg) {
40720 var key = toPrimitive(arg, "string");
40721 return _typeof(key) === "symbol" ? key : String(key);
40722 }
40723 module.exports = _toPropertyKey, module.exports.__esModule = true, module.exports["default"] = module.exports;
40724 });
40725
40726 var defineProperty = createCommonjsModule(function (module) {
40727 function _defineProperty(obj, key, value) {
40728 key = toPropertyKey(key);
40729 if (key in obj) {
40730 Object.defineProperty(obj, key, {
40731 value: value,
40732 enumerable: true,
40733 configurable: true,
40734 writable: true
40735 });
40736 } else {
40737 obj[key] = value;
40738 }
40739 return obj;
40740 }
40741 module.exports = _defineProperty, module.exports.__esModule = true, module.exports["default"] = module.exports;
40742 });
40743
40744 var _defineProperty = /*@__PURE__*/getDefaultExportFromCjs(defineProperty);
40745
40746 function count(node) {
40747 var sum = 0,
40748 children = node.children,
40749 i = children && children.length;
40750 if (!i) sum = 1;else while (--i >= 0) sum += children[i].value;
40751 node.value = sum;
40752 }
40753 function node_count () {
40754 return this.eachAfter(count);
40755 }
40756
40757 var arrayLikeToArray = createCommonjsModule(function (module) {
40758 function _arrayLikeToArray(arr, len) {
40759 if (len == null || len > arr.length) len = arr.length;
40760 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
40761 return arr2;
40762 }
40763 module.exports = _arrayLikeToArray, module.exports.__esModule = true, module.exports["default"] = module.exports;
40764 });
40765
40766 var unsupportedIterableToArray = createCommonjsModule(function (module) {
40767 function _unsupportedIterableToArray(o, minLen) {
40768 if (!o) return;
40769 if (typeof o === "string") return arrayLikeToArray(o, minLen);
40770 var n = Object.prototype.toString.call(o).slice(8, -1);
40771 if (n === "Object" && o.constructor) n = o.constructor.name;
40772 if (n === "Map" || n === "Set") return Array.from(o);
40773 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);
40774 }
40775 module.exports = _unsupportedIterableToArray, module.exports.__esModule = true, module.exports["default"] = module.exports;
40776 });
40777
40778 var createForOfIteratorHelper = createCommonjsModule(function (module) {
40779 function _createForOfIteratorHelper(o, allowArrayLike) {
40780 var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
40781 if (!it) {
40782 if (Array.isArray(o) || (it = unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
40783 if (it) o = it;
40784 var i = 0;
40785 var F = function F() {};
40786 return {
40787 s: F,
40788 n: function n() {
40789 if (i >= o.length) return {
40790 done: true
40791 };
40792 return {
40793 done: false,
40794 value: o[i++]
40795 };
40796 },
40797 e: function e(_e) {
40798 throw _e;
40799 },
40800 f: F
40801 };
40802 }
40803 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
40804 }
40805 var normalCompletion = true,
40806 didErr = false,
40807 err;
40808 return {
40809 s: function s() {
40810 it = it.call(o);
40811 },
40812 n: function n() {
40813 var step = it.next();
40814 normalCompletion = step.done;
40815 return step;
40816 },
40817 e: function e(_e2) {
40818 didErr = true;
40819 err = _e2;
40820 },
40821 f: function f() {
40822 try {
40823 if (!normalCompletion && it["return"] != null) it["return"]();
40824 } finally {
40825 if (didErr) throw err;
40826 }
40827 }
40828 };
40829 }
40830 module.exports = _createForOfIteratorHelper, module.exports.__esModule = true, module.exports["default"] = module.exports;
40831 });
40832
40833 var _createForOfIteratorHelper = /*@__PURE__*/getDefaultExportFromCjs(createForOfIteratorHelper);
40834
40835 function node_each (callback, that) {
40836 var index = -1;
40837 var _iterator = _createForOfIteratorHelper(this),
40838 _step;
40839 try {
40840 for (_iterator.s(); !(_step = _iterator.n()).done;) {
40841 var node = _step.value;
40842 callback.call(that, node, ++index, this);
40843 }
40844 } catch (err) {
40845 _iterator.e(err);
40846 } finally {
40847 _iterator.f();
40848 }
40849 return this;
40850 }
40851
40852 function node_eachBefore (callback, that) {
40853 var node = this,
40854 nodes = [node],
40855 children,
40856 i,
40857 index = -1;
40858 while (node = nodes.pop()) {
40859 callback.call(that, node, ++index, this);
40860 if (children = node.children) {
40861 for (i = children.length - 1; i >= 0; --i) {
40862 nodes.push(children[i]);
40863 }
40864 }
40865 }
40866 return this;
40867 }
40868
40869 function node_eachAfter (callback, that) {
40870 var node = this,
40871 nodes = [node],
40872 next = [],
40873 children,
40874 i,
40875 n,
40876 index = -1;
40877 while (node = nodes.pop()) {
40878 next.push(node);
40879 if (children = node.children) {
40880 for (i = 0, n = children.length; i < n; ++i) {
40881 nodes.push(children[i]);
40882 }
40883 }
40884 }
40885 while (node = next.pop()) {
40886 callback.call(that, node, ++index, this);
40887 }
40888 return this;
40889 }
40890
40891 function node_find (callback, that) {
40892 var index = -1;
40893 var _iterator = _createForOfIteratorHelper(this),
40894 _step;
40895 try {
40896 for (_iterator.s(); !(_step = _iterator.n()).done;) {
40897 var node = _step.value;
40898 if (callback.call(that, node, ++index, this)) {
40899 return node;
40900 }
40901 }
40902 } catch (err) {
40903 _iterator.e(err);
40904 } finally {
40905 _iterator.f();
40906 }
40907 }
40908
40909 function node_sum (value) {
40910 return this.eachAfter(function (node) {
40911 var sum = +value(node.data) || 0,
40912 children = node.children,
40913 i = children && children.length;
40914 while (--i >= 0) sum += children[i].value;
40915 node.value = sum;
40916 });
40917 }
40918
40919 function node_sort (compare) {
40920 return this.eachBefore(function (node) {
40921 if (node.children) {
40922 node.children.sort(compare);
40923 }
40924 });
40925 }
40926
40927 function node_path (end) {
40928 var start = this,
40929 ancestor = leastCommonAncestor(start, end),
40930 nodes = [start];
40931 while (start !== ancestor) {
40932 start = start.parent;
40933 nodes.push(start);
40934 }
40935 var k = nodes.length;
40936 while (end !== ancestor) {
40937 nodes.splice(k, 0, end);
40938 end = end.parent;
40939 }
40940 return nodes;
40941 }
40942 function leastCommonAncestor(a, b) {
40943 if (a === b) return a;
40944 var aNodes = a.ancestors(),
40945 bNodes = b.ancestors(),
40946 c = null;
40947 a = aNodes.pop();
40948 b = bNodes.pop();
40949 while (a === b) {
40950 c = a;
40951 a = aNodes.pop();
40952 b = bNodes.pop();
40953 }
40954 return c;
40955 }
40956
40957 function node_ancestors () {
40958 var node = this,
40959 nodes = [node];
40960 while (node = node.parent) {
40961 nodes.push(node);
40962 }
40963 return nodes;
40964 }
40965
40966 function node_descendants () {
40967 return Array.from(this);
40968 }
40969
40970 function node_leaves () {
40971 var leaves = [];
40972 this.eachBefore(function (node) {
40973 if (!node.children) {
40974 leaves.push(node);
40975 }
40976 });
40977 return leaves;
40978 }
40979
40980 function node_links () {
40981 var root = this,
40982 links = [];
40983 root.each(function (node) {
40984 if (node !== root) {
40985 // Don’t include the root’s parent, if any.
40986 links.push({
40987 source: node.parent,
40988 target: node
40989 });
40990 }
40991 });
40992 return links;
40993 }
40994
40995 var regeneratorRuntime$1 = createCommonjsModule(function (module) {
40996 var _typeof = _typeof_1["default"];
40997 function _regeneratorRuntime() {
40998 module.exports = _regeneratorRuntime = function _regeneratorRuntime() {
40999 return e;
41000 }, module.exports.__esModule = true, module.exports["default"] = module.exports;
41001 var t,
41002 e = {},
41003 r = Object.prototype,
41004 n = r.hasOwnProperty,
41005 o = Object.defineProperty || function (t, e, r) {
41006 t[e] = r.value;
41007 },
41008 i = "function" == typeof Symbol ? Symbol : {},
41009 a = i.iterator || "@@iterator",
41010 c = i.asyncIterator || "@@asyncIterator",
41011 u = i.toStringTag || "@@toStringTag";
41012 function define(t, e, r) {
41013 return Object.defineProperty(t, e, {
41014 value: r,
41015 enumerable: !0,
41016 configurable: !0,
41017 writable: !0
41018 }), t[e];
41019 }
41020 try {
41021 define({}, "");
41022 } catch (t) {
41023 define = function define(t, e, r) {
41024 return t[e] = r;
41025 };
41026 }
41027 function wrap(t, e, r, n) {
41028 var i = e && e.prototype instanceof Generator ? e : Generator,
41029 a = Object.create(i.prototype),
41030 c = new Context(n || []);
41031 return o(a, "_invoke", {
41032 value: makeInvokeMethod(t, r, c)
41033 }), a;
41034 }
41035 function tryCatch(t, e, r) {
41036 try {
41037 return {
41038 type: "normal",
41039 arg: t.call(e, r)
41040 };
41041 } catch (t) {
41042 return {
41043 type: "throw",
41044 arg: t
41045 };
41046 }
41047 }
41048 e.wrap = wrap;
41049 var h = "suspendedStart",
41050 l = "suspendedYield",
41051 f = "executing",
41052 s = "completed",
41053 y = {};
41054 function Generator() {}
41055 function GeneratorFunction() {}
41056 function GeneratorFunctionPrototype() {}
41057 var p = {};
41058 define(p, a, function () {
41059 return this;
41060 });
41061 var d = Object.getPrototypeOf,
41062 v = d && d(d(values([])));
41063 v && v !== r && n.call(v, a) && (p = v);
41064 var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
41065 function defineIteratorMethods(t) {
41066 ["next", "throw", "return"].forEach(function (e) {
41067 define(t, e, function (t) {
41068 return this._invoke(e, t);
41069 });
41070 });
41071 }
41072 function AsyncIterator(t, e) {
41073 function invoke(r, o, i, a) {
41074 var c = tryCatch(t[r], t, o);
41075 if ("throw" !== c.type) {
41076 var u = c.arg,
41077 h = u.value;
41078 return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
41079 invoke("next", t, i, a);
41080 }, function (t) {
41081 invoke("throw", t, i, a);
41082 }) : e.resolve(h).then(function (t) {
41083 u.value = t, i(u);
41084 }, function (t) {
41085 return invoke("throw", t, i, a);
41086 });
41087 }
41088 a(c.arg);
41089 }
41090 var r;
41091 o(this, "_invoke", {
41092 value: function value(t, n) {
41093 function callInvokeWithMethodAndArg() {
41094 return new e(function (e, r) {
41095 invoke(t, n, e, r);
41096 });
41097 }
41098 return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
41099 }
41100 });
41101 }
41102 function makeInvokeMethod(e, r, n) {
41103 var o = h;
41104 return function (i, a) {
41105 if (o === f) throw new Error("Generator is already running");
41106 if (o === s) {
41107 if ("throw" === i) throw a;
41108 return {
41109 value: t,
41110 done: !0
41111 };
41112 }
41113 for (n.method = i, n.arg = a;;) {
41114 var c = n.delegate;
41115 if (c) {
41116 var u = maybeInvokeDelegate(c, n);
41117 if (u) {
41118 if (u === y) continue;
41119 return u;
41120 }
41121 }
41122 if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
41123 if (o === h) throw o = s, n.arg;
41124 n.dispatchException(n.arg);
41125 } else "return" === n.method && n.abrupt("return", n.arg);
41126 o = f;
41127 var p = tryCatch(e, r, n);
41128 if ("normal" === p.type) {
41129 if (o = n.done ? s : l, p.arg === y) continue;
41130 return {
41131 value: p.arg,
41132 done: n.done
41133 };
41134 }
41135 "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
41136 }
41137 };
41138 }
41139 function maybeInvokeDelegate(e, r) {
41140 var n = r.method,
41141 o = e.iterator[n];
41142 if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
41143 var i = tryCatch(o, e.iterator, r.arg);
41144 if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
41145 var a = i.arg;
41146 return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
41147 }
41148 function pushTryEntry(t) {
41149 var e = {
41150 tryLoc: t[0]
41151 };
41152 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
41153 }
41154 function resetTryEntry(t) {
41155 var e = t.completion || {};
41156 e.type = "normal", delete e.arg, t.completion = e;
41157 }
41158 function Context(t) {
41159 this.tryEntries = [{
41160 tryLoc: "root"
41161 }], t.forEach(pushTryEntry, this), this.reset(!0);
41162 }
41163 function values(e) {
41164 if (e || "" === e) {
41165 var r = e[a];
41166 if (r) return r.call(e);
41167 if ("function" == typeof e.next) return e;
41168 if (!isNaN(e.length)) {
41169 var o = -1,
41170 i = function next() {
41171 for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
41172 return next.value = t, next.done = !0, next;
41173 };
41174 return i.next = i;
41175 }
41176 }
41177 throw new TypeError(_typeof(e) + " is not iterable");
41178 }
41179 return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
41180 value: GeneratorFunctionPrototype,
41181 configurable: !0
41182 }), o(GeneratorFunctionPrototype, "constructor", {
41183 value: GeneratorFunction,
41184 configurable: !0
41185 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
41186 var e = "function" == typeof t && t.constructor;
41187 return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
41188 }, e.mark = function (t) {
41189 return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
41190 }, e.awrap = function (t) {
41191 return {
41192 __await: t
41193 };
41194 }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
41195 return this;
41196 }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
41197 void 0 === i && (i = Promise);
41198 var a = new AsyncIterator(wrap(t, r, n, o), i);
41199 return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
41200 return t.done ? t.value : a.next();
41201 });
41202 }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
41203 return this;
41204 }), define(g, "toString", function () {
41205 return "[object Generator]";
41206 }), e.keys = function (t) {
41207 var e = Object(t),
41208 r = [];
41209 for (var n in e) r.push(n);
41210 return r.reverse(), function next() {
41211 for (; r.length;) {
41212 var t = r.pop();
41213 if (t in e) return next.value = t, next.done = !1, next;
41214 }
41215 return next.done = !0, next;
41216 };
41217 }, e.values = values, Context.prototype = {
41218 constructor: Context,
41219 reset: function reset(e) {
41220 if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
41221 },
41222 stop: function stop() {
41223 this.done = !0;
41224 var t = this.tryEntries[0].completion;
41225 if ("throw" === t.type) throw t.arg;
41226 return this.rval;
41227 },
41228 dispatchException: function dispatchException(e) {
41229 if (this.done) throw e;
41230 var r = this;
41231 function handle(n, o) {
41232 return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
41233 }
41234 for (var o = this.tryEntries.length - 1; o >= 0; --o) {
41235 var i = this.tryEntries[o],
41236 a = i.completion;
41237 if ("root" === i.tryLoc) return handle("end");
41238 if (i.tryLoc <= this.prev) {
41239 var c = n.call(i, "catchLoc"),
41240 u = n.call(i, "finallyLoc");
41241 if (c && u) {
41242 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
41243 if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
41244 } else if (c) {
41245 if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
41246 } else {
41247 if (!u) throw new Error("try statement without catch or finally");
41248 if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
41249 }
41250 }
41251 }
41252 },
41253 abrupt: function abrupt(t, e) {
41254 for (var r = this.tryEntries.length - 1; r >= 0; --r) {
41255 var o = this.tryEntries[r];
41256 if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
41257 var i = o;
41258 break;
41259 }
41260 }
41261 i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
41262 var a = i ? i.completion : {};
41263 return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
41264 },
41265 complete: function complete(t, e) {
41266 if ("throw" === t.type) throw t.arg;
41267 return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
41268 },
41269 finish: function finish(t) {
41270 for (var e = this.tryEntries.length - 1; e >= 0; --e) {
41271 var r = this.tryEntries[e];
41272 if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
41273 }
41274 },
41275 "catch": function _catch(t) {
41276 for (var e = this.tryEntries.length - 1; e >= 0; --e) {
41277 var r = this.tryEntries[e];
41278 if (r.tryLoc === t) {
41279 var n = r.completion;
41280 if ("throw" === n.type) {
41281 var o = n.arg;
41282 resetTryEntry(r);
41283 }
41284 return o;
41285 }
41286 }
41287 throw new Error("illegal catch attempt");
41288 },
41289 delegateYield: function delegateYield(e, r, n) {
41290 return this.delegate = {
41291 iterator: values(e),
41292 resultName: r,
41293 nextLoc: n
41294 }, "next" === this.method && (this.arg = t), y;
41295 }
41296 }, e;
41297 }
41298 module.exports = _regeneratorRuntime, module.exports.__esModule = true, module.exports["default"] = module.exports;
41299 });
41300
41301 // TODO(Babel 8): Remove this file.
41302
41303 var runtime$1 = regeneratorRuntime$1();
41304 var regenerator = runtime$1;
41305
41306 // Copied from https://github.com/facebook/regenerator/blob/main/packages/runtime/runtime.js#L736=
41307 try {
41308 regeneratorRuntime = runtime$1;
41309 } catch (accidentalStrictMode) {
41310 if (typeof globalThis === "object") {
41311 globalThis.regeneratorRuntime = runtime$1;
41312 } else {
41313 Function("r", "regeneratorRuntime = r")(runtime$1);
41314 }
41315 }
41316
41317 var _marked = /*#__PURE__*/regenerator.mark(_callee);
41318 function _callee() {
41319 var node, current, next, children, i, n;
41320 return regenerator.wrap(function _callee$(_context) {
41321 while (1) switch (_context.prev = _context.next) {
41322 case 0:
41323 node = this, next = [node];
41324 case 1:
41325 current = next.reverse(), next = [];
41326 case 2:
41327 if (!(node = current.pop())) {
41328 _context.next = 8;
41329 break;
41330 }
41331 _context.next = 5;
41332 return node;
41333 case 5:
41334 if (children = node.children) {
41335 for (i = 0, n = children.length; i < n; ++i) {
41336 next.push(children[i]);
41337 }
41338 }
41339 _context.next = 2;
41340 break;
41341 case 8:
41342 if (next.length) {
41343 _context.next = 1;
41344 break;
41345 }
41346 case 9:
41347 case "end":
41348 return _context.stop();
41349 }
41350 }, _marked, this);
41351 }
41352
41353 function hierarchy(data, children) {
41354 if (data instanceof Map) {
41355 data = [undefined, data];
41356 if (children === undefined) children = mapChildren;
41357 } else if (children === undefined) {
41358 children = objectChildren;
41359 }
41360 var root = new Node$1(data),
41361 node,
41362 nodes = [root],
41363 child,
41364 childs,
41365 i,
41366 n;
41367 while (node = nodes.pop()) {
41368 if ((childs = children(node.data)) && (n = (childs = Array.from(childs)).length)) {
41369 node.children = childs;
41370 for (i = n - 1; i >= 0; --i) {
41371 nodes.push(child = childs[i] = new Node$1(childs[i]));
41372 child.parent = node;
41373 child.depth = node.depth + 1;
41374 }
41375 }
41376 }
41377 return root.eachBefore(computeHeight);
41378 }
41379 function node_copy() {
41380 return hierarchy(this).eachBefore(copyData);
41381 }
41382 function objectChildren(d) {
41383 return d.children;
41384 }
41385 function mapChildren(d) {
41386 return Array.isArray(d) ? d[1] : null;
41387 }
41388 function copyData(node) {
41389 if (node.data.value !== undefined) node.value = node.data.value;
41390 node.data = node.data.data;
41391 }
41392 function computeHeight(node) {
41393 var height = 0;
41394 do node.height = height; while ((node = node.parent) && node.height < ++height);
41395 }
41396 function Node$1(data) {
41397 this.data = data;
41398 this.depth = this.height = 0;
41399 this.parent = null;
41400 }
41401 Node$1.prototype = hierarchy.prototype = _defineProperty({
41402 constructor: Node$1,
41403 count: node_count,
41404 each: node_each,
41405 eachAfter: node_eachAfter,
41406 eachBefore: node_eachBefore,
41407 find: node_find,
41408 sum: node_sum,
41409 sort: node_sort,
41410 path: node_path,
41411 ancestors: node_ancestors,
41412 descendants: node_descendants,
41413 leaves: node_leaves,
41414 links: node_links,
41415 copy: node_copy
41416 }, Symbol.iterator, _callee);
41417
41418 function required(f) {
41419 if (typeof f !== "function") throw new Error();
41420 return f;
41421 }
41422
41423 function constantZero() {
41424 return 0;
41425 }
41426 function constant$1 (x) {
41427 return function () {
41428 return x;
41429 };
41430 }
41431
41432 function roundNode (node) {
41433 node.x0 = Math.round(node.x0);
41434 node.y0 = Math.round(node.y0);
41435 node.x1 = Math.round(node.x1);
41436 node.y1 = Math.round(node.y1);
41437 }
41438
41439 function treemapDice (parent, x0, y0, x1, y1) {
41440 var nodes = parent.children,
41441 node,
41442 i = -1,
41443 n = nodes.length,
41444 k = parent.value && (x1 - x0) / parent.value;
41445 while (++i < n) {
41446 node = nodes[i], node.y0 = y0, node.y1 = y1;
41447 node.x0 = x0, node.x1 = x0 += node.value * k;
41448 }
41449 }
41450
41451 function partition () {
41452 var dx = 1,
41453 dy = 1,
41454 padding = 0,
41455 round = false;
41456 function partition(root) {
41457 var n = root.height + 1;
41458 root.x0 = root.y0 = padding;
41459 root.x1 = dx;
41460 root.y1 = dy / n;
41461 root.eachBefore(positionNode(dy, n));
41462 if (round) root.eachBefore(roundNode);
41463 return root;
41464 }
41465 function positionNode(dy, n) {
41466 return function (node) {
41467 if (node.children) {
41468 treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
41469 }
41470 var x0 = node.x0,
41471 y0 = node.y0,
41472 x1 = node.x1 - padding,
41473 y1 = node.y1 - padding;
41474 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
41475 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
41476 node.x0 = x0;
41477 node.y0 = y0;
41478 node.x1 = x1;
41479 node.y1 = y1;
41480 };
41481 }
41482 partition.round = function (x) {
41483 return arguments.length ? (round = !!x, partition) : round;
41484 };
41485 partition.size = function (x) {
41486 return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
41487 };
41488 partition.padding = function (x) {
41489 return arguments.length ? (padding = +x, partition) : padding;
41490 };
41491 return partition;
41492 }
41493
41494 function treemapSlice (parent, x0, y0, x1, y1) {
41495 var nodes = parent.children,
41496 node,
41497 i = -1,
41498 n = nodes.length,
41499 k = parent.value && (y1 - y0) / parent.value;
41500 while (++i < n) {
41501 node = nodes[i], node.x0 = x0, node.x1 = x1;
41502 node.y0 = y0, node.y1 = y0 += node.value * k;
41503 }
41504 }
41505
41506 var phi = (1 + Math.sqrt(5)) / 2;
41507 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
41508 var rows = [],
41509 nodes = parent.children,
41510 row,
41511 nodeValue,
41512 i0 = 0,
41513 i1 = 0,
41514 n = nodes.length,
41515 dx,
41516 dy,
41517 value = parent.value,
41518 sumValue,
41519 minValue,
41520 maxValue,
41521 newRatio,
41522 minRatio,
41523 alpha,
41524 beta;
41525 while (i0 < n) {
41526 dx = x1 - x0, dy = y1 - y0;
41527
41528 // Find the next non-empty node.
41529 do sumValue = nodes[i1++].value; while (!sumValue && i1 < n);
41530 minValue = maxValue = sumValue;
41531 alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
41532 beta = sumValue * sumValue * alpha;
41533 minRatio = Math.max(maxValue / beta, beta / minValue);
41534
41535 // Keep adding nodes while the aspect ratio maintains or improves.
41536 for (; i1 < n; ++i1) {
41537 sumValue += nodeValue = nodes[i1].value;
41538 if (nodeValue < minValue) minValue = nodeValue;
41539 if (nodeValue > maxValue) maxValue = nodeValue;
41540 beta = sumValue * sumValue * alpha;
41541 newRatio = Math.max(maxValue / beta, beta / minValue);
41542 if (newRatio > minRatio) {
41543 sumValue -= nodeValue;
41544 break;
41545 }
41546 minRatio = newRatio;
41547 }
41548
41549 // Position and record the row orientation.
41550 rows.push(row = {
41551 value: sumValue,
41552 dice: dx < dy,
41553 children: nodes.slice(i0, i1)
41554 });
41555 if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
41556 value -= sumValue, i0 = i1;
41557 }
41558 return rows;
41559 }
41560 var squarify = (function custom(ratio) {
41561 function squarify(parent, x0, y0, x1, y1) {
41562 squarifyRatio(ratio, parent, x0, y0, x1, y1);
41563 }
41564 squarify.ratio = function (x) {
41565 return custom((x = +x) > 1 ? x : 1);
41566 };
41567 return squarify;
41568 })(phi);
41569
41570 function treemap () {
41571 var tile = squarify,
41572 round = false,
41573 dx = 1,
41574 dy = 1,
41575 paddingStack = [0],
41576 paddingInner = constantZero,
41577 paddingTop = constantZero,
41578 paddingRight = constantZero,
41579 paddingBottom = constantZero,
41580 paddingLeft = constantZero;
41581 function treemap(root) {
41582 root.x0 = root.y0 = 0;
41583 root.x1 = dx;
41584 root.y1 = dy;
41585 root.eachBefore(positionNode);
41586 paddingStack = [0];
41587 if (round) root.eachBefore(roundNode);
41588 return root;
41589 }
41590 function positionNode(node) {
41591 var p = paddingStack[node.depth],
41592 x0 = node.x0 + p,
41593 y0 = node.y0 + p,
41594 x1 = node.x1 - p,
41595 y1 = node.y1 - p;
41596 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
41597 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
41598 node.x0 = x0;
41599 node.y0 = y0;
41600 node.x1 = x1;
41601 node.y1 = y1;
41602 if (node.children) {
41603 p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
41604 x0 += paddingLeft(node) - p;
41605 y0 += paddingTop(node) - p;
41606 x1 -= paddingRight(node) - p;
41607 y1 -= paddingBottom(node) - p;
41608 if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
41609 if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
41610 tile(node, x0, y0, x1, y1);
41611 }
41612 }
41613 treemap.round = function (x) {
41614 return arguments.length ? (round = !!x, treemap) : round;
41615 };
41616 treemap.size = function (x) {
41617 return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
41618 };
41619 treemap.tile = function (x) {
41620 return arguments.length ? (tile = required(x), treemap) : tile;
41621 };
41622 treemap.padding = function (x) {
41623 return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
41624 };
41625 treemap.paddingInner = function (x) {
41626 return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$1(+x), treemap) : paddingInner;
41627 };
41628 treemap.paddingOuter = function (x) {
41629 return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
41630 };
41631 treemap.paddingTop = function (x) {
41632 return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$1(+x), treemap) : paddingTop;
41633 };
41634 treemap.paddingRight = function (x) {
41635 return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$1(+x), treemap) : paddingRight;
41636 };
41637 treemap.paddingBottom = function (x) {
41638 return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$1(+x), treemap) : paddingBottom;
41639 };
41640 treemap.paddingLeft = function (x) {
41641 return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$1(+x), treemap) : paddingLeft;
41642 };
41643 return treemap;
41644 }
41645
41646 function treemapBinary (parent, x0, y0, x1, y1) {
41647 var nodes = parent.children,
41648 i,
41649 n = nodes.length,
41650 sum,
41651 sums = new Array(n + 1);
41652 for (sums[0] = sum = i = 0; i < n; ++i) {
41653 sums[i + 1] = sum += nodes[i].value;
41654 }
41655 partition(0, n, parent.value, x0, y0, x1, y1);
41656 function partition(i, j, value, x0, y0, x1, y1) {
41657 if (i >= j - 1) {
41658 var node = nodes[i];
41659 node.x0 = x0, node.y0 = y0;
41660 node.x1 = x1, node.y1 = y1;
41661 return;
41662 }
41663 var valueOffset = sums[i],
41664 valueTarget = value / 2 + valueOffset,
41665 k = i + 1,
41666 hi = j - 1;
41667 while (k < hi) {
41668 var mid = k + hi >>> 1;
41669 if (sums[mid] < valueTarget) k = mid + 1;else hi = mid;
41670 }
41671 if (valueTarget - sums[k - 1] < sums[k] - valueTarget && i + 1 < k) --k;
41672 var valueLeft = sums[k] - valueOffset,
41673 valueRight = value - valueLeft;
41674 if (x1 - x0 > y1 - y0) {
41675 var xk = value ? (x0 * valueRight + x1 * valueLeft) / value : x1;
41676 partition(i, k, valueLeft, x0, y0, xk, y1);
41677 partition(k, j, valueRight, xk, y0, x1, y1);
41678 } else {
41679 var yk = value ? (y0 * valueRight + y1 * valueLeft) / value : y1;
41680 partition(i, k, valueLeft, x0, y0, x1, yk);
41681 partition(k, j, valueRight, x0, yk, x1, y1);
41682 }
41683 }
41684 }
41685
41686 var withTreemap = function withTreemap(View) {
41687 return /** @class */function (_super) {
41688 __extends(Treemap, _super);
41689 function Treemap(props, context) {
41690 var _this = _super.call(this, props, context) || this;
41691 var color = props.color,
41692 data = props.data,
41693 theme = props.theme,
41694 _a = props.selection,
41695 selection = _a === void 0 ? {} : _a;
41696 var px2hd = context.px2hd;
41697 context.theme = deepMix(px2hd(Theme), theme);
41698 _this.coord = new coordController();
41699 _this.color = new Category$1(__assign(__assign({
41700 range: context.theme.colors
41701 }, color), {
41702 data: data
41703 }));
41704 var _b = selection.defaultSelected,
41705 defaultSelected = _b === void 0 ? null : _b;
41706 _this.state.selected = defaultSelected;
41707 _this.coordRef = createRef();
41708 _this.records = [];
41709 return _this;
41710 }
41711 Treemap.prototype.isSelected = function (record) {
41712 var state = this.state;
41713 var selected = state.selected;
41714 if (!selected || !selected.length) {
41715 return false;
41716 }
41717 for (var i = 0, len = selected.length; i < len; i++) {
41718 var item = selected[i];
41719 if (equal(record, item)) {
41720 return true;
41721 }
41722 }
41723 return false;
41724 };
41725 Treemap.prototype.getSelectionStyle = function (record) {
41726 var _a = this,
41727 state = _a.state,
41728 props = _a.props;
41729 var selected = state.selected;
41730 if (!selected || !selected.length) {
41731 return null;
41732 }
41733 var selection = props.selection;
41734 var selectedStyle = selection.selectedStyle,
41735 unSelectedStyle = selection.unSelectedStyle;
41736 var isSelected = this.isSelected(record);
41737 if (isSelected) {
41738 return isFunction(selectedStyle) ? selectedStyle(record) : selectedStyle;
41739 }
41740 return isFunction(unSelectedStyle) ? unSelectedStyle(record) : unSelectedStyle;
41741 };
41742 Treemap.prototype.willMount = function () {
41743 var _a = this,
41744 props = _a.props,
41745 coord = _a.coord,
41746 layout = _a.layout;
41747 var coordOption = props.coord;
41748 coord.updateLayout(layout);
41749 coord.create(coordOption);
41750 };
41751 Treemap.prototype.willReceiveProps = function (nextProps) {
41752 var nextSelection = nextProps.selection;
41753 var lastSelection = this.props.selection;
41754 if (!nextSelection || !lastSelection) {
41755 return;
41756 }
41757 var nextDefaultSelected = nextSelection.defaultSelected;
41758 var lastDefaultSelected = lastSelection.defaultSelected;
41759 if (!equal(nextDefaultSelected, lastDefaultSelected)) {
41760 this.state.selected = nextDefaultSelected;
41761 }
41762 };
41763 Treemap.prototype.treemapLayout = function () {
41764 var _this = this;
41765 var _a = this,
41766 props = _a.props,
41767 coord = _a.coord,
41768 colorAttr = _a.color;
41769 var _b = coord.getCoord(),
41770 width = _b.width,
41771 height = _b.height;
41772 var data = props.data,
41773 value = props.value,
41774 _c = props.space,
41775 space = _c === void 0 ? 0 : _c;
41776 var root = hierarchy({
41777 children: data
41778 }).sum(function (d) {
41779 return d[value];
41780 }).sort(function (a, b) {
41781 return b[value] - a[value];
41782 });
41783 var treemapLayout = treemap()
41784 // 默认treemapSquarify
41785 .tile(treemapBinary).round(false).size([width, height])
41786 // .padding(1);
41787 .paddingInner(space);
41788 // .paddingOuter(options.paddingOuter)
41789 // .paddingTop(options.paddingTop)
41790 // .paddingRight(options.paddingRight)
41791 // .paddingBottom(options.paddingBottom)
41792 // .paddingLeft(options.paddingLeft);
41793 var nodes = treemapLayout(root);
41794 return nodes.children.map(function (item) {
41795 var data = item.data,
41796 x0 = item.x0,
41797 y0 = item.y0,
41798 x1 = item.x1,
41799 y1 = item.y1;
41800 var color = colorAttr.mapping(data[colorAttr.field]);
41801 var rect = {
41802 xMin: x0,
41803 xMax: x1,
41804 yMin: y0,
41805 yMax: y1
41806 };
41807 var style = _this.getSelectionStyle(data);
41808 return __assign(__assign({
41809 key: data.key,
41810 origin: data,
41811 color: color
41812 }, rect), {
41813 style: style
41814 });
41815 });
41816 };
41817 Treemap.prototype.select = function (ev, trigger) {
41818 var _this = this;
41819 var points = ev.points,
41820 x = ev.canvasX,
41821 y = ev.canvasY;
41822 var _a = this.props.selection,
41823 selection = _a === void 0 ? {} : _a;
41824 var triggerOn = selection.triggerOn,
41825 _b = selection.type,
41826 type = _b === void 0 ? 'single' : _b,
41827 _c = selection.cancelable,
41828 cancelable = _c === void 0 ? true : _c;
41829 if (!triggerOn || trigger !== triggerOn) return;
41830 var point = triggerOn === 'click' ? {
41831 x: x,
41832 y: y
41833 } : points[0];
41834 var selected = this.state.selected;
41835 var origin = [];
41836 each(this.records, function (record) {
41837 if (point.x >= record.xMin && point.x <= record.xMax && point.y >= record.yMin && point.y <= record.yMax) {
41838 origin.push(record === null || record === void 0 ? void 0 : record.origin);
41839 }
41840 });
41841 // 没选中元素
41842 if (!origin) {
41843 this.setState({
41844 selected: null
41845 });
41846 return;
41847 }
41848 if (!selected) {
41849 this.setState({
41850 selected: origin
41851 });
41852 return;
41853 }
41854 // 单选
41855 var newSelected = [];
41856 origin.forEach(function (record) {
41857 if (!_this.isSelected(record)) {
41858 newSelected.push(record);
41859 }
41860 });
41861 if (type === 'single') {
41862 this.setState({
41863 selected: cancelable ? newSelected : origin
41864 });
41865 return;
41866 }
41867 this.setState({
41868 selected: __spreadArray(__spreadArray([], newSelected, true), selected, true)
41869 });
41870 };
41871 Treemap.prototype.render = function () {
41872 var _this = this;
41873 var nodes = this.treemapLayout();
41874 this.records = nodes;
41875 var _a = this,
41876 props = _a.props,
41877 coord = _a.coord;
41878 var _b = coord.getCoord(),
41879 width = _b.width,
41880 height = _b.height;
41881 return jsx("group", {
41882 style: {
41883 width: width,
41884 height: height,
41885 fill: 'transparent'
41886 },
41887 onClick: function onClick(ev) {
41888 return _this.select(ev, 'click');
41889 },
41890 onPress: function onPress(ev) {
41891 return _this.select(ev, 'press');
41892 }
41893 }, jsx(View, __assign({
41894 nodes: nodes
41895 }, props, {
41896 coord: coord.getCoord()
41897 })));
41898 };
41899 return Treemap;
41900 }(Component);
41901 };
41902
41903 var TreemapView = (function (props // Coord 在 withTreemap 被转成 Coord 类型了,所以这里需要重新定义
41904 ) {
41905 var nodes = props.nodes,
41906 coord = props.coord,
41907 onClick = props.onClick,
41908 _a = props.label,
41909 label = _a === void 0 ? false : _a;
41910 if (coord.isPolar) {
41911 var center = coord.center;
41912 var x_1 = center.x,
41913 y_1 = center.y;
41914 return jsx("group", null, nodes.map(function (node) {
41915 var xMin = node.xMin,
41916 xMax = node.xMax,
41917 yMin = node.yMin,
41918 yMax = node.yMax,
41919 color = node.color,
41920 style = node.style;
41921 return jsx("sector", {
41922 style: __assign({
41923 cx: x_1,
41924 cy: y_1,
41925 lineWidth: '1px',
41926 stroke: '#fff',
41927 startAngle: xMin,
41928 endAngle: xMax,
41929 r0: yMin,
41930 r: yMax,
41931 fill: color
41932 }, style),
41933 onClick: onClick ? function () {
41934 return onClick(node);
41935 } : null
41936 });
41937 }));
41938 }
41939 return jsx("group", null, nodes.map(function (node) {
41940 var key = node.key,
41941 xMin = node.xMin,
41942 xMax = node.xMax,
41943 yMin = node.yMin,
41944 yMax = node.yMax,
41945 color = node.color,
41946 style = node.style;
41947 return jsx("group", null, jsx("rect", {
41948 key: key,
41949 style: __assign({
41950 x: xMin,
41951 y: yMin,
41952 width: xMax - xMin,
41953 height: yMax - yMin,
41954 fill: color,
41955 lineWidth: '4px',
41956 stroke: '#fff',
41957 radius: '8px'
41958 }, style),
41959 animation: {
41960 appear: {
41961 easing: 'linear',
41962 duration: 450,
41963 property: ['fillOpacity', 'strokeOpacity'],
41964 start: {
41965 fillOpacity: 0,
41966 strokeOpacity: 0
41967 }
41968 },
41969 update: {
41970 easing: 'linear',
41971 duration: 450,
41972 property: ['x', 'y', 'width', 'height', 'radius', 'lineWidth', 'fillOpacity', 'strokeOpacity']
41973 }
41974 },
41975 onClick: onClick ? function () {
41976 return onClick(node);
41977 } : null
41978 }), label && jsx("text", {
41979 style: __assign({
41980 x: (xMin + xMax) / 2,
41981 y: (yMin + yMax) / 2,
41982 text: node.origin.name,
41983 fill: 'white',
41984 textAlign: 'center',
41985 textBaseline: 'middle'
41986 }, label)
41987 }));
41988 }));
41989 });
41990
41991 var index$8 = withTreemap(TreemapView);
41992
41993 function rootParent(data) {
41994 var d = data;
41995 while (d.depth > 1) {
41996 d = d.parent;
41997 }
41998 return d;
41999 }
42000 var withSunburst = (function (View) {
42001 return /** @class */function (_super) {
42002 __extends(Sunburst, _super);
42003 function Sunburst(props, context) {
42004 var _this = _super.call(this, props, context) || this;
42005 var color = props.color,
42006 data = props.data;
42007 _this.coord = new coordController();
42008 _this.color = new Category$1(__assign(__assign({
42009 range: Theme.colors
42010 }, color), {
42011 data: data
42012 }));
42013 return _this;
42014 }
42015 Sunburst.prototype.willMount = function () {
42016 var _a = this,
42017 props = _a.props,
42018 coord = _a.coord,
42019 layout = _a.layout;
42020 var coordOption = props.coord;
42021 coord.updateLayout(layout);
42022 coord.create(coordOption);
42023 };
42024 Sunburst.prototype.didMount = function () {};
42025 Sunburst.prototype._mapping = function (children) {
42026 var _a = this,
42027 colorAttr = _a.color,
42028 coord = _a.coord;
42029 for (var i = 0, len = children.length; i < len; i++) {
42030 var node = children[i];
42031 var root = rootParent(node);
42032 var color = colorAttr.mapping(root.data[colorAttr.field]);
42033 node.color = color;
42034 var x0 = node.x0,
42035 x1 = node.x1,
42036 y0 = node.y0,
42037 y1 = node.y1;
42038 var rect = coord.getCoord().convertRect({
42039 x: [x0, x1],
42040 y: [y0, y1]
42041 });
42042 mix(node, rect);
42043 // 递归处理
42044 if (node.children && node.children.length) {
42045 this._mapping(node.children);
42046 }
42047 }
42048 };
42049 Sunburst.prototype.sunburst = function () {
42050 var props = this.props;
42051 var data = props.data,
42052 value = props.value,
42053 _a = props.sort,
42054 sort = _a === void 0 ? true : _a;
42055 var root = hierarchy({
42056 children: data
42057 }).sum(function (d) {
42058 return d[value];
42059 });
42060 // 内置按value大小顺序排序,支持传入sort函数
42061 if (sort === true || isFunction(sort)) {
42062 var sortFn = isFunction(sort) ? sort : function (a, b) {
42063 return b[value] - a[value];
42064 };
42065 root.sort(sortFn);
42066 }
42067 var nodes = partition()(root);
42068 var children = nodes.children;
42069 this._mapping(children);
42070 return nodes;
42071 };
42072 Sunburst.prototype.render = function () {
42073 var node = this.sunburst();
42074 var _a = this,
42075 coord = _a.coord,
42076 props = _a.props;
42077 return jsx(View, __assign({}, props, {
42078 coord: coord.getCoord(),
42079 node: node,
42080 triggerRef: this.triggerRef
42081 }));
42082 };
42083 return Sunburst;
42084 }(Component);
42085 });
42086
42087 var SunburstView = (function (props) {
42088 var coord = props.coord,
42089 node = props.node,
42090 onClick = props.onClick;
42091 var children = node.children;
42092 var _a = coord.center,
42093 x = _a.x,
42094 y = _a.y;
42095 var renderNodes = function renderNodes(nodes) {
42096 return jsx("group", null, nodes.map(function (node) {
42097 var xMin = node.xMin,
42098 xMax = node.xMax,
42099 yMin = node.yMin,
42100 yMax = node.yMax,
42101 color = node.color,
42102 children = node.children;
42103 return jsx("group", {
42104 onClick: onClick
42105 }, jsx("sector", {
42106 attrs: {
42107 cx: x,
42108 cy: y,
42109 lineWidth: '1px',
42110 stroke: '#fff',
42111 startAngle: "".concat(xMin, " rad"),
42112 endAngle: "".concat(xMax, " rad"),
42113 r0: yMin,
42114 r: yMax,
42115 fill: color
42116 }
42117 }), children && children.length ? renderNodes(children) : null);
42118 }));
42119 };
42120 return renderNodes(children);
42121 });
42122
42123 var IcicleView = (function (props) {
42124 var node = props.node,
42125 onClick = props.onClick;
42126 var children = node.children;
42127 var renderNodes = function renderNodes(nodes) {
42128 return jsx("group", null, nodes.map(function (node) {
42129 var xMin = node.xMin,
42130 xMax = node.xMax,
42131 yMin = node.yMin,
42132 yMax = node.yMax,
42133 color = node.color,
42134 children = node.children;
42135 return jsx("group", {
42136 onClick: onClick
42137 }, jsx("rect", {
42138 attrs: {
42139 x: xMin,
42140 y: yMin,
42141 width: xMax - xMin,
42142 height: yMax - yMin,
42143 lineWidth: '1px',
42144 stroke: '#fff',
42145 fill: color
42146 }
42147 }), children && children.length ? renderNodes(children) : null);
42148 }));
42149 };
42150 return renderNodes(children);
42151 });
42152
42153 var View = (function (props) {
42154 var coord = props.coord;
42155 if (coord.type === 'polar') {
42156 return jsx(SunburstView, __assign({}, props));
42157 }
42158 return jsx(IcicleView, __assign({}, props));
42159 });
42160
42161 var index$9 = withSunburst(View);
42162
42163 var DEFAULT_CONFIG = {
42164 anchorOffset: '10px',
42165 inflectionOffset: '30px',
42166 sidePadding: '15px',
42167 height: '64px',
42168 adjustOffset: '30',
42169 triggerOn: 'click',
42170 // activeShape: false, // 当有图形被选中的时候,是否激活图形
42171 // activeStyle: {
42172 // offset: '1px',
42173 // appendRadius: '8px',
42174 // fillOpacity: 0.5,
42175 // },
42176 label1OffsetY: '-4px',
42177 label2OffsetY: '4px'
42178 };
42179 function getEndPoint(center, angle, r) {
42180 return {
42181 x: center.x + r * Math.cos(angle),
42182 y: center.y + r * Math.sin(angle)
42183 };
42184 }
42185 // 计算中间角度
42186 function getMiddleAngle(startAngle, endAngle) {
42187 if (endAngle < startAngle) {
42188 endAngle += Math.PI * 2;
42189 }
42190 return (endAngle + startAngle) / 2;
42191 }
42192 function move(from, to, count, center) {
42193 var x = center.x;
42194 var sort = from.sort(function (a, b) {
42195 var aDistance = Math.abs(a.x - x);
42196 var bDistance = Math.abs(b.x - x);
42197 return bDistance - aDistance;
42198 });
42199 return [sort.slice(0, sort.length - count), sort.slice(sort.length - count).concat(to)];
42200 }
42201 // 第一象限
42202 function isFirstQuadrant(angle) {
42203 return angle >= -Math.PI / 2 && angle < 0;
42204 }
42205 // 第二象限
42206 function isSecondQuadrant(angle) {
42207 return angle >= 0 && angle < Math.PI / 2;
42208 }
42209 function isThirdQuadrant(angle) {
42210 return angle >= Math.PI / 2 && angle < Math.PI;
42211 }
42212 function isFourthQuadrant(angle) {
42213 return angle >= Math.PI && angle < Math.PI * 3 / 2;
42214 }
42215 var withPieLabel = (function (View) {
42216 return /** @class */function (_super) {
42217 __extends(PieLabel, _super);
42218 function PieLabel(props) {
42219 return _super.call(this, props) || this;
42220 }
42221 PieLabel.prototype.willMount = function () {};
42222 /**
42223 * 绑定事件
42224 */
42225 PieLabel.prototype.didMount = function () {};
42226 PieLabel.prototype.getLabels = function (props) {
42227 var chart = props.chart,
42228 coord = props.coord,
42229 anchorOffset = props.anchorOffset,
42230 inflectionOffset = props.inflectionOffset,
42231 label1 = props.label1,
42232 label2 = props.label2,
42233 itemHeight = props.height,
42234 sidePadding = props.sidePadding;
42235 var center = coord.center,
42236 radius = coord.radius,
42237 coordWidth = coord.width,
42238 coordHeight = coord.height,
42239 coordLeft = coord.left,
42240 coordRight = coord.right,
42241 coordTop = coord.top;
42242 var maxCountForOneSide = Math.floor(coordHeight / itemHeight);
42243 var maxCount = maxCountForOneSide * 2;
42244 var geometry = chart.getGeometrys()[0];
42245 var records = geometry.flatRecords()
42246 // 按角度大到小排序
42247 .sort(function (a, b) {
42248 var angle1 = a.xMax - a.xMin;
42249 var angle2 = b.xMax - b.xMin;
42250 return angle2 - angle1;
42251 })
42252 // 只取前 maxCount 个显示
42253 .slice(0, maxCount);
42254 // 存储左右 labels
42255 var halves = [[], [] // right
42256 ];
42257
42258 records.forEach(function (record) {
42259 var xMin = record.xMin,
42260 xMax = record.xMax,
42261 color = record.color,
42262 origin = record.origin;
42263 // 锚点角度
42264 var anchorAngle = getMiddleAngle(xMin, xMax);
42265 // 锚点坐标
42266 var anchorPoint = getEndPoint(center, anchorAngle, radius + anchorOffset);
42267 // 拐点坐标
42268 var inflectionPoint = getEndPoint(center, anchorAngle, radius + inflectionOffset);
42269 // 锚点方向
42270 var side = anchorPoint.x < center.x ? 'left' : 'right';
42271 var label = {
42272 origin: origin,
42273 angle: anchorAngle,
42274 anchor: anchorPoint,
42275 inflection: inflectionPoint,
42276 side: side,
42277 x: inflectionPoint.x,
42278 y: inflectionPoint.y,
42279 r: radius + inflectionOffset,
42280 color: color,
42281 label1: isFunction(label1) ? label1(origin, record) : label1,
42282 label2: isFunction(label2) ? label2(origin, record) : label2
42283 };
42284 // 判断文本的方向
42285 if (side === 'left') {
42286 halves[0].push(label);
42287 } else {
42288 halves[1].push(label);
42289 }
42290 });
42291 // 判断是有一边超过了显示的最大
42292 if (halves[0].length > maxCountForOneSide) {
42293 halves = move(halves[0], halves[1], halves[0].length - maxCountForOneSide, center);
42294 } else if (halves[1].length > maxCountForOneSide) {
42295 var _a = move(halves[1], halves[0], halves[1].length - maxCountForOneSide, center),
42296 right = _a[0],
42297 left = _a[1];
42298 halves = [left, right];
42299 }
42300 // label 的最大宽度
42301 var labelWidth = coordWidth / 2 - radius - anchorOffset - inflectionOffset - 2 * sidePadding;
42302 var labels = [];
42303 halves.forEach(function (half, index) {
42304 var showSide = index === 0 ? 'left' : 'right';
42305 // 顺时针方向排序
42306 half.sort(function (a, b) {
42307 var aAngle = a.angle;
42308 var bAngle = b.angle;
42309 if (showSide === 'left') {
42310 // 是否在第一象限
42311 aAngle = isFirstQuadrant(aAngle) ? aAngle + Math.PI * 2 : aAngle;
42312 bAngle = isFirstQuadrant(bAngle) ? bAngle + Math.PI * 2 : bAngle;
42313 return bAngle - aAngle;
42314 } else {
42315 // 是否在第四象限
42316 aAngle = isFourthQuadrant(aAngle) ? aAngle - Math.PI * 2 : aAngle;
42317 bAngle = isFourthQuadrant(bAngle) ? bAngle - Math.PI * 2 : bAngle;
42318 return aAngle - bAngle;
42319 }
42320 });
42321 var pointsY = half.map(function (label) {
42322 return label.y;
42323 });
42324 var maxY = Math.max.apply(null, pointsY);
42325 var minY = Math.min.apply(null, pointsY);
42326 // 每个 label 占用的高度
42327 var labelCount = half.length;
42328 var labelHeight = coordHeight / labelCount;
42329 var halfLabelHeight = labelHeight / 2;
42330 // 线之间的间隔
42331 var lineInterval = 2;
42332 if (showSide === 'left') {
42333 half.forEach(function (label, index) {
42334 var anchor = label.anchor,
42335 inflection = label.inflection,
42336 angle = label.angle,
42337 x = label.x,
42338 y = label.y;
42339 var points = [anchor, inflection];
42340 var endX = coordLeft + sidePadding;
42341 var endY = coordTop + halfLabelHeight + labelHeight * index;
42342 // 文本开始点
42343 var labelStart = {
42344 x: endX + labelWidth + lineInterval * index,
42345 y: endY
42346 };
42347 // 文本结束点
42348 var labelEnd = {
42349 x: endX,
42350 y: endY
42351 };
42352 // 第四象限
42353 if (isFirstQuadrant(angle)) {
42354 var pointY = minY - lineInterval * (labelCount - index);
42355 points.push({
42356 x: x,
42357 y: pointY
42358 });
42359 points.push({
42360 x: labelStart.x,
42361 y: pointY
42362 });
42363 } else if (isThirdQuadrant(angle) || isFourthQuadrant(angle)) {
42364 points.push({
42365 x: labelStart.x,
42366 y: y
42367 });
42368 } else if (isSecondQuadrant(angle)) {
42369 var pointY = maxY + lineInterval * index;
42370 points.push({
42371 x: x,
42372 y: pointY
42373 });
42374 points.push({
42375 x: labelStart.x,
42376 y: pointY
42377 });
42378 }
42379 points.push(labelStart);
42380 points.push(labelEnd);
42381 label.points = points;
42382 label.side = showSide;
42383 labels.push(label);
42384 });
42385 } else {
42386 half.forEach(function (label, index) {
42387 var anchor = label.anchor,
42388 inflection = label.inflection,
42389 angle = label.angle,
42390 x = label.x,
42391 y = label.y;
42392 // 折线的点
42393 var points = [anchor, inflection];
42394 var endX = coordRight - sidePadding;
42395 var endY = coordTop + halfLabelHeight + labelHeight * index;
42396 // 文本开始点
42397 var labelStart = {
42398 x: endX - labelWidth - lineInterval * index,
42399 y: endY
42400 };
42401 // 文本结束点
42402 var labelEnd = {
42403 x: endX,
42404 y: endY
42405 };
42406 // 第四象限
42407 if (isFourthQuadrant(angle)) {
42408 var pointY = minY - lineInterval * (labelCount - index);
42409 points.push({
42410 x: x,
42411 y: pointY
42412 });
42413 points.push({
42414 x: labelStart.x,
42415 y: pointY
42416 });
42417 } else if (isFirstQuadrant(angle) || isSecondQuadrant(angle)) {
42418 points.push({
42419 x: labelStart.x,
42420 y: y
42421 });
42422 } else if (isThirdQuadrant(angle)) {
42423 var pointY = maxY + lineInterval * index;
42424 points.push({
42425 x: x,
42426 y: pointY
42427 });
42428 points.push({
42429 x: labelStart.x,
42430 y: pointY
42431 });
42432 }
42433 points.push(labelStart);
42434 points.push(labelEnd);
42435 label.points = points;
42436 label.side = showSide;
42437 labels.push(label);
42438 });
42439 }
42440 });
42441 return labels;
42442 };
42443 PieLabel.prototype.render = function () {
42444 var context = this.context;
42445 var props = context.px2hd(deepMix({}, DEFAULT_CONFIG, this.props));
42446 var labels = this.getLabels(props);
42447 return jsx(View, __assign({
42448 labels: labels
42449 }, props));
42450 };
42451 return PieLabel;
42452 }(Component);
42453 });
42454
42455 var PieLabelView = (function (props) {
42456 var lineStyle = props.lineStyle,
42457 anchorStyle = props.anchorStyle,
42458 labels = props.labels,
42459 label1OffsetY = props.label1OffsetY,
42460 label2OffsetY = props.label2OffsetY,
42461 triggerRef = props.triggerRef,
42462 onClick = props.onClick;
42463 return jsx("group", {
42464 ref: triggerRef
42465 }, labels.map(function (label) {
42466 var origin = label.origin,
42467 anchor = label.anchor,
42468 side = label.side,
42469 color = label.color,
42470 label1 = label.label1,
42471 label2 = label.label2,
42472 points = label.points;
42473 var end = points[points.length - 1];
42474 return jsx("group", {
42475 onClick: onClick ? function () {
42476 onClick(label);
42477 } : null
42478 }, jsx("circle", {
42479 attrs: __assign({
42480 r: '4px',
42481 cx: anchor.x,
42482 cy: anchor.y,
42483 fill: color
42484 }, anchorStyle)
42485 }), jsx("polyline", {
42486 attrs: __assign({
42487 points: points.map(function (d) {
42488 return [d.x, d.y];
42489 }),
42490 lineWidth: '2px',
42491 stroke: color
42492 }, lineStyle)
42493 }), jsx("text", {
42494 className: "click",
42495 attrs: __assign({
42496 x: end.x,
42497 y: end.y + label1OffsetY,
42498 fontSize: '24px',
42499 lineHeight: '24px',
42500 fill: color,
42501 textBaseline: 'bottom',
42502 textAlign: side === 'left' ? 'left' : 'right'
42503 }, label1),
42504 data: origin
42505 }), jsx("text", {
42506 className: "click",
42507 attrs: __assign({
42508 x: end.x,
42509 y: end.y + label2OffsetY,
42510 fontSize: '24px',
42511 lineHeight: '24px',
42512 fill: '#808080',
42513 textBaseline: 'top',
42514 textAlign: side === 'left' ? 'left' : 'right'
42515 }, label2),
42516 data: origin
42517 }));
42518 }));
42519 });
42520
42521 var index$a = withPieLabel(PieLabelView);
42522
42523 var getPoint$1 = function getPoint(cener, angle, r) {
42524 var x = cener.x + Math.cos(angle) * r;
42525 var y = cener.y + Math.sin(angle) * r;
42526 return {
42527 x: x,
42528 y: y
42529 };
42530 };
42531 var getTicks = function getTicks(start, end, tickCount, center, r, tickOffset, tickLength) {
42532 var ticks = [];
42533 var diff = end - start;
42534 for (var i = 0; i <= tickCount; i++) {
42535 var tickValue = start + diff * i / tickCount;
42536 var startPoint = getPoint$1(center, tickValue, r + tickOffset - tickLength);
42537 var endPoint = getPoint$1(center, tickValue, r + tickOffset);
42538 ticks.push({
42539 tickValue: tickValue,
42540 start: startPoint,
42541 end: endPoint
42542 });
42543 }
42544 return ticks;
42545 };
42546 var withGauge = function withGauge(View) {
42547 return /** @class */function (_super) {
42548 __extends(Gauge, _super);
42549 function Gauge() {
42550 return _super !== null && _super.apply(this, arguments) || this;
42551 }
42552 Gauge.prototype.render = function () {
42553 var _a = this,
42554 props = _a.props,
42555 context = _a.context;
42556 var startAngle = props.startAngle,
42557 endAngle = props.endAngle,
42558 tickCount = props.tickCount,
42559 center = props.center,
42560 r = props.r,
42561 tickOffset = props.tickOffset,
42562 tickLength = props.tickLength;
42563 var ticks = getTicks(startAngle, endAngle, tickCount, center, context.px2hd(r), context.px2hd(tickOffset), context.px2hd(tickLength));
42564 return jsx(View, __assign({}, props, {
42565 ticks: ticks
42566 }));
42567 };
42568 return Gauge;
42569 }(Component);
42570 };
42571
42572 var GaugeView = (function (props) {
42573 var center = props.center,
42574 startAngle = props.startAngle,
42575 endAngle = props.endAngle,
42576 r = props.r,
42577 percent = props.percent,
42578 ticks = props.ticks;
42579 var x = center.x,
42580 y = center.y;
42581 var diff = endAngle - startAngle;
42582 return jsx("group", null, jsx("arc", {
42583 attrs: {
42584 cx: x,
42585 cy: y,
42586 r: r,
42587 startAngle: "".concat(startAngle, " rad"),
42588 endAngle: "".concat(endAngle, " rad"),
42589 lineWidth: '20px',
42590 lineCap: 'round',
42591 stroke: '#e7e7e7'
42592 }
42593 }), jsx("arc", {
42594 attrs: {
42595 cx: x,
42596 cy: y,
42597 r: r,
42598 startAngle: "".concat(startAngle, " rad"),
42599 endAngle: "".concat(startAngle, " rad"),
42600 lineWidth: '40px',
42601 lineCap: 'round',
42602 stroke: '#0075ff'
42603 },
42604 animation: {
42605 appear: {
42606 easing: 'linear',
42607 duration: 500,
42608 property: ['endAngle'],
42609 start: {
42610 endAngle: "".concat(startAngle, " rad")
42611 },
42612 end: {
42613 endAngle: "".concat(startAngle + diff * percent, " rad")
42614 }
42615 }
42616 }
42617 }), ticks.map(function (tick) {
42618 var start = tick.start,
42619 end = tick.end;
42620 return jsx("line", {
42621 attrs: {
42622 x1: start.x,
42623 y1: start.y,
42624 x2: end.x,
42625 y2: end.y,
42626 lineWidth: '6px',
42627 lineCap: 'round',
42628 stroke: '#e7e7e7'
42629 }
42630 });
42631 }));
42632 });
42633
42634 var index$b = withGauge(GaugeView);
42635
42636 // 判断新老values是否相等,这里只要判断前后是否相等即可
42637 function isValuesEqual(values, newValues) {
42638 if (values.length !== newValues.length) {
42639 return false;
42640 }
42641 var lastIndex = values.length - 1;
42642 return values[0] === newValues[0] && values[lastIndex] === newValues[lastIndex];
42643 }
42644 function updateCategoryRange(scale, originScale, range) {
42645 var currentValues = scale.values,
42646 currentTicks = scale.ticks,
42647 tickMethod = scale.tickMethod,
42648 tickCount = scale.tickCount;
42649 var originValues = originScale.values;
42650 var start = range[0],
42651 end = range[1];
42652 var len = originValues.length;
42653 var valueStart = start * len;
42654 var valueEnd = end * len;
42655 // 保持滑动时个数的稳定
42656 var diff = valueEnd - valueStart;
42657 var precision = parseFloat(diff.toFixed(3)); // js 计算精度问题
42658 var count = Math.round(precision);
42659 var sliceSatrt = Math.min(Math.round(valueStart), len - count);
42660 // 从原始数据里截取需要显示的数据
42661 var newValues = originValues.slice(sliceSatrt, sliceSatrt + count);
42662 // 根据当前数据的比例,和定义的tickCount计算应该需要多少个ticks
42663 var newTickCount = Math.round(tickCount * originValues.length / newValues.length);
42664 // 计算新的ticks
42665 var catTicks = getTickMethod(tickMethod);
42666 var newTicks = catTicks({
42667 tickCount: newTickCount,
42668 values: originValues
42669 });
42670 // 如果新数组和当前显示的数组相同,则不更新
42671 if (isValuesEqual(currentValues, newValues) && isValuesEqual(currentTicks, newTicks)) {
42672 return;
42673 }
42674 scale.change({
42675 values: newValues,
42676 ticks: newTicks
42677 });
42678 return scale;
42679 }
42680 function updateLinearRange(scale, originScale, range) {
42681 var min = originScale.min,
42682 max = originScale.max;
42683 var start = range[0],
42684 end = range[1];
42685 var newMin = min + (max - min) * start;
42686 var newMax = min + (max - min) * end;
42687 scale.change({
42688 min: newMin,
42689 max: newMax,
42690 nice: false
42691 });
42692 }
42693 function updateScale(scale, values) {
42694 var isLinear = scale.isLinear;
42695 if (isLinear) {
42696 var _a = getRange(values),
42697 min = _a.min,
42698 max = _a.max;
42699 return scale.change({
42700 min: min,
42701 max: max,
42702 nice: true
42703 });
42704 }
42705 }
42706 function updateRange(scale, originScale, range) {
42707 var isCategory = scale.isCategory,
42708 isLinear = scale.isLinear;
42709 if (isCategory) {
42710 return updateCategoryRange(scale, originScale, range);
42711 }
42712 if (isLinear) {
42713 return updateLinearRange(scale, originScale, range);
42714 }
42715 }
42716 function updateFollow(scales, mainScale, data) {
42717 var mainField = mainScale.field,
42718 mainType = mainScale.type,
42719 mainValues = mainScale.values;
42720 // 转成 map 提高查询性能
42721 var mainValuesMap = {};
42722 mainValues.forEach(function (item) {
42723 mainValuesMap[item] = true;
42724 });
42725 return scales.map(function (scale) {
42726 var followField = scale.field;
42727 var values = [];
42728 data.forEach(function (item) {
42729 var value = mainType === 'timeCat' ? toTimeStamp$1(item[mainField]) : item[mainField];
42730 if (mainValuesMap[value]) {
42731 var followItemValue = item[followField];
42732 if (isArray(followItemValue)) {
42733 values.push.apply(values, followItemValue);
42734 } else {
42735 values.push(followItemValue);
42736 }
42737 }
42738 });
42739 return updateScale(scale, values);
42740 });
42741 }
42742
42743 function quadraticOut(k) {
42744 return k * (2 - k);
42745 }
42746
42747 function lerp$1(min, max, fraction) {
42748 return (max - min) * fraction + min;
42749 }
42750 function isNumberEqualRange(aRange, bRange) {
42751 if (!bRange) return false;
42752 for (var i = 0, len = aRange.length; i < len; i++) {
42753 if (!isNumberEqual(aRange[i], bRange[i])) return false;
42754 }
42755 return true;
42756 }
42757 function isEqualRange(aRange, bRange) {
42758 if (!bRange) return false;
42759 if (isArray(aRange)) {
42760 return isNumberEqualRange(aRange, bRange);
42761 }
42762 // object
42763 for (var i in aRange) {
42764 if (!isNumberEqualRange(aRange[i], bRange[i])) return false;
42765 }
42766 return true;
42767 }
42768 function cloneScale$1(scale, scaleConfig) {
42769 // @ts-ignore
42770 return new scale.constructor(__assign(__assign({}, scale.__cfg__), scaleConfig));
42771 }
42772 var withZoom = (function (View) {
42773 return /** @class */function (_super) {
42774 __extends(Zoom, _super);
42775 function Zoom(props) {
42776 var _this = this;
42777 var defaultProps = {
42778 onPanStart: function onPanStart() {},
42779 onPinchStart: function onPinchStart() {},
42780 onPan: function onPan() {},
42781 onPinch: function onPinch() {},
42782 onInit: function onInit() {},
42783 onPanEnd: function onPanEnd() {},
42784 onPinchEnd: function onPinchEnd() {},
42785 minCount: 10
42786 };
42787 _this = _super.call(this, __assign(__assign({}, defaultProps), props)) || this;
42788 _this.scale = {};
42789 _this.originScale = {};
42790 //swipe end x y
42791 _this.swipeEnd = {
42792 startX: 0,
42793 startY: 0,
42794 endX: 0,
42795 endY: 0
42796 };
42797 _this.onStart = function () {
42798 var state = _this.state;
42799 var range = state.range;
42800 _this.startRange = range;
42801 _this.loop && cancelAnimationFrame(_this.loop);
42802 };
42803 _this.onPan = function (ev) {
42804 var dims = _this.dims;
42805 var range = {};
42806 each(dims, function (dim) {
42807 if (dim === 'x') {
42808 range['x'] = _this._doXPan(ev);
42809 return;
42810 }
42811 if (dim === 'y') {
42812 range['y'] = _this._doYPan(ev);
42813 return;
42814 }
42815 });
42816 _this.renderRange(range);
42817 };
42818 _this.onSwipe = function (ev) {
42819 var _a = _this,
42820 props = _a.props,
42821 state = _a.state;
42822 // 滑动速率
42823 var velocity = ev.velocity,
42824 direction = ev.direction,
42825 _b = ev.velocityX,
42826 velocityX = _b === void 0 ? 0 : _b,
42827 _c = ev.velocityY,
42828 velocityY = _c === void 0 ? 0 : _c,
42829 points = ev.points;
42830 var mode = props.mode,
42831 swipe = props.swipe;
42832 var range = state.range;
42833 if (!swipe || !mode) {
42834 return;
42835 }
42836 if (mode.length === 1) {
42837 _this.animateSwipe(mode, range[mode], direction === 'right' || direction === 'down' ? -velocity : velocity);
42838 return;
42839 }
42840 var _d = points[0],
42841 x = _d.x,
42842 y = _d.y;
42843 // 边界处理
42844 if (Math.abs((range === null || range === void 0 ? void 0 : range.x[0]) - 0) < 0.0005 && velocityX > 0) return;
42845 if (Math.abs((range === null || range === void 0 ? void 0 : range.x[1]) - 1) < 0.0005 && velocityX < 0) return;
42846 if (Math.abs((range === null || range === void 0 ? void 0 : range.y[0]) - 0) < 0.0005 && velocityY < 0) return;
42847 if (Math.abs((range === null || range === void 0 ? void 0 : range.x[1]) - 1) < 0.0005 && velocityY > 0) return;
42848 _this.swipeEnd = {
42849 startX: x,
42850 startY: y,
42851 endX: x + velocityX * 50,
42852 endY: y - velocityY * 50
42853 };
42854 _this.onStart();
42855 _this.update();
42856 };
42857 _this.onPinch = function (ev) {
42858 var dims = _this.dims;
42859 var range = {};
42860 each(dims, function (dim) {
42861 if (dim === 'x') {
42862 range['x'] = _this._doXPinch(ev);
42863 return;
42864 }
42865 if (dim === 'y') {
42866 range['y'] = _this._doYPinch(ev);
42867 return;
42868 }
42869 });
42870 _this.renderRange(range);
42871 };
42872 _this.onEnd = function () {
42873 _this.startRange = null;
42874 };
42875 var mode = props.mode;
42876 _this.dims = isArray(mode) ? mode : [mode];
42877 return _this;
42878 }
42879 Zoom.prototype.didMount = function () {
42880 var scale = this.scale;
42881 var onInit = this.props.onInit;
42882 onInit({
42883 scale: scale
42884 });
42885 this._bindEvents();
42886 };
42887 Zoom.prototype.willReceiveProps = function (nextProps) {
42888 var nextRange = nextProps.range;
42889 var lastRange = this.props.range;
42890 if (!equal(nextRange, lastRange)) {
42891 var cacheRange_1 = {};
42892 each(this.dims, function (dim) {
42893 cacheRange_1[dim] = nextRange;
42894 });
42895 this.state = {
42896 range: cacheRange_1
42897 };
42898 }
42899 };
42900 Zoom.prototype.willMount = function () {
42901 var _this = this;
42902 var _a = this,
42903 props = _a.props,
42904 dims = _a.dims;
42905 var minCount = props.minCount,
42906 range = props.range;
42907 var valueLength = Number.MIN_VALUE;
42908 var cacheRange = {};
42909 each(dims, function (dim) {
42910 var scale = _this._getScale(dim);
42911 var values = scale.values;
42912 valueLength = values.length > valueLength ? values.length : valueLength;
42913 _this.scale[dim] = scale;
42914 _this.originScale[dim] = cloneScale$1(scale);
42915 _this.updateRange(range, dim);
42916 cacheRange[dim] = range;
42917 });
42918 // 图表上最少显示 MIN_COUNT 个数据
42919 this.minScale = minCount / valueLength;
42920 this.renderRange(cacheRange);
42921 };
42922 Zoom.prototype.willUpdate = function () {
42923 var _this = this;
42924 var _a = this,
42925 props = _a.props,
42926 state = _a.state,
42927 dims = _a.dims;
42928 var minCount = props.minCount,
42929 range = props.range;
42930 var valueLength = Number.MIN_VALUE;
42931 var cacheRange = {};
42932 each(dims, function (dim) {
42933 var scale = _this._getScale(dim);
42934 // scale 没有变化, 不处理
42935 if (scale === _this.scale[dim]) {
42936 return;
42937 }
42938 var values = scale.values;
42939 valueLength = values.length > valueLength ? values.length : valueLength;
42940 _this.scale[dim] = scale;
42941 _this.originScale[dim] = cloneScale$1(scale);
42942 // 让 range 触发更新
42943 _this.state.range[dim] = [0, 1];
42944 _this.updateRange(range, dim);
42945 cacheRange[dim] = range;
42946 });
42947 // 有变化
42948 if (Object.keys(cacheRange).length > 0) {
42949 this.minScale = minCount / valueLength;
42950 var newRange = __assign(__assign({}, state.range), cacheRange);
42951 this.renderRange(newRange);
42952 }
42953 };
42954 Zoom.prototype.didUnmount = function () {
42955 this.loop && cancelAnimationFrame(this.loop);
42956 };
42957 Zoom.prototype._bindEvents = function () {
42958 var _this = this;
42959 var scale = this.scale;
42960 var _a = this.props,
42961 chart = _a.chart,
42962 onPinchStart = _a.onPinchStart,
42963 onPanStart = _a.onPanStart,
42964 onPanEnd = _a.onPanEnd,
42965 pan = _a.pan,
42966 pinch = _a.pinch,
42967 swipe = _a.swipe,
42968 onPan = _a.onPan,
42969 onPinch = _a.onPinch,
42970 onPinchEnd = _a.onPinchEnd;
42971 // 统一绑定事件
42972 if (pan !== false) {
42973 chart.on('panstart', function () {
42974 _this.onStart();
42975 onPanStart({
42976 scale: scale
42977 });
42978 });
42979 chart.on('pan', function (ev) {
42980 _this.onPan(ev);
42981 onPan(ev);
42982 });
42983 chart.on('panend', function () {
42984 _this.onEnd();
42985 onPanEnd({
42986 scale: scale
42987 });
42988 });
42989 }
42990 if (pinch !== false) {
42991 chart.on('pinchstart', function () {
42992 _this.onStart();
42993 onPinchStart();
42994 });
42995 chart.on('pinch', function (ev) {
42996 _this.onPinch(ev);
42997 onPinch(ev);
42998 });
42999 chart.on('pinchend', function () {
43000 _this.onEnd();
43001 onPinchEnd({
43002 scale: scale
43003 });
43004 });
43005 }
43006 if (swipe !== false) {
43007 chart.on('swipe', this.onSwipe);
43008 }
43009 };
43010 Zoom.prototype.update = function () {
43011 var _this = this;
43012 var _a = this.swipeEnd,
43013 startX = _a.startX,
43014 startY = _a.startY,
43015 endX = _a.endX,
43016 endY = _a.endY;
43017 var x = lerp$1(startX, endX, 0.05);
43018 var y = lerp$1(startY, endY, 0.05);
43019 this.swipeEnd = {
43020 startX: x,
43021 startY: y,
43022 endX: endX,
43023 endY: endY
43024 };
43025 var props = this.props;
43026 var coord = props.coord;
43027 var coordWidth = coord.width,
43028 coordHeight = coord.height;
43029 var range = {};
43030 range['x'] = this._doPan((x - startX) / coordWidth, 'x');
43031 range['y'] = this._doPan((y - startY) / coordHeight, 'y');
43032 this.renderRange(range);
43033 this.startRange = range;
43034 this.loop = requestAnimationFrame(function () {
43035 return _this.update();
43036 });
43037 if (Math.abs(x - endX) < 0.0005 && Math.abs(y - endY) < 0.0005) {
43038 this.onEnd();
43039 cancelAnimationFrame(this.loop);
43040 }
43041 };
43042 Zoom.prototype.animateSwipe = function (dim, dimRange, velocity) {
43043 var _this = this;
43044 var _a = this,
43045 context = _a.context,
43046 props = _a.props;
43047 var requestAnimationFrame = context.canvas.requestAnimationFrame;
43048 var _b = props.swipeDuration,
43049 swipeDuration = _b === void 0 ? 1000 : _b;
43050 var diff = (dimRange[1] - dimRange[0]) * velocity;
43051 var startTime = Date.now();
43052 var updateRange = function updateRange(t) {
43053 var newDimRange = [dimRange[0] + diff * t, dimRange[1] + diff * t];
43054 var newRange = _this.updateRange(newDimRange, dim);
43055 _this.renderRange({
43056 x: newRange
43057 });
43058 };
43059 // 更新动画
43060 var update = function update() {
43061 // 计算动画已经进行的时间
43062 var currentTime = Date.now() - startTime;
43063 // 如果动画已经结束,则清除定时器
43064 if (currentTime >= swipeDuration) {
43065 updateRange(1);
43066 return;
43067 }
43068 // 计算缓动值
43069 var progress = currentTime / swipeDuration;
43070 var easedProgress = quadraticOut(progress);
43071 updateRange(easedProgress);
43072 requestAnimationFrame(function () {
43073 update();
43074 });
43075 };
43076 update();
43077 };
43078 Zoom.prototype._doXPan = function (ev) {
43079 var direction = ev.direction,
43080 deltaX = ev.deltaX;
43081 if (this.props.mode.length === 1 && (direction === 'up' || direction === 'down')) {
43082 return this.state.range['x'];
43083 }
43084 ev.preventDefault && ev.preventDefault();
43085 var props = this.props;
43086 var coord = props.coord,
43087 _a = props.panSensitive,
43088 panSensitive = _a === void 0 ? 1 : _a;
43089 var coordWidth = coord.width;
43090 var ratio = deltaX / coordWidth * panSensitive;
43091 var newRange = this._doPan(ratio, 'x');
43092 return newRange;
43093 };
43094 Zoom.prototype._doYPan = function (ev) {
43095 var direction = ev.direction,
43096 deltaY = ev.deltaY;
43097 if (this.props.mode.length === 1 && (direction === 'left' || direction === 'right')) {
43098 return this.state.range['y'];
43099 }
43100 ev.preventDefault && ev.preventDefault();
43101 var props = this.props;
43102 var coord = props.coord,
43103 _a = props.panSensitive,
43104 panSensitive = _a === void 0 ? 1 : _a;
43105 var coordHeight = coord.height;
43106 var ratio = -deltaY / coordHeight * panSensitive;
43107 var newRange = this._doPan(ratio, 'y');
43108 return newRange;
43109 };
43110 Zoom.prototype._doPan = function (ratio, dim) {
43111 var startRange = this.startRange;
43112 var _a = startRange[dim],
43113 start = _a[0],
43114 end = _a[1];
43115 var rangeLen = end - start;
43116 var rangeOffset = rangeLen * ratio;
43117 var newStart = start - rangeOffset;
43118 var newEnd = end - rangeOffset;
43119 var newRange = this.updateRange([newStart, newEnd], dim);
43120 return newRange;
43121 };
43122 Zoom.prototype._doXPinch = function (ev) {
43123 ev.preventDefault && ev.preventDefault();
43124 var zoom = ev.zoom,
43125 center = ev.center;
43126 var props = this.props;
43127 var coord = props.coord;
43128 var coordWidth = coord.width,
43129 left = coord.left,
43130 right = coord.right;
43131 var leftLen = Math.abs(center.x - left);
43132 var rightLen = Math.abs(right - center.x);
43133 // 计算左右缩放的比例
43134 var leftZoom = leftLen / coordWidth;
43135 var rightZoom = rightLen / coordWidth;
43136 var newRange = this._doPinch(leftZoom, rightZoom, zoom, 'x');
43137 return newRange;
43138 };
43139 Zoom.prototype._doYPinch = function (ev) {
43140 ev.preventDefault && ev.preventDefault();
43141 var zoom = ev.zoom,
43142 center = ev.center;
43143 var props = this.props;
43144 var coord = props.coord;
43145 var coordHeight = coord.height,
43146 top = coord.top,
43147 bottom = coord.bottom;
43148 var topLen = Math.abs(center.y - top);
43149 var bottomLen = Math.abs(bottom - center.y);
43150 // 计算左右缩放的比例
43151 var topZoom = topLen / coordHeight;
43152 var bottomZoom = bottomLen / coordHeight;
43153 var newRange = this._doPinch(topZoom, bottomZoom, zoom, 'y');
43154 return newRange;
43155 };
43156 Zoom.prototype._doPinch = function (startRatio, endRatio, zoom, dim) {
43157 var _a = this,
43158 startRange = _a.startRange,
43159 minScale = _a.minScale,
43160 props = _a.props;
43161 var _b = props.pinchSensitive,
43162 pinchSensitive = _b === void 0 ? 1 : _b;
43163 var _c = startRange[dim],
43164 start = _c[0],
43165 end = _c[1];
43166 var zoomOffset = zoom < 1 ? (1 / zoom - 1) * pinchSensitive : (1 - zoom) * pinchSensitive;
43167 var rangeLen = end - start;
43168 var rangeOffset = rangeLen * zoomOffset;
43169 var startOffset = rangeOffset * startRatio;
43170 var endOffset = rangeOffset * endRatio;
43171 var newStart = Math.max(0, start - startOffset);
43172 var newEnd = Math.min(1, end + endOffset);
43173 var newRange = [newStart, newEnd];
43174 // 如果已经到了最小比例,则不能再继续再放大
43175 if (newEnd - newStart < minScale) {
43176 return this.state.range[dim];
43177 }
43178 return this.updateRange(newRange, dim);
43179 };
43180 Zoom.prototype.updateRange = function (originalRange, dim) {
43181 if (!originalRange) return;
43182 var start = originalRange[0],
43183 end = originalRange[1];
43184 var rangeLength = end - start;
43185 // 处理边界值
43186 var newRange;
43187 if (start < 0) {
43188 newRange = [0, rangeLength];
43189 } else if (end > 1) {
43190 newRange = [1 - rangeLength, 1];
43191 } else {
43192 newRange = originalRange;
43193 }
43194 var _a = this,
43195 props = _a.props,
43196 scale = _a.scale,
43197 originScale = _a.originScale,
43198 state = _a.state;
43199 var data = props.data,
43200 autoFit = props.autoFit;
43201 var range = state.range;
43202 if (range && isEqualRange(newRange, range[dim])) return newRange;
43203 // 更新主 scale
43204 updateRange(scale[dim], originScale[dim], newRange);
43205 if (autoFit) {
43206 var followScale = this._getFollowScales(dim);
43207 this.updateFollow(followScale, scale[dim], data);
43208 }
43209 return newRange;
43210 };
43211 Zoom.prototype.updateFollow = function (scales, mainScale, data) {
43212 updateFollow(scales, mainScale, data);
43213 };
43214 Zoom.prototype._getScale = function (dim) {
43215 var _a = this.props,
43216 coord = _a.coord,
43217 chart = _a.chart;
43218 if (dim === 'x') {
43219 return coord.transposed ? chart.getYScales()[0] : chart.getXScales()[0];
43220 } else {
43221 return coord.transposed ? chart.getXScales()[0] : chart.getYScales()[0];
43222 }
43223 };
43224 Zoom.prototype._getFollowScales = function (dim) {
43225 var _a = this.props,
43226 coord = _a.coord,
43227 chart = _a.chart;
43228 if (dim === 'x') {
43229 return coord.transposed ? chart.getXScales() : chart.getYScales();
43230 }
43231 if (dim === 'y') {
43232 return coord.transposed ? chart.getYScales() : chart.getXScales();
43233 }
43234 };
43235 Zoom.prototype.renderRange = function (range) {
43236 var _a = this,
43237 state = _a.state,
43238 props = _a.props;
43239 if (isEqualRange(range, state.range)) return;
43240 var chart = props.chart;
43241 // 手势变化不执行动画
43242 var animate = chart.animate;
43243 chart.setAnimate(false);
43244 // 后面的 forceUpdate 会强制更新,所以不用 setState,直接更新
43245 state.range = range;
43246 chart.forceUpdate(function () {
43247 chart.setAnimate(animate);
43248 });
43249 };
43250 Zoom.prototype.render = function () {
43251 return jsx(View, __assign({}, this.props, this.state));
43252 };
43253 return Zoom;
43254 }(Component);
43255 });
43256
43257 var withScrollBar = (function (View) {
43258 return /** @class */function (_super) {
43259 __extends(ScrollBar, _super);
43260 function ScrollBar() {
43261 return _super !== null && _super.apply(this, arguments) || this;
43262 }
43263 ScrollBar.prototype.willMount = function () {
43264 _super.prototype.willMount.call(this);
43265 var _a = this,
43266 context = _a.context,
43267 props = _a.props;
43268 var visible = props.visible,
43269 _b = props.position,
43270 position = _b === void 0 ? 'bottom' : _b,
43271 _c = props.margin,
43272 margin = _c === void 0 ? '16px' : _c,
43273 chart = props.chart;
43274 var marginNumber = context.px2hd(margin);
43275 if (visible === false) {
43276 return null;
43277 }
43278 chart.updateCoordFor(this, {
43279 position: position,
43280 width: position === 'left' || position === 'right' ? marginNumber : 0,
43281 height: position === 'bottom' || position === 'top' ? marginNumber : 0
43282 });
43283 };
43284 ScrollBar.prototype.render = function () {
43285 var _a = this,
43286 props = _a.props,
43287 state = _a.state;
43288 var visible = props.visible;
43289 if (visible === false) {
43290 return null;
43291 }
43292 return jsx(View, __assign({
43293 position: "bottom"
43294 }, props, state));
43295 };
43296 return ScrollBar;
43297 }(withZoom(View));
43298 });
43299
43300 var Horizontal = (function (props, context) {
43301 var coord = props.coord,
43302 range = props.range,
43303 position = props.position,
43304 layout = props.layout;
43305 var left = coord.left,
43306 width = coord.width;
43307 var top = layout.top,
43308 height = layout.height;
43309 var _a = (range === null || range === void 0 ? void 0 : range.x) || (range === null || range === void 0 ? void 0 : range.y),
43310 start = _a[0],
43311 end = _a[1];
43312 var barLeft = width * start;
43313 var barWidth = width * (end - start);
43314 if (isNaN(barWidth)) return;
43315 return jsx("group", {
43316 style: {
43317 display: 'flex',
43318 left: left,
43319 top: position === 'top' ? top - context.px2hd('8px') : top + height
43320 }
43321 }, jsx("line", {
43322 style: {
43323 display: 'flex',
43324 position: 'absolute',
43325 left: 0,
43326 width: width,
43327 height: 0,
43328 stroke: 'rgba(202, 215, 239, .2)',
43329 lineCap: 'round',
43330 lineWidth: '8px'
43331 }
43332 }), jsx("line", {
43333 style: {
43334 display: 'flex',
43335 position: 'absolute',
43336 left: barLeft,
43337 width: barWidth,
43338 height: 0,
43339 stroke: 'rgba(202, 215, 239, .5)',
43340 lineCap: 'round',
43341 lineWidth: '8px'
43342 }
43343 }));
43344 });
43345
43346 var Vertical = (function (props, context) {
43347 var coord = props.coord,
43348 range = props.range,
43349 position = props.position,
43350 layout = props.layout;
43351 var top = coord.top,
43352 height = coord.height;
43353 var left = layout.left,
43354 width = layout.width;
43355 var _a = (range === null || range === void 0 ? void 0 : range.y) || (range === null || range === void 0 ? void 0 : range.x),
43356 start = _a[0],
43357 end = _a[1];
43358 var barTop = height * start;
43359 var barHeight = height * (end - start);
43360 return jsx("group", {
43361 style: {
43362 display: 'flex',
43363 top: top,
43364 left: position === 'left' ? left - context.px2hd('8px') : left + width
43365 }
43366 }, jsx("line", {
43367 style: {
43368 position: 'absolute',
43369 top: 0,
43370 left: 0,
43371 width: 0,
43372 height: height,
43373 stroke: 'rgba(202, 215, 239, .2)',
43374 lineCap: 'round',
43375 lineWidth: '8px'
43376 }
43377 }), jsx("line", {
43378 style: {
43379 position: 'absolute',
43380 top: barTop,
43381 width: 0,
43382 height: barHeight,
43383 stroke: 'rgba(202, 215, 239, .5)',
43384 lineCap: 'round',
43385 lineWidth: '8px'
43386 }
43387 }));
43388 });
43389
43390 var ScrollBarView = (function (props) {
43391 var position = props.position,
43392 mode = props.mode;
43393 if (mode.length > 1) {
43394 return jsx("group", null, jsx(Vertical, __assign({}, props)), jsx(Horizontal, __assign({}, props)));
43395 }
43396 if (position === 'left' || position === 'right') {
43397 return jsx(Vertical, __assign({}, props));
43398 }
43399 return jsx(Horizontal, __assign({}, props));
43400 });
43401
43402 var index$c = withScrollBar(ScrollBarView);
43403
43404 // 默认配色
43405 var COLORS = ['#E62C3B', '#0E9976', '#999999' // 平盘
43406 ];
43407
43408 var withCandlestick = (function (View) {
43409 return /** @class */function (_super) {
43410 __extends(Candlestick, _super);
43411 function Candlestick() {
43412 return _super !== null && _super.apply(this, arguments) || this;
43413 }
43414 Candlestick.prototype.getDefaultCfg = function () {
43415 return {
43416 geomType: 'candlestick'
43417 };
43418 };
43419 Candlestick.prototype.getSize = function () {
43420 var _a = this,
43421 attrs = _a.attrs,
43422 props = _a.props;
43423 var _b = props.sizeRatio,
43424 sizeRatio = _b === void 0 ? 0.5 : _b;
43425 var x = attrs.x;
43426 var scale = x.scale;
43427 var values = scale.values;
43428 return 1 / values.length * sizeRatio;
43429 };
43430 Candlestick.prototype.mapping = function () {
43431 var records = _super.prototype.mapping.call(this);
43432 var props = this.props;
43433 var coord = props.coord;
43434 var y0 = this.getY0Value();
43435 var defaultSize = this.getSize();
43436 var colorAttr = this.getAttr('color');
43437 var colors = colorAttr ? colorAttr.range : COLORS;
43438 for (var i = 0, len = records.length; i < len; i++) {
43439 var record = records[i];
43440 var children = record.children;
43441 for (var j = 0, len_1 = children.length; j < len_1; j++) {
43442 var child = children[j];
43443 var normalized = child.normalized,
43444 mappedSize = child.size;
43445 // 没有指定size,则根据数据来计算默认size
43446 if (isNil(mappedSize)) {
43447 var x = normalized.x,
43448 y_1 = normalized.y,
43449 _a = normalized.size,
43450 size = _a === void 0 ? defaultSize : _a;
43451 mix(child, coord.convertRect({
43452 x: x,
43453 y: y_1,
43454 y0: y0,
43455 size: size
43456 }));
43457 } else {
43458 var x = child.x,
43459 y_2 = child.y;
43460 var rect = {
43461 x: x,
43462 y: y_2,
43463 y0: y0,
43464 size: mappedSize
43465 };
43466 mix(child, coord.transformToRect(rect));
43467 }
43468 // 处理颜色
43469 var y = normalized.y;
43470 var open_1 = y[0],
43471 close_1 = y[1];
43472 child.color = close_1 > open_1 ? colors[0] : close_1 < open_1 ? colors[1] : colors[2];
43473 mix(child.shape, this.getSelectionStyle(child));
43474 }
43475 }
43476 return records;
43477 };
43478 Candlestick.prototype.render = function () {
43479 var props = this.props;
43480 var records = this.mapping();
43481 return jsx(View, __assign({}, props, {
43482 records: records
43483 }));
43484 };
43485 return Candlestick;
43486 }(Geometry);
43487 });
43488
43489 var CandlestickView = (function (props) {
43490 var records = props.records,
43491 animation = props.animation,
43492 y0 = props.y0,
43493 onClick = props.onClick;
43494 return jsx("group", null, records.map(function (record) {
43495 var key = record.key,
43496 children = record.children;
43497 return jsx("group", {
43498 key: key
43499 }, children.map(function (item) {
43500 var key = item.key,
43501 xMin = item.xMin,
43502 xMax = item.xMax,
43503 yMin = item.yMin,
43504 yMax = item.yMax,
43505 x = item.x,
43506 y = item.y,
43507 color = item.color,
43508 shape = item.shape;
43509 if (isNaN(xMin) || isNaN(xMax) || isNaN(yMin) || isNaN(yMax)) {
43510 return null;
43511 }
43512 return jsx("group", null, jsx("line", {
43513 style: {
43514 x1: x,
43515 y1: y[2],
43516 x2: x,
43517 y2: y[3],
43518 stroke: color,
43519 lineWidth: '2px',
43520 lineCap: 'round'
43521 },
43522 animation: {
43523 appear: {
43524 easing: 'linear',
43525 duration: 300,
43526 property: ['y1', 'y2'],
43527 // @ts-ignore
43528 start: {
43529 y1: 0,
43530 y2: 0
43531 }
43532 },
43533 update: {
43534 easing: 'linear',
43535 duration: 300,
43536 property: ['x1', 'y1', 'x2', 'y2']
43537 }
43538 }
43539 }), jsx("rect", {
43540 key: key,
43541 style: __assign({
43542 x: xMin,
43543 y: yMin,
43544 width: xMax - xMin,
43545 height: yMax - yMin,
43546 fill: color,
43547 radius: '2px'
43548 }, shape),
43549 onClick: onClick,
43550 animation: deepMix({
43551 appear: {
43552 easing: 'linear',
43553 duration: 300,
43554 property: ['y', 'height'],
43555 start: {
43556 y: y0,
43557 height: 0
43558 }
43559 },
43560 update: {
43561 easing: 'linear',
43562 duration: 300,
43563 property: ['x', 'y', 'width', 'height']
43564 }
43565 }, animation)
43566 }));
43567 }));
43568 }));
43569 });
43570
43571 var index$d = withCandlestick(CandlestickView);
43572
43573 exports.ArcGuide = ArcGuide;
43574 exports.Area = index$1;
43575 exports.AreaView = AreaView;
43576 exports.Axis = index$4;
43577 exports.AxisView = AxisView;
43578 exports.Candlestick = index$d;
43579 exports.CandlestickView = CandlestickView;
43580 exports.Canvas = Canvas$1;
43581 exports.CanvasRenderer = Renderer;
43582 exports.Chart = Chart;
43583 exports.Children = Children;
43584 exports.Component = Component;
43585 exports.Fragment = fragment;
43586 exports.Gauge = index$b;
43587 exports.GaugeView = GaugeView;
43588 exports.Geometry = Geometry;
43589 exports.Gesture = Gesture;
43590 exports.Guide = index$6;
43591 exports.ImageGuide = ImageGuide;
43592 exports.Interval = index$2;
43593 exports.IntervalView = intervalView;
43594 exports.Legend = index$5;
43595 exports.LegendView = LegendView;
43596 exports.Line = index;
43597 exports.LineGuide = LineGuide;
43598 exports.LineView = LineView;
43599 exports.LottieGuide = LottieGuide;
43600 exports.PieLabel = index$a;
43601 exports.PieLabelView = PieLabelView;
43602 exports.Player = Player;
43603 exports.Point = index$3;
43604 exports.PointGuide = PointGuide;
43605 exports.PointView = PointView;
43606 exports.RectGuide = RectGuide;
43607 exports.Scale = Scale;
43608 exports.ScrollBar = index$c;
43609 exports.ScrollBarView = ScrollBarView;
43610 exports.Smooth = smooth;
43611 exports.Sunburst = index$9;
43612 exports.SunburstView = SunburstView;
43613 exports.TagGuide = TagGuide;
43614 exports.TextGuide = TextGuide;
43615 exports.Timeline = Timeline;
43616 exports.Tooltip = index$7;
43617 exports.TooltipView = TooltipView;
43618 exports.Treemap = index$8;
43619 exports.TreemapView = TreemapView;
43620 exports.Zoom = withZoom;
43621 exports.computeLayout = computeLayout$1;
43622 exports.createContext = createContext;
43623 exports.createElement = jsx;
43624 exports.createRef = createRef;
43625 exports.isEqual = equal;
43626 exports.jsx = jsx;
43627 exports.registerTag = registerTag;
43628 exports.withArea = withArea;
43629 exports.withAxis = withAxis;
43630 exports.withCandlestick = withCandlestick;
43631 exports.withGauge = withGauge;
43632 exports.withGuide = withGuide;
43633 exports.withInterval = withInterval;
43634 exports.withLegend = withLegend;
43635 exports.withLine = withLine;
43636 exports.withPieLabel = withPieLabel;
43637 exports.withPoint = withPoint;
43638 exports.withScrollBar = withScrollBar;
43639 exports.withSunburst = withSunburst;
43640 exports.withTooltip = withTooltip;
43641 exports.withTreemap = withTreemap;
43642
43643 Object.defineProperty(exports, '__esModule', { value: true });
43644
43645})));