123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- import {
- WholeLineAttrib,
- WholeLineLine,
- WholeLinePoint,
- WholeLinePointAttrib,
- WholeLinePolygonAttrib,
- } from "../view";
- import { KonvaEventObject } from "konva/lib/Node";
- import { shapeParentsEq } from "../../../shared";
- import {
- wholeLineAddPoint,
- wholeLineFixLineAddPoint,
- wholeLinePolygonLastAddPoint,
- } from "./whole-line-mouse";
- import { Container } from "../../container";
- import { Attrib, ShapeType } from "../../../type";
- import {
- WholeLineChange,
- generateWholeLinePoygonId,
- getWholeLinePoint,
- getWholeLinePolygonPoints,
- mergeChange,
- wholeLineAddLineByPointIds,
- wholeLineDelPointByPointIds,
- } from "./whole-line-base";
- import { getAdsorbPosition } from "../../../shared/adsorb";
- export type PenWholeLinePoygonsEditProps<
- P extends Omit<WholeLinePointAttrib, "id">
- > = {
- tree: Container;
- config: WholeLineAttrib<P & Attrib>;
- polygonId?: string;
- adsorbRadius?: number;
- pointAttribFactory?: (pos: number[]) => Omit<P, "id">;
- quotePoint?: boolean;
- canOper?: (
- tree: WholeLineLine | WholeLinePoint,
- operShape: ShapeType
- ) => boolean;
- canDelPoint?: (point: P, evt: KonvaEventObject<any>) => boolean;
- changePolygon?: (polygonId: string) => void;
- autoClose?: boolean;
- };
- /**
- * 钢笔模式编辑多边形
- * @param polygonId
- */
- export const penWholeLinePoygonsEdit = <
- P extends Omit<WholeLinePointAttrib, "id">
- >({
- tree,
- config,
- polygonId,
- pointAttribFactory,
- quotePoint,
- canOper,
- adsorbRadius,
- canDelPoint,
- changePolygon,
- autoClose,
- }: PenWholeLinePoygonsEditProps<P>) => {
- pointAttribFactory =
- pointAttribFactory ||
- ((pos: number[]) =>
- ({
- x: pos[0],
- y: pos[1],
- } as P));
- const getPolygonAttrib = (polygonId: string) => {
- if (!polygonId) {
- const id = generateWholeLinePoygonId(config);
- config.polygons.push({
- id,
- lineIds: [],
- });
- return config.polygons[config.polygons.length - 1];
- } else {
- return config.polygons.find(({ id }) => id === polygonId);
- }
- };
- let polyginAttrib: WholeLinePolygonAttrib;
- let newMode = false;
- let prevId: string | null = null;
- const start = (currentPolygonId: string | null) => {
- polyginAttrib = getPolygonAttrib(currentPolygonId);
- if (!polyginAttrib) {
- throw `${currentPolygonId}的多边形不存在!`;
- }
- changePolygon && changePolygon(polyginAttrib.id);
- polygonId = polyginAttrib.id;
- newMode = !currentPolygonId;
- prevId = null;
- };
- start(polygonId);
- const removePolygon = () => {
- const ndx = config.polygons.indexOf(polyginAttrib);
- if (~ndx) {
- config.polygons.splice(ndx, 1);
- }
- };
- const continuous = (
- evt: KonvaEventObject<any>
- ): { change: WholeLineChange; isClose?: boolean } => {
- let change: WholeLineChange = {
- lineChange: {
- del: [],
- update: [],
- add: [],
- },
- polygonChange: {
- add: [],
- update: [],
- del: [],
- },
- pointChange: {
- add: [],
- del: [],
- },
- };
- const target = shapeParentsEq(evt.target, (shape) => {
- const id = shape.id();
- return (
- id.includes(WholeLineLine.namespace) ||
- id.includes(WholeLinePoint.namespace)
- );
- });
- const child = target && tree.find(target.id());
- const pixel = [evt.evt.offsetX, evt.evt.offsetY];
- if (child instanceof WholeLineLine) {
- if (!canOper || canOper(child, evt.target)) {
- if (polyginAttrib.lineIds.includes(child.attrib.id)) {
- const { change: cChange } = wholeLineFixLineAddPoint(
- config,
- child.attrib.id,
- pointAttribFactory(tree.getRealFromStage(pixel))
- );
- return { change: mergeChange(change, cChange), isClose: false };
- }
- }
- }
- let pointAttrib: P & Attrib;
- if (child instanceof WholeLinePoint) {
- if (canOper && !canOper(child, evt.target)) {
- return { change, isClose: false };
- }
- pointAttrib = quotePoint ? child.attrib : { ...child.attrib };
- if (polyginAttrib.id === prevId) {
- return { change, isClose: false };
- }
- }
- const polygonPoints = getWholeLinePolygonPoints(config, polyginAttrib.id);
- if (!pointAttrib) {
- let position: number[];
- if (adsorbRadius) {
- const points = polygonPoints.map(({ x, y }) => [x, y]);
- if (prevId) {
- const prev = getWholeLinePoint(config, prevId);
- points.push([prev.x, prev.y]);
- }
- position = getAdsorbPosition({
- tree,
- pixel,
- radius: adsorbRadius,
- points,
- });
- } else {
- position = tree.getRealFromStage(pixel);
- }
- pointAttrib = pointAttribFactory(position) as P & Attrib;
- }
- const curNdx = polygonPoints.findIndex(({ id }) => id === pointAttrib.id);
- const isClose = curNdx === 0 && (!autoClose || polygonPoints.length >= 3);
- // 存在的情况下删除
- if (curNdx >= 0 && !isClose) {
- const cChange = wholeLineDelPointByPointIds(
- config,
- pointAttrib.id,
- !canDelPoint || canDelPoint(pointAttrib, evt)
- );
- change = mergeChange(change, cChange);
- if (polyginAttrib.lineIds.length === 0) {
- removePolygon();
- const repPoint = cChange.pointChange.del.find(
- ({ id }) => id !== pointAttrib.id
- );
- delete repPoint.id;
- start(null);
- prevId = wholeLineAddPoint(config, repPoint).id;
- change.pointChange.add.push({
- ...repPoint,
- id: prevId,
- });
- }
- return { change, isClose };
- }
- if (!quotePoint) {
- delete pointAttrib.id;
- }
- if (polyginAttrib.lineIds.length > 0) {
- if (newMode) {
- const mChange = wholeLinePolygonLastAddPoint(
- config,
- polygonId,
- pointAttrib
- ).change;
- // 持续添加模式
- return { change: mergeChange(change, mChange), isClose };
- } else {
- // 直接当成新建操作
- start(null);
- return continuous(evt);
- }
- } else if (prevId) {
- const { line, change: mChange } = wholeLineAddLineByPointIds(config, [
- prevId,
- wholeLineAddPoint(config, pointAttrib).id,
- ]);
- change = mergeChange(change, mChange, {
- polygonChange: {
- update: [
- {
- before: { ...polyginAttrib, lineIds: [...polyginAttrib.lineIds] },
- after: {
- ...polyginAttrib,
- lineIds: [...polyginAttrib.lineIds, line.id],
- },
- },
- ],
- },
- pointChange: {
- add: [pointAttrib],
- },
- });
- polyginAttrib.lineIds.push(line.id);
- prevId = null;
- return { change, isClose };
- } else {
- const addPoint = wholeLineAddPoint(config, pointAttrib)!;
- prevId = addPoint.id;
- change.pointChange.add.push(addPoint);
- return { change, isClose };
- }
- };
- const end = () => {
- // 没有两个点以上的多边形直接删除
- if (polyginAttrib.lineIds.length === 0) {
- if (prevId) {
- wholeLineDelPointByPointIds(config, prevId);
- }
- removePolygon();
- }
- changePolygon && changePolygon(null);
- };
- const getStatus = () => ({
- newMode,
- polyginAttribId: polyginAttrib.id,
- prevId,
- config,
- });
- return {
- continuous,
- end,
- getStatus,
- setStatus: (status: ReturnType<typeof getStatus>) => {
- newMode = status.newMode;
- polyginAttrib = status.config.polygons.find(
- ({ id }) => id === status.polyginAttribId
- );
- polygonId = polyginAttrib.id;
- prevId = status.prevId;
- config = status.config;
- },
- };
- };
|