graphic-pixi/lib/index.js
2023-12-14 13:07:09 +08:00

8052 lines
272 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
var pixi_js = require('pixi.js');
var EventEmitter = require('eventemitter3');
var pixiViewport = require('pixi-viewport');
var stompjs = require('@stomp/stompjs');
var mqtt = require('mqtt');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* ID生成器
*/
var IdGenerator = /** @class */ (function () {
function IdGenerator(type) {
this.serial = 0;
this.type = type;
}
IdGenerator.prototype.next = function () {
++this.serial;
// console.log(this.getType() + this.serial)
return this.getType() + this.serial;
};
IdGenerator.prototype.getType = function () {
return this.type;
};
IdGenerator.prototype.initSerial = function (serial) {
// console.log(serial)
this.serial = serial;
};
return IdGenerator;
}());
var GraphicIdGenerator = new IdGenerator('');
exports.InteractionPluginType = void 0;
(function (InteractionPluginType) {
InteractionPluginType["App"] = "app";
InteractionPluginType["Graphic"] = "graphic";
InteractionPluginType["Other"] = "other";
})(exports.InteractionPluginType || (exports.InteractionPluginType = {}));
var InteractionPluginBase = /** @class */ (function () {
function InteractionPluginBase(app, name, type) {
this._type = type;
this.app = app;
this.name = name;
this._pause = true;
app.registerInteractionPlugin(this);
}
/**
* 恢复
*/
InteractionPluginBase.prototype.resume = function () {
this.bind();
this._pause = false;
this.app.emit('interaction-plugin-resume', this);
};
/**
* 停止
*/
InteractionPluginBase.prototype.pause = function () {
this.unbind();
this._pause = true;
this.app.emit('interaction-plugin-pause', this);
};
/**
* 是否生效
*/
InteractionPluginBase.prototype.isActive = function () {
return !this._pause;
};
InteractionPluginBase.prototype.isGraphicPlugin = function () {
return this._type === exports.InteractionPluginType.Graphic;
};
InteractionPluginBase.prototype.isAppPlugin = function () {
return this._type === exports.InteractionPluginType.App;
};
InteractionPluginBase.prototype.isOtherPlugin = function () {
return this._type === exports.InteractionPluginType.Other;
};
return InteractionPluginBase;
}());
var OtherInteractionPlugin = /** @class */ (function (_super) {
__extends(OtherInteractionPlugin, _super);
function OtherInteractionPlugin(app, name) {
return _super.call(this, app, name, exports.InteractionPluginType.Other) || this;
}
return OtherInteractionPlugin;
}(InteractionPluginBase));
var AppDragEvent = /** @class */ (function () {
function AppDragEvent(app, type, target, original, start) {
this.app = app;
this.type = type;
this.target = target;
this.original = original;
this.start = start;
}
Object.defineProperty(AppDragEvent.prototype, "isMouse", {
get: function () {
return this.original.pointerType === 'mouse';
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "isLeftButton", {
get: function () {
return (this.isMouse &&
((this.original.button === -1 && this.original.buttons === 1) ||
(this.original.button === 0 && this.original.buttons === 0)));
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "isRightButton", {
get: function () {
return (this.isMouse &&
((this.original.button === -1 && this.original.buttons === 2) ||
(this.original.button === 2 && this.original.buttons === 0)));
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "isMiddleButton", {
get: function () {
return (this.isMouse &&
((this.original.button === -1 && this.original.buttons === 4) ||
(this.original.button === 1 && this.original.buttons === 0)));
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "isTouch", {
get: function () {
return this.original.pointerType === 'touch';
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "end", {
/**
* 终点坐标(画布坐标)
*/
get: function () {
return this.app.toCanvasCoordinates(this.original.global);
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "dx", {
get: function () {
var move = this.original.movement;
return move.x / this.app.viewport.scaled;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "dy", {
get: function () {
var move = this.original.movement;
return move.y / this.app.viewport.scaled;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "dsx", {
get: function () {
return this.end.x - this.start.x;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AppDragEvent.prototype, "dsy", {
get: function () {
return this.end.y - this.start.y;
},
enumerable: false,
configurable: true
});
/**
* 转换为目标对象的位移距离
*/
AppDragEvent.prototype.toTargetShiftLen = function (target) {
var sl = target.canvasToLocalPoint(this.start);
var el = target.canvasToLocalPoint(this.end);
return { dx: el.x - sl.x, dy: el.y - sl.y };
};
return AppDragEvent;
}());
/**
* 拖拽操作插件
*/
var DragPlugin = /** @class */ (function (_super) {
__extends(DragPlugin, _super);
function DragPlugin(app) {
var _this = _super.call(this, app, DragPlugin.Name) || this;
_this.threshold = 3;
_this.target = null;
_this.start = null;
_this.startClientPoint = null;
_this.drag = false;
app.on('options-update', function (options) {
if (options.threshold !== undefined) {
_this.threshold = options.threshold;
}
});
return _this;
}
DragPlugin.new = function (app) {
return new DragPlugin(app);
};
DragPlugin.prototype.bind = function () {
var canvas = this.app.canvas;
canvas.on('pointerdown', this.onPointerDown, this);
};
DragPlugin.prototype.unbind = function () {
var canvas = this.app.canvas;
canvas.off('pointerdown', this.onPointerDown, this);
canvas.off('pointerup', this.onPointerUp, this);
canvas.off('pointerupoutside', this.onPointerUp, this);
};
DragPlugin.prototype.onPointerDown = function (e) {
this.target = e.target;
this.start = this.app.toCanvasCoordinates(e.global);
this.startClientPoint = e.global.clone();
var canvas = this.app.canvas;
canvas.on('pointermove', this.onPointerMove, this);
canvas.on('pointerup', this.onPointerUp, this);
canvas.on('pointerupoutside', this.onPointerUp, this);
};
DragPlugin.prototype.onPointerMove = function (e) {
if (this.start && this.startClientPoint) {
var current = e.global;
var sgp = this.startClientPoint;
var dragStart = Math.abs(current.x - sgp.x) > this.threshold ||
Math.abs(current.y - sgp.y) > this.threshold;
if (this.target && this.start && !this.drag && dragStart) {
this.app.emit('drag_op_start', new AppDragEvent(this.app, 'start', this.target, e, this.start));
this.drag = true;
}
// drag移动处理
if (this.target && this.drag && this.start) {
// console.log('drag move', e.movement);
this.app.emit('drag_op_move', new AppDragEvent(this.app, 'move', this.target, e, this.start));
}
}
};
DragPlugin.prototype.onPointerUp = function (e) {
if (this.target && this.drag && this.start) {
// console.log('drag end');
this.app.emit('drag_op_end', new AppDragEvent(this.app, 'end', this.target, e, this.start));
}
else if (this.target && this.start && !this.drag) {
// this.target.emit('click', this.target);
var ade = new AppDragEvent(this.app, 'end', this.target, e, this.start);
var graphic = this.target.getGraphic();
if (ade.isRightButton) {
this.target.emit('_rightclick', e);
if (graphic != null) {
graphic.emit('_rightclick', e);
}
}
else if (ade.isLeftButton) {
this.target.emit('_leftclick', e);
if (graphic != null) {
graphic.emit('_leftclick', e);
}
}
}
var canvas = this.app.canvas;
canvas.off('mousemove', this.onPointerMove, this);
canvas.off('mouseup', this.onPointerUp, this);
canvas.off('mouseupoutside', this.onPointerUp, this);
this.clearCache();
};
/**
* 清理缓存
*/
DragPlugin.prototype.clearCache = function () {
this.drag = false;
this.start = null;
this.startClientPoint = null;
this.target = null;
};
DragPlugin.Name = '__drag_operation_plugin';
return DragPlugin;
}(OtherInteractionPlugin));
/**
* 视口移动插件
*/
var ViewportMovePlugin = /** @class */ (function (_super) {
__extends(ViewportMovePlugin, _super);
function ViewportMovePlugin(app) {
var _this = _super.call(this, app, ViewportMovePlugin.Name) || this;
_this.moveHandler = null;
_this.moveSpeedx = 0;
_this.moveSpeedy = 0;
return _this;
}
ViewportMovePlugin.new = function (app) {
return new ViewportMovePlugin(app);
};
ViewportMovePlugin.prototype.pause = function () {
_super.prototype.pause.call(this);
this.stopMove();
};
ViewportMovePlugin.prototype.bind = function () {
this.app.canvas.on('pointermove', this.viewportMove, this);
};
ViewportMovePlugin.prototype.unbind = function () {
this.app.canvas.off('pointermove', this.viewportMove, this);
};
ViewportMovePlugin.prototype.startMove = function (moveSpeedx, moveSpeedy) {
var _this = this;
this.moveSpeedx = moveSpeedx;
this.moveSpeedy = moveSpeedy;
if (this.moveHandler == null) {
var viewport_1 = this.app.viewport;
this.moveHandler = setInterval(function () {
viewport_1.moveCorner(viewport_1.corner.x + _this.moveSpeedx, viewport_1.corner.y + _this.moveSpeedy);
}, ViewportMovePlugin.MoveInterval);
}
};
ViewportMovePlugin.prototype.stopMove = function () {
if (this.moveHandler != null) {
clearInterval(this.moveHandler);
this.moveHandler = null;
this.app.canvas.cursor = 'auto';
}
};
ViewportMovePlugin.prototype.calculateBoundaryMoveSpeed = function (sp) {
var moveSpeedx = 0;
var moveSpeedy = 0;
var range = ViewportMovePlugin.TriggerRange;
var viewport = this.app.viewport;
if (sp.x < range) {
moveSpeedx = this.calculateMoveSpeed(sp.x - range);
}
else if (sp.x > viewport.screenWidth - range) {
moveSpeedx = this.calculateMoveSpeed(sp.x + range - viewport.screenWidth);
}
else {
moveSpeedx = 0;
}
if (sp.y < range) {
moveSpeedy = this.calculateMoveSpeed(sp.y - range);
}
else if (sp.y > viewport.screenHeight - range) {
moveSpeedy = this.calculateMoveSpeed(sp.y + range - viewport.screenHeight);
}
else {
moveSpeedy = 0;
}
return { moveSpeedx: moveSpeedx, moveSpeedy: moveSpeedy };
};
ViewportMovePlugin.prototype.calculateMoveSpeed = function (dd) {
return ((dd / ViewportMovePlugin.TriggerRange) *
ViewportMovePlugin.DefaultMoveSpeed);
};
ViewportMovePlugin.prototype.viewportMove = function (e) {
var sp = e.global;
var _a = this.calculateBoundaryMoveSpeed(sp), moveSpeedx = _a.moveSpeedx, moveSpeedy = _a.moveSpeedy;
if (moveSpeedx == 0 && moveSpeedy == 0) {
this.app.canvas.cursor = 'auto';
this.stopMove();
}
else {
this.app.canvas.cursor = 'grab';
this.startMove(moveSpeedx, moveSpeedy);
}
};
ViewportMovePlugin.Name = '__viewport_move_plugin';
ViewportMovePlugin.MoveInterval = 20; // 移动间隔单位ms
ViewportMovePlugin.TriggerRange = 100; // 边界触发范围,单位px
ViewportMovePlugin.DefaultMoveSpeed = 200 / ViewportMovePlugin.MoveInterval; // 默认移动速度
return ViewportMovePlugin;
}(OtherInteractionPlugin));
/**
* 应用交互插件,同时只能生效一个
*/
var AppInteractionPlugin = /** @class */ (function (_super) {
__extends(AppInteractionPlugin, _super);
function AppInteractionPlugin(name, app) {
return _super.call(this, app, name, exports.InteractionPluginType.App) || this;
}
/**
* 恢复app交互插件同时只能生效一个
*/
AppInteractionPlugin.prototype.resume = function () {
this.app.pauseAppInteractionPlugins();
_super.prototype.resume.call(this);
};
return AppInteractionPlugin;
}(InteractionPluginBase));
/**
* 图形交互插件,可同时生效
*/
var GraphicInteractionPlugin = /** @class */ (function () {
function GraphicInteractionPlugin(name, app) {
var _this = this;
this._type = exports.InteractionPluginType.Graphic;
this.app = app;
this.name = name;
this._pause = true;
app.registerInteractionPlugin(this);
this.resume();
// 新增的图形对象绑定
this.app.on('graphicstored', function (g) {
if (_this.isActive()) {
_this.binds(_this.filter(g));
}
});
this.app.on('graphicdeleted', function (g) {
if (_this.isActive()) {
_this.unbinds(_this.filter(g));
}
});
}
GraphicInteractionPlugin.prototype.isActive = function () {
return !this._pause;
};
GraphicInteractionPlugin.prototype.isAppPlugin = function () {
return false;
};
GraphicInteractionPlugin.prototype.isOtherPlugin = function () {
return false;
};
GraphicInteractionPlugin.prototype.isGraphicPlugin = function () {
return true;
};
GraphicInteractionPlugin.prototype.resume = function () {
var list = this.filter.apply(this, this.app.queryStore.getAllGraphics());
this.binds(list);
this._pause = false;
this.app.emit('interaction-plugin-resume', this);
};
GraphicInteractionPlugin.prototype.pause = function () {
var list = this.filter.apply(this, this.app.queryStore.getAllGraphics());
this.unbinds(list);
this._pause = true;
this.app.emit('interaction-plugin-pause', this);
};
GraphicInteractionPlugin.prototype.binds = function (list) {
var _this = this;
if (list) {
list.forEach(function (g) { return _this.bind(g); });
}
};
GraphicInteractionPlugin.prototype.unbinds = function (list) {
var _this = this;
if (list) {
list.forEach(function (g) { return _this.unbind(g); });
}
};
return GraphicInteractionPlugin;
}());
var CompleteMouseToolOptions = /** @class */ (function () {
function CompleteMouseToolOptions() {
this.boxSelect = true;
this.viewportDrag = true;
this.wheelZoom = true;
this.viewportDragLeft = false;
}
CompleteMouseToolOptions.prototype.update = function (options) {
if (options.boxSelect != undefined) {
this.boxSelect = options.boxSelect;
}
if (options.viewportDrag != undefined) {
this.viewportDrag = options.viewportDrag;
}
if (options.viewportDragLeft != undefined) {
this.viewportDragLeft = options.viewportDragLeft;
}
if (options.wheelZoom != undefined) {
this.wheelZoom = options.wheelZoom;
}
this.selectFilter = options.selectFilter;
};
return CompleteMouseToolOptions;
}());
/**
* 通用交互工具
*/
var CommonMouseTool = /** @class */ (function (_super) {
__extends(CommonMouseTool, _super);
function CommonMouseTool(scene) {
var _this = _super.call(this, CommonMouseTool.Name, scene) || this;
_this.leftDownTarget = null;
_this.drag = false;
_this.graphicSelect = false;
_this.rightTarget = null;
_this.options = new CompleteMouseToolOptions();
_this.box = new pixi_js.Graphics();
_this.box.name = CommonMouseTool.SelectBox;
_this.box.visible = false;
_this.app.canvas.addAssistantAppends(_this.box);
scene.on('options-update', function (options) {
if (options.mouseToolOptions) {
_this.options.update(options.mouseToolOptions);
if (_this.isActive()) {
_this.pause();
_this.resume();
}
}
});
return _this;
}
CommonMouseTool.new = function (app) {
return new CommonMouseTool(app);
};
CommonMouseTool.prototype.bind = function () {
var canvas = this.app.canvas;
canvas.on('mousedown', this.onMouseDown, this);
canvas.on('mouseup', this.onMouseUp, this);
this.app.on('drag_op_start', this.onDragStart, this);
this.app.on('drag_op_move', this.onDragMove, this);
this.app.on('drag_op_end', this.onDragEnd, this);
if (this.options.viewportDrag) {
if (this.options.viewportDragLeft) {
this.app.viewport.drag({
mouseButtons: 'left',
});
canvas.on('mousedown', this.setLeftCursor, this);
canvas.on('mouseup', this.resumeLeftCursor, this);
canvas.on('mouseupoutside', this.resumeLeftCursor, this);
}
else {
this.app.viewport.drag({
mouseButtons: 'right',
});
canvas.on('rightdown', this.setCursor, this);
canvas.on('rightup', this.resumeCursor, this);
canvas.on('rightupoutside', this.resumeCursor, this);
}
}
if (this.options.wheelZoom) {
this.app.viewport.wheel({
percent: 0.01,
});
}
};
CommonMouseTool.prototype.unbind = function () {
var canvas = this.app.canvas;
// 确保所有事件取消监听
canvas.off('mousedown', this.onMouseDown, this);
canvas.off('mouseup', this.onMouseUp, this);
this.app.off('drag_op_start', this.onDragStart, this);
this.app.off('drag_op_move', this.onDragMove, this);
this.app.off('drag_op_end', this.onDragEnd, this);
this.app.viewport.plugins.remove('drag');
canvas.off('mousedown', this.setLeftCursor, this);
canvas.off('mouseup', this.resumeLeftCursor, this);
canvas.off('mouseupoutside', this.resumeLeftCursor, this);
canvas.off('rightdown', this.setCursor, this);
canvas.off('rightup', this.resumeCursor, this);
canvas.off('rightupoutside', this.resumeCursor, this);
this.app.viewport.plugins.remove('wheel');
this.clearCache();
};
CommonMouseTool.prototype.onDragStart = function (event) {
// console.log(
// 'start',
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
// );
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
this.box.visible = true;
this.app.interactionPlugin(ViewportMovePlugin.Name).resume();
}
this.drag = true;
};
CommonMouseTool.prototype.onDragMove = function (event) {
// console.log(
// 'moving',
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
// );
if (this.boxSelect && event.target.isCanvas()) {
this.boxSelectDraw(event.start, event.end);
}
};
CommonMouseTool.prototype.onDragEnd = function (event) {
// console.log(
// 'end',
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
// );
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
this.boxSelectDraw(event.start, event.end);
this.boxSelectGraphicCheck();
this.app.interactionPlugin(ViewportMovePlugin.Name).pause();
this.box.clear();
this.box.visible = false;
}
};
CommonMouseTool.prototype.setLeftCursor = function (e) {
var target = e.target;
this.leftDownTarget = target;
if (target.isCanvas() && this.app.pixi.view.style) {
this.app.pixi.view.style.cursor = 'grab';
}
};
CommonMouseTool.prototype.resumeLeftCursor = function () {
if (this.leftDownTarget &&
this.leftDownTarget.isCanvas() &&
this.app.pixi.view.style) {
this.app.pixi.view.style.cursor = 'inherit';
}
this.leftDownTarget = null;
};
CommonMouseTool.prototype.setCursor = function (e) {
var target = e.target;
this.rightTarget = target;
if (target.isCanvas() && this.app.pixi.view.style) {
this.app.pixi.view.style.cursor = 'grab';
}
};
CommonMouseTool.prototype.resumeCursor = function () {
if (this.rightTarget &&
this.rightTarget.isCanvas() &&
this.app.pixi.view.style) {
this.app.pixi.view.style.cursor = 'inherit';
}
this.rightTarget = null;
};
CommonMouseTool.prototype.onMouseDown = function (e) {
this.leftDownTarget = e.target;
this.graphicSelect = false;
// 图形
var graphic = this.leftDownTarget.getGraphic();
if (graphic) {
var app = this.app;
// console.log(this.leftDownTarget.isGraphic());
// 图形选中
if (!e.ctrlKey && !graphic.selected && graphic.selectable) {
app.updateSelected(graphic);
graphic.childEdit = false;
this.graphicSelect = true;
}
else if (!e.ctrlKey && graphic.selected && graphic.childEdit) {
if (this.leftDownTarget.isGraphicChild() &&
this.leftDownTarget.selectable) {
graphic.setChildSelected(this.leftDownTarget);
}
else {
graphic.exitChildEdit();
}
}
}
};
/**
* 选中处理
* @param e
*/
CommonMouseTool.prototype.onMouseUp = function (e) {
var app = this.app;
if (!this.drag) {
var target = e.target;
var graphic = e.target.getGraphic();
if (graphic &&
graphic.selected &&
!this.graphicSelect &&
app.selectedGraphics.length == 1 &&
target === this.leftDownTarget &&
target.isGraphicChild() &&
target.selectable) {
graphic.childEdit = true;
}
if (e.ctrlKey) {
// 多选
if (graphic) {
if (graphic.childEdit && target === this.leftDownTarget) {
graphic.invertChildSelected(target);
}
else {
graphic.invertSelected();
}
}
}
else {
// 非多选
if (e.target.isCanvas()) {
this.app.updateSelected();
}
else {
if (graphic &&
graphic.childEdit &&
app.selectedGraphics.length === 1 &&
target === this.leftDownTarget) {
graphic.setChildSelected(target);
}
}
}
// 多个图形选中,退出子元素编辑模式
var selecteds = this.app.selectedGraphics;
if (selecteds.length > 1) {
selecteds.forEach(function (g) { return g.exitChildEdit(); });
}
}
this.clearCache();
};
/**
* 清理缓存
*/
CommonMouseTool.prototype.clearCache = function () {
this.drag = false;
this.leftDownTarget = null;
};
Object.defineProperty(CommonMouseTool.prototype, "boxSelect", {
get: function () {
return this.options.boxSelect;
},
enumerable: false,
configurable: true
});
Object.defineProperty(CommonMouseTool.prototype, "selectFilter", {
get: function () {
return this.options.selectFilter;
},
enumerable: false,
configurable: true
});
/**
* 框选图形绘制并检查
*/
CommonMouseTool.prototype.boxSelectDraw = function (start, end) {
if (!this.drag)
return;
// 绘制框选矩形框
this.box.clear();
this.box.lineStyle({
width: 2,
color: this.app.appOptions.assistantElementColor ||
AppConsts.assistantElementColor,
});
var dsx = end.x - start.x;
var dsy = end.y - start.y;
var x = start.x, y = start.y;
if (dsx < 0) {
x += dsx;
}
if (dsy < 0) {
y += dsy;
}
var width = Math.abs(dsx);
var height = Math.abs(dsy);
this.box.drawRect(x, y, width, height);
};
/**
* 框选图形判断
* @returns
*/
CommonMouseTool.prototype.boxSelectGraphicCheck = function () {
var _this = this;
if (!this.drag)
return;
// 遍历筛选
var boxRect = this.box.getLocalBounds();
var app = this.app;
var selects = [];
app.queryStore.getAllGraphics().forEach(function (g) {
if ((_this.selectFilter == undefined && g.visible) ||
(!!_this.selectFilter && _this.selectFilter(g))) {
// 选择过滤器
if (g.boxIntersectCheck(boxRect)) {
selects.push(g);
}
}
});
app.updateSelected.apply(app, selects);
};
CommonMouseTool.Name = 'mouse-tool';
CommonMouseTool.SelectBox = '__select_box';
return CommonMouseTool;
}(AppInteractionPlugin));
var target;
var GlobalKeyboardHelper = /** @class */ (function () {
function GlobalKeyboardHelper() {
var _this = this;
this.appKeyboardPluginMap = [];
window.onkeydown = function (e) {
_this.appKeyboardPluginMap.forEach(function (plugin) {
var listenerMap = plugin.getKeyListener(e);
listenerMap === null || listenerMap === void 0 ? void 0 : listenerMap.forEach(function (listener) {
if (listener.global) {
listener.press(e, plugin.app);
}
});
});
if (e.ctrlKey) {
if (e.code == 'KeyS') {
// 屏蔽全局Ctrl+S保存操作
// console.log('屏蔽全局Ctrl+S')
return false;
}
}
if (target && target.nodeName == 'CANVAS') {
// 事件的目标是画布时,屏蔽总的键盘操作操作
if (e.ctrlKey) {
if (e.code == 'KeyA' || e.code == 'KeyS') {
// 屏蔽Canvas上的Ctrl+A、Ctrl+S操作
return false;
}
}
}
return true;
};
window.onkeyup = function (e) {
_this.appKeyboardPluginMap.forEach(function (plugin) {
var listenerMap = plugin.getKeyListener(e);
listenerMap === null || listenerMap === void 0 ? void 0 : listenerMap.forEach(function (listener) {
if (listener.global) {
listener.release(e, plugin.app);
}
});
});
};
}
GlobalKeyboardHelper.prototype.registerGAKPlugin = function (plugin) {
if (!this.appKeyboardPluginMap.find(function (pg) { return pg == plugin; })) {
this.appKeyboardPluginMap.push(plugin);
}
};
GlobalKeyboardHelper.prototype.removeGAKPlugin = function (plugin) {
var index = this.appKeyboardPluginMap.findIndex(function (pg) { return pg == plugin; });
if (index >= 0) {
this.appKeyboardPluginMap.splice(index, 1);
}
};
return GlobalKeyboardHelper;
}());
var GlobalKeyboardPlugin = new GlobalKeyboardHelper();
var JlGraphicAppKeyboardPlugin = /** @class */ (function () {
function JlGraphicAppKeyboardPlugin(app) {
var _this = this;
/**
* 结构为Map<key.code|key.key|key.keyCode, Map<KeyListener.identifier, KeyListener>>
*/
this.keyListenerMap = new Map(); // 键值监听map
this.keyListenerStackMap = new Map(); // 键值监听栈(多次注册相同的监听会把之前注册的监听器入栈,移除最新的监听会从栈中弹出一个作为指定事件监听处理器)
this.app = app;
GlobalKeyboardPlugin.registerGAKPlugin(this);
var onMouseUpdateTarget = function (e) {
var node = e.target;
target = node;
// console.log('Mousedown Event', node.nodeName, node.nodeType, node.nodeValue)
};
var keydownHandle = function (e) {
var _a;
// console.debug(e.key, e.code, e.keyCode);
if (target && target == ((_a = _this.app.dom) === null || _a === void 0 ? void 0 : _a.getElementsByTagName('canvas')[0])) {
var listenerMap = _this.getKeyListener(e);
listenerMap === null || listenerMap === void 0 ? void 0 : listenerMap.forEach(function (listener) {
if (!listener.global) {
listener.press(e, _this.app);
}
});
}
};
var keyupHandle = function (e) {
var _a;
if (target && target == ((_a = _this.app.dom) === null || _a === void 0 ? void 0 : _a.getElementsByTagName('canvas')[0])) {
var listenerMap = _this.getKeyListener(e);
listenerMap === null || listenerMap === void 0 ? void 0 : listenerMap.forEach(function (listener) {
if (!listener.global) {
listener.release(e, _this.app);
}
});
}
};
document.addEventListener('mousedown', onMouseUpdateTarget, false);
document.addEventListener('keydown', keydownHandle, false);
document.addEventListener('keyup', keyupHandle, false);
this.app.on('destroy', function () {
document.removeEventListener('mousedown', onMouseUpdateTarget, false);
document.removeEventListener('keydown', keydownHandle, false);
document.removeEventListener('keyup', keyupHandle, false);
GlobalKeyboardPlugin.removeGAKPlugin(_this);
});
}
JlGraphicAppKeyboardPlugin.prototype.getOrInit = function (key) {
var map = this.keyListenerMap.get(key);
if (map === undefined) {
map = new Map();
this.keyListenerMap.set(key, map);
}
return map;
};
JlGraphicAppKeyboardPlugin.prototype.getOrInitStack = function (key) {
var stack = this.keyListenerStackMap.get(key);
if (stack === undefined) {
stack = [];
this.keyListenerStackMap.set(key, stack);
}
return stack;
};
/**
* 注册按键监听,若有旧的,旧的入栈
* @param keyListener
*/
JlGraphicAppKeyboardPlugin.prototype.addKeyListener = function (keyListener) {
var map = this.getOrInit(keyListener.value);
// 查询是否有旧的监听,若有入栈
var old = map.get(keyListener.identifier);
if (old) {
var stack = this.getOrInitStack(keyListener.identifier);
stack.push(old);
}
map.set(keyListener.identifier, keyListener);
// console.log(this.getAllListenedKeys());
};
/**
* 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听
* @param keyListener
*/
JlGraphicAppKeyboardPlugin.prototype.removeKeyListener = function (keyListener) {
keyListener.onRemove();
var map = this.getOrInit(keyListener.value);
var old = map.get(keyListener.identifier);
map.delete(keyListener.identifier);
var stack = this.getOrInitStack(keyListener.identifier);
if (old && old === keyListener) {
// 是旧的监听
var listener = stack.pop();
if (listener) {
map.set(keyListener.identifier, listener);
}
}
else {
// 移除栈中的
var index = stack.findIndex(function (ls) { return ls === keyListener; });
if (index >= 0) {
stack.splice(index, 1);
}
}
// console.log(this);
};
JlGraphicAppKeyboardPlugin.prototype.getKeyListenerBy = function (key) {
return this.keyListenerMap.get(key);
};
JlGraphicAppKeyboardPlugin.prototype.getKeyListener = function (e) {
return (this.getKeyListenerBy(e.key) ||
this.getKeyListenerBy(e.code) ||
this.getKeyListenerBy(e.keyCode));
};
JlGraphicAppKeyboardPlugin.prototype.isKeyListened = function (key) {
return this.getOrInit(key).size > 0;
};
/**
* 获取所有注册监听的键值(组合键)
*/
JlGraphicAppKeyboardPlugin.prototype.getAllListenedKeys = function () {
var keys = [];
this.keyListenerMap.forEach(function (v) {
return v.forEach(function (_listener, ck) { return keys.push(ck); });
});
return keys;
};
return JlGraphicAppKeyboardPlugin;
}());
exports.CombinationKey = void 0;
(function (CombinationKey) {
CombinationKey["Ctrl"] = "Ctrl";
CombinationKey["Alt"] = "Alt";
CombinationKey["Shift"] = "Shift";
})(exports.CombinationKey || (exports.CombinationKey = {}));
var DefaultKeyListenerOptions = {
value: '',
combinations: [],
global: false,
onPress: undefined,
pressTriggerAsOriginalEvent: false,
onRelease: undefined,
};
var KeyListener = /** @class */ (function () {
function KeyListener(options) {
this.isPress = false;
this.options = Object.assign({}, DefaultKeyListenerOptions, options);
}
KeyListener.create = function (options) {
return new KeyListener(options);
};
Object.defineProperty(KeyListener.prototype, "value", {
get: function () {
return this.options.value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "combinations", {
get: function () {
return this.options.combinations;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "identifier", {
get: function () {
return this.options.combinations.join('+') + '+' + this.options.value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "global", {
get: function () {
return this.options.global;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "onPress", {
get: function () {
return this.options.onPress;
},
set: function (v) {
this.options.onPress = v;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "onRelease", {
get: function () {
return this.options.onRelease;
},
set: function (v) {
this.options.onRelease = v;
},
enumerable: false,
configurable: true
});
Object.defineProperty(KeyListener.prototype, "pressTriggerEveryTime", {
get: function () {
return this.options.pressTriggerAsOriginalEvent;
},
set: function (v) {
this.options.pressTriggerAsOriginalEvent = v;
},
enumerable: false,
configurable: true
});
KeyListener.prototype.press = function (e, app) {
if (!this.checkCombinations(e)) {
console.debug('组合键不匹配, 不执行press', e, this);
return;
}
if (this.pressTriggerEveryTime || !this.isPress) {
// console.log('Keydown: ', e, this.onPress);
this.isPress = true;
if (this.onPress) {
this.onPress(e, app);
}
}
};
/**
* 检查组合键是否匹配
*/
KeyListener.prototype.checkCombinations = function (e) {
var cbs = this.combinations;
if (cbs.length > 0) {
if (((e.altKey && cbs.includes(exports.CombinationKey.Alt)) ||
(!e.altKey && !cbs.includes(exports.CombinationKey.Alt))) &&
((e.ctrlKey && cbs.includes(exports.CombinationKey.Ctrl)) ||
(!e.ctrlKey && !cbs.includes(exports.CombinationKey.Ctrl))) &&
((e.shiftKey && cbs.includes(exports.CombinationKey.Shift)) ||
(!e.shiftKey && !cbs.includes(exports.CombinationKey.Shift)))) {
return true;
}
}
else {
return !e.altKey && !e.ctrlKey && !e.shiftKey;
}
return false;
};
KeyListener.prototype.release = function (e, app) {
if (this.isPress) {
// console.log('Keyup : ', e.key, e);
this.isPress = false;
if (this.onRelease) {
this.onRelease(e, app);
}
}
};
KeyListener.prototype.onRemove = function () {
// 重置按下状态
this.isPress = false;
};
return KeyListener;
}());
/**
* 图形复制插件
*/
var GraphicCopyPlugin = /** @class */ (function () {
function GraphicCopyPlugin(scene) {
var _this = this;
this.running = false;
this.scene = scene;
this.container = new pixi_js.Container();
this.copys = [];
this.keyListeners = [];
this.keyListeners.push(new KeyListener({
// ESC 用于取消复制操作
value: 'Escape',
global: true,
// combinations: [CombinationKey.Ctrl],
onPress: function () {
_this.cancle();
},
}), new KeyListener({
// X 限制只能在x轴移动
value: 'KeyX',
global: true,
// combinations: [CombinationKey.Ctrl],
onPress: function () {
_this.updateMoveLimit('x');
},
}), new KeyListener({
// Y 限制只能在y轴移动
value: 'KeyY',
global: true,
// combinations: [CombinationKey.Ctrl],
onPress: function () {
_this.updateMoveLimit('y');
},
}));
}
GraphicCopyPlugin.prototype.updateMoveLimit = function (limit) {
if (this.moveLimit === limit) {
this.moveLimit = undefined;
}
else {
this.moveLimit = limit;
}
};
GraphicCopyPlugin.prototype.init = function () {
var _this = this;
if (this.running)
return;
if (this.scene.selectedGraphics.length === 0) {
throw new Error('没有选中图形,复制取消');
}
this.running = true;
this.copys = [];
this.container.alpha = 0.5;
this.scene.canvas.addChild(this.container);
var app = this.scene;
this.scene.selectedGraphics.forEach(function (g) {
var template = app.getGraphicTemplatesByType(g.type);
var clone = template.clone(g);
_this.copys.push(clone);
_this.container.position.set(0, 0);
_this.container.addChild(clone);
clone.repaint();
});
this.scene.canvas.on('mousemove', this.onPointerMove, this);
this.scene.canvas.on('mouseup', this.onFinish, this);
this.scene.canvas.on('rightup', this.cancle, this);
this.keyListeners.forEach(function (kl) {
_this.scene.app.addKeyboardListener(kl);
});
};
GraphicCopyPlugin.prototype.clear = function () {
var _this = this;
this.running = false;
this.start = undefined;
this.moveLimit = undefined;
this.copys = [];
this.container.removeChildren();
this.scene.canvas.removeChild(this.container);
this.scene.canvas.off('mousemove', this.onPointerMove, this);
this.scene.canvas.off('mouseup', this.onFinish, this);
this.scene.canvas.off('rightup', this.cancle, this);
this.keyListeners.forEach(function (kl) {
_this.scene.app.removeKeyboardListener(kl);
});
};
GraphicCopyPlugin.prototype.onPointerMove = function (e) {
var cp = this.scene.toCanvasCoordinates(e.global);
if (!this.start) {
this.start = cp;
}
else {
if (this.moveLimit === 'x') {
var dx = cp.x - this.start.x;
this.container.position.x = dx;
this.container.position.y = 0;
}
else if (this.moveLimit === 'y') {
var dy = cp.y - this.start.y;
this.container.position.x = 0;
this.container.position.y = dy;
}
else {
var dx = cp.x - this.start.x;
var dy = cp.y - this.start.y;
this.container.position.x = dx;
this.container.position.y = dy;
}
}
};
GraphicCopyPlugin.prototype.onFinish = function () {
var _a, _b;
var _this = this;
console.log('复制确认');
// 将图形添加到app
this.copys.forEach(function (g) {
g.position.x += _this.container.position.x;
g.position.y += _this.container.position.y;
});
(_a = this.scene.app).addGraphicAndRecord.apply(_a, this.copys);
this.scene.detectRelations();
(_b = this.scene).updateSelected.apply(_b, this.copys);
this.clear();
};
GraphicCopyPlugin.prototype.cancle = function () {
console.log('复制操作取消');
this.scene.canvas.removeChild(this.container);
this.clear();
};
return GraphicCopyPlugin;
}());
var VectorGraphicUtil = /** @class */ (function () {
function VectorGraphicUtil() {
}
VectorGraphicUtil.handle = function (obj) {
var vg = obj;
var onScaleChange = function (obj) {
if (vg.isParent(obj)) {
vg.updateOnScaled();
}
};
var registerScaleChange = function registerScaleChange(obj) {
if (!obj.scaledListenerOn) {
obj.scaledListenerOn = true;
obj.getGraphicApp().on('viewport-scaled', onScaleChange);
}
};
var unregisterScaleChange = function unregisterScaleChange(obj) {
obj.scaledListenerOn = false;
obj.getGraphicApp().off('viewport-scaled', onScaleChange);
};
obj.onAddToCanvas = function onAddToCanvas() {
obj.updateOnScaled();
registerScaleChange(obj);
};
obj.onRemoveFromCanvas = function onRemoveFromCanvas() {
// console.debug('矢量图像onRemoveFromCanvas');
unregisterScaleChange(obj);
};
obj.on('added', function (container) {
if (container.isInCanvas()) {
obj.onAddToCanvas(container.getCanvas());
}
});
};
return VectorGraphicUtil;
}());
/**
* 矢量文字.实现原理在缩放发生变化时更新fontSize
*/
var VectorText = /** @class */ (function (_super) {
__extends(VectorText, _super);
function VectorText(text, style, canvas) {
var _this = _super.call(this, text, style, canvas) || this;
_this.vectorFontSize = 8;
_this.scaled = 1;
_this.scaledListenerOn = false;
VectorGraphicUtil.handle(_this);
return _this;
}
VectorText.prototype.updateOnScaled = function () {
var scaled = this.getAllParentScaled();
var scale = Math.max(scaled.x, scaled.y);
this.style.fontSize = this.vectorFontSize * scale;
this.scale.set(1 / scale, 1 / scale);
};
/**
* 设置矢量文字的字体大小
*/
VectorText.prototype.setVectorFontSize = function (fontSize) {
if (this.vectorFontSize !== fontSize) {
this.vectorFontSize = fontSize;
this.updateOnScaled();
}
};
return VectorText;
}(pixi_js.Text));
/**
* 拖拽点参数
*/
var DraggablePointParam = {
lineWidth: 1,
lineColor: 0x000000,
fillColor: 0xffffff,
radius: 5, // 半径
};
var DraggablePointGraphic = new pixi_js.Graphics();
DraggablePointGraphic.lineStyle(DraggablePointParam.lineWidth, DraggablePointParam.lineColor);
DraggablePointGraphic.beginFill(DraggablePointParam.fillColor);
DraggablePointGraphic.drawCircle(0, 0, DraggablePointParam.radius);
DraggablePointGraphic.endFill();
/**
* 拖拽点,用于更新图形属性
*/
var DraggablePoint = /** @class */ (function (_super) {
__extends(DraggablePoint, _super);
/**
*
* @param point 画布坐标点
*/
function DraggablePoint(point) {
var _this = _super.call(this, DraggablePointGraphic.geometry) || this;
_this.scaledListenerOn = false;
_this.position.copyFrom(point);
_this.eventMode = 'static';
_this.draggable = true;
_this.cursor = 'crosshair';
VectorGraphicUtil.handle(_this);
return _this;
}
DraggablePoint.prototype.updateOnScaled = function () {
var scaled = this.getAllParentScaled();
var scale = Math.max(scaled.x, scaled.y);
this.scale.set(1 / scale, 1 / scale);
};
return DraggablePoint;
}(pixi_js.Graphics));
/**
* 浮点数相等判断误差值
*/
var epsilon = 0.00001;
/**
* 判断浮点数是不是0
* @param v
* @returns
*/
function isZero(v) {
if (Math.abs(v) < epsilon) {
return true;
}
return false;
}
/**
* 两浮点数是否相等
* @param f1
* @param f2
* @returns
*/
function floatEquals(f1, f2) {
return isZero(f1 - f2);
}
/* eslint-disable @typescript-eslint/no-this-alias */
var Vector2 = /** @class */ (function () {
function Vector2(values) {
this.values = new Float32Array(2);
if (values !== undefined) {
this.xy = values;
}
}
Vector2.from = function (p) {
return new Vector2([p.x, p.y]);
};
Object.defineProperty(Vector2.prototype, "x", {
get: function () {
return this.values[0];
},
set: function (value) {
this.values[0] = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Vector2.prototype, "y", {
get: function () {
return this.values[1];
},
set: function (value) {
this.values[1] = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Vector2.prototype, "xy", {
get: function () {
return [this.values[0], this.values[1]];
},
set: function (values) {
this.values[0] = values[0];
this.values[1] = values[1];
},
enumerable: false,
configurable: true
});
Vector2.prototype.at = function (index) {
return this.values[index];
};
Vector2.prototype.reset = function () {
this.x = 0;
this.y = 0;
};
Vector2.prototype.copy = function (dest) {
if (!dest) {
dest = new Vector2();
}
dest.x = this.x;
dest.y = this.y;
return dest;
};
Vector2.prototype.negate = function (dest) {
if (!dest) {
dest = this;
}
dest.x = -this.x;
dest.y = -this.y;
return dest;
};
Vector2.prototype.equals = function (vector, threshold) {
if (threshold === void 0) { threshold = epsilon; }
if (Math.abs(this.x - vector.x) > threshold) {
return false;
}
if (Math.abs(this.y - vector.y) > threshold) {
return false;
}
return true;
};
Vector2.prototype.length = function () {
return Math.sqrt(this.squaredLength());
};
Vector2.prototype.squaredLength = function () {
var x = this.x;
var y = this.y;
return x * x + y * y;
};
Vector2.prototype.add = function (vector) {
this.x += vector.x;
this.y += vector.y;
return this;
};
Vector2.prototype.subtract = function (vector) {
this.x -= vector.x;
this.y -= vector.y;
return this;
};
Vector2.prototype.multiply = function (vector) {
this.x *= vector.x;
this.y *= vector.y;
return this;
};
Vector2.prototype.divide = function (vector) {
this.x /= vector.x;
this.y /= vector.y;
return this;
};
Vector2.prototype.scale = function (value, dest) {
if (!dest) {
dest = this;
}
dest.x *= value;
dest.y *= value;
return dest;
};
Vector2.prototype.normalize = function (dest) {
if (!dest) {
dest = this;
}
var length = this.length();
if (length === 1) {
return this;
}
if (length === 0) {
dest.x = 0;
dest.y = 0;
return dest;
}
length = 1.0 / length;
dest.x *= length;
dest.y *= length;
return dest;
};
// multiplyMat2(matrix: mat2, dest?: Vector2): Vector2 {
// if (!dest) {
// dest = this;
// }
// return matrix.multiplyVec2(this, dest);
// }
// multiplyMat3(matrix: mat3, dest?: Vector2): Vector2 {
// if (!dest) {
// dest = this;
// }
// return matrix.multiplyVec2(this, dest);
// }
// static cross(vector: Vector2, vector2: Vector2, dest?: vec3): vec3 {
// if (!dest) {
// dest = new vec3();
// }
// const x = vector.x;
// const y = vector.y;
// const x2 = vector2.x;
// const y2 = vector2.y;
// const z = x * y2 - y * x2;
// dest.x = 0;
// dest.y = 0;
// dest.z = z;
// return dest;
// }
/**
* 向量点乘
* @param vector
* @param vector2
* @returns
*/
Vector2.dot = function (vector, vector2) {
return vector.x * vector2.x + vector.y * vector2.y;
};
/**
* 向量长度
* @param vector
* @param vector2
* @returns
*/
Vector2.distance = function (vector, vector2) {
return Math.sqrt(this.squaredDistance(vector, vector2));
};
/**
* 向量长度平方
* @param vector
* @param vector2
* @returns
*/
Vector2.squaredDistance = function (vector, vector2) {
var x = vector2.x - vector.x;
var y = vector2.y - vector.y;
return x * x + y * y;
};
/**
* v2->v1的方向的单位向量
* @param v1
* @param v2
* @param dest
* @returns
*/
Vector2.direction = function (v1, v2, dest) {
if (!dest) {
dest = new Vector2();
}
var x = v1.x - v2.x;
var y = v1.y - v2.y;
var length = Math.sqrt(x * x + y * y);
if (length === 0) {
dest.x = 0;
dest.y = 0;
return dest;
}
length = 1 / length;
dest.x = x * length;
dest.y = y * length;
return dest;
};
Vector2.mix = function (vector, vector2, time, dest) {
if (!dest) {
dest = new Vector2();
}
var x = vector.x;
var y = vector.y;
var x2 = vector2.x;
var y2 = vector2.y;
dest.x = x + time * (x2 - x);
dest.y = y + time * (y2 - y);
return dest;
};
/**
* 向量加法
* @param vector
* @param vector2
* @param dest
* @returns
*/
Vector2.sum = function (vector, vector2, dest) {
if (!dest) {
dest = new Vector2();
}
dest.x = vector.x + vector2.x;
dest.y = vector.y + vector2.y;
return dest;
};
/**
* 向量减法
* @param vector
* @param vector2
* @param dest
* @returns
*/
Vector2.difference = function (vector, vector2, dest) {
if (!dest) {
dest = new Vector2();
}
dest.x = vector.x - vector2.x;
dest.y = vector.y - vector2.y;
return dest;
};
/**
* 向量乘法
* @param vector
* @param vector2
* @param dest
* @returns
*/
Vector2.product = function (vector, vector2, dest) {
if (!dest) {
dest = new Vector2();
}
dest.x = vector.x * vector2.x;
dest.y = vector.y * vector2.y;
return dest;
};
/**
* 向量除法
* @param vector
* @param vector2
* @param dest
* @returns
*/
Vector2.quotient = function (vector, vector2, dest) {
if (!dest) {
dest = new Vector2();
}
dest.x = vector.x / vector2.x;
dest.y = vector.y / vector2.y;
return dest;
};
Vector2.zero = new Vector2([0, 0]);
Vector2.one = new Vector2([1, 1]);
return Vector2;
}());
/**
* 递归父节点执行逻辑
* @param obj
* @param handler
*/
function recursiveParents(obj, handler) {
if (obj.parent) {
handler(obj.parent);
recursiveParents(obj.parent, handler);
}
}
/**
* 递归父节点查询父节点对象
* @param obj
* @param finder
* @returns
*/
function recursiveFindParent(obj, finder) {
if (obj.parent) {
if (finder(obj.parent)) {
return obj.parent;
}
else {
return recursiveFindParent(obj.parent, finder);
}
}
return null;
}
/**
* 递归子节点执行逻辑
* @param container
* @param handler
*/
function recursiveChildren(container, handler) {
container.children.forEach(function (child) {
handler(child);
if (child.children) {
recursiveChildren(child, handler);
}
});
}
/**
* 递归子节点查询子节点对象
*/
function recursiveFindChild(container, finder) {
var result = null;
for (var i = 0; i < container.children.length; i++) {
var child = container.children[i];
if (finder(child)) {
return child;
}
else if (child.children) {
result = recursiveFindChild(child, finder);
}
}
return result;
}
/**
* 判断贝塞尔曲线数据是否正确
* @param points
*/
function assertBezierPoints(points) {
if (points.length < 4 || points.length % 3 !== 1) {
throw new Error("bezierCurve \u6570\u636E\u9519\u8BEF: ".concat(points));
}
}
/**
* 转换为贝塞尔曲线参数
* @param points
* @returns
*/
function convertToBezierParams(points) {
assertBezierPoints(points);
var bps = [];
for (var i = 0; i < points.length - 3; i += 3) {
var p1 = new pixi_js.Point(points[i].x, points[i].y);
var p2 = new pixi_js.Point(points[i + 3].x, points[i + 3].y);
var cp1 = new pixi_js.Point(points[i + 1].x, points[i + 1].y);
var cp2 = new pixi_js.Point(points[i + 2].x, points[i + 2].y);
bps.push({
p1: p1,
p2: p2,
cp1: cp1,
cp2: cp2,
});
}
return bps;
}
/**
* 根据分段数计算贝塞尔曲线所有点坐标
* @param basePoints
* @param segmentsCount
* @returns
*/
function calculateBezierPoints(basePoints, segmentsCount) {
var bps = convertToBezierParams(basePoints);
var points = [];
bps.forEach(function (bp) {
points.push.apply(points, calculateOneBezierPoints(bp.p1, bp.p2, bp.cp1, bp.cp2, segmentsCount));
});
return points;
}
/**
* 根据分段数计算贝塞尔曲线所有点坐标
* @param basePoints
* @param segmentsCount
* @returns
*/
function calculateOneBezierPoints(p1, p2, cp1, cp2, segmentsCount) {
var points = [];
var fromX = p1.x;
var fromY = p1.y;
var n = segmentsCount;
var dt = 0;
var dt2 = 0;
var dt3 = 0;
var t2 = 0;
var t3 = 0;
var cpX = cp1.x;
var cpY = cp1.y;
var cpX2 = cp2.x;
var cpY2 = cp2.y;
var toX = p2.x;
var toY = p2.y;
points.push(new pixi_js.Point(p1.x, p1.y));
for (var i = 1, j = 0; i <= n; ++i) {
j = i / n;
dt = 1 - j;
dt2 = dt * dt;
dt3 = dt2 * dt;
t2 = j * j;
t3 = t2 * j;
var px = dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX;
var py = dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY;
points.push(new pixi_js.Point(px, py));
}
return points;
}
/**
* 计算矩形中点
*/
function getRectangleCenter(rectangle) {
return new pixi_js.Point(rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2);
}
/**
* 计算两个矩形中心对齐的坐标, PS: 计算的是较大包围框的中心
* @param rect1
* @param rect2
* @returns
*/
function getCenterOfTwoRectangle(rect1, rect2) {
var x = Math.abs(rect1.width - rect2.width) / 2;
var y = Math.abs(rect1.height - rect2.height) / 2;
return new pixi_js.Point(x, y);
}
/**
* 序列化图形变换
* @param obj
* @returns
*/
function serializeTransform(obj) {
var position = obj.position;
var scale = obj.scale;
var angle = obj.angle;
var skew = obj.skew;
return [position.x, position.y, scale.x, scale.y, angle, skew.x, skew.y];
}
/**
* 反序列化变换数据到图形对象
* @param obj
* @param transform
*/
function deserializeTransformInto(obj, transform) {
if (transform.length === 7) {
obj.position.set(transform[0], transform[1]);
obj.scale.set(transform[2], transform[3]);
obj.angle = transform[4];
obj.skew.set(transform[5], transform[6]);
}
else if (transform.length > 0) {
console.warn('错误的变换数据', transform);
}
}
/**
* 将直线转换为多边形
* @param p1
* @param p2
* @param thick
* @returns
*/
function convertLineToPolygonPoints(p1, p2, thick) {
var angle = Math.atan2(p2.y - p1.y, p2.x - p1.x) - Math.PI / 2;
var half = thick / 2;
var cos = Math.cos(angle) * half;
var sin = Math.sin(angle) * half;
return [
new pixi_js.Point(p1.x - cos, p1.y - sin),
new pixi_js.Point(p2.x - cos, p2.y - sin),
new pixi_js.Point(p2.x + cos, p2.y + sin),
new pixi_js.Point(p1.x + cos, p1.y + sin),
];
}
/**
* 转换矩形为多边形点坐标
* @param rect 矩形
* @returns
*/
function convertRectangleToPolygonPoints(rect) {
return [
new pixi_js.Point(rect.x, rect.y),
new pixi_js.Point(rect.x + rect.width, rect.y),
new pixi_js.Point(rect.x + rect.width, rect.y + rect.height),
new pixi_js.Point(rect.x, rect.y + rect.height),
];
}
/**
* 计算线段中点坐标
* @param p1
* @param p2
* @returns
*/
function calculateLineMidpoint(p1, p2) {
var x = (p1.x + p2.x) / 2;
var y = (p1.y + p2.y) / 2;
return new pixi_js.Point(x, y);
}
/**
* 计算线段细分坐标--线段分成几份
* @param p1
* @param p2
* @param knife
* @returns
*/
function calculateLineSegmentingPoint(p1, p2, knife) {
var segmentingPoints = [];
var x = p1.x < p2.x ? p1.x : p2.x;
var y = p1.y < p2.y ? p1.y : p2.y;
var w = Math.abs(p1.x - p2.x);
var h = Math.abs(p1.y - p2.y);
for (var i = 0; i < knife - 1; i++) {
var pointX = x + (w * (i + 1)) / knife;
var pointy = y + (h * (i + 1)) / knife;
segmentingPoints.push(new pixi_js.Point(pointX, pointy));
}
return segmentingPoints;
}
/**
* 计算点到直线距离
* @param p1
* @param p2
* @param p
*/
function calculateDistanceFromPointToLine(p1, p2, p) {
// 求直线的一般方程参数ABC直线的一般式方程AX+BY+C=0
var A = p1.y - p2.y;
var B = p2.x - p1.x;
var C = p1.x * p2.y - p1.y * p2.x;
// 计算点到直线垂直距离: d = |Ax+By+C|/sqrt(A*A+B*B),其中x,y为点坐标
var dl = Math.abs(A * p.x + B * p.y + C) / Math.sqrt(A * A + B * B);
return dl;
}
/**
* 计算点到直线的垂足坐标
* @param p
* @param p1
* @param p2
*/
function calculateFootPointFromPointToLine(p1, p2, p) {
if (p1.x == p2.x && p1.y == p2.y) {
throw new Error("\u76F4\u7EBF\u4E24\u5750\u6807\u70B9\u76F8\u7B49:".concat(p1));
}
var k = -(((p1.x - p.x) * (p2.x - p1.x) + (p1.y - p.y) * (p2.y - p1.y)) /
(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)));
if (isZero(k)) {
return new pixi_js.Point(p.x, p.y);
}
var xf = k * (p2.x - p1.x) + p1.x;
var yf = k * (p2.y - p1.y) + p1.y;
return new pixi_js.Point(xf, yf);
}
/**
* 计算直线与圆的交点
* 1用直线到圆心的距离和半径相比判断是否和圆有交点
* 2求出圆心在直线上面的垂点
* 3算出直线的单位向量e
* 4求出一侧交点(Intersection)到projectPoint的长度(sideLength)
* 5求出sideLength和这侧端点到projectPoint距离的比例(ratio)
* 6projectPoint +/- ratio * e = 两侧交点;
* @param p0 圆心坐标
* @param radius 圆半径
* @param p1 直线坐标1
* @param p2 直线坐标2
* @returns 交点坐标可能2/1/0个
*/
function calculateIntersectionPointOfCircleAndLine(p0, radius, p1, p2) {
var distance = calculateDistanceFromPointToLine(p1, p2, p0);
if (distance <= radius) {
// 有交点
// 计算垂点
var pr = calculateFootPointFromPointToLine(p1, p2, p0);
if (floatEquals(distance, radius)) {
// 切线
return [pr];
}
var vpr = new Vector2([pr.x, pr.y]);
var vc = new Vector2([p0.x, p0.y]);
// 计算直线单位向量
var v1 = new Vector2([p1.x, p1.y]);
var v2 = new Vector2([p2.x, p2.y]);
var ve = Vector2.direction(v2, v1);
var base = Math.sqrt(Math.abs(radius * radius - Vector2.difference(vpr, vc).squaredLength()));
var vl = ve.scale(base);
var ip1 = Vector2.sum(vpr, vl);
var ip2 = Vector2.difference(vpr, vl);
return [new pixi_js.Point(ip1.x, ip1.y), new pixi_js.Point(ip2.x, ip2.y)];
}
else {
// 无交点
return [];
}
}
/**
* 计算圆心与圆心外一点与圆的交点(取圆心到点的向量与圆的交点)
* @param p0 圆心坐标
* @param radius 圆半径
* @param p 点坐标
* @returns
*/
function calculateIntersectionPointOfCircleAndPoint(p0, radius, p) {
var points = calculateIntersectionPointOfCircleAndLine(p0, radius, p0, p);
var vc = new Vector2([p0.x, p0.y]);
var vp = new Vector2([p.x, p.y]);
var vecp = Vector2.direction(vp, vc);
for (var i = 0; i < points.length; i++) {
var ip = points[i];
var ve = Vector2.direction(new Vector2([ip.x, ip.y]), vc);
if (ve.equals(vecp)) {
return ip;
}
}
throw new Error('计算圆心与圆心外一点与圆的交点逻辑错误');
}
/**
* 计算点基于点的镜像点坐标
* @param bp 基准点
* @param p 待镜像的点坐标
* @param distance 镜像点到基准点的距离默认为p到基准点的距离,即对称
* @returns
*/
function calculateMirrorPoint(bp, p, distance) {
var vbp = Vector2.from(bp);
var vp = Vector2.from(p);
var direction = Vector2.direction(vbp, vp);
if (distance == undefined) {
distance = Vector2.distance(vbp, vp);
}
var vmp = Vector2.sum(vbp, direction.scale(distance));
return new pixi_js.Point(vmp.x, vmp.y);
}
/**
* 计算基于给定轴的给定点的镜像点坐标
* @param pa 给定轴线的坐标
* @param pb 给定轴线的坐标
* @param p 待镜像点坐标
* @param distance
* @returns
*/
function calculateMirrorPointBasedOnAxis(pa, pb, p, distance) {
var fp = calculateFootPointFromPointToLine(pa, pb, p);
if (fp.equals(p)) {
return fp;
}
else {
return calculateMirrorPoint(fp, p, distance);
}
}
/**
* 计算直线与水平夹角,角度按顺时针从0开始
* @param p1
* @param p2
* @returns 角度,范围[0, 360)
*/
function angleToAxisx(p1, p2) {
if (p1.x == p2.x && p1.y == p2.y) {
throw new Error('一个点无法计算角度');
}
var dx = Math.abs(p1.x - p2.x);
var dy = Math.abs(p1.y - p2.y);
if (p2.x == p1.x) {
if (p2.y > p1.y) {
return 90;
}
else {
return 270;
}
}
if (p2.y == p1.y) {
if (p2.x > p1.x) {
return 0;
}
else {
return 180;
}
}
var angle = (Math.atan2(dy, dx) * 180) / Math.PI;
if (p2.x > p1.x) {
if (p2.y > p1.y) {
return angle;
}
else if (p2.y < p1.y) {
return 360 - angle;
}
}
else if (p2.x < p1.x) {
if (p2.y > p1.y) {
return 180 - angle;
}
else {
return 180 + angle;
}
}
return angle;
}
/**
* 计算两线夹角,pc与pa,pb的夹角顺时针为正逆时针为负
* @param pa 交点
* @param pb 锚定
* @param pc
* @returns 夹角, [-180, 180]
*/
function angleOfIncludedAngle(pa, pb, pc) {
var abAngle = angleToAxisx(pa, pb);
var acAngle = angleToAxisx(pa, pc);
var angle = acAngle - abAngle;
if (angle < -180) {
angle = 360 + angle;
}
else if (angle > 180) {
angle = -(360 - angle);
}
return angle;
}
/**
* 计算两点连线的法向量
* @param point1
* @param point2
* @returns 单位法向量
*/
function getNormalVector(point1, point2) {
var x1 = point1.x, y1 = point1.y;
var x2 = point2.x, y2 = point2.y;
var length = Math.sqrt(Math.pow((y2 - y1), 2) + Math.pow((x2 - x1), 2));
return [(y2 - y1) / length, (x1 - x2) / length];
}
/**
* 点延向量方向移动
* @param point
* @param normal 单位向量
* @param length 平移长度
* @returns 移动后的点
*/
function movePointAlongNormal(point, normal, length) {
var newPoint = new pixi_js.Point(point.x + length * normal[0], point.y + length * normal[1]);
return newPoint;
}
/**
* 计算两组点各自组成直线的相交点(若两线平行 返回第一组坐标第一个点)
* @param line1 两点坐标列表
* @param line2 两点坐标列表
* @returns 相交点
*/
function getIntersectionPoint(line1, line2) {
var a1 = line1[0], b1 = line1[1];
var a2 = line1[2], b2 = line1[3];
var a3 = line2[0], b3 = line2[1];
var a4 = line2[2], b4 = line2[3];
var denominator = (a3 - a4) * (b1 - b2) - (a1 - a2) * (b3 - b4);
if (denominator === 0) {
return new pixi_js.Point(a1, b1);
}
var x = ((a3 - a4) * (a2 * b1 - a1 * b2) - (a1 - a2) * (a4 * b3 - a3 * b4)) /
denominator;
var y = ((b3 - b4) * (b2 * a1 - b1 * a2) - (b1 - b2) * (b4 * a3 - b3 * a4)) /
-denominator;
return new pixi_js.Point(x, y);
}
/**
* 是否平行线
* @param p1
* @param p2
* @param pa
* @param pb
* @returns
*/
function isParallelLines(p1, p2, pa, pb) {
var vle1 = Vector2.direction(Vector2.from(p1), Vector2.from(p2));
var vle2 = Vector2.direction(Vector2.from(pa), Vector2.from(pb));
if (vle2.equals(vle1)) {
return true;
}
return vle1.equals(Vector2.direction(Vector2.from(pb), Vector2.from(pa)));
}
/**
* 点是否在线段上
* @param p1
* @param p2
* @param p
* @returns
*/
function isPointOnLine(p1, p2, p) {
var vp1 = Vector2.from(p1);
var vp2 = Vector2.from(p2);
var vp = Vector2.from(p);
if (vp1.equals(vp) || vp2.equals(vp)) {
return true;
}
var vle = Vector2.direction(vp1, Vector2.from(p2));
var vpe = Vector2.direction(vp1, vp);
if (vle.equals(vpe)) {
return (Vector2.difference(vp1, vp2).squaredLength() >=
Vector2.difference(vp1, vp).squaredLength());
}
return false;
}
/**
* 两条线段是否存在包含关系
* @param line1
* @param line2
* @returns
*/
function isLineContainOther(line1, line2) {
return ((isPointOnLine(line1.p1, line1.p2, line2.p1) &&
isPointOnLine(line1.p1, line1.p2, line2.p2)) ||
(isPointOnLine(line2.p1, line2.p2, line1.p1) &&
isPointOnLine(line2.p1, line2.p2, line1.p2)));
}
/** 均分线段, 返回各线段端点 */
function splitLineEvenly(p1, p2, count) {
var _a = [(p2.x - p1.x) / count, (p2.y - p1.y) / count], stepX = _a[0], stepY = _a[1];
return Array(count)
.fill(1)
.map(function (_, i) {
return [
{ x: p1.x + stepX * i, y: p1.y + stepY * i },
{ x: p1.x + stepX * (i + 1), y: p1.y + stepY * (i + 1) },
];
});
}
function splitPolyline(points, count) {
if (points.length !== 2) {
var totalLen_1 = 0;
var lengths = [];
for (var i = 1; i < points.length; i++) {
var _a = points[i - 1], x1 = _a.x, y1 = _a.y, _b = points[i], x2 = _b.x, y2 = _b.y;
var len = new Vector2([x2 - x1, y2 - y1]).length();
totalLen_1 += len;
lengths.push(len);
}
var counts = lengths.map(function (length) {
return Math.round((count * length) / totalLen_1);
});
if (counts.reduce(function (p, c) { return p + c; }, 0) !== count) {
var intersection = counts.reduce(function (p, c) { return p + c; }, 0) - count;
var maxCountIndex_1 = 0, maxCount_1 = 0;
counts.forEach(function (c, i) {
if (c > maxCount_1) {
maxCount_1 = c;
maxCountIndex_1 = i;
}
});
counts[maxCountIndex_1] + intersection;
}
return counts
.map(function (count, i) {
return splitLineEvenly(points[i], points[i + 1], count);
})
.flat();
}
else {
return splitLineEvenly(points[0], points[points.length - 1], count);
}
}
function getParallelOfPolyline(points, offset, side) {
var PI = Math.PI, cos = Math.cos, acos = Math.acos;
var angleBase = side === 'L' ? -PI / 2 : PI / 2;
return points.map(function (p, i) {
var baseUnitVec; //上一段的基准单位向量
var angle; //偏转角度
var len; //结合偏转角度的实际偏移量
if (!points[i - 1] || !points[i + 1]) {
angle = angleBase;
len = offset;
baseUnitVec = points[i - 1]
? new Vector2([
p.x - points[i - 1].x,
p.y - points[i - 1].y,
]).normalize()
: new Vector2([
points[i + 1].x - p.x,
points[i + 1].y - p.y,
]).normalize();
}
else {
var vp = new Vector2([p.x - points[i - 1].x, p.y - points[i - 1].y]);
var vn = new Vector2([points[i + 1].x - p.x, points[i + 1].y - p.y]);
var cosTheta = Vector2.dot(vn, vp) / (vp.length() * vn.length());
var direction = vp.x * vn.y - vp.y * vn.x > 0; //det(vp|vn)>0?
var theta = direction ? acos(cosTheta) : -acos(cosTheta);
angle = angleBase + theta / 2;
len = offset / cos(theta / 2);
baseUnitVec = Vector2.from(vp).normalize();
}
return new pixi_js.Matrix()
.scale(len, len)
.rotate(angle)
.translate(p.x, p.y)
.apply(baseUnitVec);
});
}
// /**
// * 点线碰撞检测
// * @param pa 线段a端坐标
// * @param pb 线段b端坐标
// * @param p 点坐标
// * @param tolerance 容忍度,越大检测范围越大
// * @returns
// */
// export function linePoint(pa: Point, pb: Point, p: Point, tolerance: number): boolean {
// return (Math.abs(distanceSquared(pa.x, pa.y, pb.x, pb.y) - (distanceSquared(pa.x, pa.y, p.x, p.y) + distanceSquared(pb.x, pb.y, p.x, p.y))) <= tolerance)
// }
/**
* 根据点到直线的垂直距离计算碰撞
* @param pa 线段a端坐标
* @param pb 线段b端坐标
* @param p 点坐标
* @param lineWidth 线宽
* @param exact 是否精确使用给定线宽否则线宽会设置为8
* @returns
*/
function linePoint(pa, pb, p, lineWidth, exact) {
if (exact === void 0) { exact = false; }
if (!exact && lineWidth < 6) {
lineWidth = 6;
}
// 求直线的一般方程参数ABC直线的一般式方程AX+BY+C=0
var A = pa.y - pb.y;
var B = pb.x - pa.x;
var C = pa.x * pb.y - pa.y * pb.x;
// 计算点到直线垂直距离: d = |Ax+By+C|/sqrt(A*A+B*B),其中x,y为点坐标
var dl = Math.abs(A * p.x + B * p.y + C) / Math.sqrt(A * A + B * B);
var intersect = dl <= lineWidth / 2;
if (intersect) {
// 距离在线宽范围内,再判断点是否超过线段两端点范围外(两端点外会有一点误差,两端点线宽一半半径的圆范围内)
var da = distance(pa.x, pa.y, p.x, p.y);
var db = distance(pb.x, pb.y, p.x, p.y);
var dab = distance(pa.x, pa.y, pb.x, pb.y);
return da <= dl + dab && db <= dl + dab;
}
return false;
}
/**
* 折线与点碰撞
* @param points 折线端点列表
* @param p 点座标
* @param lineWidth 线宽
*/
function polylinePoint(points, p, lineWidth) {
var len = points.length;
for (var i = 0; i < len - 1; i++) {
if (linePoint(points[i], points[i + 1], p, lineWidth)) {
return true;
}
}
return false;
}
/**
* 线线碰撞检测
* @param pa 线段1a端坐标
* @param pb 线段1b端坐标
* @param p1 线段2a端坐标
* @param p2 线段2b端坐标
* @returns
*/
function lineLine(pa, pb, p1, p2) {
var x1 = pa.x;
var y1 = pa.y;
var x2 = pb.x;
var y2 = pb.y;
var x3 = p1.x;
var y3 = p1.y;
var x4 = p2.x;
var y4 = p2.y;
var s1_x = x2 - x1;
var s1_y = y2 - y1;
var s2_x = x4 - x3;
var s2_y = y4 - y3;
var s = (-s1_y * (x1 - x3) + s1_x * (y1 - y3)) / (-s2_x * s1_y + s1_x * s2_y);
var t = (s2_x * (y1 - y3) - s2_y * (x1 - x3)) / (-s2_x * s1_y + s1_x * s2_y);
return s >= 0 && s <= 1 && t >= 0 && t <= 1;
}
/**
* 点和矩形碰撞检测
* @param p 点作弊
* @param rect 矩形
* @returns
*/
function pointBox(p, rect) {
var x = rect.x, y = rect.y, width = rect.width, height = rect.height;
var x2 = p.x;
var y2 = p.y;
return x2 >= x && x2 <= x + width && y2 >= y && y2 <= y + height;
}
/**
* 线和矩形碰撞检测
* @param pa 线段a端坐标
* @param pb 线段b端坐标
* @param rect 矩形
* @returns
*/
function lineBox(pa, pb, rect) {
if (pointBox(pa, rect) || pointBox(pb, rect)) {
return true;
}
var x = rect.x, y = rect.y, width = rect.width, height = rect.height;
var rp1 = new pixi_js.Point(x, y);
var rp2 = new pixi_js.Point(x + width, y);
var rp3 = new pixi_js.Point(x + width, y + height);
var rp4 = new pixi_js.Point(x, y + height);
return (lineLine(pa, pb, rp1, rp2) ||
lineLine(pa, pb, rp2, rp3) ||
lineLine(pa, pb, rp3, rp4) ||
lineLine(pa, pb, rp1, rp4));
}
/**
* 多线段和矩形碰撞检测
* @param points
* @param rect
* @returns false / 碰撞的线段序号
*/
function polylineBox(points, rect) {
if (points.length < 2) {
return false;
}
for (var i = 0; i < points.length - 1; i++) {
var p1 = points[i];
var p2 = points[i + 1];
if (lineBox(p1, p2, rect)) {
return true;
}
}
return false;
}
/**
* 两点碰撞检测
* @param p1
* @param p2
* @param tolerance
* @returns
*/
function pointPoint2(p1, p2, tolerance) {
return pointPoint(p1.x, p1.y, p2.x, p2.y, tolerance);
}
/**
* 两点碰撞检测
* @param x1
* @param y1
* @param x2
* @param y2
* @param tolerance 容忍度/两点半径和
* @returns
*/
function pointPoint(x1, y1, x2, y2, tolerance) {
return distance(x1, y1, x2, y2) <= tolerance;
}
/**
* 两点距离
* @param x1
* @param y1
* @param x2
* @param y2
* @returns
*/
function distance(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
/**
* 两点距离
* @param p1
* @param p2
* @returns
*/
function distance2(p1, p2) {
return distance(p1.x, p1.y, p2.x, p2.y);
}
/**
* 圆和点的碰撞检测
* @param x1 圆心x
* @param y1 圆心y
* @param r1 圆半径
* @param x2 点x
* @param y2 点y
* @returns
*/
function circlePoint(x1, y1, r1, x2, y2) {
var x = x2 - x1;
var y = y2 - y1;
return x * x + y * y <= r1 * r1;
}
/**
* 圆和点的碰撞检测--不包括圆内部
*/
function circlePoint2(x1, y1, r1, x2, y2, tolerance) {
var x = x2 - x1;
var y = y2 - y1;
return (x * x + y * y <= (r1 + tolerance) * (r1 + tolerance) &&
x * x + y * y >= (r1 - tolerance) * (r1 - tolerance));
}
/**
* 点和多边形碰撞检测
*/
function pointPolygon(p, points, lineWidth) {
var x = p.x, y = p.y;
var length = points.length;
var c = false;
var i, j;
for (i = 0, j = length - 1; i < length; i++) {
if (points[i].y > y !== points[j].y > y &&
x <
((points[j].x - points[i].x) * (y - points[i].y)) /
(points[j].y - points[i].y) +
points[i].x) {
c = !c;
}
j = i;
}
if (c) {
return true;
}
for (i = 0; i < length - 1; i++) {
var p1 = void 0, p2 = void 0;
if (i === length - 1) {
p1 = points[i];
p2 = points[0];
}
else {
p1 = points[i];
p2 = points[i + 1];
}
if (linePoint(p1, p2, p, lineWidth)) {
return true;
}
}
return false;
}
/**
* 线和多边形碰撞检测
* @param p1
* @param p2
* @param points
* @param tolerance 多边形包围线宽
* @returns
*/
function linePolygon(p1, p2, points, lineWidth, polygonWidth) {
if (pointPolygon(p1, points, polygonWidth)) {
return true;
}
var length = points.length;
for (var i = 0; i < length; i++) {
var pa = void 0, pb = void 0;
if (i === length - 1) {
pa = points[i];
pb = points[0];
}
else {
pa = points[i];
pb = points[i + 1];
}
// TODO:此处后续需考虑有线宽的情况
if (lineLine(pa, pb, p1, p2)) {
return true;
}
}
return false;
}
/**
* 多边线与多边形碰撞检测
* @param polylinePoints 多边线所有点坐标
* @param polygonPoints 多边形所有点坐标
* @param polylineWidth 多边线的线宽
* @param polygonWidth 多边形线宽
* @returns
*/
function polylinePolygon(polylinePoints, polygonPoints, polylineWidth, polygonWidth) {
var length = polylinePoints.length;
for (var i = 0; i < length - 1; i++) {
var p1 = polylinePoints[i];
var p2 = polylinePoints[i + 1];
if (linePolygon(p1, p2, polygonPoints, polylineWidth, polygonWidth)) {
return true;
}
}
return false;
}
function debounce(fn, waitMs) {
if (waitMs === void 0) { waitMs = 250; }
var timeoutId;
var debouncedFunction = function (context) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var invokeFunction = function () {
timeoutId = undefined;
fn.apply(context, args);
};
if (timeoutId !== undefined) {
console.debug('debounce clear timeout', fn);
clearTimeout(timeoutId);
}
timeoutId = setTimeout(invokeFunction, waitMs);
};
debouncedFunction.cancel = function () {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
};
return debouncedFunction;
}
var UP = new pixi_js.Point(0, -1);
var DOWN = new pixi_js.Point(0, 1);
var LEFT = new pixi_js.Point(-1, 0);
var RIGHT = new pixi_js.Point(1, 0);
/**
* 越界结果
*/
var OutOfBound = /** @class */ (function () {
function OutOfBound(left, top, right, bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
OutOfBound.check = function (rect, bound) {
var left = rect.left < bound.left;
var top = rect.top < bound.top;
var right = rect.right > bound.right;
var bottom = rect.bottom > bound.bottom;
return new OutOfBound(left, top, right, bottom);
};
OutOfBound.none = function () {
return new OutOfBound(false, false, false, false);
};
OutOfBound.leftOut = function () {
return new OutOfBound(true, false, false, false);
};
OutOfBound.topOut = function () {
return new OutOfBound(false, true, false, false);
};
OutOfBound.rightOut = function () {
return new OutOfBound(false, false, true, false);
};
OutOfBound.bottomOut = function () {
return new OutOfBound(false, false, false, true);
};
OutOfBound.leftTopOut = function () {
return new OutOfBound(true, true, false, false);
};
OutOfBound.rightBottomOut = function () {
return new OutOfBound(false, false, true, true);
};
return OutOfBound;
}());
/**
* 可吸附点图形参数
*/
var AbsorbablePointParam = {
lineWidth: 1,
lineColor: '#000000',
fillColor: '#E77E0E',
radius: 5, // 半径
};
var AbsorbablePointGraphic = new pixi_js.Graphics();
// AbsorbablePointGraphic.lineStyle(
// AbsorbablePointParam.lineWidth,
// AbsorbablePointParam.lineColor
// );
AbsorbablePointGraphic.beginFill(AbsorbablePointParam.fillColor);
AbsorbablePointGraphic.drawCircle(0, 0, AbsorbablePointParam.radius);
AbsorbablePointGraphic.endFill();
/**
* 可吸附点
*/
/** @class */ ((function (_super) {
__extends(AbsorbablePoint, _super);
/**
*
* @param point 画布坐标
* @param absorbRange
*/
function AbsorbablePoint(point, absorbRange) {
if (absorbRange === void 0) { absorbRange = 10; }
var _this = _super.call(this, AbsorbablePointGraphic.geometry) || this;
_this.scaledListenerOn = false;
_this._point = new pixi_js.Point(point.x, point.y);
_this.absorbRange = absorbRange;
_this.position.copyFrom(_this._point);
_this.interactive;
VectorGraphicUtil.handle(_this);
return _this;
}
AbsorbablePoint.prototype.compareTo = function (other) {
if (other instanceof AbsorbablePoint) {
return this.absorbRange - other.absorbRange;
}
throw new Error('非可吸附点');
};
AbsorbablePoint.prototype.isOverlapping = function (other) {
if (other instanceof AbsorbablePoint) {
return (this._point.equals(other._point) &&
this.absorbRange === other.absorbRange);
}
return false;
};
AbsorbablePoint.prototype.tryAbsorb = function () {
var objs = [];
for (var _i = 0; _i < arguments.length; _i++) {
objs[_i] = arguments[_i];
}
for (var i = 0; i < objs.length; i++) {
var obj = objs[i];
var canvasPosition = obj.getPositionOnCanvas();
if (distance(this._point.x, this._point.y, canvasPosition.x, canvasPosition.y) < this.absorbRange) {
obj.updatePositionByCanvasPosition(this._point);
}
}
};
AbsorbablePoint.prototype.updateOnScaled = function () {
var scaled = this.getAllParentScaled();
var scale = Math.max(scaled.x, scaled.y);
this.scale.set(1 / scale, 1 / scale);
};
return AbsorbablePoint;
})(pixi_js.Graphics));
/**
* 可吸附线
*/
var AbsorbableLine = /** @class */ (function (_super) {
__extends(AbsorbableLine, _super);
/**
*
* @param p1 画布坐标
* @param p2 画布坐标
* @param absorbRange
*/
function AbsorbableLine(p1, p2, absorbRange) {
if (absorbRange === void 0) { absorbRange = 20; }
var _this = _super.call(this) || this;
_this._color = '#E77E0E';
_this.p1 = new pixi_js.Point(p1.x, p1.y);
_this.p2 = new pixi_js.Point(p2.x, p2.y);
_this.absorbRange = absorbRange;
_this.redraw();
return _this;
}
AbsorbableLine.prototype.isOverlapping = function (other) {
if (other instanceof AbsorbableLine) {
var contain = isLineContainOther({ p1: this.p1, p2: this.p2 }, { p1: other.p1, p2: other.p2 });
return contain;
}
return false;
};
AbsorbableLine.prototype.compareTo = function (other) {
if (other instanceof AbsorbableLine) {
return distance2(this.p1, this.p2) - distance2(other.p1, other.p2);
}
throw new Error('非可吸附线');
};
AbsorbableLine.prototype.redraw = function () {
this.clear();
this.lineStyle(1, new pixi_js.Color(this._color));
this.moveTo(this.p1.x, this.p1.y);
this.lineTo(this.p2.x, this.p2.y);
};
AbsorbableLine.prototype.tryAbsorb = function () {
var objs = [];
for (var _i = 0; _i < arguments.length; _i++) {
objs[_i] = arguments[_i];
}
for (var i = 0; i < objs.length; i++) {
var obj = objs[i];
var canvasPosition = obj.getPositionOnCanvas();
if (linePoint(this.p1, this.p2, canvasPosition, this.absorbRange, true)) {
var fp = calculateFootPointFromPointToLine(this.p1, this.p2, canvasPosition);
obj.updatePositionByCanvasPosition(fp);
}
}
};
return AbsorbableLine;
}(pixi_js.Graphics));
/**
* 可吸附圆
*/
var AbsorbableCircle = /** @class */ (function (_super) {
__extends(AbsorbableCircle, _super);
/**
*
* @param p 画布坐标
* @param radius
* @param absorbRange
*/
function AbsorbableCircle(p, radius, absorbRange) {
if (absorbRange === void 0) { absorbRange = 10; }
var _this = _super.call(this) || this;
_this._color = '#E77E0E';
_this.p0 = new pixi_js.Point(p.x, p.y);
_this.radius = radius;
_this.absorbRange = absorbRange;
_this.redraw();
return _this;
}
AbsorbableCircle.prototype.isOverlapping = function (other) {
if (other instanceof AbsorbableCircle) {
return this.p0.equals(other.p0) && this.radius === other.radius;
}
return false;
};
AbsorbableCircle.prototype.compareTo = function (other) {
if (other instanceof AbsorbableCircle) {
return this.absorbRange - other.absorbRange;
}
throw new Error('非可吸附圆');
};
AbsorbableCircle.prototype.redraw = function () {
this.clear();
this.lineStyle(1, new pixi_js.Color(this._color));
this.drawCircle(this.p0.x, this.p0.y, this.radius);
};
AbsorbableCircle.prototype.tryAbsorb = function () {
var objs = [];
for (var _i = 0; _i < arguments.length; _i++) {
objs[_i] = arguments[_i];
}
for (var i = 0; i < objs.length; i++) {
var obj = objs[i];
var canvasPosition = obj.getPositionOnCanvas();
var len = distance(this.p0.x, this.p0.y, canvasPosition.x, canvasPosition.y);
if (len > this.radius - this.absorbRange &&
len < this.radius + this.absorbRange) {
// 吸附,计算直线与圆交点,更新对象坐标
var p = calculateIntersectionPointOfCircleAndPoint(this.p0, this.radius, canvasPosition);
obj.updatePositionByCanvasPosition(p);
}
}
};
return AbsorbableCircle;
}(pixi_js.Graphics));
var DefaultDashedLineOptions = {
length: 4,
startSpace: 0,
space: 4,
lineWidth: 1,
color: '#0000ff',
};
var DashedLine = /** @class */ (function (_super) {
__extends(DashedLine, _super);
function DashedLine(p1, p2, options) {
var _this = _super.call(this) || this;
var config = Object.assign({}, DefaultDashedLineOptions, options);
_this._options = config;
_this.p1 = new pixi_js.Point(p1.x, p1.y);
_this.p2 = new pixi_js.Point(p2.x, p2.y);
_this.redraw();
return _this;
}
DashedLine.prototype.setOptions = function (options) {
if (options.startSpace != undefined) {
this._options.startSpace = options.startSpace;
}
if (options.length != undefined) {
this._options.length = options.length;
}
if (options.space != undefined) {
this._options.space = options.space;
}
if (options.lineWidth != undefined) {
this._options.lineWidth = options.lineWidth;
}
if (options.color != undefined) {
this._options.color = options.color;
}
this.redraw();
};
DashedLine.prototype.redraw = function () {
this.removeChildren();
var p1 = this.p1;
var p2 = this.p2;
var option = this._options;
var total = Math.pow(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2), 0.5);
var len = option.startSpace;
while (len < total) {
var dashedLen = option.length;
if (len + option.length > total) {
dashedLen = total - len;
}
var line = new pixi_js.Graphics();
line.lineStyle(option.lineWidth, option.color);
line.moveTo(len, 0);
line.lineTo(len + dashedLen, 0);
this.addChild(line);
len = len + dashedLen + option.space;
}
this.pivot.set(0, option.lineWidth / 2);
this.position.set(p1.x, p1.y);
this.angle = angleToAxisx(p1, p2);
};
return DashedLine;
}(pixi_js.Container));
var ShiftData = /** @class */ (function () {
function ShiftData(startPosition, currentPosition, lastPosition) {
this.startPosition = startPosition;
this.lastPosition = lastPosition;
this.currentPosition = currentPosition;
}
ShiftData.new = function (startPosition, currentPosition, lastPosition) {
return new ShiftData(startPosition, currentPosition, lastPosition);
};
Object.defineProperty(ShiftData.prototype, "dx", {
get: function () {
if (!this.lastPosition || !this.currentPosition) {
throw new Error('错误的位移数据或阶段');
}
return this.currentPosition.x - this.lastPosition.x;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ShiftData.prototype, "dy", {
get: function () {
if (!this.lastPosition || !this.currentPosition) {
throw new Error('错误的位移数据或阶段');
}
return this.currentPosition.y - this.lastPosition.y;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ShiftData.prototype, "dsx", {
get: function () {
if (!this.currentPosition) {
throw new Error('错误的位移数据或阶段');
}
return this.currentPosition.x - this.startPosition.x;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ShiftData.prototype, "dsy", {
get: function () {
if (!this.currentPosition) {
throw new Error('错误的位移数据或阶段');
}
return this.currentPosition.y - this.startPosition.y;
},
enumerable: false,
configurable: true
});
return ShiftData;
}());
var ScaleData = /** @class */ (function () {
function ScaleData(start, current, last) {
this.start = start;
this.current = current;
this.last = last;
}
ScaleData.new = function (start, current, last) {
return new ScaleData(start, current, last);
};
return ScaleData;
}());
/**
* 图形平移事件
*/
var GraphicTransformEvent = /** @class */ (function () {
function GraphicTransformEvent(target, type, data) {
this.target = target;
this.type = type;
this.data = data;
}
GraphicTransformEvent.prototype.getData = function () {
return this.data;
};
GraphicTransformEvent.shift = function (target, data) {
return new GraphicTransformEvent(target, 'shift', data);
};
GraphicTransformEvent.scale = function (target) {
return new GraphicTransformEvent(target, 'scale', null);
};
GraphicTransformEvent.rotate = function (target) {
return new GraphicTransformEvent(target, 'rotate', null);
};
GraphicTransformEvent.skew = function (target) {
return new GraphicTransformEvent(target, 'skew', null);
};
GraphicTransformEvent.prototype.isShift = function () {
return this.type === 'shift';
};
GraphicTransformEvent.prototype.isRotate = function () {
return this.type === 'rotate';
};
GraphicTransformEvent.prototype.isScale = function () {
return this.type === 'scale';
};
GraphicTransformEvent.prototype.isSkew = function () {
return this.type === 'skew';
};
return GraphicTransformEvent;
}());
var GraphicTransformPlugin = /** @class */ (function (_super) {
__extends(GraphicTransformPlugin, _super);
function GraphicTransformPlugin(app) {
var _this = _super.call(this, app, GraphicTransformPlugin.Name, exports.InteractionPluginType.Other) || this;
_this.apContainer = new pixi_js.Container();
_this.apContainer.name = GraphicTransformPlugin.AbsorbablePosisiontsName;
_this.app.canvas.addAssistantAppend(_this.apContainer);
app.on('options-update', function (options) {
if (options.absorbablePositions) {
_this.absorbablePositions = _this.filterAbsorbablePositions(options.absorbablePositions);
}
});
return _this;
}
/**
* 过滤重复的吸附位置
* @param positions
* @returns
*/
GraphicTransformPlugin.prototype.filterAbsorbablePositions = function (positions) {
var aps = [];
for (var i = 0; i < positions.length; i++) {
var ap1 = positions[i];
var ap = ap1;
for (var j = positions.length - 1; j > i; j--) {
var ap2 = positions[j];
if (ap.isOverlapping(ap2) && ap.compareTo(ap2) <= 0) {
ap = null;
break;
}
}
if (ap != null) {
aps.push(ap);
}
}
// console.log(positions, aps);
return aps;
};
GraphicTransformPlugin.new = function (app) {
return new GraphicTransformPlugin(app);
};
GraphicTransformPlugin.prototype.bind = function () {
this.app.on('drag_op_start', this.onDragStart, this);
this.app.on('drag_op_move', this.onDragMove, this);
this.app.on('drag_op_end', this.onDragEnd, this);
this.app.on('graphicselectedchange', this.onGraphicSelectedChange, this);
this.app.on('graphicchildselectedchange', this.onGraphicSelectedChange, this);
};
GraphicTransformPlugin.prototype.unbind = function () {
this.app.off('drag_op_start', this.onDragStart, this);
this.app.off('drag_op_move', this.onDragMove, this);
this.app.off('drag_op_end', this.onDragEnd, this);
this.app.off('graphicselectedchange', this.onGraphicSelectedChange, this);
this.app.off('graphicchildselectedchange', this.onGraphicSelectedChange, this);
};
GraphicTransformPlugin.prototype.getDraggedTargets = function (e) {
var _a;
var targets = [];
if (e.target.isGraphicChild() && e.target.selected && e.target.draggable) {
var graphic = e.target.getGraphic();
// 图形子元素
recursiveChildren(graphic, function (child) {
if (child.selected && child.draggable) {
targets.push(child);
}
});
}
else if ((e.target.isGraphic() || e.target.isGraphicChild()) &&
((_a = e.target.getGraphic()) === null || _a === void 0 ? void 0 : _a.draggable)) {
// 图形对象
targets.push.apply(targets, this.app.selectedGraphics);
}
else if (e.target.draggable) {
targets.push(e.target);
}
return targets;
};
GraphicTransformPlugin.prototype.onDragStart = function (e) {
var _a;
if (!e.target.isCanvas() && e.isLeftButton) {
var targets = this.getDraggedTargets(e);
if (targets.length > 0) {
targets.forEach(function (target) {
target.shiftStartPoint = target.position.clone();
target.emit('transformstart', GraphicTransformEvent.shift(target, ShiftData.new(target.shiftStartPoint)));
});
// 显示吸附图形
if (this.absorbablePositions && this.absorbablePositions.length > 0) {
this.apContainer.removeChildren();
(_a = this.apContainer).addChild.apply(_a, this.absorbablePositions);
}
}
}
};
GraphicTransformPlugin.prototype.onDragMove = function (e) {
if (!e.target.isCanvas() && e.isLeftButton) {
var targets = this.getDraggedTargets(e);
if (targets.length > 0) {
// 处理位移
targets.forEach(function (target) {
if (target.shiftStartPoint) {
target.shiftLastPoint = target.position.clone();
var _a = e.toTargetShiftLen(target.parent), dx = _a.dx, dy = _a.dy;
target.position.set(target.shiftStartPoint.x + dx, target.shiftStartPoint.y + dy);
}
});
// 处理吸附
if (this.absorbablePositions) {
for (var i = 0; i < this.absorbablePositions.length; i++) {
var ap = this.absorbablePositions[i];
ap.tryAbsorb.apply(ap, targets);
}
}
// const start = new Date().getTime();
// 事件发布
targets.forEach(function (target) {
if (target.shiftStartPoint && target.shiftLastPoint) {
target.emit('transforming', GraphicTransformEvent.shift(target, ShiftData.new(target.shiftStartPoint, target.position.clone(), target.shiftLastPoint)));
}
});
// const dt = new Date().getTime() - start;
// console.log('拖拽耗时', `${dt}ms`, targets);
}
}
};
GraphicTransformPlugin.prototype.onDragEnd = function (e) {
if (!e.target.isCanvas() && e.isLeftButton) {
var targets = this.getDraggedTargets(e);
targets.forEach(function (target) {
if (target.shiftStartPoint) {
target.emit('transformend', GraphicTransformEvent.shift(target, ShiftData.new(target.shiftStartPoint, target.position.clone())));
}
target.shiftStartPoint = null;
});
}
this.clearCache();
};
/**
* 清理缓存
*/
GraphicTransformPlugin.prototype.clearCache = function () {
// 移除吸附图形
this.absorbablePositions = [];
this.apContainer.removeChildren();
};
GraphicTransformPlugin.prototype.onGraphicSelectedChange = function (g, selected) {
var br = g.getAssistantAppend(BoundsGraphic.Name);
if (!br) {
// 绘制辅助包围框
br = new BoundsGraphic(g);
}
if (selected) {
if (br) {
br.redraw();
br.visible = true;
}
}
else {
if (br) {
br.visible = false;
}
}
if (g.scalable || g.rotatable) {
// 缩放点
var sp = g.getAssistantAppend(TransformPoints.Name);
if (!sp) {
sp = new TransformPoints(g);
}
if (selected) {
sp.update();
sp.visible = true;
}
else {
sp.visible = false;
}
}
};
GraphicTransformPlugin.Name = '__graphic_transform_plugin';
GraphicTransformPlugin.AbsorbablePosisiontsName = '__AbsorbablePosisionts';
return GraphicTransformPlugin;
}(InteractionPluginBase));
/**
* 缩放、旋转辅助
*/
var TransformPoints = /** @class */ (function (_super) {
__extends(TransformPoints, _super);
function TransformPoints(obj) {
var _this = _super.call(this) || this;
_this.ltLocal = new pixi_js.Point();
_this.tLocal = new pixi_js.Point();
_this.tCanvas = new pixi_js.Point();
_this.rtLocal = new pixi_js.Point();
_this.rLocal = new pixi_js.Point();
_this.rbLocal = new pixi_js.Point();
_this.bLocal = new pixi_js.Point();
_this.lbLocal = new pixi_js.Point();
_this.lLocal = new pixi_js.Point();
_this.originScale = new pixi_js.Point();
_this.scalePivot = new pixi_js.Point();
/**
* 起始图形角度
*/
_this.startAngle = 0;
/**
* 旋转角度步长
*/
_this.angleStep = 1;
/**
* 修改旋转步长键盘监听
*/
_this.rotateAngleStepKeyListeners = [];
_this.obj = obj;
_this.name = TransformPoints.Name;
_this.angleAssistantText = new VectorText('', {
fill: AppConsts.assistantElementColor,
});
_this.angleAssistantText.setVectorFontSize(16);
_this.angleAssistantText.anchor.set(0.5);
// 创建缩放拖拽点
_this.ltScalePoint = new DraggablePoint(new pixi_js.Point());
_this.ltScalePoint.name = TransformPoints.LeftTopName;
_this.addChild(_this.ltScalePoint);
_this.tScalePoint = new DraggablePoint(new pixi_js.Point());
_this.tScalePoint.name = TransformPoints.TopName;
_this.addChild(_this.tScalePoint);
_this.rtScalePoint = new DraggablePoint(new pixi_js.Point());
_this.rtScalePoint.name = TransformPoints.RightTopName;
_this.addChild(_this.rtScalePoint);
_this.rScalePoint = new DraggablePoint(new pixi_js.Point());
_this.rScalePoint.name = TransformPoints.RightName;
_this.addChild(_this.rScalePoint);
_this.rbScalePoint = new DraggablePoint(new pixi_js.Point());
_this.rbScalePoint.name = TransformPoints.RightBottomName;
_this.addChild(_this.rbScalePoint);
_this.bScalePoint = new DraggablePoint(new pixi_js.Point());
_this.bScalePoint.name = TransformPoints.BottomName;
_this.addChild(_this.bScalePoint);
_this.lbScalePoint = new DraggablePoint(new pixi_js.Point());
_this.lbScalePoint.name = TransformPoints.LeftBottomName;
_this.addChild(_this.lbScalePoint);
_this.lScalePoint = new DraggablePoint(new pixi_js.Point());
_this.lScalePoint.name = TransformPoints.LeftName;
_this.addChild(_this.lScalePoint);
_this.obj.on('transformstart', _this.onObjTransformStart, _this);
_this.obj.on('transformend', _this.onObjTransformEnd, _this);
if (_this.obj.children && _this.obj.children.length > 0) {
recursiveChildren(_this.obj, function (child) {
child.on('transformstart', _this.onObjTransformStart, _this);
child.on('transformend', _this.onObjTransformEnd, _this);
});
}
var pg = _this.obj.getGraphic();
if (pg != null) {
pg.on('transformstart', _this.onObjTransformStart, _this);
pg.on('transformend', _this.onObjTransformEnd, _this);
}
_this.obj.on('repaint', _this.onGraphicRepaint, _this);
_this.children.forEach(function (dp) {
dp.on('transformstart', _this.onScaleDragStart, _this);
dp.on('transforming', _this.onScaleDragMove, _this);
dp.on('transformend', _this.onScaleDragEnd, _this);
});
// 创建旋转拖拽点
_this.rotatePoint = new DraggablePoint(new pixi_js.Point());
_this.addChild(_this.rotatePoint);
_this.rotatePoint.on('transformstart', _this.onRotateStart, _this);
_this.rotatePoint.on('transforming', _this.onRotateMove, _this);
_this.rotatePoint.on('transformend', _this.onRotateEnd, _this);
_this.rotatePivot = new pixi_js.Point();
_this.rotateLastPoint = new pixi_js.Point();
var _loop_1 = function (i) {
this_1.rotateAngleStepKeyListeners.push(KeyListener.create({
value: '' + i,
onPress: function () {
// console.log('修改角度step');
_this.angleStep = i;
},
}));
};
var this_1 = this;
// 初始化旋转角度修改键盘监听器
for (var i = 1; i < 10; i++) {
_loop_1(i);
}
_this.obj.addAssistantAppend(_this);
return _this;
}
TransformPoints.prototype.onObjTransformStart = function () {
this.visible = false;
};
TransformPoints.prototype.onObjTransformEnd = function () {
this.update();
this.visible = true;
};
TransformPoints.prototype.onGraphicRepaint = function () {
if (this.visible) {
this.update();
}
};
/**
* 旋转开始
* @param de
*/
TransformPoints.prototype.onRotateStart = function (de) {
this.hideAll();
var assistantPoint = this.obj.localToCanvasPoint(this.obj.pivot);
this.rotatePivot.copyFrom(assistantPoint);
this.rotateLastPoint.copyFrom(de.target.position);
this.startAngle = this.obj.angle;
var app = this.obj.getGraphicApp();
this.rotateAngleStepKeyListeners.forEach(function (listener) {
return app.addKeyboardListener(listener);
});
this.obj.emit('transformstart', GraphicTransformEvent.rotate(this.obj));
// app.emit('transformstart', app.selectedGraphics);
this.obj.getCanvas().addAssistantAppends(this.angleAssistantText);
this.updateAngleAssistantText(de);
};
TransformPoints.prototype.updateAngleAssistantText = function (de) {
var _a, _b, _c;
this.angleAssistantText.text = this.obj.angle + '°';
var cursorPoint = (_a = de.data) === null || _a === void 0 ? void 0 : _a.startPosition;
if ((_b = de.data) === null || _b === void 0 ? void 0 : _b.currentPosition) {
cursorPoint = (_c = de.data) === null || _c === void 0 ? void 0 : _c.currentPosition;
}
if (cursorPoint) {
this.angleAssistantText.position.x = cursorPoint.x;
this.angleAssistantText.position.y = cursorPoint.y - 10;
}
};
/**
* 旋转移动
* @param de
*/
TransformPoints.prototype.onRotateMove = function (de) {
// 旋转角度计算逻辑取锚点y负方向一点作为旋转点求旋转点和锚点所形成的直线与x轴角度此角度+90°即为最终旋转角度再将旋转角度限制到(-180,180]之间
var angle = angleToAxisx(this.rotatePivot, de.target.position);
angle = Math.floor(angle / this.angleStep) * this.angleStep;
var parentAngle = this.obj.parent.worldAngle;
angle = (angle + 90 - parentAngle) % 360;
if (angle > 180) {
angle = angle - 360;
}
this.obj.angle = angle;
this.updateAngleAssistantText(de);
// this.obj.emit('rotatemove', this.obj);
};
/**
* 旋转结束
* @param de
*/
TransformPoints.prototype.onRotateEnd = function () {
var _this = this;
this.showAll();
this.obj.getCanvas().removeAssistantAppends(this.angleAssistantText);
this.rotateAngleStepKeyListeners.forEach(function (listener) {
return _this.obj.getGraphicApp().removeKeyboardListener(listener);
});
this.obj.emit('transformend', GraphicTransformEvent.rotate(this.obj));
};
/**
* 缩放开始
*/
TransformPoints.prototype.onScaleDragStart = function () {
this.hideAll();
var points = convertRectangleToPolygonPoints(this.obj.getLocalBounds());
var p0 = points[0];
var p1 = points[1];
var p2 = points[2];
var p3 = points[3];
this.scalePivot = this.obj.pivot.clone();
this.ltLocal.copyFrom(p0);
this.tCanvas.copyFrom(this.obj.localToCanvasPoint(calculateLineMidpoint(p0, p1)));
this.tLocal.copyFrom(calculateLineMidpoint(p0, p1));
this.rtLocal.copyFrom(p1);
this.rLocal.copyFrom(calculateLineMidpoint(p1, p2));
this.rbLocal.copyFrom(p2);
this.bLocal.copyFrom(calculateLineMidpoint(p2, p3));
this.lbLocal.copyFrom(p3);
this.lLocal.copyFrom(calculateLineMidpoint(p0, p3));
this.originScale = this.obj.scale.clone();
this.obj.emit('transformstart', GraphicTransformEvent.scale(this.obj));
};
TransformPoints.prototype.onScaleDragMove = function (e) {
// 缩放计算逻辑共8个方向缩放点根据所拖拽的方向:
// 1,计算缩放为1时的此点在拖拽开始时的位置到锚点x、y距离
// 2,计算拖拽点的当前位置到锚点的x、y方向距离
// PS:以上两个计算都是在local也就是图形对象本地坐标系
// 用当前距离除以原始距离即为缩放比例
var defaultScale = new pixi_js.Point(1, 1);
var originWidth = 0;
var originHeight = 0;
var width = 0;
var height = 0;
this.obj.scale.copyFrom(defaultScale);
var point = this.obj.toLocal(e.target.parent.localToScreenPoint(e.target.position));
if (e.target === this.ltScalePoint) {
// 左上角
originWidth = Math.abs(this.ltLocal.x - this.scalePivot.x);
originHeight = Math.abs(this.ltLocal.y - this.scalePivot.y);
width = Math.abs(point.x - this.scalePivot.x);
height = Math.abs(point.y - this.scalePivot.y);
}
else if (e.target == this.tScalePoint) {
// 上
originHeight = Math.abs(this.tLocal.y - this.scalePivot.y);
height = Math.abs(point.y - this.scalePivot.y);
}
else if (e.target == this.rtScalePoint) {
// 右上
originWidth = Math.abs(this.rtLocal.x - this.scalePivot.x);
originHeight = Math.abs(this.rtLocal.y - this.scalePivot.y);
width = Math.abs(point.x - this.scalePivot.x);
height = Math.abs(point.y - this.scalePivot.y);
}
else if (e.target == this.rScalePoint) {
// 右
originWidth = Math.abs(this.rLocal.x - this.scalePivot.x);
width = Math.abs(point.x - this.scalePivot.x);
}
else if (e.target == this.rbScalePoint) {
// 右下
originWidth = Math.abs(this.rbLocal.x - this.scalePivot.x);
originHeight = Math.abs(this.rbLocal.y - this.scalePivot.y);
width = Math.abs(point.x - this.scalePivot.x);
height = Math.abs(point.y - this.scalePivot.y);
}
else if (e.target == this.bScalePoint) {
// 下
originHeight = Math.abs(this.bLocal.y - this.scalePivot.y);
height = Math.abs(point.y - this.scalePivot.y);
}
else if (e.target == this.lbScalePoint) {
// 左下
originWidth = Math.abs(this.lbLocal.x - this.scalePivot.x);
originHeight = Math.abs(this.lbLocal.y - this.scalePivot.y);
width = Math.abs(point.x - this.scalePivot.x);
height = Math.abs(point.y - this.scalePivot.y);
}
else {
// 左
originWidth = Math.abs(this.lLocal.x - this.scalePivot.x);
width = Math.abs(point.x - this.scalePivot.x);
}
// 计算缩放比例,并根据是否保持纵横比两种情况进行缩放处理
var sx = originWidth == 0 ? this.originScale.x : width / originWidth;
var sy = originHeight == 0 ? this.originScale.y : height / originHeight;
// console.log(originWidth, originHeight, width, height, sx, sy);
if (this.obj.keepAspectRatio) {
var max = Math.max(sx, sy);
if (originWidth == 0) {
max = sy;
}
else if (originHeight == 0) {
max = sx;
}
this.obj.scale.set(max, max);
}
else {
this.obj.scale.x = sx;
this.obj.scale.y = sy;
}
};
TransformPoints.prototype.onScaleDragEnd = function () {
this.showAll();
this.obj.emit('transformend', GraphicTransformEvent.scale(this.obj));
};
TransformPoints.prototype.hideOthers = function (dg) {
this.children.forEach(function (child) {
if (child.name !== dg.name) {
child.visible = false;
}
});
};
TransformPoints.prototype.hideAll = function () {
this.children.forEach(function (child) { return (child.visible = false); });
};
TransformPoints.prototype.showAll = function () {
this.update();
this.children.forEach(function (child) { return (child.visible = true); });
};
TransformPoints.prototype.getObjBounds = function () {
var points = this.obj.localBoundsToCanvasPoints();
var p0 = points[0];
var p1 = points[1];
var p3 = points[3];
var width = distance(p0.x, p0.y, p1.x, p1.y);
var height = distance(p0.x, p0.y, p3.x, p3.y);
return { width: width, height: height };
};
/**
* 更新位置和cursor
* @returns
*/
TransformPoints.prototype.update = function () {
if (this.obj.scalable) {
this.updateScalePoints();
}
if (this.obj.rotatable) {
this.updateRotatePoint();
}
};
TransformPoints.prototype.updateRotatePoint = function () {
var rect = this.obj.getLocalBounds();
var lp = this.obj.pivot.clone();
var dy = 10 / this.obj.scale.y;
lp.y = rect.y - dy;
var p = this.obj.localToCanvasPoint(lp);
this.rotatePoint.position.copyFrom(p);
};
TransformPoints.prototype.updateScalePoints = function () {
var points = this.obj.localBoundsToCanvasPoints();
this.ltScalePoint.position.copyFrom(points[0]);
this.tScalePoint.position.copyFrom(calculateLineMidpoint(points[0], points[1]));
this.rtScalePoint.position.copyFrom(points[1]);
this.rScalePoint.position.copyFrom(calculateLineMidpoint(points[1], points[2]));
this.rbScalePoint.position.copyFrom(points[2]);
this.bScalePoint.position.copyFrom(calculateLineMidpoint(points[2], points[3]));
this.lbScalePoint.position.copyFrom(points[3]);
this.lScalePoint.position.copyFrom(calculateLineMidpoint(points[3], points[0]));
var angle = this.obj.worldAngle;
var angle360 = (360 + angle) % 360;
if ((angle >= -22.5 && angle <= 22.5) ||
(angle360 >= 180 - 22.5 && angle360 <= 180 + 22.5)) {
this.ltScalePoint.cursor = 'nw-resize';
this.tScalePoint.cursor = 'n-resize';
this.rtScalePoint.cursor = 'ne-resize';
this.rScalePoint.cursor = 'e-resize';
this.rbScalePoint.cursor = 'se-resize';
this.bScalePoint.cursor = 's-resize';
this.lbScalePoint.cursor = 'sw-resize';
this.lScalePoint.cursor = 'w-resize';
}
else if ((angle >= 22.5 && angle <= 67.5) ||
(angle360 >= 180 + 22.5 && angle360 <= 180 + 67.5)) {
this.ltScalePoint.cursor = 'n-resize';
this.tScalePoint.cursor = 'ne-resize';
this.rtScalePoint.cursor = 'e-resize';
this.rScalePoint.cursor = 'se-resize';
this.rbScalePoint.cursor = 's-resize';
this.bScalePoint.cursor = 'sw-resize';
this.lbScalePoint.cursor = 'w-resize';
this.lScalePoint.cursor = 'nw-resize';
}
else if ((angle >= 67.5 && angle < 112.5) ||
(angle360 >= 180 + 67.5 && angle360 <= 180 + 112.5)) {
this.ltScalePoint.cursor = 'ne-resize';
this.tScalePoint.cursor = 'e-resize';
this.rtScalePoint.cursor = 'se-resize';
this.rScalePoint.cursor = 's-resize';
this.rbScalePoint.cursor = 'sw-resize';
this.bScalePoint.cursor = 'w-resize';
this.lbScalePoint.cursor = 'nw-resize';
this.lScalePoint.cursor = 'n-resize';
}
else {
this.ltScalePoint.cursor = 'e-resize';
this.tScalePoint.cursor = 'se-resize';
this.rtScalePoint.cursor = 's-resize';
this.rScalePoint.cursor = 'sw-resize';
this.rbScalePoint.cursor = 'w-resize';
this.bScalePoint.cursor = 'nw-resize';
this.lbScalePoint.cursor = 'n-resize';
this.lScalePoint.cursor = 'ne-resize';
}
};
TransformPoints.Name = 'transformPoints';
TransformPoints.MinLength = 40;
TransformPoints.LeftTopName = 'lt-scale-point';
TransformPoints.TopName = 't-scale-point';
TransformPoints.RightTopName = 'rt-scale-point';
TransformPoints.RightName = 'r-scale-point';
TransformPoints.RightBottomName = 'rb-scale-point';
TransformPoints.BottomName = 'b-scale-point';
TransformPoints.LeftBottomName = 'lb-scale-point';
TransformPoints.LeftName = 'l-scale-point';
TransformPoints.RotateName = 'rotate-point';
return TransformPoints;
}(pixi_js.Container));
/**
* 包围盒矩形图形,现使用外边框转画布多边形实现
*/
var BoundsGraphic = /** @class */ (function (_super) {
__extends(BoundsGraphic, _super);
function BoundsGraphic(graphic) {
var _this = _super.call(this) || this;
_this.obj = graphic;
_this.name = BoundsGraphic.Name;
_this.visible = false;
_this.debouncedRedraw = debounce(_this.doRedraw, 50);
_this.obj.on('transformstart', _this.onObjTransformStart, _this);
_this.obj.on('transformend', _this.onObjTransformEnd, _this);
if (_this.obj.children && _this.obj.children.length > 0) {
recursiveChildren(_this.obj, function (child) {
child.on('transformstart', _this.onObjTransformStart, _this);
child.on('transformend', _this.onObjTransformEnd, _this);
});
}
var pg = _this.obj.getGraphic();
if (pg != null) {
pg.on('transformstart', _this.onObjTransformStart, _this);
pg.on('transformend', _this.onObjTransformEnd, _this);
}
_this.obj.on('repaint', _this.onGraphicRepaint, _this);
graphic.addAssistantAppend(_this);
return _this;
}
BoundsGraphic.prototype.onObjTransformStart = function () {
this.visible = false;
};
BoundsGraphic.prototype.onObjTransformEnd = function () {
this.redraw();
this.visible = true;
};
BoundsGraphic.prototype.onGraphicRepaint = function () {
if (this.visible) {
this.redraw();
}
};
BoundsGraphic.prototype.destroy = function (options) {
if (this.obj.isGraphic()) {
this.obj.off('repaint', this.onGraphicRepaint, this);
}
_super.prototype.destroy.call(this, options);
};
BoundsGraphic.prototype.redraw = function () {
this.debouncedRedraw(this);
};
BoundsGraphic.prototype.doRedraw = function () {
var visible = this.visible;
this.visible = false; // 屏蔽包围框本身
var bounds = new pixi_js.Polygon(this.obj.localBoundsToCanvasPoints());
this.clear().lineStyle(BoundsGraphic.BoundsLineStyle).drawShape(bounds);
this.visible = visible;
};
BoundsGraphic.Name = '_BoundsRect';
BoundsGraphic.BoundsLineStyle = {
width: 1,
color: '#1976d2',
alpha: 1,
};
return BoundsGraphic;
}(pixi_js.Graphics));
/**
* 图形动画管理
*/
var AnimationManager = /** @class */ (function () {
function AnimationManager(app) {
this.app = app;
this._pause = false;
this.graphicAnimationMap = new Map();
// 动画控制
app.pixi.ticker.add(this.run, this);
}
AnimationManager.prototype.run = function (dt) {
if (this._pause) {
// 暂停
return;
}
this.graphicAnimationMap.forEach(function (map) {
map.forEach(function (animation) {
if (animation.running) {
animation.run(dt);
}
});
});
};
AnimationManager.prototype.pause = function () {
this._pause = true;
};
AnimationManager.prototype.resume = function () {
this._pause = false;
};
AnimationManager.prototype.destroy = function () {
this.app.pixi.ticker.remove(this.run, this);
};
/**
* 图形对象的所有动画map
* @param graphic
* @returns
*/
AnimationManager.prototype.animationMap = function (graphic) {
var map = this.graphicAnimationMap.get(graphic.id);
if (!map) {
map = new Map();
this.graphicAnimationMap.set(graphic.id, map);
}
return map;
};
/**
* 注册图形动画
* @param graphic
* @param animation
*/
AnimationManager.prototype.registerAnimation = function (graphic, animation) {
this.animationMap(graphic).set(animation.name, animation);
};
/**
* 删除图形动画
* @param graphic
* @param name
*/
AnimationManager.prototype.unregisterAnimation = function (graphic, name) {
this.animationMap(graphic).delete(name);
};
/**
* 删除所有图形动画
* @param graphic
*/
AnimationManager.prototype.unregisterGraphicAnimations = function (graphic) {
this.animationMap(graphic).clear();
};
/**
* 获取图形指定名称动画
* @param graphic
* @param name
* @returns
*/
AnimationManager.prototype.animation = function (graphic, name) {
return this.animationMap(graphic).get(name);
};
return AnimationManager;
}());
/**
* 操作
*/
var JlOperation = /** @class */ (function () {
function JlOperation(app, type) {
this.description = ''; // 操作描述
this.app = app;
this.type = type;
}
JlOperation.prototype.undo1 = function () {
var _a;
var updates = this.undo();
if (updates) {
(_a = this.app).updateSelected.apply(_a, updates);
}
};
JlOperation.prototype.redo1 = function () {
var _a;
var updates = this.redo();
if (updates) {
(_a = this.app).updateSelected.apply(_a, updates);
}
};
return JlOperation;
}());
/**
* 操作记录
*/
var OperationRecord = /** @class */ (function () {
function OperationRecord(maxLen) {
if (maxLen === void 0) { maxLen = 100; }
this.undoStack = [];
this.redoStack = [];
this.maxLen = maxLen;
}
Object.defineProperty(OperationRecord.prototype, "hasUndo", {
get: function () {
return this.undoStack.length > 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(OperationRecord.prototype, "hasRedo", {
get: function () {
return this.redoStack.length > 0;
},
enumerable: false,
configurable: true
});
OperationRecord.prototype.setMaxLen = function (v) {
this.maxLen = v;
var len = this.undoStack.length;
if (len > v) {
var removeCount = len - v;
this.undoStack.splice(0, removeCount);
}
};
/**
* 记录
* @param op
*/
OperationRecord.prototype.record = function (op) {
if (this.undoStack.length >= this.maxLen) {
this.undoStack.shift();
}
// console.log('operation record', op)
this.undoStack.push(op);
this.redoStack.splice(0, this.redoStack.length);
};
/**
* 撤销
*/
OperationRecord.prototype.undo = function () {
var op = this.undoStack.pop();
// console.log('撤销', op);
if (op) {
op.undo1();
this.redoStack.push(op);
}
};
/**
* 重做
*/
OperationRecord.prototype.redo = function () {
var op = this.redoStack.pop();
// console.log('重做', op);
if (op) {
op.redo1();
this.undoStack.push(op);
}
};
return OperationRecord;
}());
/**
* 更新画布操作
*/
var UpdateCanvasOperation = /** @class */ (function (_super) {
__extends(UpdateCanvasOperation, _super);
function UpdateCanvasOperation(app, obj, old, data) {
var _this = _super.call(this, app, 'update-canvas') || this;
_this.description = '';
_this.app = app;
_this.obj = obj;
_this.old = old;
_this.data = data;
return _this;
}
UpdateCanvasOperation.prototype.undo = function () {
this.obj.update(this.old);
return [];
};
UpdateCanvasOperation.prototype.redo = function () {
this.obj.update(this.data);
return [];
};
return UpdateCanvasOperation;
}(JlOperation));
/**
* 创建图形操作
*/
var GraphicCreateOperation = /** @class */ (function (_super) {
__extends(GraphicCreateOperation, _super);
function GraphicCreateOperation(app, obj) {
var _this = _super.call(this, app, 'graphic-create') || this;
_this.description = '';
_this.app = app;
_this.obj = obj;
return _this;
}
GraphicCreateOperation.prototype.undo = function () {
var _a;
(_a = this.app).deleteGraphics.apply(_a, this.obj);
};
GraphicCreateOperation.prototype.redo = function () {
var _a;
(_a = this.app).addGraphics.apply(_a, this.obj);
return this.obj;
};
return GraphicCreateOperation;
}(JlOperation));
/**
* 删除图形操作
*/
var GraphicDeleteOperation = /** @class */ (function (_super) {
__extends(GraphicDeleteOperation, _super);
function GraphicDeleteOperation(app, obj) {
var _this = _super.call(this, app, 'graphic-delete') || this;
_this.app = app;
_this.obj = obj;
return _this;
}
GraphicDeleteOperation.prototype.undo = function () {
var _a;
(_a = this.app).addGraphics.apply(_a, this.obj);
return this.obj;
};
GraphicDeleteOperation.prototype.redo = function () {
var _a;
(_a = this.app).deleteGraphics.apply(_a, this.obj);
};
return GraphicDeleteOperation;
}(JlOperation));
var GraphicDataUpdateOperation = /** @class */ (function (_super) {
__extends(GraphicDataUpdateOperation, _super);
function GraphicDataUpdateOperation(app, obj, oldData, newData) {
var _this = _super.call(this, app, 'graphic-drag') || this;
_this.obj = __spreadArray([], obj, true);
_this.oldData = oldData;
_this.newData = newData;
return _this;
}
GraphicDataUpdateOperation.prototype.undo = function () {
for (var i = 0; i < this.obj.length; i++) {
var g = this.obj[i];
// g.exitChildEdit();
g.updateData(this.oldData[i]);
}
return this.obj;
};
GraphicDataUpdateOperation.prototype.redo = function () {
for (var i = 0; i < this.obj.length; i++) {
var g = this.obj[i];
// g.exitChildEdit();
g.updateData(this.newData[i]);
}
return this.obj;
};
return GraphicDataUpdateOperation;
}(JlOperation));
/**
* 图形关系数据
*/
var GraphicRelationParam = /** @class */ (function () {
function GraphicRelationParam(g, param) {
if (param === void 0) { param = null; }
this.g = g;
this.param = param;
}
GraphicRelationParam.prototype.isTheGraphic = function (g) {
return this.g.id === g.id;
};
GraphicRelationParam.prototype.getGraphic = function () {
return this.g;
};
GraphicRelationParam.prototype.getParam = function () {
return this.param;
};
GraphicRelationParam.prototype.equals = function (other) {
return this.isTheGraphic(other.g) && this.param === other.param;
};
return GraphicRelationParam;
}());
/**
* 图形关系
*/
var GraphicRelation = /** @class */ (function () {
function GraphicRelation(rp1, rp2) {
this.rp1 = rp1;
this.rp2 = rp2;
}
GraphicRelation.prototype.contains = function (g) {
return this.rp1.isTheGraphic(g) || this.rp2.isTheGraphic(g);
};
/**
* 获取给定图形的关系参数
* @param g
* @returns
*/
GraphicRelation.prototype.getRelationParam = function (g) {
if (!this.contains(g)) {
throw new Error("\u56FE\u5F62\u5173\u7CFB".concat(this.rp1.g.id, "-").concat(this.rp2.g.id, "\u4E2D\u4E0D\u5305\u542B\u7ED9\u5B9A\u56FE\u5F62").concat(g.id));
}
if (this.rp1.isTheGraphic(g)) {
return this.rp1;
}
else {
return this.rp2;
}
};
/**
* 获取关联的另一个图形的关系参数
* @param g
* @returns
*/
GraphicRelation.prototype.getOtherRelationParam = function (g) {
if (!this.contains(g)) {
throw new Error("\u56FE\u5F62\u5173\u7CFB".concat(this.rp1.g.id, "-").concat(this.rp2.g.id, "\u4E2D\u4E0D\u5305\u542B\u7ED9\u5B9A\u56FE\u5F62").concat(g.id));
}
if (this.rp1.isTheGraphic(g)) {
return this.rp2;
}
else {
return this.rp1;
}
};
/**
* 获取关联的另一个图形对象
* @param g
* @returns graphic
*/
GraphicRelation.prototype.getOtherGraphic = function (g) {
return this.getOtherRelationParam(g).g;
};
GraphicRelation.prototype.equals = function (orp1, orp2) {
if (this.rp1.isTheGraphic(orp1.g)) {
return this.rp1.equals(orp1) && this.rp2.equals(orp2);
}
else if (this.rp1.isTheGraphic(orp2.g)) {
return this.rp1.equals(orp2) && this.rp2.equals(orp1);
}
return false;
};
GraphicRelation.prototype.isEqualOther = function (other) {
return this.equals(other.rp1, other.rp2);
};
return GraphicRelation;
}());
/**
* 图形关系管理
*/
var RelationManage = /** @class */ (function () {
function RelationManage() {
this.relations = [];
}
RelationManage.prototype.isContainsRelation = function (rp1, rp2) {
var relation = this.relations.find(function (relation) {
return relation.equals(rp1, rp2);
});
return !!relation;
};
RelationManage.prototype.addRelation = function (rp1, rp2) {
if (!(rp1 instanceof GraphicRelationParam)) {
rp1 = new GraphicRelationParam(rp1);
}
if (!(rp2 instanceof GraphicRelationParam)) {
rp2 = new GraphicRelationParam(rp2);
}
if (!this.isContainsRelation(rp1, rp2)) {
var relation = new GraphicRelation(rp1, rp2);
this.relations.push(relation);
}
};
/**
* 获取图形的所有关系
* @param g
* @returns
*/
RelationManage.prototype.getRelationsOfGraphic = function (g) {
return this.relations.filter(function (rl) { return rl.contains(g); });
};
/**
* 获取指定图形的指定关系图形类型的所有关系
* @param g 指定图形
* @param type 关联图形的类型
* @returns
*/
RelationManage.prototype.getRelationsOfGraphicAndOtherType = function (g, type) {
return this.relations.filter(function (rl) { return rl.contains(g) && rl.getOtherGraphic(g).type === type; });
};
/**
* 删除关系
* @param relation
*/
RelationManage.prototype.deleteRelation = function (relation) {
var index = this.relations.findIndex(function (rl) { return rl.isEqualOther(relation); });
if (index >= 0) {
this.relations.splice(index, 1);
}
};
/**
* 删除指定图形的所有关系
* @param g
*/
RelationManage.prototype.deleteRelationOfGraphic = function (g) {
var _this = this;
var relations = this.getRelationsOfGraphic(g);
relations.forEach(function (rl) { return _this.deleteRelation(rl); });
};
/**
* 删除指定图形的所有关系
* @param g
*/
RelationManage.prototype.deleteRelationOfGraphicAndOtherType = function (g, type) {
var _this = this;
var relations = this.getRelationsOfGraphicAndOtherType(g, type);
relations.forEach(function (rl) { return _this.deleteRelation(rl); });
};
/**
* 清空
*/
RelationManage.prototype.clear = function () {
this.relations.splice(0, this.relations.length);
};
return RelationManage;
}());
/**
* 图形存储
*/
var GraphicStore = /** @class */ (function () {
function GraphicStore() {
this.store = new Map();
this.relationManage = new RelationManage();
}
/**
* 获取所有图形对象
*/
GraphicStore.prototype.getAllGraphics = function () {
return __spreadArray([], this.store.values(), true);
};
GraphicStore.prototype.queryById = function (id) {
var graphic = this.store.get(id);
if (!graphic)
throw Error("\u672A\u627E\u5230id\u4E3A [".concat(id, "] \u7684\u56FE\u5F62."));
return this.store.get(id);
};
GraphicStore.prototype.queryByIdAmbiguous = function (id) {
var list = [];
this.store.forEach(function (g) {
if (g.id.search(id) >= 0) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByType = function (type) {
var list = [];
this.store.forEach(function (g) {
if (g.type === type) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByCode = function (code) {
var list = [];
this.store.forEach(function (g) {
if (g.code === code) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByCodeAmbiguous = function (code) {
var list = [];
this.store.forEach(function (g) {
if (g.code.search(code) >= 0) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByIdOrCode = function (s) {
var list = [];
this.store.forEach(function (g) {
if (g.isIdOrCode(s)) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByIdOrCodeAndType = function (s, type) {
var list = [];
this.store.forEach(function (g) {
if (g.isIdOrCode(s) && g.type === type) {
list.push(g);
}
});
return list;
};
GraphicStore.prototype.queryByCodeAndType = function (code, type) {
for (var _i = 0, _a = this.store.values(); _i < _a.length; _i++) {
var item = _a[_i];
if (item.code === code && item.type === type) {
return item;
}
}
};
GraphicStore.prototype.queryByCodeAndTypeAmbiguous = function (code, type) {
var list = [];
this.store.forEach(function (g) {
if (g.type === type && g.code.search(code) >= 0) {
list.push(g);
}
});
return list;
};
/**
* 存储图形对象
* @param graphics 要存储的图形
*/
GraphicStore.prototype.storeGraphics = function (graphic) {
if (!graphic.id || graphic.id.trim() === '') {
throw new Error("\u5B58\u50A8\u56FE\u5F62\u5BF9\u8C61\u5F02\u5E38: id\u4E3A\u7A7A, ".concat(graphic));
}
if (this.store.has(graphic.id)) {
// 已经存在
var exist = this.store.get(graphic.id);
console.error("\u5DF2\u7ECF\u5B58\u5728id=".concat(graphic.id, "\u7684\u8BBE\u5907").concat(exist));
return false;
}
else {
this.store.set(graphic.id, graphic);
graphic.queryStore = this;
graphic.relationManage = this.relationManage;
return true;
}
};
/**
* 删除图形
* @param graph 要删除的图形
*/
GraphicStore.prototype.deleteGraphics = function (graphic) {
var id = graphic.id;
var remove = this.store.get(id);
if (remove) {
this.store.delete(id);
// 删除图形关系
this.relationManage.deleteRelationOfGraphic(remove);
}
return remove;
};
/**
* 清空
*/
GraphicStore.prototype.clear = function () {
this.relationManage.clear();
this.store.clear();
};
return GraphicStore;
}());
var MessageClient = /** @class */ (function (_super) {
__extends(MessageClient, _super);
function MessageClient(options) {
var _this = _super.call(this) || this;
_this.subClients = []; // 订阅客户端
_this.options = options;
return _this;
}
MessageClient.prototype.unsubscribe = function (destination) {
this.unsubscribe0(destination);
var idx = this.subClients.findIndex(function (cli) { return cli.destination === destination; });
if (idx >= 0) {
this.subClients.splice(idx, 1);
}
};
MessageClient.prototype.getOrNewSubClient = function (destination) {
var cli = this.subClients.find(function (cli) { return cli.destination === destination; });
if (!cli) {
// 不存在,新建
cli = new SubscriptionClient(this, destination, this.options.protocol);
this.subClients.push(cli);
}
return cli;
};
MessageClient.prototype.addSubscription = function (destination, handler) {
var cli = this.getOrNewSubClient(destination);
cli.addHandler(handler);
};
MessageClient.prototype.removeSubscription = function (destination, handle) {
this.getOrNewSubClient(destination).removeHandler(handle);
};
return MessageClient;
}(EventEmitter));
var SubscriptionClient = /** @class */ (function () {
function SubscriptionClient(mc, destination, protocal) {
this.handlers = [];
this.subscripted = false;
this.mc = mc;
this.destination = destination;
this.protocol = protocal;
this.mc.on('disconnected', this.onDisconnect, this);
this.mc.on('connected', this.trySubscribe, this);
}
SubscriptionClient.prototype.addHandler = function (handler) {
if (this.handlers.filter(function (h) { return h.App === handler.App; }).length == 0) {
this.handlers.push(handler);
}
if (!this.subscripted) {
this.trySubscribe();
}
};
SubscriptionClient.prototype.removeHandler = function (handler) {
var idx = this.handlers.findIndex(function (h) { return h.App === handler.App; });
if (idx >= 0) {
this.handlers.splice(idx, 1);
}
if (this.handlers.length == 0) {
console.log("\u8BA2\u9605".concat(this.destination, "\u6CA1\u6709\u6D88\u606F\u76D1\u542C\u5904\u7406,\u79FB\u9664\u8BA2\u9605"));
this.unsubscribe();
}
};
SubscriptionClient.prototype.trySubscribe = function () {
var _this = this;
if (this.mc.connected) {
this.subscripted = this.mc.subscribe(this.destination, function (data) {
_this.handleMessage(data);
});
}
};
SubscriptionClient.prototype.unsubscribe = function () {
this.mc.unsubscribe(this.destination);
};
SubscriptionClient.prototype.handleMessage = function (data) {
if (this.protocol === 'json') {
console.debug('收到消息:', data);
}
this.handlers.forEach(function (handler) {
try {
handler.handle(data);
}
catch (error) {
console.error('图形应用状态消息处理异常', error);
}
});
};
SubscriptionClient.prototype.onDisconnect = function () {
this.subscripted = false;
};
return SubscriptionClient;
}());
var ReconnectDelay = 3000;
var HeartbeatIncoming = 30000;
var HeartbeatOutgoing = 30000;
var StompMessagingClient = /** @class */ (function (_super) {
__extends(StompMessagingClient, _super);
function StompMessagingClient(options) {
var _this = _super.call(this, options) || this;
_this.options = options;
_this.cli = new stompjs.Client({
brokerURL: options.wsUrl,
connectHeaders: {
Authorization: options.token ? options.token : '',
},
reconnectDelay: ReconnectDelay,
heartbeatIncoming: HeartbeatIncoming,
heartbeatOutgoing: HeartbeatOutgoing,
});
_this.cli.onConnect = function () {
// this.subClients.forEach((cli) => {
// this.subscribe(cli.destination, cli.handleMessage);
// });
_this.emit('connected', '');
};
_this.cli.onStompError = function (frame) {
var errMsg = frame.headers['message'];
if (errMsg === '401') {
console.warn('认证失败,断开WebSocket连接');
_this.cli.deactivate();
}
else {
console.error('收到Stomp错误消息', frame);
}
};
_this.cli.onDisconnect = function (frame) {
console.log('Stomp 断开连接', frame);
_this.emit('disconnected', frame);
};
// websocket错误处理
_this.cli.onWebSocketError = function (err) {
console.error('websocket错误', err);
};
_this.cli.activate();
return _this;
}
Object.defineProperty(StompMessagingClient.prototype, "connected", {
get: function () {
return this.cli.connected;
},
enumerable: false,
configurable: true
});
StompMessagingClient.prototype.subscribe = function (destination, handle) {
var _this = this;
this.cli.subscribe(destination, function (frame) {
if (_this.options.protocol === 'json') {
var data = JSON.parse(frame.body);
handle(data);
}
else {
handle(frame.binaryBody);
}
}, {
id: destination,
});
return true;
};
StompMessagingClient.prototype.unsubscribe0 = function (destination) {
this.cli.unsubscribe(destination);
};
StompMessagingClient.prototype.close = function () {
this.cli.deactivate();
};
return StompMessagingClient;
}(MessageClient));
var MqttMsgClient = /** @class */ (function (_super) {
__extends(MqttMsgClient, _super);
function MqttMsgClient(options) {
var _this = _super.call(this, options) || this;
_this.retryTimes = 0;
_this.subMsgHandler = new Map();
_this.options = options;
try {
_this.cli = mqtt.connect(options.wsUrl, {
protocolVersion: 5,
clean: true,
resubscribe: false,
keepalive: options.heartbeat, //ms,心跳
connectTimeout: options.connectTimeout, // ms,连接超时
reconnectPeriod: options.retryPeriod, // ms,重连间隔
username: options.clientName || '',
password: options.token,
});
_this.cli.on('connect', function (packet) {
console.log('MQTT 连接成功!');
_this.retryTimes = 0; // 连接成功,重置
_this.emit('connected', packet);
});
_this.cli.on('disconnect', function (packet) {
console.log('MQTT 连接断开!');
_this.emit('disconnected', packet);
});
_this.cli.on('close', function () {
console.log('MQTT 关闭!');
_this.emit('disconnected', 'close');
});
_this.cli.on('reconnect', function () {
_this.retryTimes += 1;
console.log("MQTT\u7B2C ".concat(_this.retryTimes, " \u6B21\u5C1D\u8BD5\u91CD\u8FDE"));
if (_this.retryTimes > options.retryTimes) {
try {
_this.cli.end();
console.error('MQTT 达到重连最大尝试次数,停止重试');
}
catch (error) {
console.error(error);
}
}
});
_this.cli.on('error', function (error) {
console.log('MQTT 出现错误', error);
console.warn(error);
_this.emit('error', error);
});
_this.cli.on('message', function (topic, message) {
var handle = _this.subMsgHandler.get(topic);
if (handle) {
if (_this.options.protocol === 'json') {
var data = JSON.parse(message.toString());
handle(data);
}
else {
// 字节流
handle(message);
}
}
});
}
catch (err) {
console.error('MQTT connect error', err);
_this.emit('error', err);
throw err;
}
return _this;
}
MqttMsgClient.prototype.subscribe = function (destination, handle) {
console.debug('MQTT订阅执行', destination);
this.cli.subscribe(destination, { qos: 0 }, function (error, res) {
if (error) {
console.warn('MQTT 订阅失败', error);
return;
}
console.debug('MQTT 订阅成功', res);
return false;
});
this.subMsgHandler.set(destination, handle);
return true;
};
MqttMsgClient.prototype.unsubscribe0 = function (destination) {
var _this = this;
console.debug('MQTT取消订阅执行', destination);
this.cli.unsubscribe(destination, function (error, packet) {
if (error) {
console.warn('MQTT 取消订阅失败', error);
}
else {
console.debug('MQTT 取消订阅成功', packet);
_this.subMsgHandler.delete(destination);
}
});
};
Object.defineProperty(MqttMsgClient.prototype, "connected", {
get: function () {
return this.cli.connected;
},
enumerable: false,
configurable: true
});
MqttMsgClient.prototype.close = function () {
var _this = this;
try {
console.debug('MQTT关闭执行');
this.cli.end(true, function () {
console.debug('MQTT 消息客户端关闭成功');
_this.subMsgHandler.clear();
});
}
catch (error) {
console.warn('MQTT 消息客户端关闭失败', error);
}
};
return MqttMsgClient;
}(MessageClient));
exports.ClientEngine = void 0;
(function (ClientEngine) {
ClientEngine[ClientEngine["Stomp"] = 0] = "Stomp";
// Centrifugo,
ClientEngine[ClientEngine["MQTT"] = 1] = "MQTT";
})(exports.ClientEngine || (exports.ClientEngine = {}));
var DefaultStompOption = {
engine: exports.ClientEngine.Stomp,
protocol: 'protobuf',
wsUrl: '',
token: '',
connectTimeout: 30 * 1000,
heartbeat: 60,
retryPeriod: 2 * 1000,
retryTimes: 100,
};
var WsMsgCli = /** @class */ (function () {
function WsMsgCli() {
}
WsMsgCli.new = function (options) {
if (WsMsgCli.client) {
// 已经创建
return;
}
WsMsgCli.options = Object.assign({}, DefaultStompOption, options);
switch (WsMsgCli.options.engine) {
// case ClientEngine.Centrifugo: {
// WsMsgCli.client = new CentrifugeMessagingClient(WsMsgCli.options);
// break;
// }
case exports.ClientEngine.MQTT: {
WsMsgCli.client = new MqttMsgClient(WsMsgCli.options);
break;
}
case exports.ClientEngine.Stomp: {
WsMsgCli.client = new StompMessagingClient(WsMsgCli.options);
break;
}
default: {
throw new Error('未知的消息客户端引擎类型', WsMsgCli.options.engine);
}
}
var cli = WsMsgCli.client;
cli.on('connected', function () {
WsMsgCli.emitConnectStateChangeEvent(true);
});
cli.on('disconnected', function () {
WsMsgCli.emitConnectStateChangeEvent(false);
});
cli.on('error', function (err) {
console.warn('websocket 客户端错误消息发布', err);
WsMsgCli.appMsgBroker.forEach(function (broker) {
broker.app.emit('websocket-error', err);
});
});
};
WsMsgCli.isInitiated = function () {
return !!WsMsgCli.client;
};
WsMsgCli.emitConnectStateChangeEvent = function (connected) {
WsMsgCli.appMsgBroker.forEach(function (broker) {
broker.app.emit('websocket-connect-state-change', connected);
});
};
WsMsgCli.isConnected = function () {
return WsMsgCli.client && WsMsgCli.client.connected;
};
WsMsgCli.registerSubscription = function (destination, handler) {
WsMsgCli.client.addSubscription(destination, handler);
};
WsMsgCli.unregisterSubscription = function (destination, handler) {
WsMsgCli.client.removeSubscription(destination, handler);
};
WsMsgCli.registerAppMsgBroker = function (broker) {
WsMsgCli.appMsgBroker.push(broker);
};
WsMsgCli.removeAppMsgBroker = function (broker) {
var index = WsMsgCli.appMsgBroker.findIndex(function (mb) { return mb == broker; });
if (index >= 0) {
WsMsgCli.appMsgBroker.splice(index, 1);
}
};
WsMsgCli.hasAppMsgBroker = function () {
return WsMsgCli.appMsgBroker.length > 0;
};
/**
* 关闭websocket连接
*/
WsMsgCli.close = function () {
if (WsMsgCli.client) {
WsMsgCli.client.close();
}
};
WsMsgCli.appMsgBroker = [];
return WsMsgCli;
}());
var AppMessageHandler = /** @class */ (function () {
function AppMessageHandler(app, subOptions) {
this.app = app;
if (!subOptions.messageConverter && !subOptions.messageHandle) {
throw new Error("\u6CA1\u6709\u6D88\u606F\u5904\u7406\u5668\u6216\u56FE\u5F62\u72B6\u6001\u6D88\u606F\u8F6C\u6362\u5668: ".concat(subOptions));
}
this.sub = subOptions;
}
Object.defineProperty(AppMessageHandler.prototype, "App", {
get: function () {
return this.app;
},
enumerable: false,
configurable: true
});
AppMessageHandler.prototype.handle = function (data) {
var sub = this.sub;
if (sub.messageConverter) {
var graphicStates = sub.messageConverter(data);
this.app.handleGraphicStates(graphicStates, sub.graphicQueryer, sub.createOnNotFound);
}
else if (sub.messageHandle) {
sub.messageHandle(data);
}
};
return AppMessageHandler;
}());
/**
* 图形APP的websocket消息代理
*/
var AppWsMsgBroker = /** @class */ (function () {
function AppWsMsgBroker(app) {
this.subscriptions = new Map();
this.app = app;
WsMsgCli.registerAppMsgBroker(this);
}
AppWsMsgBroker.prototype.subscribe = function (sub) {
var handler = new AppMessageHandler(this.app, sub);
WsMsgCli.registerSubscription(sub.destination, handler);
this.subscriptions.set(sub.destination, handler);
};
AppWsMsgBroker.prototype.unsbuscribe = function (destination) {
var oldSub = this.subscriptions.get(destination);
if (oldSub) {
WsMsgCli.unregisterSubscription(destination, oldSub);
}
};
AppWsMsgBroker.prototype.unsubscribeAll = function () {
var _this = this;
this.subscriptions.forEach(function (record, destination) {
_this.unsbuscribe(destination);
});
};
AppWsMsgBroker.prototype.resubscribeAll = function () {
this.subscriptions.forEach(function (handler, destination) {
WsMsgCli.registerSubscription(destination, handler);
});
};
/**
* 取消所有订阅从通用Stomp客户端移除此消息代理
*/
AppWsMsgBroker.prototype.close = function () {
WsMsgCli.removeAppMsgBroker(this);
this.unsubscribeAll();
};
return AppWsMsgBroker;
}());
/**
* 默认的白色样式
*/
var DefaultWhiteStyleOptions = {
titleStyle: {
fontSize: 16,
fontColor: '#000000',
padding: [5, 15],
},
backgroundColor: '#ffffff',
border: true,
borderWidth: 1,
borderColor: '#4C4C4C',
/**
* 默认圆角
*/
borderRoundRadius: 5,
itemStyle: {
fontSize: 16,
fontColor: '#000000',
padding: [5, 25],
hoverColor: '#1E78DB',
disabledFontColor: '#9D9D9D',
},
};
/**
* 默认的白色菜单配置
*/
var DefaultWhiteMenuOptions = {
name: '',
style: DefaultWhiteStyleOptions,
groups: [],
};
var ContextMenuPlugin = /** @class */ (function () {
function ContextMenuPlugin(app) {
var _this = this;
this.contextMenuMap = new Map();
this.app = app;
var canvas = this.app.canvas;
canvas.on('pointerdown', function () {
_this.contextMenuMap.forEach(function (menu) {
menu.close();
});
});
}
ContextMenuPlugin.prototype.registerMenu = function (menu) {
this.contextMenuMap.set(menu.menuName, menu);
menu.plugin = this;
};
Object.defineProperty(ContextMenuPlugin.prototype, "screenWidth", {
/**
* 获取视口屏幕宽度
*/
get: function () {
return this.app.viewport.screenWidth;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuPlugin.prototype, "screenHeight", {
/**
* 获取视口屏幕高度
*/
get: function () {
return this.app.viewport.screenHeight;
},
enumerable: false,
configurable: true
});
/**
* 打开菜单
* @param menu
* @param global
*/
ContextMenuPlugin.prototype.open = function (menu, global) {
if (!menu.opened) {
menu.opened = true;
this.app.pixi.stage.addChild(menu);
}
// 处理超出显示范围
var screenHeight = this.screenHeight;
var bottomY = global.y + menu.height;
var oob = this.oob(menu, global);
var pos = global.clone();
if (oob.right) {
pos.x = global.x - menu.width;
}
if (oob.bottom) {
var py = global.y - menu.height;
if (py > 0) {
pos.y = py;
}
else {
pos.y = global.y - (bottomY - screenHeight);
}
}
// 移动后是否左上超出
oob = this.oob(menu, pos);
if (oob.left) {
pos.x = 0;
}
if (oob.top) {
pos.y = 0;
}
menu.position.copyFrom(pos);
};
/**
* 关闭菜单
* @param menu
*/
ContextMenuPlugin.prototype.close = function (menu) {
if (menu.opened) {
menu.opened = false;
this.app.pixi.stage.removeChild(menu);
}
};
/**
* 关闭所有菜单
*/
ContextMenuPlugin.prototype.closeAll = function () {
var _this = this;
this.contextMenuMap.forEach(function (cm) {
_this.close(cm);
});
};
/**
* 越界检查
* @param menu
* @param global
* @returns
*/
ContextMenuPlugin.prototype.oob = function (menu, global) {
var screenWidth = this.screenWidth;
var screenHeight = this.screenHeight;
var bound = new pixi_js.Rectangle(0, 0, screenWidth, screenHeight);
var menuRect = new pixi_js.Rectangle(global.x, global.y, menu.width, menu.height);
return OutOfBound.check(menuRect, bound);
};
return ContextMenuPlugin;
}());
/**
* 上下文菜单,多级嵌套
*/
var ContextMenu = /** @class */ (function (_super) {
__extends(ContextMenu, _super);
function ContextMenu(menuOptions, parentMenuItem) {
var _this = _super.call(this) || this;
_this.opened = false;
_this.padding = 5;
_this._active = false; // 激活状态
_this.menuOptions = Object.assign({}, DefaultWhiteMenuOptions, menuOptions);
_this.name = _this.menuOptions.name;
_this.bg = new pixi_js.Graphics();
_this.addChild(_this.bg);
_this.groups = [];
_this.init();
_this.parentMenuItem = parentMenuItem;
return _this;
}
ContextMenu.init = function (options) {
return new ContextMenu(options);
};
Object.defineProperty(ContextMenu.prototype, "style", {
get: function () {
return this.menuOptions.style;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenu.prototype, "parentMenu", {
/**
* 父级菜单
*/
get: function () {
var _a;
return (_a = this.parentMenuItem) === null || _a === void 0 ? void 0 : _a.menu;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenu.prototype, "rootMenu", {
/**
* 最顶级菜单
*/
get: function () {
if (this.parentMenu) {
return this.parentMenu.rootMenu;
}
return this;
},
enumerable: false,
configurable: true
});
/**
* 是否存在激活的菜单项
* @returns
*/
ContextMenu.prototype.hasActiveItem = function () {
for (var i = 0; i < this.groups.length; i++) {
var group = this.groups[i];
if (group.hasActiveItem()) {
return true;
}
}
return false;
};
Object.defineProperty(ContextMenu.prototype, "active", {
get: function () {
return (this._active ||
this.hasActiveItem() ||
(this.parentMenuItem != undefined && this.parentMenuItem._active));
},
set: function (v) {
this._active = v;
this.onActiveChanged();
},
enumerable: false,
configurable: true
});
ContextMenu.prototype.onActiveChanged = function () {
var _this = this;
if (this.parentMenuItem) {
this.parentMenuItem.onActiveChanged();
if (!this.active) {
this.timeoutCloseHandle = setTimeout(function () {
_this.close();
}, 500);
}
else {
if (this.timeoutCloseHandle) {
clearTimeout(this.timeoutCloseHandle);
}
}
}
};
ContextMenu.prototype.setOptions = function (menuOptions) {
this.menuOptions = Object.assign({}, DefaultWhiteMenuOptions, menuOptions);
this.init();
};
/**
* 初始化
*/
ContextMenu.prototype.init = function () {
var _this = this;
// this.initTitle();
this.groups = [];
var options = this.menuOptions;
options.groups.forEach(function (group) {
var menuGroup = new MenuGroup(_this, group);
_this.groups.push(menuGroup);
});
var _a = this.calculateBorderInfo(), borderHeight = _a.borderHeight, maxItemWidth = _a.maxItemWidth;
var splitLineWidth = 1;
var bgWidth = maxItemWidth + this.padding * 2;
var bgHeight = borderHeight +
this.groups.length * this.padding * 2 +
(this.groups.length - 1) * splitLineWidth;
if (options.style.border) {
this.bg.lineStyle(options.style.borderWidth, new pixi_js.Color(options.style.borderColor));
}
this.bg.beginFill(new pixi_js.Color(options.style.backgroundColor));
if (options.style.borderRoundRadius > 0) {
this.bg.drawRoundedRect(0, 0, bgWidth, bgHeight, options.style.borderRoundRadius);
}
else {
this.bg.drawRect(0, 0, bgWidth, bgHeight);
}
this.bg.endFill();
var groupHeight = 0;
this.bg.lineStyle(splitLineWidth, new pixi_js.Color(options.style.borderColor));
for (var i = 0; i < this.groups.length; i++) {
var group = this.groups[i];
group.updateItemBox(maxItemWidth);
group.position.set(this.padding, groupHeight + this.padding);
if (i === this.groups.length - 1) {
// 最后一个
break;
}
var splitLineY = groupHeight + group.height + this.padding * 2;
this.bg.moveTo(0, splitLineY);
this.bg.lineTo(bgWidth, splitLineY);
groupHeight = splitLineY + splitLineWidth;
}
this.addChild.apply(this, this.groups);
this.eventMode = 'static';
this.on('pointerover', function () {
_this.active = true;
});
this.on('pointerout', function () {
_this.active = false;
});
};
ContextMenu.prototype.initGroups = function () {
var _this = this;
this.groups = [];
var options = this.menuOptions;
options.groups.forEach(function (group) {
var menuGroup = new MenuGroup(_this, group);
_this.groups.push(menuGroup);
});
this.addChild.apply(this, this.groups);
};
ContextMenu.prototype.initTitle = function () {
if (this.menuOptions.title) {
this.title = new pixi_js.Text(this.menuOptions.title, { align: 'left' });
}
};
ContextMenu.prototype.calculateBorderInfo = function () {
var maxItemNameWidth = 0;
var maxShortcutWidth = 0;
var maxGutter = 0;
var borderHeight = 0;
this.groups.forEach(function (menuGroup) {
borderHeight += menuGroup.totalHeight;
var maxInw = menuGroup.maxItemNameWidth;
if (maxInw > maxItemNameWidth) {
maxItemNameWidth = maxInw;
}
var maxSw = menuGroup.maxShortcutWidth;
if (maxSw > maxShortcutWidth) {
maxShortcutWidth = maxSw;
}
var gutter = menuGroup.totalGutter;
if (gutter > maxGutter) {
maxGutter = gutter;
}
});
var maxItemWidth = maxItemNameWidth + maxShortcutWidth + maxGutter;
return { borderHeight: borderHeight, maxItemWidth: maxItemWidth };
};
ContextMenu.prototype.updateBg = function () {
this.bg.clear();
var options = this.menuOptions;
var _a = this.calculateBorderInfo(), borderHeight = _a.borderHeight, maxItemWidth = _a.maxItemWidth;
var splitLineWidth = 1;
var bgWidth = maxItemWidth + this.padding * 2;
var bgHeight = borderHeight +
this.groups.length * this.padding * 2 +
(this.groups.length - 1) * splitLineWidth;
if (options.style.border) {
this.bg.lineStyle(options.style.borderWidth, new pixi_js.Color(options.style.borderColor));
}
this.bg.beginFill(new pixi_js.Color(options.style.backgroundColor));
if (options.style.borderRoundRadius > 0) {
this.bg.drawRoundedRect(0, 0, bgWidth, bgHeight, options.style.borderRoundRadius);
}
else {
this.bg.drawRect(0, 0, bgWidth, bgHeight);
}
this.bg.endFill();
var groupHeight = 0;
this.bg.lineStyle(splitLineWidth, new pixi_js.Color(options.style.borderColor));
for (var i = 0; i < this.groups.length; i++) {
var group = this.groups[i];
group.updateItemBox(maxItemWidth);
group.position.set(this.padding, groupHeight + this.padding);
if (i === this.groups.length - 1) {
// 最后一个
break;
}
var splitLineY = groupHeight + group.height + this.padding * 2;
this.bg.moveTo(0, splitLineY);
this.bg.lineTo(bgWidth, splitLineY);
groupHeight = splitLineY + splitLineWidth;
}
};
ContextMenu.prototype.update = function () {
if (this.menuOptions.groups.length !== this.groups.length) {
this.init();
}
else {
this.groups.forEach(function (group) { return group.update(); });
this.updateBg();
}
};
Object.defineProperty(ContextMenu.prototype, "menuName", {
get: function () {
return this.menuOptions.name;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenu.prototype, "plugin", {
get: function () {
if (this.parentMenu) {
return this.parentMenu.plugin;
}
if (this._plugin) {
return this._plugin;
}
throw new Error("\u4E0A\u4E0B\u6587\u83DC\u5355name=".concat(this.menuOptions.name, "\u6CA1\u6709\u6DFB\u52A0\u5230\u63D2\u4EF6\u4E2D"));
},
set: function (v) {
this._plugin = v;
},
enumerable: false,
configurable: true
});
/**
* 显示菜单
*/
ContextMenu.prototype.open = function (global) {
if (this.parentMenu) {
this.parentMenu.openSub(this, global);
}
else {
this.update();
this.plugin.open(this, global);
}
};
/**
* 关闭菜单
*/
ContextMenu.prototype.close = function () {
if (this.openedSubMenu) {
this.openedSubMenu.close();
this.openedSubMenu = undefined;
}
this.plugin.close(this);
};
/**
* 打开子菜单
* @param subMenu
* @param global
*/
ContextMenu.prototype.openSub = function (subMenu, global) {
if (this.openedSubMenu) {
this.openedSubMenu.close();
}
var pos = global.clone();
var oob = this.plugin.oob(subMenu, global);
if (oob.right) {
pos.x = this.position.x - subMenu.width + this.padding;
}
if (oob.bottom) {
pos.y = this.plugin.screenHeight - subMenu.height - this.padding;
}
this.plugin.open(subMenu, pos);
this.openedSubMenu = subMenu;
};
return ContextMenu;
}(pixi_js.Container));
var MenuGroup = /** @class */ (function (_super) {
__extends(MenuGroup, _super);
function MenuGroup(menu, config) {
var _this = _super.call(this) || this;
_this.gutter = 3; // 名称、快捷键、箭头文本间隙
_this.items = [];
_this.config = config;
_this.menu = menu;
_this.init();
return _this;
}
MenuGroup.prototype.init = function () {
var _this = this;
this.items = []; // 清空
this.config.items.forEach(function (item) {
_this.items.push(new ContextMenuItem(_this.menu, item));
});
if (this.items.length === 0) {
console.error('菜单group为空', this.config, this.menu);
throw new Error("{name=".concat(this.menu.name, "}\u7684\u83DC\u5355\u7684group\u4E3A{name=").concat(this.config.name, "}\u7684\u6761\u76EE\u4E3A\u7A7A!"));
}
this.addChild.apply(this, this.items);
};
MenuGroup.prototype.hasActiveItem = function () {
for (var i = 0; i < this.items.length; i++) {
var item = this.items[i];
if (item.active) {
return true;
}
}
return false;
};
Object.defineProperty(MenuGroup.prototype, "maxItemNameWidth", {
get: function () {
var maxNameWidth = this.items
.map(function (item) { return item.nameBounds.width; })
.sort(function (a, b) { return a - b; })
.reverse()[0];
return maxNameWidth;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MenuGroup.prototype, "maxShortcutWidth", {
get: function () {
var maxShortcutWidth = this.items
.map(function (item) { return item.shortcutKeyBounds.width; })
.sort(function (a, b) { return a - b; })
.reverse()[0];
return maxShortcutWidth;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MenuGroup.prototype, "totalGutter", {
get: function () {
return this.gutter + this.items[0].paddingLeft + this.items[0].paddingRight;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MenuGroup.prototype, "totalHeight", {
get: function () {
var total = 0;
this.items.forEach(function (item) { return (total += item.totalHeight); });
return total;
},
enumerable: false,
configurable: true
});
MenuGroup.prototype.update = function () {
if (this.items.length !== this.config.items.length) {
this.init();
}
else {
var i_1 = 0;
this.items.forEach(function (item) {
item.update();
if (item.visible) {
item.position.y = i_1 * item.totalHeight;
i_1++;
}
});
}
};
MenuGroup.prototype.updateItemBox = function (maxItemWidth) {
this.items.forEach(function (item) {
return item.updateBox(maxItemWidth, item.totalHeight);
});
};
return MenuGroup;
}(pixi_js.Container));
/**
* 菜单项
*/
var ContextMenuItem = /** @class */ (function (_super) {
__extends(ContextMenuItem, _super);
function ContextMenuItem(menu, config) {
var _this = _super.call(this) || this;
_this.gutter = 3; // 名称、快捷键、箭头文本间隙
_this._active = false; // 激活状态
_this.menu = menu;
_this.config = config;
_this.box = new pixi_js.Graphics();
_this.addChild(_this.box);
_this.nameText = new pixi_js.Text(_this.config.name, {
fontSize: _this.fontSize,
fill: _this.fontColor,
});
_this.addChild(_this.nameText);
_this.initShortcutKeyText();
_this.initSubMenu();
return _this;
}
ContextMenuItem.prototype.registerEventHandler = function () {
var _this = this;
this.eventMode = 'static';
this.cursor = 'pointer';
this.on('pointerover', function () {
_this.active = true;
if (_this.config.disabled) {
_this.cursor = 'not-allowed';
}
else {
_this.cursor = 'pointer';
}
if (_this.subMenu) {
var p = _this.toGlobal(new pixi_js.Point(_this.width));
_this.subMenu.open(p);
}
});
this.on('pointerout', function () {
_this.active = false;
});
this.on('pointertap', function () {
if (_this.config.disabled) {
// 禁用,不处理
return;
}
if (_this.config.handler) {
_this.menu.plugin.app.emit('pre-menu-handle', _this.config);
_this.config.handler();
_this.menu.plugin.app.emit('post-menu-handle', _this.config);
}
if (!_this.config.subMenu || _this.config.subMenu.groups.length === 0) {
_this.active = false;
_this.menu.active = false;
_this.menu.rootMenu.close();
}
});
};
Object.defineProperty(ContextMenuItem.prototype, "active", {
get: function () {
return this._active || (this.subMenu != undefined && this.subMenu.active);
},
set: function (v) {
this._active = v;
if (this.subMenu) {
this.subMenu.onActiveChanged();
}
this.onActiveChanged();
},
enumerable: false,
configurable: true
});
ContextMenuItem.prototype.onActiveChanged = function () {
if (this.active) {
this.box.alpha = 1;
}
else {
this.box.alpha = 0;
}
};
Object.defineProperty(ContextMenuItem.prototype, "textWidth", {
get: function () {
return this.nameBounds.width + this.shortcutKeyBounds.width + this.gutter;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "nameGraphic", {
get: function () {
if (this.nameText) {
return this.nameText;
}
throw new Error("\u83DC\u5355\u9879name=".concat(this.config.name, "\u6CA1\u6709\u521D\u59CB\u5316\u540D\u79F0\u56FE\u5F62\u5BF9\u8C61"));
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "totalHeight", {
get: function () {
if (this.config.visible === false) {
return 0;
}
else {
return this.paddingTop + this.paddingBottom + this.nameGraphic.height;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "nameBounds", {
get: function () {
return this.nameGraphic.getLocalBounds();
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "shortcutKeyBounds", {
get: function () {
if (this.shortcutKeyText) {
return this.shortcutKeyText.getLocalBounds();
}
else {
return new pixi_js.Rectangle(0, 0, 0, 0);
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "style", {
get: function () {
return this.menu.style.itemStyle;
},
enumerable: false,
configurable: true
});
ContextMenuItem.prototype.checkPadding = function (padding) {
if (Array.isArray(padding)) {
if (padding.length !== 2 && padding.length !== 4) {
throw new Error('错误的padding数据');
}
}
};
ContextMenuItem.prototype.toWholePadding = function (padding) {
this.checkPadding(padding);
if (Array.isArray(padding)) {
if (padding.length == 2) {
return [padding[0], padding[1], padding[0], padding[1]];
}
else {
return padding;
}
}
else {
return [padding, padding, padding, padding];
}
};
Object.defineProperty(ContextMenuItem.prototype, "paddingTop", {
get: function () {
return this.toWholePadding(this.menu.style.itemStyle.padding)[0];
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "paddingBottom", {
get: function () {
return this.toWholePadding(this.menu.style.itemStyle.padding)[2];
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "paddingLeft", {
get: function () {
return this.toWholePadding(this.menu.style.itemStyle.padding)[3];
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "paddingRight", {
get: function () {
return this.toWholePadding(this.menu.style.itemStyle.padding)[1];
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "hoverColor", {
get: function () {
return this.style.hoverColor;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "fontSize", {
get: function () {
return this.style.fontSize;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContextMenuItem.prototype, "fontColor", {
get: function () {
if (this.config.disabled) {
return this.style.disabledFontColor;
}
else if (this.config.fontColor) {
return this.config.fontColor;
}
return this.style.fontColor;
},
enumerable: false,
configurable: true
});
ContextMenuItem.prototype.initShortcutKeyText = function () {
if (this.config.shortcutKeys && this.config.shortcutKeys.length > 0) {
this.shortcutKeyText = new pixi_js.Text(this.config.shortcutKeys.join('+'), {
fontSize: this.fontSize,
fill: this.fontColor,
});
this.addChild(this.shortcutKeyText);
return this.shortcutKeyText;
}
return undefined;
};
ContextMenuItem.prototype.initSubMenu = function () {
if (this.config.subMenu && this.config.subMenu.groups.length > 0) {
this.arrowText = new pixi_js.Text('>', {
fontSize: this.fontSize,
fill: this.fontColor,
});
this.addChild(this.arrowText);
this.subMenu = new ContextMenu(this.config.subMenu, this);
}
};
ContextMenuItem.prototype.updateBackground = function (width, height) {
this.box.clear();
var box = this.box;
var style = this.menu.style;
if (!style.itemStyle.hoverColor) {
throw new Error('未设置菜单项的hoverColor');
}
var hoverColor = style.itemStyle.hoverColor;
if (this.style && this.style.hoverColor) {
hoverColor = this.style.hoverColor;
}
box.beginFill(new pixi_js.Color(hoverColor));
if (style.borderRoundRadius > 0) {
box.drawRoundedRect(0, 0, width, height, style.borderRoundRadius);
}
else {
box.drawRect(0, 0, width, height);
}
box.endFill();
box.alpha = 0;
};
ContextMenuItem.prototype.updateBox = function (width, height) {
var _a;
this.removeAllListeners();
this.updateBackground(width, height);
(_a = this.nameText) === null || _a === void 0 ? void 0 : _a.position.set(this.paddingLeft, this.paddingTop);
if (this.shortcutKeyText) {
var skTextWidth = this.shortcutKeyBounds.width;
this.shortcutKeyText.position.set(width - skTextWidth - this.paddingRight, this.paddingTop);
}
if (this.arrowText) {
this.arrowText.position.set(width - this.paddingRight - this.gutter, this.paddingTop);
}
// 事件监听
this.hitArea = new pixi_js.Rectangle(0, 0, width, height);
this.registerEventHandler();
};
ContextMenuItem.prototype.update = function () {
if (this.config.visible === false) {
this.visible = false;
return;
}
this.visible = true;
this.nameText.text = this.config.name;
this.nameText.style.fontSize = this.fontSize;
this.nameText.style.fill = this.fontColor;
if (this.shortcutKeyText) {
if (this.config.shortcutKeys && this.config.shortcutKeys.length > 0) {
this.shortcutKeyText.text = this.config.shortcutKeys.join('+');
this.shortcutKeyText.style.fontSize = this.fontSize;
this.shortcutKeyText.style.fill = this.fontColor;
}
else {
this.shortcutKeyText.visible = false;
}
}
else {
this.initShortcutKeyText();
}
if (this.config.subMenu == undefined && this.subMenu) {
this.subMenu = undefined;
}
else if (this.config.subMenu && this.subMenu == undefined) {
this.initSubMenu();
}
if (this.subMenu) {
this.subMenu.update();
}
};
return ContextMenuItem;
}(pixi_js.Container));
var AppConsts = {
viewportname: '__viewport',
canvasname: '__jlcanvas',
AssistantAppendsName: '__assistantAppends',
// 辅助元素默认颜色
assistantElementColor: '#1976d2',
};
var CanvasData = /** @class */ (function () {
function CanvasData(properties) {
if (properties === void 0) { properties = {
width: 1920,
height: 1080,
backgroundColor: '#ffffff',
viewportTransform: GraphicTransform.default(),
}; }
this.width = properties.width;
this.height = properties.height;
this.backgroundColor = properties.backgroundColor;
this.viewportTransform = properties.viewportTransform;
}
CanvasData.prototype.copyFrom = function (properties) {
var sizeChange = false;
if (properties.width <= 0 || properties.height <= 0) {
console.error('画布宽度/高度不能小于等于0');
}
else {
var width = Math.floor(properties.width);
var height = Math.floor(properties.height);
if (this.width != width) {
this.width = width;
sizeChange = true;
}
if (this.height != height) {
this.height = height;
sizeChange = true;
}
}
this.backgroundColor = properties.backgroundColor;
this.viewportTransform = properties.viewportTransform;
return sizeChange;
};
CanvasData.prototype.clone = function () {
var cp = new CanvasData(this);
return cp;
};
return CanvasData;
}());
var JlCanvas = /** @class */ (function (_super) {
__extends(JlCanvas, _super);
function JlCanvas(scene, properties) {
if (properties === void 0) { properties = new CanvasData(); }
var _this = _super.call(this) || this;
_this.__JlCanvas = true;
_this.type = 'Canvas';
_this.bg = new pixi_js.Graphics(); // 背景
_this.scene = scene;
_this._properties = properties;
_this.eventMode = 'static';
_this.nonInteractiveContainer = new pixi_js.Container();
_this.nonInteractiveContainer.name = 'non-interactives';
_this.nonInteractiveContainer.eventMode = 'none';
_this.addChild(_this.bg);
_this.addChild(_this.nonInteractiveContainer);
_this.sortableChildren = true;
_this.assistantAppendContainer = new pixi_js.Container();
_this.assistantAppendContainer.eventMode = 'static';
_this.assistantAppendContainer.name = AppConsts.AssistantAppendsName;
_this.assistantAppendContainer.zIndex = 999;
_this.assistantAppendContainer.sortableChildren = true;
_this.addChild(_this.assistantAppendContainer);
_this.repaint();
return _this;
}
/**
* 图形重绘(数据/状态变化时触发)
*/
JlCanvas.prototype.repaint = function () {
this.doRepaint();
};
Object.defineProperty(JlCanvas.prototype, "width", {
get: function () {
return this._properties.width;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JlCanvas.prototype, "height", {
get: function () {
return this._properties.height;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JlCanvas.prototype, "backgroundColor", {
get: function () {
return this._properties.backgroundColor;
},
enumerable: false,
configurable: true
});
JlCanvas.prototype.doRepaint = function () {
this.bg.clear();
this.bg
.beginFill(new pixi_js.Color(this.backgroundColor))
.drawRect(0, 0, this._properties.width, this._properties.height)
.endFill();
};
Object.defineProperty(JlCanvas.prototype, "properties", {
get: function () {
return this._properties;
},
enumerable: false,
configurable: true
});
JlCanvas.prototype.saveData = function () {
var vp = this.getViewport();
this.properties.viewportTransform = vp.saveTransform();
return this.properties.clone();
};
JlCanvas.prototype.update = function (properties) {
// 更新画布
var old = this.properties.clone();
this._properties.copyFrom(properties);
this.repaint();
var vp = this.getViewport();
vp.loadTransform(properties.viewportTransform);
this.emit('dataupdate', this.properties, old);
};
JlCanvas.prototype.addChild = function () {
var _this = this;
var children = [];
for (var _i = 0; _i < arguments.length; _i++) {
children[_i] = arguments[_i];
}
var rt = _super.prototype.addChild.apply(this, children);
children.forEach(function (g) {
g.onAddToCanvas(_this);
recursiveChildren(g, function (child) { return child.onAddToCanvas(_this); });
});
return rt;
};
JlCanvas.prototype.removeChild = function () {
var _this = this;
var children = [];
for (var _i = 0; _i < arguments.length; _i++) {
children[_i] = arguments[_i];
}
children.forEach(function (g) {
g.onRemoveFromCanvas(_this);
recursiveChildren(g, function (child) {
return child.onRemoveFromCanvas(_this);
});
});
return _super.prototype.removeChild.apply(this, children);
};
/**
* 添加无交互Child
*/
JlCanvas.prototype.addNonInteractiveChild = function () {
var _a;
var _this = this;
var obj = [];
for (var _i = 0; _i < arguments.length; _i++) {
obj[_i] = arguments[_i];
}
(_a = this.nonInteractiveContainer).addChild.apply(_a, obj);
obj.forEach(function (g) {
g.onAddToCanvas(_this);
recursiveChildren(g, function (child) { return child.onAddToCanvas(_this); });
});
};
JlCanvas.prototype.removeGraphic = function () {
var _a;
var _this = this;
var obj = [];
for (var _i = 0; _i < arguments.length; _i++) {
obj[_i] = arguments[_i];
}
obj.forEach(function (g) {
g.onRemoveFromCanvas(_this);
recursiveChildren(g, function (child) {
return child.onRemoveFromCanvas(_this);
});
});
this.removeChild.apply(this, obj);
(_a = this.nonInteractiveContainer).removeChild.apply(_a, obj);
};
/**
* 移除无交互Child
*/
JlCanvas.prototype.removeNonInteractiveChild = function () {
var _a;
var _this = this;
var obj = [];
for (var _i = 0; _i < arguments.length; _i++) {
obj[_i] = arguments[_i];
}
obj.forEach(function (g) {
g.onRemoveFromCanvas(_this);
recursiveChildren(g, function (child) {
return child.onRemoveFromCanvas(_this);
});
});
(_a = this.nonInteractiveContainer).removeChild.apply(_a, obj);
};
JlCanvas.prototype.addAssistantAppends = function () {
var _a;
var _this = this;
var appends = [];
for (var _i = 0; _i < arguments.length; _i++) {
appends[_i] = arguments[_i];
}
(_a = this.assistantAppendContainer).addChild.apply(_a, appends);
appends.forEach(function (g) {
g.onAddToCanvas(_this);
recursiveChildren(g, function (child) { return child.onAddToCanvas(_this); });
});
};
JlCanvas.prototype.removeAssistantAppends = function () {
var _a;
var _this = this;
var appends = [];
for (var _i = 0; _i < arguments.length; _i++) {
appends[_i] = arguments[_i];
}
appends.forEach(function (g) {
g.onRemoveFromCanvas(_this);
recursiveChildren(g, function (child) { return child.onAddToCanvas(_this); });
});
(_a = this.assistantAppendContainer).removeChild.apply(_a, appends);
};
/**
* 暂停所有可交互对象
*/
JlCanvas.prototype.pauseInteractiveChildren = function () {
this.interactiveChildren = false;
};
/**
* 恢复所有可交互对象
*/
JlCanvas.prototype.resumeInteractiveChildren = function () {
this.interactiveChildren = true;
};
return JlCanvas;
}(pixi_js.Container));
var GraphicSceneBase = /** @class */ (function (_super) {
__extends(GraphicSceneBase, _super);
function GraphicSceneBase(options) {
var _this = _super.call(this) || this;
_this._loaded = false; // 是否已经加载
_this.graphicTemplateMap = new Map(); // 图形对象模板
_this.interactionPluginMap = new Map(); // 交互插件
_this.graphicStore = new GraphicStore();
_this._options = options;
// 创建pixi渲染app
_this.pixi = new pixi_js.Application({
antialias: true,
});
// 创建画布
_this.canvas = new JlCanvas(_this);
_this.canvas.name = AppConsts.canvasname;
// 创建相机
_this.viewport = new pixiViewport.Viewport({
screenWidth: window.innerWidth,
screenHeight: window.innerHeight,
worldWidth: _this.canvas._properties.width,
worldHeight: _this.canvas._properties.height,
passiveWheel: true,
events: _this.pixi.renderer.events,
disableOnContextMenu: true,
});
// 设置视口操作方式
_this.viewport
.wheel({
percent: 1,
})
.pinch()
.clampZoom({
minScale: 0.1,
maxScale: 8,
})
.clamp({
direction: 'all',
});
_this.viewport.name = AppConsts.viewportname;
_this.viewport.interactiveChildren = true;
// 添加视口到渲染器舞台
_this.pixi.stage.addChild(_this.viewport);
// 将画布置于视口
_this.viewport.addChild(_this.canvas);
// 监听并通知缩放变化事件
_this.viewport.on('zoomed-end', function () {
_this.emit('viewport-scaled', _this.viewport);
});
_this.graphicCopyPlugin = new GraphicCopyPlugin(_this);
// 添加通用交互插件
CommonMouseTool.new(_this).resume();
// drag插件
DragPlugin.new(_this).resume();
// 视口移动插件
ViewportMovePlugin.new(_this);
// 图形变换插件
GraphicTransformPlugin.new(_this).resume();
// 动画管理
_this.animationManager = new AnimationManager(_this);
_this.menuPlugin = new ContextMenuPlugin(_this);
_this.wsMsgBroker = new AppWsMsgBroker(_this);
_this.debounceEmitFunc = debounce(_this.doEmitAppGraphicSelected, 50);
_this.on('graphicselectedchange', function () {
_this.debounceEmitFunc(_this);
});
// 发布选项更新事件
_this.emit('options-update', _this._options);
return _this;
}
Object.defineProperty(GraphicSceneBase.prototype, "appOptions", {
get: function () {
return this._options;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GraphicSceneBase.prototype, "dom", {
get: function () {
return this._dom;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GraphicSceneBase.prototype, "queryStore", {
get: function () {
return this.graphicStore;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GraphicSceneBase.prototype, "selectedGraphics", {
get: function () {
return this.queryStore.getAllGraphics().filter(function (g) { return g.selected; });
},
enumerable: false,
configurable: true
});
GraphicSceneBase.prototype.load = function () {
return __awaiter(this, void 0, void 0, function () {
var storage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this._options.dataLoader) return [3 /*break*/, 3];
return [4 /*yield*/, this._options.dataLoader()];
case 1:
storage = _a.sent();
if (storage.canvasProperty) {
this.canvas.update(storage.canvasProperty);
}
if (!storage.datas) return [3 /*break*/, 3];
return [4 /*yield*/, this.loadGraphic(storage.datas)];
case 2:
_a.sent();
_a.label = 3;
case 3:
this._loaded = true;
return [2 /*return*/];
}
});
});
};
/**
* 重新加载数据
*/
GraphicSceneBase.prototype.reload = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!!this._loaded) return [3 /*break*/, 2];
this.graphicStore.clear();
return [4 /*yield*/, this.load()];
case 1:
_a.sent();
return [3 /*break*/, 3];
case 2:
console.debug('场景已经加载过数据,不重新加载', this);
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
GraphicSceneBase.prototype.forceReload = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
console.debug('场景强制重新加载数据', this);
this.graphicStore.clear();
return [4 /*yield*/, this.load()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
/**
* 更新选项
* @param options
*/
GraphicSceneBase.prototype.setOptions = function (options) {
// console.log('更新选项', options);
if (this._options) {
this._options = Object.assign(this._options, options);
}
else {
this._options = options;
}
this.emit('options-update', options);
};
GraphicSceneBase.prototype.toCanvasCoordinates = function (p) {
return this.viewport.toWorld(p);
};
/**
* 注册菜单
* @param menu
*/
GraphicSceneBase.prototype.registerMenu = function (menu) {
this.menuPlugin.registerMenu(menu);
};
/**
* 注册图形对象模板
* @param graphicTemplates
*/
GraphicSceneBase.prototype.registerGraphicTemplates = function () {
var _this = this;
var graphicTemplates = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphicTemplates[_i] = arguments[_i];
}
graphicTemplates.forEach(function (graphicTemplate) {
_this.graphicTemplateMap.set(graphicTemplate.type, graphicTemplate);
});
};
GraphicSceneBase.prototype.getGraphicTemplatesByType = function (type) {
var template = this.graphicTemplateMap.get(type);
if (!template) {
throw new Error("\u4E0D\u5B58\u5728type=".concat(type, "\u7684\u56FE\u5F62\u5BF9\u8C61\u6A21\u677F"));
}
return template;
};
GraphicSceneBase.prototype.updateViewport = function (domWidth, domHeight) {
var screenWidth = this.viewport.screenWidth;
var screenHeight = this.viewport.screenHeight;
if (domWidth) {
screenWidth = domWidth;
}
if (domHeight) {
screenHeight = domHeight;
}
var worldWidth = this.canvas._properties.width;
var worldHeight = this.canvas._properties.height;
this.pixi.resize();
this.viewport.resize(screenWidth, screenHeight, worldWidth, worldHeight);
if (this.viewport.OOB().right) {
this.viewport.right = this.viewport.right + 1;
}
else if (this.viewport.OOB().left) {
this.viewport.left = this.viewport.left - 1;
}
else if (this.viewport.OOB().top) {
this.viewport.top = this.viewport.top - 1;
}
else if (this.viewport.OOB().bottom) {
this.viewport.bottom = this.viewport.bottom + 1;
}
};
/**
* 暂停
*/
GraphicSceneBase.prototype.pause = function () {
// 暂停动画
this.animationManager.pause();
// 取消消息订阅
this.wsMsgBroker.unsubscribeAll();
// 关闭所有上下文菜单
this.menuPlugin.closeAll();
};
/**
* 恢复
*/
GraphicSceneBase.prototype.resume = function () {
// 恢复动画
this.animationManager.resume();
// 重新订阅
this.wsMsgBroker.resubscribeAll();
};
GraphicSceneBase.prototype.bindDom = function (dom) {
var _this = this;
this._dom = dom;
this.pixi.resizeTo = dom;
dom.appendChild(this.pixi.view);
this._viewportResizer = setInterval(function () {
// console.log(
// 'dom resize ',
// dom.style.width,
// dom.style.height,
// dom.clientWidth,
// dom.clientHeight
// );
_this.updateViewport(dom.clientWidth, dom.clientHeight);
}, 1000);
// 恢复
this.resume();
};
GraphicSceneBase.prototype.unbindDom = function () {
if (this._dom) {
clearInterval(this._viewportResizer);
this._dom.removeChild(this.pixi.view);
this._dom = undefined;
// 暂停
this.pause();
}
};
/**
* 加载图形,GraphicApp默认添加到无交互容器,DrawApp默认添加到交互容器,如需定制,提供选项配置
* @param protos
* @param options 添加到可交互/不可交互容器选项配置
*/
GraphicSceneBase.prototype.loadGraphic = function (protos) {
var _a;
return __awaiter(this, void 0, void 0, function () {
var _i, _b, item, max;
var _this = this;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_i = 0, _b = this.graphicTemplateMap;
_c.label = 1;
case 1:
if (!(_i < _b.length)) return [3 /*break*/, 4];
item = _b[_i];
return [4 /*yield*/, item[1].loadAssets()];
case 2:
_c.sent();
_c.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
// console.log('开始加载proto数据', protos);
// 加载数据到图形存储
protos.forEach(function (proto) {
var template = _this.getGraphicTemplatesByType(proto.graphicType);
var g = template.new();
g.loadData(proto);
_this.addGraphics(g);
});
// 加载数据关系
this.queryStore.getAllGraphics().forEach(function (g) { return g.loadRelations(); });
max = (_a = this.queryStore
.getAllGraphics()
.filter(function (g) { return !isNaN(parseInt(g.id)); })
.map(function (g) { return parseInt(g.id); })
.sort(function (a, b) { return a - b; })
.pop()) !== null && _a !== void 0 ? _a : 0;
// console.log('最大值', max)
GraphicIdGenerator.initSerial(max);
// 数据加载完成后
this.emit('postdataloaded');
// 加载完成通知
this.emit('loadfinish');
return [2 /*return*/];
}
});
});
};
/**
* 添加图形前处理
* @param graphic
*/
GraphicSceneBase.prototype.beforeGraphicStore = function (graphic) {
var interactiveGraphicTypeIncludes = this._options.interactiveGraphicTypeIncludes || [];
var interactiveGraphicTypeExcludes = this._options.interactiveGraphicTypeExcludes || [];
// 默认无交互
graphic.eventMode = 'auto';
if (interactiveGraphicTypeIncludes.findIndex(function (type) { return type === graphic.type; }) >= 0) {
graphic.eventMode = 'static';
}
else if (interactiveGraphicTypeExcludes.findIndex(function (type) { return type === graphic.type; }) < 0) {
graphic.eventMode = 'static';
}
};
/**
* 执行添加图形对象
* @param graphic
*/
GraphicSceneBase.prototype.doAddGraphics = function (graphic) {
var _this = this;
this.beforeGraphicStore(graphic);
if (this.graphicStore.storeGraphics(graphic)) {
// cullable,默认设置剪裁,如果图形包围框不在屏幕内,则不渲染,增加效率用
if (!this._options || this._options.cullable !== false) {
graphic.cullable = true;
}
if (graphic.eventMode == 'static' || graphic.eventMode == 'dynamic') {
// 添加为可交互
// console.log(`type=${graphic.type}的图形添加到交互容器`);
this.canvas.addChild(graphic);
}
else {
// 添加到不可交互容器
// console.log(`type=${graphic.type}的图形添加到无交互容器`);
this.canvas.addNonInteractiveChild(graphic);
}
graphic.repaint();
this.emit('graphicstored', graphic);
graphic.on('childselected', function (child) {
_this.emit('graphicchildselectedchange', child, true);
});
graphic.on('childunselected', function (child) {
_this.emit('graphicchildselectedchange', child, false);
});
}
};
GraphicSceneBase.prototype.doDeleteGraphics = function (graphic) {
// 从store中删除
var g = this.graphicStore.deleteGraphics(graphic);
if (g) {
// 清除选中
g.updateSelected(false);
// 从画布移除
this.canvas.removeGraphic(g);
// 对象删除处理
g.onDelete();
this.emit('graphicdeleted', g);
}
};
/**
* 存储图形
* @param graphics 图形对象
*/
GraphicSceneBase.prototype.addGraphics = function () {
var _this = this;
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
graphics.forEach(function (g) { return _this.doAddGraphics(g); });
};
/**
* 删除图形
* @param graphics 图形对象
*/
GraphicSceneBase.prototype.deleteGraphics = function () {
var _this = this;
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
var dels = graphics.filter(function (g) {
var _a;
if (((_a = _this._options) === null || _a === void 0 ? void 0 : _a.isSupportDeletion) == undefined ||
_this._options.isSupportDeletion(g)) {
_this.doDeleteGraphics(g);
return true;
}
console.debug("type=".concat(g.type, ",id=").concat(g.id, "\u7684\u56FE\u5F62\u4E0D\u652F\u6301\u5220\u9664"));
return false;
});
return dels;
};
/**
* 检测并构建关系
*/
GraphicSceneBase.prototype.detectRelations = function () {
this.queryStore.getAllGraphics().forEach(function (g) { return g.buildRelation(); });
};
/**
* 全选
*/
GraphicSceneBase.prototype.selectAllGraphics = function (filter) {
if (filter == undefined) {
filter = function (g) { return g.visible; };
}
this.updateSelected.apply(this, this.queryStore.getAllGraphics().filter(filter));
};
/**
* 更新选中
*/
GraphicSceneBase.prototype.updateSelected = function () {
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
this.selectedGraphics.forEach(function (graphic) {
if (graphics.findIndex(function (g) { return g.id === graphic.id; }) >= 0) {
return;
}
if (graphic.selected) {
graphic.updateSelected(false);
}
});
graphics.forEach(function (graphic) {
graphic.updateSelected(true);
});
};
GraphicSceneBase.prototype.doEmitAppGraphicSelected = function () {
// 场景发布图形选中
this.emit('graphicselected', this.selectedGraphics);
// this.app.emit('graphicselected', this.selectedGraphics);
};
/**
* 更新画布
* @param param
*/
GraphicSceneBase.prototype.updateCanvas = function (param) {
this.canvas.update(param);
};
/**
* 使图形居中显示(所有图形的外包围盒)
*/
GraphicSceneBase.prototype.makeGraphicCenterShow = function () {
var group = [];
for (var _i = 0; _i < arguments.length; _i++) {
group[_i] = arguments[_i];
}
if (group.length > 0) {
var bounds0 = group[0].getBounds();
var lx = bounds0.x;
var ly = bounds0.y;
var rx = bounds0.x + bounds0.width;
var ry = bounds0.y + bounds0.height;
if (group.length > 1) {
for (var i = 1; i < group.length; i++) {
var g = group[i];
var bound = g.getBounds();
if (bound.x < lx) {
lx = bound.x;
}
if (bound.y < ly) {
ly = bound.y;
}
var brx = bound.x + bound.width;
if (brx > rx) {
rx = brx;
}
var bry = bound.y + bound.height;
if (bry > ry) {
ry = bry;
}
}
}
var _a = getRectangleCenter(new pixi_js.Rectangle(lx, ly, rx - lx, ry - ly)), x = _a.x, y = _a.y;
var p = this.viewport.toWorld(x, y);
this.viewport.moveCenter(p.x, p.y);
}
};
/**
* 注册交互插件,会替换旧的
*/
GraphicSceneBase.prototype.registerInteractionPlugin = function () {
var _this = this;
var plugins = [];
for (var _i = 0; _i < arguments.length; _i++) {
plugins[_i] = arguments[_i];
}
plugins.forEach(function (plugin) {
var old = _this.interactionPluginMap.get(plugin.name);
if (old) {
console.warn("\u5DF2\u7ECF\u5B58\u5728name=".concat(plugin.name, "\u7684\u4EA4\u4E92\u63D2\u4EF6,\u5FFD\u7565\u6B64\u63D2\u4EF6\u6CE8\u518C!"));
return;
}
_this.interactionPluginMap.set(plugin.name, plugin);
});
};
/**
* 根据名称获取交互插件
* @param name
* @returns
*/
GraphicSceneBase.prototype.interactionPlugin = function (name) {
var plugin = this.interactionPluginMap.get(name);
if (!plugin) {
throw new Error("\u672A\u627E\u5230name=".concat(name, "\u7684\u4EA4\u4E92\u63D2\u4EF6"));
}
return plugin;
};
/**
* 停止应用交互插件
*/
GraphicSceneBase.prototype.pauseAppInteractionPlugins = function () {
var _this = this;
this.interactionPluginMap.forEach(function (plugin) {
if (plugin.isActive() && plugin._type === exports.InteractionPluginType.App) {
_this.doPauseInteractionPlugin(plugin);
}
});
};
GraphicSceneBase.prototype.doPauseInteractionPlugin = function (plugin) {
if (plugin && plugin.isActive()) {
plugin.pause();
this.emit('interaction-plugin-pause', plugin);
}
};
/**
* 移除交互插件
*/
GraphicSceneBase.prototype.removeInteractionPlugin = function (plugin) {
this.interactionPluginMap.delete(plugin.name);
};
GraphicSceneBase.prototype.checkWsMsgCli = function () {
if (!WsMsgCli.isInitiated()) {
throw new Error('订阅消息需先启动消息代理, 执行app.enableWebsocket()');
}
};
/**
* 订阅websocket消息
*/
GraphicSceneBase.prototype.subscribe = function (sub) {
this.checkWsMsgCli();
this.wsMsgBroker.subscribe(sub);
};
/**
* 取消websocket订阅
*/
GraphicSceneBase.prototype.unsubscribe = function (destination) {
this.checkWsMsgCli();
this.wsMsgBroker.unsbuscribe(destination);
};
/**
* 处理图形状态
* @param graphicStates
*/
GraphicSceneBase.prototype.handleGraphicStates = function (graphicStates, queryer, createOnNotFound) {
var _this = this;
graphicStates.forEach(function (state) {
var g;
if (queryer) {
g = queryer(state, _this.queryStore);
}
else {
g = _this.queryStore.queryByCodeAndType(state.code, state.graphicType);
}
try {
if (!g) {
// 未找到图形对象
if (!state.remove &&
createOnNotFound &&
createOnNotFound.graphicTypes &&
createOnNotFound.graphicTypes.findIndex(function (v) { return v === state.graphicType; }) >= 0) {
var template = _this.getGraphicTemplatesByType(state.graphicType);
var g_1 = template.new();
g_1.loadState(state);
_this.addGraphics(g_1);
}
}
else {
// 找到
if (state.remove) {
_this.deleteGraphics(g);
g.destroy({ children: true });
}
else if (g.updateStates(state)) {
g.repaint();
}
}
}
catch (err) {
console.error('图形状态处理异常', g, state, err);
// throw err;
}
});
};
/**
* 销毁
*/
GraphicSceneBase.prototype.destroy = function () {
console.debug('场景销毁', this);
this.unbindDom();
if (this.wsMsgBroker) {
this.wsMsgBroker.close();
}
this.interactionPluginMap.forEach(function (plugin) {
plugin.pause();
});
this.animationManager.destroy();
this.canvas.destroy(true);
this.viewport.destroy();
this.pixi.destroy(true, true);
};
return GraphicSceneBase;
}(EventEmitter));
/**
* 图形app基类
*/
var GraphicApp = /** @class */ (function (_super) {
__extends(GraphicApp, _super);
function GraphicApp(options) {
var _this = _super.call(this, options) || this;
/**
* 场景列表
*/
_this.scenes = new Map();
// console.log('创建图形App')
_this.opRecord = new OperationRecord();
// 绑定键盘监听
_this.keyboardPlugin = new JlGraphicAppKeyboardPlugin(_this);
return _this;
}
Object.defineProperty(GraphicApp.prototype, "app", {
get: function () {
return this;
},
enumerable: false,
configurable: true
});
GraphicApp.prototype.setOptions = function (options) {
// console.log('更新选项', options);
if (options.maxOperationRecords && options.maxOperationRecords > 0) {
this.opRecord.setMaxLen(options.maxOperationRecords);
}
_super.prototype.setOptions.call(this, options);
};
GraphicApp.prototype.addGraphicAndRecord = function () {
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
this.addGraphics.apply(this, graphics);
this.opRecord.record(new GraphicCreateOperation(this, graphics));
};
GraphicApp.prototype.deleteGraphicAndRecord = function () {
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
this.deleteGraphics.apply(this, graphics);
this.opRecord.record(new GraphicDeleteOperation(this, graphics));
};
/**
* 实例化一个场景
* @param code 场景标识
* @returns
*/
GraphicApp.prototype.initScene = function (code, options) {
var scene = this.scenes.get(code);
if (!scene) {
scene = new JlScene(this, code, options);
this.scenes.set(code, scene);
}
return scene;
};
/**
* 获取场景
* @param code
* @returns
*/
GraphicApp.prototype.getScene = function (code) {
var scene = this.scenes.get(code);
if (!scene) {
throw new Error("\u4E0D\u5B58\u5728code=".concat(code, "\u7684\u573A\u666F"));
}
return scene;
};
GraphicApp.prototype.switchScene = function (code, dom) {
var scene = this.getScene(code);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (var _i = 0, _a = this.scenes; _i < _a.length; _i++) {
var _b = _a[_i]; _b[0]; var pre = _b[1];
if (pre.dom === dom) {
pre.unbindDom();
break;
}
}
scene.bindDom(dom);
};
GraphicApp.prototype.removeScene = function (code) {
var scene = this.scenes.get(code);
if (scene) {
this.scenes.delete(code);
scene.destroy();
}
};
/**
* 启动websocket消息客户端
*/
GraphicApp.prototype.enableWsMassaging = function (options) {
WsMsgCli.new(options);
this.wsMsgBroker = new AppWsMsgBroker(this);
};
/**
* 添加键盘监听器,如果是相同的按键,新注册的会覆盖旧的,当移除新的时,旧的自动生效
* @param keyListeners
*/
GraphicApp.prototype.addKeyboardListener = function () {
var _this = this;
var keyListeners = [];
for (var _i = 0; _i < arguments.length; _i++) {
keyListeners[_i] = arguments[_i];
}
keyListeners.forEach(function (keyListener) {
return _this.keyboardPlugin.addKeyListener(keyListener);
});
};
/**
* 移除键盘监听器
* @param keyListeners
*/
GraphicApp.prototype.removeKeyboardListener = function () {
var _this = this;
var keyListeners = [];
for (var _i = 0; _i < arguments.length; _i++) {
keyListeners[_i] = arguments[_i];
}
keyListeners.forEach(function (keyListener) {
return _this.keyboardPlugin.removeKeyListener(keyListener);
});
};
/**
* 销毁
*/
GraphicApp.prototype.destroy = function () {
console.debug('图形应用销毁', this);
this.emit('destroy', this);
_super.prototype.destroy.call(this);
this.scenes.forEach(function (scene) { return scene.destroy(); });
};
return GraphicApp;
}(GraphicSceneBase));
/**
* 场景
*/
var JlScene = /** @class */ (function (_super) {
__extends(JlScene, _super);
function JlScene(app, code, options) {
var _this = _super.call(this, options) || this;
_this.code = code;
_this.app = app;
return _this;
}
return JlScene;
}(GraphicSceneBase));
/**
* 图形绘制助手
*/
var GraphicDrawAssistant = /** @class */ (function (_super) {
__extends(GraphicDrawAssistant, _super);
function GraphicDrawAssistant(graphicApp, graphicTemplate, icon, description) {
var _this = _super.call(this, graphicTemplate.type, graphicApp) || this;
_this.__GraphicDrawAssistant = true;
_this.container = new pixi_js.Container();
_this.escListener = new KeyListener({
value: 'Escape',
onRelease: function () {
_this.onEsc();
},
});
_this.app = graphicApp;
_this.type = graphicTemplate.type;
_this.graphicTemplate = graphicTemplate;
_this.icon = icon;
_this.description = description;
_this.app.registerGraphicTemplates(_this.graphicTemplate);
return _this;
}
GraphicDrawAssistant.prototype.onEsc = function () {
this.createAndStore(true);
};
Object.defineProperty(GraphicDrawAssistant.prototype, "canvas", {
get: function () {
return this.app.canvas;
},
enumerable: false,
configurable: true
});
GraphicDrawAssistant.prototype.bind = function () {
this.app.drawing = true;
var canvas = this.canvas;
canvas.addChild(this.container);
canvas.on('mousedown', this.onLeftDown, this);
canvas.on('mousemove', this.onMouseMove, this);
canvas.on('mouseup', this.onLeftUp, this);
canvas.on('rightdown', this.onRightDown, this);
canvas.on('rightup', this.onRightUp, this);
canvas.on('_rightclick', this.onRightClick, this);
this.app.viewport.wheel({
percent: 0.01,
});
this.app.addKeyboardListener(this.escListener);
this.app.viewport.drag({
mouseButtons: 'right',
});
};
GraphicDrawAssistant.prototype.unbind = function () {
var _a;
this.clearCache();
var canvas = this.canvas;
if ((_a = this.container) === null || _a === void 0 ? void 0 : _a.parent) {
canvas.removeChild(this.container);
}
canvas.off('mousedown', this.onLeftDown, this);
canvas.off('mousemove', this.onMouseMove, this);
canvas.off('mouseup', this.onLeftUp, this);
canvas.off('rightdown', this.onRightDown, this);
canvas.off('rightup', this.onRightUp, this);
this.app.viewport.plugins.remove('wheel');
this.app.removeKeyboardListener(this.escListener);
this.app.viewport.plugins.remove('drag');
this.app.drawing = false;
};
GraphicDrawAssistant.prototype.onLeftDown = function (e) { };
GraphicDrawAssistant.prototype.onMouseMove = function (e) {
this.redraw(this.toCanvasCoordinates(e.global));
};
GraphicDrawAssistant.prototype.onLeftUp = function (e) { };
GraphicDrawAssistant.prototype.onRightDown = function (e) { };
GraphicDrawAssistant.prototype.onRightUp = function (e) { };
GraphicDrawAssistant.prototype.onRightClick = function (e) {
this.finish();
};
/**
* 获取下一个id
*/
GraphicDrawAssistant.prototype.nextId = function () {
return GraphicIdGenerator.next();
};
GraphicDrawAssistant.prototype.clearCache = function () { };
GraphicDrawAssistant.prototype.toCanvasCoordinates = function (p) {
return this.app.toCanvasCoordinates(p);
};
/**
* 保存创建的图形对象
*/
GraphicDrawAssistant.prototype.storeGraphic = function () {
var _a;
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
(_a = this.app).addGraphicAndRecord.apply(_a, graphics);
};
/**
* 创建并添加到图形App
*/
GraphicDrawAssistant.prototype.createAndStore = function (finish) {
var data = this.graphicTemplate.datas;
data.id = this.nextId();
data.graphicType = this.graphicTemplate.type;
if (!this.prepareData(data)) {
if (finish) {
this.finish();
}
return null;
}
var template = this.graphicTemplate;
var g = template.new();
g.loadData(data);
this.storeGraphic(g);
if (finish) {
this.finish(g);
}
return g;
};
/**
* 绘制完成
*/
GraphicDrawAssistant.prototype.finish = function () {
var _a;
var graphics = [];
for (var _i = 0; _i < arguments.length; _i++) {
graphics[_i] = arguments[_i];
}
this.clearCache();
this.app.interactionPlugin(CommonMouseTool.Name).resume();
(_a = this.app).updateSelected.apply(_a, graphics);
};
return GraphicDrawAssistant;
}(AppInteractionPlugin));
/**
* 绘制应用
*/
var JlDrawApp = /** @class */ (function (_super) {
__extends(JlDrawApp, _super);
function JlDrawApp(options) {
var _this = _super.call(this, options) || this;
_this.font = pixi_js.BitmapFont.from('coordinates', {
fontFamily: 'Roboto',
fontSize: 16,
fill: '#ff2700',
}, { chars: ['画布坐标:() 屏幕坐标:() 缩放:.,', ['0', '9']] });
_this.coordinates = new pixi_js.BitmapText('画布坐标: (0, 0) 屏幕坐标:(0, 0)', {
fontName: 'coordinates',
});
_this.scaleText = new pixi_js.BitmapText('缩放: 1', {
fontName: 'coordinates',
});
_this.drawAssistants = [];
_this._drawing = false;
_this.formData = undefined;
_this.appendDrawStatesDisplay();
// 拖拽操作记录
_this.appOperationRecord();
// 绑定通用键盘操作
_this.bindKeyboardOperation();
_this.formDataSyncListen();
_this.debouncedFormDataUpdator = debounce(_this.doFormDataUpdate, 60);
return _this;
}
Object.defineProperty(JlDrawApp.prototype, "drawing", {
get: function () {
return this._drawing;
},
set: function (value) {
this._drawing = value;
},
enumerable: false,
configurable: true
});
JlDrawApp.prototype.setOptions = function (options) {
_super.prototype.setOptions.call(this, options);
};
JlDrawApp.prototype.registerInteractionPlugin = function () {
var _this = this;
var plugins = [];
for (var _i = 0; _i < arguments.length; _i++) {
plugins[_i] = arguments[_i];
}
plugins.forEach(function (plugin) {
if (plugin instanceof GraphicDrawAssistant) {
_this.drawAssistants.push(plugin);
}
_super.prototype.registerInteractionPlugin.call(_this, plugin);
});
};
JlDrawApp.prototype.getDrawAssistant = function (graphicType) {
var sda = this.drawAssistants
.filter(function (da) { return da.type === graphicType; })
.pop();
if (!sda) {
throw new Error("\u672A\u627E\u5230\u56FE\u5F62\u7ED8\u5236\u52A9\u624B: ".concat(graphicType));
}
return sda;
};
JlDrawApp.prototype.appOperationRecord = function () {
var _this = this;
var dragStartDatas = [];
this.on('drag_op_start', function (e) {
// 图形拖拽,记录初始数据
if (!e.target.isCanvas()) {
dragStartDatas = _this.selectedGraphics.map(function (g) { return g.saveData(); });
}
});
// 图形拖拽操作监听
this.on('drag_op_end', function () {
// 图形拖拽,记录操作
if (dragStartDatas.length > 0) {
var newData = _this.selectedGraphics.map(function (g) { return g.saveData(); });
_this.opRecord.record(new GraphicDataUpdateOperation(_this, _this.selectedGraphics, dragStartDatas, newData));
dragStartDatas = [];
}
});
// 菜单操作
var preMenuHandleDatas = [];
this.on('pre-menu-handle', function (menu) {
if (menu.name === '撤销' || menu.name === '重做') {
return;
}
preMenuHandleDatas = _this.selectedGraphics.map(function (g) { return g.saveData(); });
});
this.on('post-menu-handle', function () {
if (preMenuHandleDatas.length > 0) {
var newData = _this.selectedGraphics.map(function (g) { return g.saveData(); });
_this.opRecord.record(new GraphicDataUpdateOperation(_this, _this.selectedGraphics, preMenuHandleDatas, newData));
preMenuHandleDatas = [];
}
});
};
/**
* 绘制状态信息显示
*/
JlDrawApp.prototype.appendDrawStatesDisplay = function () {
var _this = this;
this.pixi.stage.addChild(this.coordinates);
this.pixi.stage.addChild(this.scaleText);
var bound = this.coordinates.getLocalBounds();
this.scaleText.position.set(bound.width + 10, 0);
this.canvas.on('mousemove', function (e) {
if (e.target) {
var _a = _this.toCanvasCoordinates(e.global), x = _a.x, y = _a.y;
var cpTxt = "(".concat(x, ", ").concat(y, ")");
var tp = e.global;
var tpTxt = "(".concat(tp.x, ", ").concat(tp.y, ")");
_this.coordinates.text = "\u753B\u5E03\u5750\u6807:".concat(cpTxt, " \u5C4F\u5E55\u5750\u6807:").concat(tpTxt);
var bound_1 = _this.coordinates.getLocalBounds();
_this.scaleText.position.set(bound_1.width + 10, 0);
}
});
this.viewport.on('zoomed-end', function () {
_this.scaleText.text = "\u7F29\u653E: ".concat(_this.viewport.scaled);
});
};
JlDrawApp.prototype.bindKeyboardOperation = function () {
var _this = this;
this.addKeyboardListener(
// Ctrl + A
new KeyListener({
value: 'KeyA',
combinations: [exports.CombinationKey.Ctrl],
onPress: function (e, app) {
if (e.ctrlKey) {
app.selectAllGraphics();
}
},
}));
// 复制功能
this.addKeyboardListener(new KeyListener({
value: 'KeyD',
combinations: [exports.CombinationKey.Shift],
onPress: function (e, app) {
_this.graphicCopyPlugin.init();
},
}));
this.addKeyboardListener(new KeyListener({
// Ctrl + Z
value: 'KeyZ',
global: true,
combinations: [exports.CombinationKey.Ctrl],
onPress: function (e, app) {
app.opRecord.undo();
},
}));
this.addKeyboardListener(new KeyListener({
// Ctrl + Shift + Z
value: 'KeyZ',
global: true,
combinations: [exports.CombinationKey.Ctrl, exports.CombinationKey.Shift],
onPress: function (e, app) {
app.opRecord.redo();
},
}));
this.addKeyboardListener(new KeyListener({
value: 'Delete',
onPress: function (e, app) {
app.deleteGraphicAndRecord.apply(app, app.selectedGraphics);
},
}));
this.addKeyboardListener(new KeyListener({
value: 'ArrowUp',
pressTriggerAsOriginalEvent: true,
onPress: function (e, app) {
updateGraphicPositionOnKeyboardEvent(app, UP);
},
onRelease: function (e, app) {
recordGraphicMoveOperation(app);
},
}));
this.addKeyboardListener(new KeyListener({
value: 'ArrowDown',
pressTriggerAsOriginalEvent: true,
onPress: function (e, app) {
updateGraphicPositionOnKeyboardEvent(app, DOWN);
},
onRelease: function (e, app) {
recordGraphicMoveOperation(app);
},
}));
this.addKeyboardListener(new KeyListener({
value: 'ArrowLeft',
pressTriggerAsOriginalEvent: true,
onPress: function (e, app) {
updateGraphicPositionOnKeyboardEvent(app, LEFT);
},
onRelease: function (e, app) {
recordGraphicMoveOperation(app);
},
}));
this.addKeyboardListener(new KeyListener({
value: 'ArrowRight',
pressTriggerAsOriginalEvent: true,
onPress: function (e, app) {
updateGraphicPositionOnKeyboardEvent(app, RIGHT);
},
onRelease: function (e, app) {
recordGraphicMoveOperation(app);
},
}));
};
/**
* 图形对象存储处理,默认添加图形交互
* @param graphic
*/
JlDrawApp.prototype.beforeGraphicStore = function (graphic) {
var _this = this;
graphic.eventMode = 'static';
graphic.selectable = true;
graphic.draggable = true;
graphic.on('repaint', function () {
_this.handleFormDataUpdate(graphic);
});
graphic.on('transformend', function () {
_this.handleFormDataUpdate(graphic);
});
};
/**
* 绑定form表单对象
* @param form
*/
JlDrawApp.prototype.bindFormData = function (form) {
this.formData = form;
if (this.formData && this.selectedGraphics.length == 1) {
if (this.formData.graphicType == this.selectedGraphics[0].type) {
this.formData.copyFrom(this.selectedGraphics[0].saveData());
}
else {
this.formData = undefined;
}
}
};
/**
* 移除form绑定
* @param form
*/
JlDrawApp.prototype.unbindFormData = function (form) {
if (this.formData == form) {
this.formData = undefined;
}
};
JlDrawApp.prototype.formDataSyncListen = function () {
var _this = this;
this.on('graphicselected', function () {
if (_this.selectedGraphics.length == 1) {
_this.handleFormDataUpdate(_this.selectedGraphics[0]);
}
});
};
/**
* 处理表单数据更新使用debounce限流
*/
JlDrawApp.prototype.handleFormDataUpdate = function (g) {
this.debouncedFormDataUpdator(this, g);
};
JlDrawApp.prototype.doFormDataUpdate = function (g) {
if (this.selectedGraphics.length > 1)
return;
if (this.formData && g.type === this.formData.graphicType) {
this.formData.copyFrom(g.saveData());
}
};
JlDrawApp.prototype.updateCanvasAndRecord = function (data) {
var old = this.canvas.properties.clone();
this.canvas.update(data);
var newVal = this.canvas.properties.clone();
this.opRecord.record(new UpdateCanvasOperation(this, this.canvas, old, newVal));
};
JlDrawApp.prototype.updateGraphicAndRecord = function (g, data) {
var old = g.saveData();
g.updateData(data);
var newVal = g.saveData();
this.opRecord.record(new GraphicDataUpdateOperation(this, [g], [old], [newVal]));
};
return JlDrawApp;
}(GraphicApp));
var dragStartDatas = [];
function handleArrowKeyMoveGraphics(app, handler) {
if (app.selectedGraphics.length === 1 &&
app.selectedGraphics[0].hasSelectedChilds()) {
recursiveChildren(app.selectedGraphics[0], function (child) {
if (child.selected && child.draggable) {
handler(child);
}
});
}
else {
app.selectedGraphics.forEach(function (g) {
handler(g);
});
}
}
function updateGraphicPositionOnKeyboardEvent(app, dp) {
var dragStart = false;
if (dragStartDatas.length === 0) {
dragStartDatas = app.selectedGraphics.map(function (g) { return g.saveData(); });
dragStart = true;
}
handleArrowKeyMoveGraphics(app, function (g) {
if (dragStart) {
g.shiftStartPoint = g.position.clone();
g.emit('transformstart', GraphicTransformEvent.shift(g, ShiftData.new(g.shiftStartPoint)));
}
else {
g.shiftLastPoint = g.position.clone();
}
g.position.x += dp.x;
g.position.y += dp.y;
if (!dragStart) {
if (g.shiftStartPoint && g.shiftLastPoint) {
g.emit('transforming', GraphicTransformEvent.shift(g, ShiftData.new(g.shiftStartPoint, g.position.clone(), g.shiftLastPoint)));
}
}
});
}
function recordGraphicMoveOperation(app) {
if (dragStartDatas.length > 0 &&
dragStartDatas.length === app.selectedGraphics.length) {
var newData = app.selectedGraphics.map(function (g) { return g.saveData(); });
app.opRecord.record(new GraphicDataUpdateOperation(app, app.selectedGraphics, dragStartDatas, newData));
handleArrowKeyMoveGraphics(app, function (g) {
if (g.shiftStartPoint) {
g.emit('transformend', GraphicTransformEvent.shift(g, ShiftData.new(g.shiftStartPoint, g.position.clone())));
}
});
}
dragStartDatas = [];
}
/**
* 实例化图形app
* @param options
* @returns
*/
function newGraphicApp(options) {
return new GraphicApp(options);
}
/**
* 实例化绘图app
* @param options
* @returns
*/
function newDrawApp(options) {
return new JlDrawApp(options);
}
//基础图形对象扩展
pixi_js.DisplayObject.prototype._selectable = false; //是否可选中
pixi_js.DisplayObject.prototype._selected = false;
pixi_js.DisplayObject.prototype._childEdit = false;
pixi_js.DisplayObject.prototype._transformSave = false;
pixi_js.DisplayObject.prototype._assistantAppendMap = null;
pixi_js.DisplayObject.prototype._draggable = false;
pixi_js.DisplayObject.prototype._shiftStartPoint = null;
pixi_js.DisplayObject.prototype._shiftLastPoint = null;
pixi_js.DisplayObject.prototype._scalable = false;
pixi_js.DisplayObject.prototype._keepAspectRatio = true;
pixi_js.DisplayObject.prototype._rotatable = false;
Object.defineProperties(pixi_js.DisplayObject.prototype, {
assistantAppendMap: {
get: function () {
if (this._assistantAppendMap == null) {
this._assistantAppendMap = new Map();
}
return this._assistantAppendMap;
},
},
selectable: {
get: function () {
return this._selectable;
},
set: function (value) {
this._selectable = value;
},
},
selected: {
get: function () {
return this._selected;
},
set: function (v) {
this._selected = v;
},
},
childEdit: {
get: function () {
return this._childEdit;
},
set: function (v) {
this._childEdit = v;
},
},
transformSave: {
get: function () {
return this._transformSave;
},
set: function (v) {
this._transformSave = v;
},
},
draggable: {
get: function () {
return this._draggable;
},
set: function (v) {
this._draggable = v;
},
},
shiftStartPoint: {
get: function () {
return this._shiftStartPoint;
},
set: function (v) {
this._shiftStartPoint = v;
},
},
shiftLastPoint: {
get: function () {
return this._shiftLastPoint;
},
set: function (v) {
this._shiftLastPoint = v;
},
},
scalable: {
get: function () {
return this._scalable;
},
set: function (v) {
this._scalable = v;
},
},
keepAspectRatio: {
get: function () {
return this._keepAspectRatio;
},
set: function (v) {
this._keepAspectRatio = v;
},
},
rotatable: {
get: function () {
return this._rotatable;
},
set: function (v) {
this._rotatable = v;
},
},
worldAngle: {
get: function () {
var angle = this.angle;
var parent = this.parent;
while (parent != undefined && parent != null) {
angle += parent.angle;
parent = parent.parent;
}
angle = angle % 360;
if (angle > 180) {
angle = angle - 360;
}
return angle;
},
},
});
pixi_js.DisplayObject.prototype.getAllParentScaled =
function getAllParentScaled() {
var scaled = new pixi_js.Point(1, 1);
recursiveParents(this, function (parent) {
scaled.x *= parent.scale.x;
scaled.y *= parent.scale.y;
});
return scaled;
};
pixi_js.DisplayObject.prototype.getPositionOnCanvas =
function getPositionOnCanvas() {
if (this.parent.isCanvas()) {
return this.position;
}
else {
return this.parent.localToCanvasPoint(this.position);
}
};
pixi_js.DisplayObject.prototype.updatePositionByCanvasPosition =
function updatePositionByCanvasPosition(p) {
if (this.parent.isCanvas()) {
this.position.copyFrom(p);
}
else {
var localPosition = this.parent.canvasToLocalPoint(p);
this.position.copyFrom(localPosition);
}
};
pixi_js.DisplayObject.prototype.saveTransform = function saveTransform() {
return GraphicTransform.fromObject(this);
};
pixi_js.DisplayObject.prototype.loadTransform = function loadTransform(transfrom) {
this.position.copyFrom(transfrom.position);
this.scale.copyFrom(transfrom.scale);
this.rotation = transfrom.rotation;
this.skew.copyFrom(transfrom.skew);
};
pixi_js.DisplayObject.prototype.isChild = function isChild(obj) {
return recursiveFindChild(this, function (child) { return child == obj; }) != null;
};
pixi_js.DisplayObject.prototype.isParent = function isParent(obj) {
return recursiveFindParent(this, function (parent) { return parent == obj; }) != null;
};
pixi_js.DisplayObject.prototype.isAssistantAppend =
function isAssistantAppend() {
return (recursiveFindParent(this, function (parent) {
return parent.name === AppConsts.AssistantAppendsName;
}) != null);
};
pixi_js.DisplayObject.prototype.addAssistantAppend = function addAssistantAppend() {
var _this = this;
var appends = [];
for (var _i = 0; _i < arguments.length; _i++) {
appends[_i] = arguments[_i];
}
appends.forEach(function (append) {
if (append.name == null || append.name.trim() == '') {
throw new Error('辅助附加name不能为空');
}
_this.assistantAppendMap.set(append.name, append);
_this.getCanvas().addAssistantAppends(append);
});
};
pixi_js.DisplayObject.prototype.getAssistantAppend = function getAssistantAppend(name) {
return this.assistantAppendMap.get(name);
};
pixi_js.DisplayObject.prototype.removeAssistantAppend = function removeAssistantAppend() {
var _this = this;
var appends = [];
for (var _i = 0; _i < arguments.length; _i++) {
appends[_i] = arguments[_i];
}
appends.forEach(function (append) {
if (append.name) {
_this.removeAssistantAppendByName(append.name);
}
});
};
pixi_js.DisplayObject.prototype.removeAssistantAppendByName =
function removeAssistantAppendByName() {
var _this = this;
var names = [];
for (var _i = 0; _i < arguments.length; _i++) {
names[_i] = arguments[_i];
}
names.forEach(function (name) {
var append = _this.getAssistantAppend(name);
if (append) {
_this.getCanvas().removeAssistantAppends(append);
_this.assistantAppendMap.delete(name);
append.destroy();
}
});
};
pixi_js.DisplayObject.prototype.removeAllAssistantAppend =
function removeAllAssistantAppend() {
if (this._assistantAppendMap != null) {
this.assistantAppendMap.forEach(function (append) {
append.getCanvas().removeAssistantAppends(append);
});
this.assistantAppendMap.clear();
}
};
pixi_js.DisplayObject.prototype.isGraphic = function isGraphic() {
return Object.hasOwn(this, '__JlGraphic');
};
pixi_js.DisplayObject.prototype.getGraphic = function getGraphic() {
var graphic = this;
while (graphic && !Object.hasOwn(graphic, '__JlGraphic')) {
graphic = graphic.parent;
}
if (graphic) {
return graphic;
}
return null;
};
pixi_js.DisplayObject.prototype.isGraphicChild = function isGraphicChild() {
var g = this.getGraphic();
return g != null && !this.isAssistantAppend() && g.isChild(this);
};
pixi_js.DisplayObject.prototype.onAddToCanvas = function onAddToCanvas(_canvas) { };
pixi_js.DisplayObject.prototype.onRemoveFromCanvas = function onRemoveFromCanvas(_canvas) { };
pixi_js.DisplayObject.prototype.isInCanvas = function isInCanvas() {
var graphic = this;
while (graphic && !Object.hasOwn(graphic, '__JlCanvas')) {
graphic = graphic.parent;
}
if (graphic) {
return true;
}
return false;
};
pixi_js.DisplayObject.prototype.getCanvas = function getCanvas() {
var graphic = this;
while (graphic && !Object.hasOwn(graphic, '__JlCanvas')) {
graphic = graphic.parent;
}
if (graphic) {
return graphic;
}
throw new Error("\u56FE\u5F62".concat(this.name, "\u4E0D\u5728\u753B\u5E03\u4E2D"));
};
pixi_js.DisplayObject.prototype.isCanvas = function isCanvas() {
return Object.hasOwn(this, '__JlCanvas');
};
pixi_js.DisplayObject.prototype.getViewport = function getViewport() {
var canvas = this.getCanvas();
return canvas.parent;
};
pixi_js.DisplayObject.prototype.getGraphicApp = function getGraphicApp() {
var canvas = this.getCanvas();
return canvas.scene.app;
};
pixi_js.DisplayObject.prototype.localToCanvasPoint = function localToCanvasPoint(p) {
return this.getViewport().toWorld(this.toGlobal(p));
};
pixi_js.DisplayObject.prototype.localToCanvasPoints = function localToCanvasPoints() {
var _this = this;
var points = [];
for (var _i = 0; _i < arguments.length; _i++) {
points[_i] = arguments[_i];
}
return points.map(function (p) { return _this.localToCanvasPoint(p); });
};
pixi_js.DisplayObject.prototype.canvasToLocalPoint = function canvasToLocalPoint(p) {
return this.toLocal(this.getViewport().toScreen(p));
};
pixi_js.DisplayObject.prototype.canvasToLocalPoints = function canvasToLocalPoints() {
var _this = this;
var points = [];
for (var _i = 0; _i < arguments.length; _i++) {
points[_i] = arguments[_i];
}
return points.map(function (p) { return _this.canvasToLocalPoint(p); });
};
pixi_js.DisplayObject.prototype.localToScreenPoint = function localToScreenPoint(p) {
return this.toGlobal(p);
};
pixi_js.DisplayObject.prototype.localToScreenPoints = function localToScreenPoints() {
var _this = this;
var points = [];
for (var _i = 0; _i < arguments.length; _i++) {
points[_i] = arguments[_i];
}
return points.map(function (p) { return _this.toGlobal(p); });
};
pixi_js.DisplayObject.prototype.screenToLocalPoint = function screenToLocalPoint(p) {
return this.toLocal(p);
};
pixi_js.DisplayObject.prototype.screenToLocalPoints = function screenToLocalPoints() {
var _this = this;
var points = [];
for (var _i = 0; _i < arguments.length; _i++) {
points[_i] = arguments[_i];
}
return points.map(function (p) { return _this.toLocal(p); });
};
pixi_js.DisplayObject.prototype.localBoundsToCanvasPoints =
function localBoundsToCanvasPoints() {
var rect = this.getLocalBounds();
var pps = convertRectangleToPolygonPoints(rect);
return this.localToCanvasPoints.apply(this, pps);
};
// 扩展pixijs图形对象添加自定义绘制贝塞尔曲线可自定义分段数
pixi_js.Graphics.prototype.drawBezierCurve = function drawBezierCurve(p1, p2, cp1, cp2, segmentsCount) {
var fromX = p1.x;
var fromY = p1.y;
var n = segmentsCount;
var dt = 0;
var dt2 = 0;
var dt3 = 0;
var t2 = 0;
var t3 = 0;
var cpX = cp1.x;
var cpY = cp1.y;
var cpX2 = cp2.x;
var cpY2 = cp2.y;
var toX = p2.x;
var toY = p2.y;
this.moveTo(p1.x, p1.y);
for (var i = 1, j = 0; i <= n; ++i) {
j = i / n;
dt = 1 - j;
dt2 = dt * dt;
dt3 = dt2 * dt;
t2 = j * j;
t3 = t2 * j;
var px = dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX;
var py = dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY;
this.lineTo(px, py);
}
return this;
};
/**
* 图形变换数据
*/
var GraphicTransform = /** @class */ (function () {
function GraphicTransform(position, scale, rotation, skew) {
this.position = position;
this.scale = scale;
this.rotation = rotation;
this.skew = skew;
}
GraphicTransform.default = function () {
return new GraphicTransform(new pixi_js.Point(0, 0), new pixi_js.Point(1, 1), 0, new pixi_js.Point(0, 0));
};
GraphicTransform.fromObject = function (obj) {
return new GraphicTransform(obj.position.clone(), obj.scale.clone(), obj.rotation, obj.skew.clone());
};
GraphicTransform.from = function (transform) {
if (transform) {
return new GraphicTransform(new pixi_js.Point(transform.position.x, transform.position.y), new pixi_js.Point(transform.scale.x, transform.scale.y), transform.rotation, new pixi_js.Point(transform.skew.x, transform.skew.y));
}
return GraphicTransform.default();
};
return GraphicTransform;
}());
/**
* 图形子元素变换
*/
var ChildTransform = /** @class */ (function () {
function ChildTransform(name, transform) {
this.name = name;
this.transform = transform;
}
ChildTransform.fromChild = function (child) {
var _a;
if (child.name == null ||
child.name == undefined ||
child.name.trim() == '') {
throw new Error("\u56FE\u5F62type=".concat((_a = child.getGraphic()) === null || _a === void 0 ? void 0 : _a.type, "\u7684\u5B50\u5143\u7D20").concat(child, "name\u4E3A\u7A7A\uFF0C\u4F46\u8BBE\u7F6E\u4E3A\u9700\u8981\u4FDD\u5B58\u53D8\u6362\u6570\u636E"));
}
return new ChildTransform(child.name, GraphicTransform.fromObject(child));
};
ChildTransform.from = function (ct) {
return new ChildTransform(ct.name, GraphicTransform.from(ct.transform));
};
return ChildTransform;
}());
var GraphicAnimation = /** @class */ (function () {
function GraphicAnimation(options) {
this.options = options;
this._running = false;
this._xSpeed = 1;
}
GraphicAnimation.init = function (options) {
return new GraphicAnimation(options);
};
GraphicAnimation.prototype.pause = function () {
this._running = false;
return this;
};
GraphicAnimation.prototype.resume = function () {
this._running = true;
return this;
};
Object.defineProperty(GraphicAnimation.prototype, "name", {
get: function () {
return this.options.name;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GraphicAnimation.prototype, "running", {
get: function () {
return this._running;
},
enumerable: false,
configurable: true
});
Object.defineProperty(GraphicAnimation.prototype, "xSpeed", {
get: function () {
return this._xSpeed;
},
set: function (v) {
this._xSpeed = v;
},
enumerable: false,
configurable: true
});
GraphicAnimation.prototype.run = function (dt) {
if (this.options.run) {
this.options.run(dt * this.xSpeed);
}
return this;
};
return GraphicAnimation;
}());
/**
* 图形对象基类
*/
var JlGraphic = /** @class */ (function (_super) {
__extends(JlGraphic, _super);
function JlGraphic(type) {
var _this = _super.call(this) || this;
_this.__JlGraphic = true;
_this._id = ''; // 图形的唯一标识,不具有业务意义,唯一,不可重复,可用做图形数据关联。
_this._code = ''; // 业务编号/名称,用于标识图形对象,具有业务意义
_this.type = type;
_this.draggable = false;
_this.filters;
return _this;
}
/**
* 添加图形动画,只有在画布上才能添加
* @param animation
*/
JlGraphic.prototype.addAnimation = function (animation) {
var app = this.getGraphicApp();
app.animationManager.registerAnimation(this, animation);
};
JlGraphic.prototype.removeAnimation = function (name) {
var app = this.getGraphicApp();
app.animationManager.unregisterAnimation(this, name);
};
JlGraphic.prototype.animation = function (name) {
var app = this.getGraphicApp();
return app.animationManager.animation(this, name);
};
JlGraphic.prototype.removeAllAnimation = function () {
var app = this.getGraphicApp();
app.animationManager.unregisterGraphicAnimations(this);
};
/**
* 更新选中状态
* @param selected
* @returns 是否更新
*/
JlGraphic.prototype.updateSelected = function (selected) {
if (this.selected !== selected) {
this.selected = selected;
this.fireSelected();
return true;
}
return false;
};
JlGraphic.prototype.invertSelected = function () {
this.selected = !this.selected;
this.fireSelected();
};
JlGraphic.prototype.fireSelected = function () {
if (this.selected) {
this.emit('selected', this);
}
else {
this.exitChildEdit();
this.removeAllChildSelected();
this.emit('unselected', this);
}
var app = this.getGraphicApp();
if (app) {
app.emit('graphicselectedchange', this, this.selected);
}
};
JlGraphic.prototype.hasSelectedChilds = function () {
return (recursiveFindChild(this, function (child) {
if (child.selected) {
return true;
}
return false;
}) != null);
};
JlGraphic.prototype.setChildSelected = function (child) {
if (child.isGraphicChild() && child.selectable) {
this.removeAllChildSelected();
child.selected = true;
this.fireChildSelected(child);
}
return false;
};
JlGraphic.prototype.invertChildSelected = function (child) {
if (child.isGraphicChild() && child.selectable) {
child.selected = !child.selected;
this.fireChildSelected(child);
}
return false;
};
JlGraphic.prototype.removeAllChildSelected = function () {
var _this = this;
recursiveChildren(this, function (child) {
if (child.selected) {
child.selected = false;
_this.fireChildSelected(child);
}
});
};
JlGraphic.prototype.fireChildSelected = function (child) {
var selected = child.selected;
if (selected) {
this.emit('childselected', child);
}
else {
this.emit('childunselected', child);
}
var app = this.getGraphicApp();
if (app) {
app.emit('graphicchildselectedchange', child, selected);
}
};
JlGraphic.prototype.exitChildEdit = function () {
this.childEdit = false;
this.removeAllChildSelected();
};
/**
* 是否此对象id/code
*/
JlGraphic.prototype.isIdOrCode = function (s) {
return this.id === s || this.code === s;
};
Object.defineProperty(JlGraphic.prototype, "id", {
/**
* 获取图形id如果图形数据对象存在则返回图形数据对象id
*/
get: function () {
if (this._datas) {
return this._datas.id;
}
return this._id;
},
/**
* 设置图形id如果图形数据存在则同时设置图形数据id
*/
set: function (v) {
this._id = v;
if (this._datas) {
this._datas.id = v;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(JlGraphic.prototype, "code", {
/**
* 获取图形业务code如果业务code在图形数据或图形状态中则需要重写此方法
*/
get: function () {
return this._code;
},
/**
* 设置图形业务code如果业务code在图形数据或图形状态中则需要重写此方法
*/
set: function (v) {
this._code = v;
},
enumerable: false,
configurable: true
});
JlGraphic.prototype.getDatas = function () {
if (this._datas) {
return this._datas;
}
throw new Error("id=".concat(this.id, ",type=").concat(this.type, "\u7684\u56FE\u5F62\u6CA1\u6709\u6570\u636E"));
};
JlGraphic.prototype.getStates = function () {
if (this._states) {
return this._states;
}
throw new Error("id=".concat(this.id, ",type=").concat(this.type, "\u7684\u7684\u56FE\u5F62\u6CA1\u6709\u72B6\u6001"));
};
Object.defineProperty(JlGraphic.prototype, "queryStore", {
get: function () {
if (this._queryStore) {
return this._queryStore;
}
throw new Error("type=".concat(this.type, "\u7684\u56FE\u5F62\u6CA1\u6709QueryStore"));
},
set: function (v) {
this._queryStore = v;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JlGraphic.prototype, "relationManage", {
get: function () {
if (this._relationManage) {
return this._relationManage;
}
throw new Error("type=".concat(this.type, "\u7684\u56FE\u5F62\u6CA1\u6709\u5173\u7CFB\u7BA1\u7406"));
},
set: function (v) {
this._relationManage = v;
},
enumerable: false,
configurable: true
});
/**
* 构建图形关系
* @param g
*/
JlGraphic.prototype.buildRelation = function () { };
/**
* 从数据加载恢复图形关系
*/
JlGraphic.prototype.loadRelations = function () { };
/**
* 获取当前图形的所有图形关系
* @returns
*/
JlGraphic.prototype.getAllRelations = function () {
return this.relationManage.getRelationsOfGraphic(this);
};
/**
* 获取当前图形的所有指定类型图形关系
* @param type
* @returns
*/
JlGraphic.prototype.queryRelationByType = function (type) {
return this.relationManage.getRelationsOfGraphicAndOtherType(this, type);
};
/**
* 删除当前图形关联的指定类型的关系
* @param type
*/
JlGraphic.prototype.deleteRelationByType = function (type) {
this.relationManage.deleteRelationOfGraphicAndOtherType(this, type);
};
/**
* 构建并保存关系数据到datas中
*/
JlGraphic.prototype.saveRelations = function () { };
/**
* 保存数据,复制,非原始数据
* @returns
*/
JlGraphic.prototype.saveData = function () {
this.getDatas().graphicType = this.type;
this.getDatas().transform = GraphicTransform.fromObject(this);
this.getDatas().childTransforms = this.buildChildTransforms();
this.saveRelations();
return this.getDatas().clone();
};
/**
* 构建子元素变换列表
* @returns
*/
JlGraphic.prototype.buildChildTransforms = function () {
var childTransforms = [];
recursiveChildren(this, function (child) {
if (child.transformSave) {
childTransforms.push(ChildTransform.fromChild(child));
}
});
return childTransforms;
};
/**
* 加载数据
* @param data
*/
JlGraphic.prototype.loadData = function (data) {
if (data.graphicType !== this.type) {
throw new Error("\u4E0D\u540C\u7684\u56FE\u5F62\u7C7B\u578B,\u8BF7\u68C0\u67E5\u6570\u636E\u662F\u5426\u6B63\u5E38: data.graphicType=\"".concat(data.graphicType, ", type=\"").concat(this.type));
}
this._datas = data;
this.loadTransformFrom(data);
};
JlGraphic.prototype.loadTransformFrom = function (data) {
var _this = this;
if (data.transform) {
this.loadTransform(data.transform);
}
if (data.childTransforms) {
data.childTransforms.forEach(function (ct) {
var child = _this.getChildByName(ct.name, true);
if (child) {
child.loadTransform(ct.transform);
}
});
}
};
/**
* 更新图形数据
* @param data
* @returns
*/
JlGraphic.prototype.updateData = function (data) {
var update = false;
if (!this.getDatas().eq(data)) {
update = true;
var old = this.getDatas().clone();
this.getDatas().copyFrom(data);
this.onDataChange(data, old);
this.loadTransformFrom(data);
this.emit('dataupdate', this.getDatas(), old);
this.repaint();
}
return update;
};
/**
* 图形数据更新
*/
JlGraphic.prototype.onDataChange = function (newVal, old) { };
/**
* 加载状态
* @param state
*/
JlGraphic.prototype.loadState = function (state) {
if (state.graphicType !== this.type) {
throw new Error("\u4E0D\u540C\u7684\u56FE\u5F62\u7C7B\u578B,\u8BF7\u68C0\u67E5\u6570\u636E\u662F\u5426\u6B63\u5E38: state.graphicType=\"".concat(state.graphicType, ", type=\"").concat(this.type));
}
this._states = state;
};
/**
* 更新状态
* @param state
* @returns
*/
JlGraphic.prototype.updateStates = function (state) {
var stateChange = false;
if (!this.getStates().eq(state)) {
// 判断并更新状态,默认状态
var old = this.getStates().clone();
this.getStates().copyFrom(state);
this.onStateChange(state, old);
stateChange = true;
this.emit('stateupdate', this.getStates(), old);
// this.repaint();
}
return stateChange;
};
/**
* 图形状态更新处理
*/
JlGraphic.prototype.onStateChange = function (newVal, old) { };
JlGraphic.prototype.repaint = function () {
try {
this.doRepaint();
this.emit('repaint', this);
}
catch (e) {
console.error("\u8BBE\u5907id=".concat(this.id, ",type=").concat(this.type, "\u91CD\u7ED8\u903B\u8F91\u5F02\u5E38"), e);
}
};
/**
* 处理删除逻辑
*/
JlGraphic.prototype.onDelete = function () {
this.removeAllAssistantAppend();
this.removeAllListeners();
recursiveChildren(this, function (child) { return child.removeAllAssistantAppend(); });
};
/**
* 框选检测,默认取图形包围盒判定,若需要精细判定-子类重写此方法
* @param box
* @returns
*/
JlGraphic.prototype.boxIntersectCheck = function (box) {
return box.intersects(this.getLocalBounds(), this.localTransform);
};
return JlGraphic;
}(pixi_js.Container));
/**
* 图形对象模板
*/
var JlGraphicTemplate = /** @class */ (function () {
function JlGraphicTemplate(type, options) {
this.type = type;
this.options = options;
}
Object.defineProperty(JlGraphicTemplate.prototype, "datas", {
get: function () {
if (this.options.dataTemplate) {
return this.options.dataTemplate.clone();
}
throw new Error("type=".concat(this.type, "\u7684\u56FE\u5F62\u6A21\u677F\u6CA1\u6709\u6570\u636E\u6A21\u677F"));
},
enumerable: false,
configurable: true
});
Object.defineProperty(JlGraphicTemplate.prototype, "states", {
get: function () {
if (this.options.stateTemplate) {
return this.options.stateTemplate.clone();
}
throw new Error("type=".concat(this.type, "\u7684\u56FE\u5F62\u6A21\u677F\u6CA1\u6709\u72B6\u6001\u6A21\u677F"));
},
enumerable: false,
configurable: true
});
/**
* 加载图形对象需要用到的资源
*/
JlGraphicTemplate.prototype.loadAssets = function () {
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/];
}); });
};
/**
* 克隆图形对象
* @param graphic
* @returns
*/
JlGraphicTemplate.prototype.clone = function (graphic) {
var g = this.new();
if (graphic._datas) {
// 数据克隆
var datas = graphic.saveData();
g.loadData(datas);
}
if (graphic._states) {
// 状态克隆
var state = graphic.getStates().clone();
g.loadState(state);
}
g.id = GraphicIdGenerator.next();
return g;
};
return JlGraphicTemplate;
}());
exports.AbsorbableCircle = AbsorbableCircle;
exports.AbsorbableLine = AbsorbableLine;
exports.AbsorbablePointParam = AbsorbablePointParam;
exports.AnimationManager = AnimationManager;
exports.AppConsts = AppConsts;
exports.AppDragEvent = AppDragEvent;
exports.AppInteractionPlugin = AppInteractionPlugin;
exports.AppWsMsgBroker = AppWsMsgBroker;
exports.BoundsGraphic = BoundsGraphic;
exports.ChildTransform = ChildTransform;
exports.CommonMouseTool = CommonMouseTool;
exports.DOWN = DOWN;
exports.DashedLine = DashedLine;
exports.DragPlugin = DragPlugin;
exports.DraggablePoint = DraggablePoint;
exports.DraggablePointParam = DraggablePointParam;
exports.GlobalKeyboardHelper = GlobalKeyboardHelper;
exports.GraphicAnimation = GraphicAnimation;
exports.GraphicCopyPlugin = GraphicCopyPlugin;
exports.GraphicDataUpdateOperation = GraphicDataUpdateOperation;
exports.GraphicDrawAssistant = GraphicDrawAssistant;
exports.GraphicIdGenerator = GraphicIdGenerator;
exports.GraphicInteractionPlugin = GraphicInteractionPlugin;
exports.GraphicRelation = GraphicRelation;
exports.GraphicRelationParam = GraphicRelationParam;
exports.GraphicStore = GraphicStore;
exports.GraphicTransform = GraphicTransform;
exports.GraphicTransformEvent = GraphicTransformEvent;
exports.GraphicTransformPlugin = GraphicTransformPlugin;
exports.IdGenerator = IdGenerator;
exports.InteractionPluginBase = InteractionPluginBase;
exports.JlGraphic = JlGraphic;
exports.JlGraphicAppKeyboardPlugin = JlGraphicAppKeyboardPlugin;
exports.JlGraphicTemplate = JlGraphicTemplate;
exports.JlOperation = JlOperation;
exports.KeyListener = KeyListener;
exports.LEFT = LEFT;
exports.OperationRecord = OperationRecord;
exports.OtherInteractionPlugin = OtherInteractionPlugin;
exports.OutOfBound = OutOfBound;
exports.RIGHT = RIGHT;
exports.RelationManage = RelationManage;
exports.ScaleData = ScaleData;
exports.ShiftData = ShiftData;
exports.TransformPoints = TransformPoints;
exports.UP = UP;
exports.VectorGraphicUtil = VectorGraphicUtil;
exports.VectorText = VectorText;
exports.ViewportMovePlugin = ViewportMovePlugin;
exports.WsMsgCli = WsMsgCli;
exports.angleOfIncludedAngle = angleOfIncludedAngle;
exports.angleToAxisx = angleToAxisx;
exports.assertBezierPoints = assertBezierPoints;
exports.calculateBezierPoints = calculateBezierPoints;
exports.calculateDistanceFromPointToLine = calculateDistanceFromPointToLine;
exports.calculateFootPointFromPointToLine = calculateFootPointFromPointToLine;
exports.calculateIntersectionPointOfCircleAndLine = calculateIntersectionPointOfCircleAndLine;
exports.calculateIntersectionPointOfCircleAndPoint = calculateIntersectionPointOfCircleAndPoint;
exports.calculateLineMidpoint = calculateLineMidpoint;
exports.calculateLineSegmentingPoint = calculateLineSegmentingPoint;
exports.calculateMirrorPoint = calculateMirrorPoint;
exports.calculateMirrorPointBasedOnAxis = calculateMirrorPointBasedOnAxis;
exports.calculateOneBezierPoints = calculateOneBezierPoints;
exports.circlePoint = circlePoint;
exports.circlePoint2 = circlePoint2;
exports.convertLineToPolygonPoints = convertLineToPolygonPoints;
exports.convertRectangleToPolygonPoints = convertRectangleToPolygonPoints;
exports.convertToBezierParams = convertToBezierParams;
exports.debounce = debounce;
exports.deserializeTransformInto = deserializeTransformInto;
exports.distance = distance;
exports.distance2 = distance2;
exports.getCenterOfTwoRectangle = getCenterOfTwoRectangle;
exports.getIntersectionPoint = getIntersectionPoint;
exports.getNormalVector = getNormalVector;
exports.getParallelOfPolyline = getParallelOfPolyline;
exports.getRectangleCenter = getRectangleCenter;
exports.isLineContainOther = isLineContainOther;
exports.isParallelLines = isParallelLines;
exports.isPointOnLine = isPointOnLine;
exports.lineBox = lineBox;
exports.lineLine = lineLine;
exports.linePoint = linePoint;
exports.linePolygon = linePolygon;
exports.movePointAlongNormal = movePointAlongNormal;
exports.newDrawApp = newDrawApp;
exports.newGraphicApp = newGraphicApp;
exports.pointBox = pointBox;
exports.pointPoint = pointPoint;
exports.pointPoint2 = pointPoint2;
exports.pointPolygon = pointPolygon;
exports.polylineBox = polylineBox;
exports.polylinePoint = polylinePoint;
exports.polylinePolygon = polylinePolygon;
exports.recursiveChildren = recursiveChildren;
exports.recursiveFindChild = recursiveFindChild;
exports.recursiveFindParent = recursiveFindParent;
exports.recursiveParents = recursiveParents;
exports.serializeTransform = serializeTransform;
exports.splitLineEvenly = splitLineEvenly;
exports.splitPolyline = splitPolyline;