8052 lines
272 KiB
JavaScript
8052 lines
272 KiB
JavaScript
'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;
|