@visactor/vrender-core
Version:
```typescript import { xxx } from '@visactor/vrender-core'; ```
1,595 lines (1,576 loc) • 1.19 MB
JavaScript
import { EventEmitter, Logger, isBoolean, isObject, isFunction, isString, has, isUndefined, tau, halfPi as halfPi$1, AABBBounds, degreeToRadian, PointService, Point, abs, max, min, atan2, epsilon, Matrix, pi2, isArray, cos, sin, pi, pointAt, isNumber as isNumber$1, sqrt, isPointInLine, Color, DEFAULT_COLORS, LRU, OBBBounds, isEqual, isNil, normalTransform, isValidUrl, isBase64, lowerCamelCaseToMiddle, isValid, getContextFont, rotatePoint, transformBoundsWithMatrix, clampAngleByRadian, asin, isNumberClose, TextMeasure, Bounds, getRectIntersect, isRectIntersect, arrayEqual, acos, getIntersectPoint, merge, calculateAnchorOfBounds, styleStringToObject } from '@visactor/vutils';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
class Hook {
constructor(args, name) {
this._args = args;
this.name = name;
this.taps = [];
}
tap(options, fn) {
this._tap('sync', options, fn);
}
unTap(options, fn) {
const name = typeof options === 'string' ? options.trim() : options.name;
if (name) {
this.taps = this.taps.filter(tap => !(tap.name === name && (!fn || tap.fn === fn)));
}
}
_parseOptions(type, options, fn) {
let _options;
if (typeof options === 'string') {
_options = {
name: options.trim()
};
}
else if (typeof options !== 'object' || options === null) {
throw new Error('Invalid tap options');
}
if (typeof _options.name !== 'string' || _options.name === '') {
throw new Error('Missing name for tap');
}
_options = Object.assign({ type, fn }, _options);
return _options;
}
_tap(type, options, fn) {
this._insert(this._parseOptions(type, options, fn));
}
_insert(item) {
let before;
if (typeof item.before === 'string') {
before = new Set([item.before]);
}
else if (Array.isArray(item.before)) {
before = new Set(item.before);
}
let stage = 0;
if (typeof item.stage === 'number') {
stage = item.stage;
}
let i = this.taps.length;
while (i > 0) {
i--;
const x = this.taps[i];
this.taps[i + 1] = x;
const xStage = x.stage || 0;
if (before) {
if (before.has(x.name)) {
before.delete(x.name);
continue;
}
if (before.size > 0) {
continue;
}
}
if (xStage > stage) {
continue;
}
i++;
break;
}
this.taps[i] = item;
}
}
class SyncHook extends Hook {
call(...args) {
const cbs = this.taps.map(t => t.fn);
cbs.forEach(cb => cb(...args));
return undefined;
}
}
class Generator {
static GenAutoIncrementId() {
return Generator.auto_increment_id++;
}
}
Generator.auto_increment_id = 0;
class Application {
}
const APPLICATION_STATE_SYMBOL = Symbol.for('@visactor/vrender-core/application-state');
function createApplicationState() {
return {
application: new Application()
};
}
function getApplicationState() {
const scope = globalThis;
if (!scope[APPLICATION_STATE_SYMBOL]) {
scope[APPLICATION_STATE_SYMBOL] = createApplicationState();
}
return scope[APPLICATION_STATE_SYMBOL];
}
const application = getApplicationState().application;
let idx = 0;
class PerformanceRAF {
constructor() {
this.nextAnimationFrameCbs = new Map();
this._rafHandle = null;
this.runAnimationFrame = (time) => {
this._rafHandle = null;
const cbs = this.nextAnimationFrameCbs;
this.nextAnimationFrameCbs = new Map();
cbs.forEach(cb => cb(time));
};
this.tryRunAnimationFrameNextFrame = () => {
if (this._rafHandle !== null || this.nextAnimationFrameCbs.size === 0) {
return;
}
this._rafHandle = application.global.getRequestAnimationFrame()(this.runAnimationFrame);
};
}
addAnimationFrameCb(callback) {
this.nextAnimationFrameCbs.set(++idx, callback);
this.tryRunAnimationFrameNextFrame();
return idx;
}
removeAnimationFrameCb(index) {
if (this.nextAnimationFrameCbs.has(index)) {
this.nextAnimationFrameCbs.delete(index);
return true;
}
return false;
}
wait() {
return new Promise(resolve => {
this.addAnimationFrameCb(() => resolve());
});
}
}
class EventListenerManager {
constructor() {
this._listenerMap = new Map();
this._eventListenerTransformer = event => event;
}
setEventListenerTransformer(transformer) {
this._eventListenerTransformer = transformer || (event => event);
}
addEventListener(type, listener, options) {
if (!listener) {
return;
}
const capture = this._resolveCapture(options);
const once = this._resolveOnce(options);
const listenerTypeMap = this._getOrCreateListenerTypeMap(type);
const wrappedMap = this._getOrCreateWrappedMap(listenerTypeMap, listener);
if (wrappedMap.has(capture)) {
return;
}
const wrappedListener = (event) => {
const transformedEvent = this._eventListenerTransformer(event);
if (typeof listener === 'function') {
listener(transformedEvent);
}
else if (listener.handleEvent) {
listener.handleEvent(transformedEvent);
}
if (once) {
this._deleteListenerRecord(type, listener, capture);
}
};
wrappedMap.set(capture, { wrappedListener, options });
this._nativeAddEventListener(type, wrappedListener, options);
}
removeEventListener(type, listener, options) {
var _a, _b;
if (!listener) {
return;
}
const capture = this._resolveCapture(options);
const wrappedRecord = (_b = (_a = this._listenerMap.get(type)) === null || _a === void 0 ? void 0 : _a.get(listener)) === null || _b === void 0 ? void 0 : _b.get(capture);
if (wrappedRecord) {
this._nativeRemoveEventListener(type, wrappedRecord.wrappedListener, capture);
this._deleteListenerRecord(type, listener, capture);
}
}
dispatchEvent(event) {
return this._nativeDispatchEvent(event);
}
clearAllEventListeners() {
this._listenerMap.forEach((listenerMap, type) => {
listenerMap.forEach(wrappedMap => {
wrappedMap.forEach((wrappedRecord, capture) => {
this._nativeRemoveEventListener(type, wrappedRecord.wrappedListener, capture);
});
});
});
this._listenerMap.clear();
}
_resolveCapture(options) {
if (typeof options === 'boolean') {
return options;
}
return !!(options === null || options === void 0 ? void 0 : options.capture);
}
_resolveOnce(options) {
return typeof options === 'object' && !!(options === null || options === void 0 ? void 0 : options.once);
}
_getOrCreateListenerTypeMap(type) {
let listenerTypeMap = this._listenerMap.get(type);
if (!listenerTypeMap) {
listenerTypeMap = new Map();
this._listenerMap.set(type, listenerTypeMap);
}
return listenerTypeMap;
}
_getOrCreateWrappedMap(listenerTypeMap, listener) {
let wrappedMap = listenerTypeMap.get(listener);
if (!wrappedMap) {
wrappedMap = new Map();
listenerTypeMap.set(listener, wrappedMap);
}
return wrappedMap;
}
_deleteListenerRecord(type, listener, capture) {
const listenerTypeMap = this._listenerMap.get(type);
if (!listenerTypeMap) {
return;
}
const wrappedMap = listenerTypeMap.get(listener);
if (!wrappedMap) {
return;
}
wrappedMap.delete(capture);
if (wrappedMap.size === 0) {
listenerTypeMap.delete(listener);
}
if (listenerTypeMap.size === 0) {
this._listenerMap.delete(type);
}
}
_nativeAddEventListener(type, listener, options) {
throw new Error('_nativeAddEventListener must be implemented by derived classes');
}
_nativeRemoveEventListener(type, listener, options) {
throw new Error('_nativeRemoveEventListener must be implemented by derived classes');
}
_nativeDispatchEvent(event) {
throw new Error('_nativeDispatchEvent must be implemented by derived classes');
}
}
const defaultEnv = 'browser';
class DefaultGlobal extends EventListenerManager {
get env() {
return this._env;
}
get isImageAnonymous() {
return this._isImageAnonymous;
}
set isImageAnonymous(isImageAnonymous) {
this._isImageAnonymous = isImageAnonymous;
}
get devicePixelRatio() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.getDevicePixelRatio();
}
get supportEvent() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.supportEvent;
}
set supportEvent(support) {
if (!this._env) {
this.setEnv(defaultEnv);
}
this.envContribution.supportEvent = support;
}
get supportsTouchEvents() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.supportsTouchEvents;
}
set supportsTouchEvents(support) {
if (!this._env) {
this.setEnv(defaultEnv);
}
this.envContribution.supportsTouchEvents = support;
}
get supportsPointerEvents() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.supportsPointerEvents;
}
set supportsPointerEvents(support) {
if (!this._env) {
this.setEnv(defaultEnv);
}
this.envContribution.supportsPointerEvents = support;
}
get supportsMouseEvents() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.supportsMouseEvents;
}
set supportsMouseEvents(support) {
if (!this._env) {
this.setEnv(defaultEnv);
}
this.envContribution.supportsMouseEvents = support;
}
get applyStyles() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.applyStyles;
}
set applyStyles(support) {
if (!this._env) {
this.setEnv(defaultEnv);
}
this.envContribution.applyStyles = support;
}
constructor(contributions) {
super();
this.contributions = contributions;
this._isImageAnonymous = true;
this._performanceRAFList = [];
this.eventListenerTransformer = event => event;
this.id = Generator.GenAutoIncrementId();
this.hooks = {
onSetEnv: new SyncHook(['lastEnv', 'env', 'global'])
};
this.measureTextMethod = 'native';
this.optimizeVisible = false;
}
_nativeAddEventListener(type, listener, options) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.addEventListener(type, listener, options);
}
_nativeRemoveEventListener(type, listener, options) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.removeEventListener(type, listener, options);
}
_nativeDispatchEvent(event) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.dispatchEvent(event);
}
bindContribution(params) {
const promiseArr = [];
this.contributions.getContributions().forEach(contribution => {
const data = contribution.configure(this, params);
if (data && data.then) {
promiseArr.push(data);
}
});
if (promiseArr.length) {
return Promise.all(promiseArr);
}
}
getDynamicCanvasCount() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.getDynamicCanvasCount();
}
getStaticCanvasCount() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.getStaticCanvasCount();
}
setEnv(env, params) {
if (!(params && params.force === true) && this._env === env) {
return;
}
this.deactiveCurrentEnv();
return this.activeEnv(env, params);
}
deactiveCurrentEnv() {
this.envContribution && this.envContribution.release();
}
activeEnv(env, params) {
const lastEnv = this._env;
this._env = env;
const data = this.bindContribution(params);
if (data && data.then) {
return data.then(() => {
this.envParams = params;
this.hooks.onSetEnv.call(lastEnv, env, this);
});
}
this.envParams = params;
this.hooks.onSetEnv.call(lastEnv, env, this);
}
setActiveEnvContribution(contribution) {
this.envContribution = contribution;
}
createCanvas(params) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.createCanvas(params);
}
createOffscreenCanvas(params) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.createOffscreenCanvas(params);
}
releaseCanvas(canvas) {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.releaseCanvas(canvas);
}
getRequestAnimationFrame() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.getRequestAnimationFrame();
}
getSpecifiedRequestAnimationFrame(id) {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this._performanceRAFList[id]) {
this._performanceRAFList[id] = new PerformanceRAF();
}
const performanceRAF = this._performanceRAFList[id];
return (callback) => {
return performanceRAF.addAnimationFrameCb(callback);
};
}
getSpecifiedPerformanceRAF(id) {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this._performanceRAFList[id]) {
this._performanceRAFList[id] = new PerformanceRAF();
}
return this._performanceRAFList[id];
}
getSpecifiedCancelAnimationFrame(id) {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this._performanceRAFList[id]) {
return () => false;
}
const performanceRAF = this._performanceRAFList[id];
return (handle) => {
return performanceRAF.removeAnimationFrameCb(handle);
};
}
getCancelAnimationFrame() {
if (!this._env) {
this.setEnv(defaultEnv);
}
return this.envContribution.getCancelAnimationFrame();
}
getElementById(str) {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this.envContribution.getElementById) {
return null;
}
return this.envContribution.getElementById(str);
}
getRootElement() {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this.envContribution.getRootElement) {
return null;
}
return this.envContribution.getRootElement();
}
getDocument() {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this.envContribution.getDocument) {
return null;
}
return this.envContribution.getDocument();
}
mapToCanvasPoint(event, domElement) {
if (!this._env) {
this.setEnv(defaultEnv);
}
if (!this.envContribution.mapToCanvasPoint) {
return null;
}
return this.envContribution.mapToCanvasPoint(event, domElement);
}
loadImage(url) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadImage(url);
}
loadSvg(str) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadSvg(str);
}
loadJson(url) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadJson(url);
}
loadArrayBuffer(url) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadArrayBuffer(url);
}
loadBlob(url) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadBlob(url);
}
loadFont(name, source, descriptors) {
return __awaiter(this, void 0, void 0, function* () {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.loadFont(name, source, descriptors);
});
}
isChrome() {
if (this._isChrome != null) {
return this._isChrome;
}
if (!this._env) {
this.setEnv('browser');
}
this._isChrome = this._env === 'browser' && navigator.userAgent.indexOf('Chrome') > -1;
return this._isChrome;
}
isSafari() {
if (this._isSafari != null) {
return this._isSafari;
}
if (!this._env) {
this.setEnv('browser');
}
this._isSafari =
this._env === 'browser' && /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
return this._isSafari;
}
getNativeAABBBounds(dom) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.getNativeAABBBounds(dom);
}
removeDom(dom) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.removeDom(dom);
}
createDom(params) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.createDom(params);
}
updateDom(dom, params) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.updateDom(dom, params);
}
getElementTop(dom, baseWindow = false) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.getElementTop(dom, baseWindow);
}
getElementLeft(dom, baseWindow = false) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.getElementLeft(dom, baseWindow);
}
getElementTopLeft(dom, baseWindow = false) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.getElementTopLeft(dom, baseWindow);
}
isMacOS() {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.isMacOS();
}
copyToClipBoard(text) {
if (!this._env) {
this.setEnv('browser');
}
return this.envContribution.copyToClipBoard(text);
}
}
class Node extends EventEmitter {
get previousSibling() {
return this._prev;
}
get nextSibling() {
return this._next;
}
get children() {
return this.getChildren();
}
get firstChild() {
return this._firstChild;
}
get lastChild() {
return this._lastChild;
}
get count() {
return this._count;
}
get childrenCount() {
if (!this._idMap) {
return 0;
}
return this._idMap.size;
}
constructor() {
super();
this._uid = Generator.GenAutoIncrementId();
this._firstChild = null;
this._lastChild = null;
this.parent = null;
this._count = 1;
}
onParentSharedStateTreeChanged(_stage, _layer) {
return;
}
forEachChildren(cb, reverse = false) {
if (reverse) {
let child = this._lastChild;
let i = 0;
while (child) {
const breakTag = cb(child, i++);
if (breakTag) {
return;
}
child = child._prev;
}
}
else {
let child = this._firstChild;
let i = 0;
while (child) {
const breakTag = cb(child, i++);
if (breakTag) {
return;
}
child = child._next;
}
}
}
forEachChildrenAsync(cb, reverse = false) {
return __awaiter(this, void 0, void 0, function* () {
if (reverse) {
let child = this._lastChild;
let i = 0;
while (child) {
let breakTag = cb(child, i++);
if (breakTag.then) {
breakTag = yield breakTag;
}
if (breakTag) {
return;
}
child = child._prev;
}
}
else {
let child = this._firstChild;
let i = 0;
while (child) {
let breakTag = cb(child, i++);
if (breakTag.then) {
breakTag = yield breakTag;
}
if (breakTag) {
return;
}
child = child._next;
}
}
});
}
forEach(cb) {
return this.forEachChildren(cb);
}
appendChild(node, highPerformance = true) {
if (this._uid === node._uid) {
return null;
}
if (!highPerformance && node.isAncestorsOf(this)) {
throw new Error('【Node::appendChild】不能将父辈元素append为子元素');
}
node.parent && node.parent.removeChild(node);
node.parent = this;
if (!this._lastChild) {
this._firstChild = this._lastChild = node;
node._prev = node._next = null;
}
else {
this._lastChild._next = node;
node._prev = this._lastChild;
this._lastChild = node;
}
if (!this._idMap) {
this._idMap = new Map();
}
this._idMap.set(node._uid, node);
this.setCount(node.count);
this._structEdit = true;
return node;
}
appendChildArrHighPerformance(nodes, replace = false) {
console.error('暂不支持该函数');
return nodes;
}
insertBefore(newNode, referenceNode) {
if (!referenceNode) {
return this.appendChild(newNode);
}
if (this === newNode || newNode === referenceNode) {
return null;
}
if (newNode.isAncestorsOf(this)) {
throw new Error('【Node::insertBefore】不能将父辈元素insert为子元素');
}
if (referenceNode.parent !== this) {
return null;
}
newNode.parent && newNode.parent.removeChild(newNode);
newNode.parent = this;
newNode._prev = referenceNode._prev;
if (!referenceNode._prev) {
this._firstChild = newNode;
}
else {
referenceNode._prev._next = newNode;
}
referenceNode._prev = newNode;
newNode._next = referenceNode;
if (!this._idMap) {
this._idMap = new Map();
}
this._idMap.set(newNode._uid, newNode);
this._structEdit = true;
this.setCount(newNode.count);
return newNode;
}
insertAfter(newNode, referenceNode) {
if (!referenceNode) {
return this.appendChild(newNode);
}
if (this === newNode || newNode === referenceNode) {
return null;
}
if (newNode.isAncestorsOf(this)) {
throw new Error('【Node::insertAfter】不能将父辈元素insert为子元素');
}
if (referenceNode.parent !== this) {
return null;
}
newNode.parent && newNode.parent.removeChild(newNode);
newNode.parent = this;
if (!referenceNode._next) {
this._lastChild = newNode;
}
else {
referenceNode._next._prev = newNode;
newNode._next = referenceNode._next;
}
referenceNode._next = newNode;
newNode._prev = referenceNode;
if (!this._idMap) {
this._idMap = new Map();
}
this._idMap.set(newNode._uid, newNode);
this._structEdit = true;
this.setCount(newNode.count);
return newNode;
}
insertInto(newNode, idx) {
if (!this._ignoreWarn && this._nodeList) {
Logger.getInstance().warn('insertIntoKeepIdx和insertInto混用可能会存在错误');
}
if (idx >= this.childrenCount) {
return this.appendChild(newNode);
}
if (this === newNode) {
return null;
}
if (newNode.isAncestorsOf(this)) {
throw new Error('【Node::insertBefore】不能将父辈元素insert为子元素');
}
newNode.parent && newNode.parent.removeChild(newNode);
newNode.parent = this;
if (idx === 0) {
newNode._next = this._firstChild;
this._firstChild && (this._firstChild._prev = newNode);
newNode._prev = null;
this._firstChild = newNode;
}
else {
let child = this._firstChild;
for (let i = 0; i < idx; i++) {
if (!child) {
return null;
}
if (i > 0) {
child = child._next;
}
}
if (!child) {
return null;
}
newNode._next = child._next;
newNode._prev = child;
child._next = newNode;
if (newNode._next) {
newNode._next._prev = newNode;
}
}
if (!this._idMap) {
this._idMap = new Map();
}
this._idMap.set(newNode._uid, newNode);
this._structEdit = true;
this.setCount(newNode.count);
return newNode;
}
insertIntoKeepIdx(newNode, idx) {
if (!this._nodeList) {
this._nodeList = this.children;
}
if (this._nodeList[idx]) {
const node = this._nodeList[idx];
this._nodeList.splice(idx, 0, newNode);
return this.insertBefore(newNode, node);
}
this._nodeList[idx] = newNode;
let node;
for (let i = idx - 1; i >= 0; i--) {
node = this._nodeList[i];
if (node) {
break;
}
}
if (node) {
return node._next ? this.insertBefore(newNode, node._next) : this.appendChild(newNode);
}
this._ignoreWarn = true;
const data = this.insertInto(newNode, 0);
this._ignoreWarn = false;
return data;
}
removeChild(child) {
if (!this._idMap) {
return null;
}
if (!this._idMap.has(child._uid)) {
return null;
}
this._idMap.delete(child._uid);
if (this._nodeList) {
const idx = this._nodeList.findIndex(n => n === child);
if (idx >= 0) {
this._nodeList.splice(idx, 1);
}
}
if (!child._prev) {
this._firstChild = child._next;
}
else {
child._prev._next = child._next;
}
if (child._next) {
child._next._prev = child._prev;
}
else {
this._lastChild = child._prev;
}
child.parent = null;
child._prev = null;
child._next = null;
this._structEdit = true;
this.setCount(-child.count);
return child;
}
delete() {
if (this.parent) {
this.parent.removeChild(this);
}
}
removeAllChild(deep) {
if (!this._idMap) {
return;
}
if (this._nodeList) {
this._nodeList.length = 0;
}
let child = this._firstChild;
while (child) {
const next = child._next;
child.parent = null;
child._prev = null;
child._next = null;
child = child._next;
child = next;
}
this._firstChild = null;
this._lastChild = null;
this._idMap.clear();
this._structEdit = true;
this.setCount(-this._count + 1);
}
replaceChild(newChild, oldChild) {
throw new Error('暂不支持');
}
find(callback, deep = false) {
let target = null;
this.forEachChildren((node, index) => {
if (node !== this && callback(node, index)) {
target = node;
return true;
}
return false;
});
if (deep) {
this.forEachChildren(child => {
if (child.isContainer) {
const node = child.find(callback, true);
if (node) {
target = node;
return true;
}
}
return false;
});
}
return target;
}
findAll(callback, deep = false) {
let nodes = [];
this.forEachChildren((node, index) => {
if (node !== this && callback(node, index)) {
nodes.push(node);
}
});
if (deep) {
this.forEachChildren(child => {
if (child.isContainer) {
const targets = child.findAll(callback, true);
if (targets.length) {
nodes = nodes.concat(targets);
}
}
});
}
return nodes;
}
getElementById(id) {
return this.find(node => node.id === id, true);
}
findChildById(id) {
return this.getElementById(id);
}
findChildByUid(uid) {
if (!this._idMap) {
return null;
}
return this._idMap.get(uid) || null;
}
getElementsByName(name) {
return this.findAll(node => node.name === name, true);
}
findChildrenByName(name) {
return this.getElementsByName(name);
}
getElementsByType(type) {
return this.findAll(node => node.type === type, true);
}
getChildByName(name, deep = false) {
return this.find(node => node.name === name, deep);
}
getChildAt(idx) {
let c = this._firstChild;
if (!c) {
return null;
}
for (let i = 0; i < idx; i++) {
if (!c._next) {
return null;
}
c = c._next;
}
return c;
}
at(idx) {
return this.getChildAt(idx);
}
containNode(node) {
if (!this._idMap) {
return false;
}
if (this._idMap.has(node._uid)) {
return true;
}
let child = this._firstChild;
while (child) {
if (child.containNode(node)) {
return true;
}
child = child._next;
}
return false;
}
getRootNode() {
let parent = this.parent;
while (parent === null || parent === void 0 ? void 0 : parent.parent) {
parent = parent.parent;
}
return parent || this;
}
hasChildNodes() {
return this._firstChild !== null;
}
addChild(node) {
return this.appendChild(node);
}
add(node) {
return this.appendChild(node);
}
getChildren() {
const nodes = [];
let child = this._firstChild;
while (child) {
nodes.push(child);
child = child._next;
}
return nodes;
}
isChildOf(node) {
if (!this.parent) {
return false;
}
return this.parent._uid === node._uid;
}
isParentOf(node) {
return node.isChildOf(this);
}
isDescendantsOf(node) {
let parent = this.parent;
if (!parent) {
return false;
}
do {
if (parent._uid === node._uid) {
return true;
}
parent = parent.parent;
} while (parent !== null);
return false;
}
isAncestorsOf(node) {
return node.isDescendantsOf(this);
}
getAncestor(idx) {
throw new Error('暂不支持');
}
setAllDescendantsProps(propsName, propsValue) {
let child = this._firstChild;
while (child) {
child[propsName] = propsValue;
child.setAllDescendantsProps(propsName, propsValue);
child = child._next;
}
}
setCount(deltaCount) {
this._count += deltaCount;
let parent = this.parent;
if (!parent) {
return;
}
do {
parent._count += deltaCount;
parent = parent.parent;
} while (parent !== null);
}
clone() {
throw new Error('暂不支持');
}
cloneTo(node) {
throw new Error('暂不支持');
}
getParent() {
return this.parent;
}
del(child) {
return this.removeChild(child);
}
addEventListener(type, listener, options) {
const capture = (isBoolean(options, true) && options) || (isObject(options) && options.capture);
const once = isObject(options) && options.once;
const context = isFunction(listener) ? undefined : listener;
type = capture ? `${type}capture` : type;
listener = isFunction(listener) ? listener : listener.handleEvent;
if (once) {
super.once(type, listener, context);
}
else {
super.on(type, listener, context);
}
return this;
}
on(type, listener, options) {
return this.addEventListener(type, listener, options);
}
removeEventListener(type, listener, options) {
const capture = (isBoolean(options, true) && options) || (isObject(options) && options.capture);
const context = isFunction(listener) ? undefined : listener;
type = capture ? `${type}capture` : type;
listener = isFunction(listener) ? listener : listener.handleEvent;
const once = isObject(options) && options.once;
super.off(type, listener, context, once);
return this;
}
off(type, listener, options) {
return this.removeEventListener(type, listener, options);
}
once(type, listener, options) {
if (isObject(options)) {
options.once = true;
return this.addEventListener(type, listener, options);
}
return this.addEventListener(type, listener, { once: true });
}
removeAllEventListeners() {
super.removeAllListeners();
return this;
}
removeAllListeners() {
return this.removeAllEventListeners();
}
dispatchEvent(event, ...args) {
super.emit(event.type, event, ...args);
return !event.defaultPrevented;
}
emit(event, data) {
return this.dispatchEvent(event, data);
}
release() {
this.removeAllListeners();
}
}
class FederatedEvent {
get layerX() {
return this.layer.x;
}
get layerY() {
return this.layer.y;
}
get pageX() {
return this.page.x;
}
get pageY() {
return this.page.y;
}
get x() {
return this.canvas.x;
}
get y() {
return this.canvas.y;
}
get canvasX() {
return this.canvas.x;
}
get canvasY() {
return this.canvas.y;
}
get viewX() {
return this.viewport.x;
}
get viewY() {
return this.viewport.y;
}
constructor(manager) {
this.bubbles = true;
this.cancelBubble = true;
this.cancelable = false;
this.composed = false;
this.defaultPrevented = false;
this.eventPhase = FederatedEvent.prototype.NONE;
this.propagationStopped = false;
this.propagationImmediatelyStopped = false;
this.layer = {
x: 0,
y: 0
};
this.page = {
x: 0,
y: 0
};
this.canvas = {
x: 0,
y: 0
};
this.viewport = {
x: 0,
y: 0
};
this.NONE = 0;
this.CAPTURING_PHASE = 1;
this.AT_TARGET = 2;
this.BUBBLING_PHASE = 3;
this.manager = manager;
}
composedPath() {
if (this.manager && (!this.path || this.path[this.path.length - 1] !== this.target)) {
this.path = this.target ? this.manager.propagationPath(this.target) : [];
}
this.composedDetailPath();
return this.path;
}
composedDetailPath() {
if (this.pickParams && this.pickParams.graphic) {
this.detailPath = this.path.slice();
this._composedDetailPath(this.pickParams);
}
else {
this.detailPath = this.path.slice();
}
return this.detailPath;
}
_composedDetailPath(params) {
if (params && params.graphic) {
const g = params.graphic;
if (g.stage) {
const path = g.stage.eventSystem.manager.propagationPath(g);
this.detailPath.push(path);
this._composedDetailPath(params.params);
}
}
}
preventDefault() {
try {
if (this.nativeEvent instanceof Event && this.nativeEvent.cancelable) {
this.nativeEvent.preventDefault();
}
}
catch (err) {
this.nativeEvent.preventDefault &&
isFunction(this.nativeEvent.preventDefault) &&
this.nativeEvent.preventDefault();
}
this.defaultPrevented = true;
}
stopImmediatePropagation() {
this.propagationImmediatelyStopped = true;
}
stopPropagation() {
try {
if (this.nativeEvent instanceof Event && this.nativeEvent.cancelable) {
this.nativeEvent.stopPropagation();
}
}
catch (err) {
this.nativeEvent.stopPropagation &&
isFunction(this.nativeEvent.stopPropagation) &&
this.nativeEvent.stopPropagation();
}
this.propagationStopped = true;
}
initEvent() {
return;
}
initUIEvent() {
return;
}
clone() {
throw new Error('Method not implemented.');
}
}
class FederatedMouseEvent extends FederatedEvent {
constructor() {
super(...arguments);
this.client = {
x: 0,
y: 0
};
this.movement = {
x: 0,
y: 0
};
this.offset = {
x: 0,
y: 0
};
this.global = {
x: 0,
y: 0
};
this.screen = {
x: 0,
y: 0
};
}
get clientX() {
return this.client.x;
}
get clientY() {
return this.client.y;
}
get movementX() {
return this.movement.x;
}
get movementY() {
return this.movement.y;
}
get offsetX() {
return this.offset.x;
}
get offsetY() {
return this.offset.y;
}
get globalX() {
return this.global.x;
}
get globalY() {
return this.global.y;
}
get screenX() {
return this.screen.x;
}
get screenY() {
return this.screen.y;
}
getModifierState(key) {
return 'getModifierState' in this.nativeEvent && this.nativeEvent.getModifierState(key);
}
initMouseEvent(_typeArg, _canBubbleArg, _cancelableArg, _viewArg, _detailArg, _screenXArg, _screenYArg, _clientXArg, _clientYArg, _ctrlKeyArg, _altKeyArg, _shiftKeyArg, _metaKeyArg, _buttonArg, _relatedTargetArg) {
throw new Error('Method not implemented.');
}
}
class FederatedPointerEvent extends FederatedMouseEvent {
constructor() {
super(...arguments);
this.width = 0;
this.height = 0;
this.isPrimary = false;
}
getCoalescedEvents() {
if (this.type === 'pointermove' || this.type === 'mousemove' || this.type === 'touchmove') {
return [this];
}
return [];
}
getPredictedEvents() {
throw new Error('getPredictedEvents is not supported!');
}
clone() {
var _a, _b, _c;
const event = new FederatedPointerEvent(this.manager);
event.eventPhase = event.NONE;
event.currentTarget = null;
event.path = [];
event.detailPath = [];
event.target = null;
event.nativeEvent = this.nativeEvent;
event.originalEvent = this.originalEvent;
(_a = this.manager) === null || _a === void 0 ? void 0 : _a.copyPointerData(this, event);
(_b = this.manager) === null || _b === void 0 ? void 0 : _b.copyMouseData(this, event);
(_c = this.manager) === null || _c === void 0 ? void 0 : _c.copyData(this, event);
event.target = this.target;
event.path = this.composedPath().slice();
const p = this.composedDetailPath();
event.detailPath = p && p.slice();
event.type = this.type;
return event;
}
}
class FederatedWheelEvent extends FederatedMouseEvent {
constructor() {
super(...arguments);
this.DOM_DELTA_PIXEL = 0;
this.DOM_DELTA_LINE = 1;
this.DOM_DELTA_PAGE = 2;
}
clone() {
var _a, _b, _c;
const event = new FederatedWheelEvent(this.manager);
event.eventPhase = event.NONE;
event.currentTarget = null;
event.path = [];
event.detailPath = [];
event.target = null;
event.nativeEvent = this.nativeEvent;
event.originalEvent = this.originalEvent;
(_a = this.manager) === null || _a === void 0 ? void 0 : _a.copyWheelData(this, event);
(_b = this.manager) === null || _b === void 0 ? void 0 : _b.copyMouseData(this, event);
(_c = this.manager) === null || _c === void 0 ? void 0 : _c.copyData(this, event);
event.target = this.target;
event.path = this.composedPath().slice();
const p = this.composedDetailPath();
event.detailPath = p && p.slice();
event.type = this.type;
return event;
}
}
FederatedWheelEvent.DOM_DELTA_PIXEL = 0;
FederatedWheelEvent.DOM_DELTA_LINE = 1;
FederatedWheelEvent.DOM_DELTA_PAGE = 2;
class CustomEvent extends FederatedEvent {
constructor(eventName, object) {
super();
this.type = eventName;
this.detail = object;
}
}
const WILDCARD = '*';
const clock = typeof performance === 'object' && performance.now ? performance : Date;
const PROPAGATION_LIMIT = 2048;
function isMouseLike(pointerType) {
return pointerType === 'mouse' || pointerType === 'pen';
}
const DEFAULT_CLICK_INTERVAL = 200;
class EventManager {
constructor(root, config) {
this.dispatch = new EventEmitter();
this.cursorTarget = null;
this.pauseNotify = false;
this.mappingState = {
trackingData: {}
};
this.eventPool = new Map();
this.onPointerDown = (from, target) => {
if (!(from instanceof FederatedPointerEvent)) {
Logger.getInstance().warn('EventManager cannot map a non-pointer event as a pointer event');
return;
}
const e = this.createPointerEvent(from, from.type, target);
this.dispatchEvent(e, 'pointerdown');
if (e.pointerType === 'touch') {
this.dispatchEvent(e, 'touchstart');
}
else if (isMouseLike(e.pointerType)) {
const isRightButton = e.button === 2;
this.dispatchEvent(e, isRightButton ? 'rightdown' : 'mousedown');
}
const trackingData = this.trackingData(from.pointerId);
trackingData.pressTargetsByButton[from.button] = e.composedPath();
this.freeEvent(e);
};
this.onPointerMove = (from, target) => {
var _a, _b;
if (!(from instanceof FederatedPointerEvent)) {
Logger.getInstance().warn('EventManager cannot map a non-pointer event as a pointer event');
return;
}
const e = this.createPointerEvent(from, from.type, target);
const isMouse = isMouseLike(e.pointerType);
const trackingData = this.trackingData(from.pointerId);
const outTarget = this.findMountedTarget(trackingData.overTargets);
if (trackingData.overTargets && outTarget && outTarget !== this.rootTarget && outTarget !== e.target) {
const outType = from.type === 'mousemove' ? 'mouseout' : 'pointerout';
const outEvent = this.createPointerEvent(from, outType, outTarget || undefined);
this.dispatchEvent(outEvent, 'pointerout');
if (isMouse) {
this.dispatchEvent(outEvent, 'mouseout');
}
if (!e.composedPath().includes(outTarget)) {
const leaveEvent = this.createPointerEvent(from, 'pointerleave', outTarget || undefined);
leaveEvent.eventPhase = leaveEvent.AT_TARGET;
while (leaveEvent.target && !e.composedPath().includes(leaveEvent.target)) {
leaveEvent.currentTarget = leaveEvent.target;
this.notifyTarget(leaveEvent);
if (isMouse) {
this.notifyTarget(leaveEvent, 'mouseleave');
}
leaveEvent.target = leaveEvent.target.parent;
}
this.freeEvent(leaveEvent);
}
this.freeEvent(outEvent);
}
if (outTarget !== e.target) {
const overType = from.type === 'mousemove' ? 'mouseover' : 'pointerover';
const overEvent = this.clonePointerEvent(e, overType);
this.dispatchEvent(overEvent, 'pointerover');
if (isMouse) {
this.dispatchEvent(overEvent, 'mouseover');
}
let overTargetAncestor = outTarget === null || outTarget === void 0 ? void 0 : outTarget.parent;
while (overTargetAncestor && overTargetAncestor !== this.rootTarget.parent) {
if (overTargetAncestor === e.target) {
break;
}
overTargetAncestor = overTargetAncestor.parent;
}
const didPointerE