|
@@ -5,6 +5,7 @@ import {
|
|
|
globalWatch,
|
|
|
installGlobalVar,
|
|
|
useCan,
|
|
|
+ useDownKeys,
|
|
|
useStage,
|
|
|
useTransformIngShapes,
|
|
|
} from "./use-global-vars.ts";
|
|
@@ -18,69 +19,114 @@ import {
|
|
|
useTransformer,
|
|
|
} from "./use-transformer.ts";
|
|
|
import { useAniamtion } from "./use-animation.ts";
|
|
|
+import { KonvaEventObject } from "konva/lib/Node";
|
|
|
+
|
|
|
+export const getHoverShape = (stage: Stage) => {
|
|
|
+ const hover = ref<EntityShape>();
|
|
|
+ const enterHandler = (ev: KonvaEventObject<any, Stage>) => {
|
|
|
+ leaveHandler();
|
|
|
+ const target = ev.target;
|
|
|
+ hover.value = target;
|
|
|
+ target.on("pointerleave", leaveHandler);
|
|
|
+ };
|
|
|
+ const leaveHandler = () => {
|
|
|
+ if (hover.value) {
|
|
|
+ hover.value.off("pointerleave", leaveHandler);
|
|
|
+ hover.value = undefined;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ stage.on("pointerenter", enterHandler);
|
|
|
+ return [
|
|
|
+ hover,
|
|
|
+ () => {
|
|
|
+ stage.off("pointerenter", enterHandler);
|
|
|
+ leaveHandler();
|
|
|
+ },
|
|
|
+ ] as const;
|
|
|
+};
|
|
|
+
|
|
|
+export const useShapeIsTransformerInner = () => {
|
|
|
+ const transformer = useTransformer();
|
|
|
+ const pointerIsTransformerInner = usePointerIsTransformerInner();
|
|
|
+ const stage = useStage();
|
|
|
+
|
|
|
+ return (shape: EntityShape) => {
|
|
|
+ const inner = ref(true);
|
|
|
+ const $stage = stage.value!.getNode();
|
|
|
+ const updateInner = () => {
|
|
|
+ inner.value =
|
|
|
+ transformer.isTransforming() ||
|
|
|
+ (transformer.queueShapes.value.includes(shape) &&
|
|
|
+ pointerIsTransformerInner());
|
|
|
+ };
|
|
|
+
|
|
|
+ const stop = watch(
|
|
|
+ transformer.queueShapes,
|
|
|
+ (_a, _, onCleanup) => {
|
|
|
+ updateInner();
|
|
|
+ if (inner.value) {
|
|
|
+ $stage.on("pointermove", updateInner);
|
|
|
+ onCleanup(() => {
|
|
|
+ $stage.off("pointermove", updateInner);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true, flush: "sync" }
|
|
|
+ );
|
|
|
+
|
|
|
+ return [inner, stop] as const;
|
|
|
+ };
|
|
|
+};
|
|
|
|
|
|
export const useMouseShapesStatus = installGlobalVar(() => {
|
|
|
- const can = useCan()
|
|
|
+ const can = useCan();
|
|
|
const stage = useStage();
|
|
|
const listeners = ref([]) as Ref<EntityShape[]>;
|
|
|
const hovers = ref([]) as Ref<EntityShape[]>;
|
|
|
const press = ref([]) as Ref<EntityShape[]>;
|
|
|
const selects = ref([]) as Ref<EntityShape[]>;
|
|
|
const actives = ref([]) as Ref<EntityShape[]>;
|
|
|
- const transformer = useTransformer();
|
|
|
- const pointerIsTransformerInner = usePointerIsTransformerInner();
|
|
|
+ const keys = useDownKeys();
|
|
|
+ const shapeIsTransformerInner = useShapeIsTransformerInner();
|
|
|
|
|
|
const init = (stage: Stage) => {
|
|
|
let downTime: number;
|
|
|
let downTarget: EntityShape | null;
|
|
|
- const inner = new WeakMap<EntityShape, boolean>();
|
|
|
|
|
|
- stage.on("pointerenter.mouse-status", async (ev) => {
|
|
|
- const target = shapeTreeContain(listeners.value, ev.target);
|
|
|
- if (!target) return;
|
|
|
- inner.set(target, true);
|
|
|
- if (hovers.value.includes(target)) return;
|
|
|
-
|
|
|
- hovers.value.push(target);
|
|
|
- const targetLeave = () => {
|
|
|
- target.off("pointerleave.mouse-status");
|
|
|
- stage.off("pointermove.mouse-status");
|
|
|
- stopIncludeWatch! && stopIncludeWatch();
|
|
|
- const ndx = hovers.value.indexOf(target);
|
|
|
- if (~ndx) {
|
|
|
- hovers.value.splice(ndx, 1);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- let stopIncludeWatch: () => void;
|
|
|
- target.on("pointerleave.mouse-status", (ev) => {
|
|
|
- const target = shapeTreeContain(listeners.value, ev.target);
|
|
|
- if (!target) return;
|
|
|
- inner.set(target, false);
|
|
|
-
|
|
|
- // TODO: 有可能在transformer上,需要额外检测
|
|
|
- stopIncludeWatch! && stopIncludeWatch();
|
|
|
- stopIncludeWatch = watch(
|
|
|
- transformer.queueShapes,
|
|
|
- (queueShapes, _, onCleanup) => {
|
|
|
- if (inner.get(target)) return;
|
|
|
-
|
|
|
- if (!queueShapes.includes(target) || !pointerIsTransformerInner()) {
|
|
|
- targetLeave();
|
|
|
- } else {
|
|
|
- stage.on("pointermove.mouse-status", () => {
|
|
|
- if (!inner.get(target) && !pointerIsTransformerInner()) {
|
|
|
- targetLeave();
|
|
|
- }
|
|
|
- });
|
|
|
- onCleanup(() => stage.off("pointermove.mouse-status"));
|
|
|
+ const prevent = computed(() => keys.has(" "));
|
|
|
+ const [hover, hoverDestory] = getHoverShape(stage);
|
|
|
+ const hoverChange = (onCleanup: any) => {
|
|
|
+ if (prevent.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const pHover =
|
|
|
+ hover.value && shapeTreeContain(listeners.value, hover.value);
|
|
|
+ // TODO首先确定之前的有没有离开
|
|
|
+ if (hovers.value.length && hovers.value[0] !== pHover) {
|
|
|
+ const check = hovers.value[0];
|
|
|
+ const [inner] = shapeIsTransformerInner(check);
|
|
|
+ onCleanup(
|
|
|
+ watchEffect(() => {
|
|
|
+ if (!inner.value && !prevent.value) {
|
|
|
+ hovers.value.pop();
|
|
|
}
|
|
|
- },
|
|
|
- { immediate: true }
|
|
|
+ })
|
|
|
);
|
|
|
- });
|
|
|
- });
|
|
|
+ } else if (pHover) {
|
|
|
+ hovers.value[0] = pHover;
|
|
|
+ } else if (hovers.value.length) {
|
|
|
+ hovers.value.pop();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const stopHoverCheck = watch(
|
|
|
+ () => [hover.value, prevent.value, hovers.value[0]],
|
|
|
+ (_a, _b, onCleanup) => hoverChange(onCleanup)
|
|
|
+ );
|
|
|
+
|
|
|
stage.on("pointerdown.mouse-status", (ev) => {
|
|
|
+ if (prevent.value) return;
|
|
|
downTime = Date.now();
|
|
|
const target = shapeTreeContain(listeners.value, ev.target);
|
|
|
if (target && !press.value.includes(target)) {
|
|
@@ -90,7 +136,10 @@ export const useMouseShapesStatus = installGlobalVar(() => {
|
|
|
});
|
|
|
|
|
|
return mergeFuns(
|
|
|
+ stopHoverCheck,
|
|
|
+ hoverDestory,
|
|
|
listener(stage.container(), "pointerup", () => {
|
|
|
+ if (prevent.value) return;
|
|
|
press.value = [];
|
|
|
if (Date.now() - downTime >= 300) return;
|
|
|
if (downTarget) {
|