123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import { watch } from "vue";
- import { Attrib, ShapeType } from "../type";
- import { Layer } from "konva/lib/Layer";
- import { Entity, EntityProps, EntityType } from "./entity";
- import { Stage } from "konva/lib/Stage";
- import {
- IncEntitysFactory,
- incEntitysFactoryGenerate,
- } from "../shared/entity-utils";
- import { Shape } from "konva/lib/Shape";
- import { Group } from "konva/lib/Group";
- import { getAbsoluteTransform } from "../shared";
- import mitt, { Emitter } from "mitt";
- export type ContainerProps<
- T extends string = string,
- R extends Attrib = Attrib,
- S extends ShapeType = ShapeType,
- C extends EntityType<R, S> = EntityType<R, S>,
- TYPES extends { [key in T]: C } = { [key in T]: C },
- DATA extends { [key in T]?: R | R[] } = { [key in T]?: R | R[] }
- > = {
- types: TYPES;
- data?: DATA;
- dom: HTMLDivElement;
- } & Omit<EntityProps<Attrib & { data: DATA }>, "attrib">;
- export class Container<
- T extends string = string,
- R extends Attrib = Attrib,
- S extends ShapeType = ShapeType,
- C extends EntityType<R, S> = EntityType<R, S>,
- TYPES extends { [key in T]: C } = { [key in T]: C },
- DATA extends { [key in T]?: R | R[] } = { [key in T]?: R | R[] },
- ENTRYS extends { [key in T]: InstanceType<TYPES[key]>[] } = {
- [key in T]: InstanceType<TYPES[key]>[];
- }
- > extends Entity<Attrib & { data: DATA }, Layer> {
- bus: Emitter<{
- active: Entity;
- dataChange: void;
- dataChangeBefore: void;
- dataChangeAfter: void;
- }>;
- tempLayer: Layer;
- config: ContainerProps<T, R, S, C, TYPES, DATA>;
- entrys = {} as ENTRYS;
- stage: Stage;
- incFactorys = {} as {
- [key in T]: IncEntitysFactory<R, InstanceType<C>>;
- };
- constructor(config: ContainerProps<T, R, S, C, TYPES, DATA>) {
- for (const key in config.types) {
- config.data[key as any] = config.data[key] || [];
- }
- for (const key in config.data) {
- if (!(key in config.types)) {
- delete config.data[key];
- }
- }
- super({
- name: "container",
- attrib: { id: "0", data: config.data },
- ...config,
- });
- this.config = config;
- this.container = this;
- const { dom } = this.config;
- this.stage = new Stage({
- container: dom,
- width: dom.offsetWidth,
- height: dom.offsetHeight,
- });
- this.bus = mitt();
- // this.tempLayer = new Layer();
- // this.stage.add(this.tempLayer);
- }
- initShape() {
- const viewLayer = new Layer();
- return viewLayer;
- }
- init() {
- this.initIncFactory();
- super.init();
- this.mount(this.stage);
- this.mounted();
- }
- initIncFactory() {
- const types = this.config.types as any;
- let active: Entity | null = null;
- for (const key in types) {
- this.incFactorys[key] = incEntitysFactoryGenerate(
- types[key],
- this,
- (instance) => {
- const entity = instance as Entity;
- if (!this.entrys[key]) {
- this.entrys[key] = [];
- }
- this.entrys[key].push(entity);
- const destory = entity.destory.bind(entity);
- entity.destory = () => {
- destory();
- const ndx = this.entrys[key].indexOf(entity);
- if (~ndx) {
- this.entrys[key].splice(ndx, 1);
- }
- };
- },
- (instance) => {
- if (!instance.actShape?.active) return;
- const entity = instance as Entity;
- entity.enableActive((actived) => {
- if (actived) {
- if (active !== entity) {
- this.bus.emit("active", entity);
- active = entity;
- }
- } else {
- if (active === entity) {
- this.bus.emit("active", null);
- active = null;
- }
- }
- });
- const destory = entity.destory.bind(entity);
- entity.destory = () => {
- if (active === entity) {
- this.bus.emit("active", null);
- active = null;
- }
- return destory();
- };
- }
- );
- }
- }
- diffRedraw() {
- const data = this.attrib.data as any;
- const result = {} as {
- [key in T]: ReturnType<IncEntitysFactory<R, InstanceType<C>>>;
- };
- for (const key in data) {
- if (key in this.incFactorys) {
- result[key] = this.incFactorys[key](data[key]);
- }
- }
- return result;
- }
- initReactive() {
- return watch(
- () => {
- const result = {} as { [key in T]: string | string[] };
- for (const key in this.attrib.data as any) {
- const child = this.attrib.data[key];
- result[key] = Array.isArray(child)
- ? child.map(({ id }) => id)
- : child.id;
- }
- return result;
- },
- this.diffRedraw.bind(this),
- { immediate: true, flush: "sync" }
- );
- }
- // 临时绘制
- tempDraw(...shapes: Entity<Attrib, Group | Shape>[]) {
- const tels = shapes.map((shape) => shape.teleport);
- shapes.forEach((shape) => {
- shape.mount(this.tempLayer);
- });
- return () => {
- shapes.forEach((shape, ndx) => {
- shape.mount(tels[ndx]);
- });
- };
- }
- getPixelFromStage(pos: number[]) {
- const tf = getAbsoluteTransform(this.stage, true);
- const { x, y } = tf.point({ x: pos[0], y: pos[1] });
- return [x, y];
- }
- getRealFromStage(pos: number[]) {
- const tf = getAbsoluteTransform(this.stage, true).invert();
- const { x, y } = tf.point({ x: pos[0], y: pos[1] });
- return [x, y];
- }
- private prevCursor: string;
- setCursor(ico: string | null) {
- const defs = ["move", "inherit", "pointer"];
- ico = defs.includes(ico) ? ico : ico ? `url("${ico}"), auto` : "inherit";
- this.config.dom.style.cursor = ico;
- this.prevCursor = ico;
- return () => {
- if (this.prevCursor === ico) {
- this.config.dom.style.cursor = "inherit";
- this.prevCursor = "inherit";
- }
- };
- }
- getSameLevelData<T extends Entity>(
- entity: T
- ): T extends { attrib: infer A } ? A[] : never {
- const parentAttrib = this.attrib.data;
- for (const key in parentAttrib) {
- if (
- Array.isArray(parentAttrib[key]) &&
- ~(parentAttrib[key] as Attrib[]).indexOf(entity.attrib)
- ) {
- return parentAttrib[key] as any;
- }
- }
- }
- }
|