2

我在 React 16.8 中使用 Konva 4.0.18。应用程序,迄今为止在独立 (CRA) 中运行良好。当将此工作解决方案集成到现有的应用程序框架中时,我遇到了一个在转换矩形时出现的错误(即使再次单击时矩形转换停止,也会在移动鼠标时不断出现):

Transformer.js:316 未捕获的类型错误:无法在默认被动事件.js:6 处读取 e._handleMouseMove (Transformer.js:316) 处未定义的属性“getStage”

函数“findOne”的调试器屏幕截图,该函数返回“未定义”

有一个Masking组件可以导入 Konva 的Stage, LayoutandImage以及MaskingRectangle可以转换的。

import React, { useState, useEffect, useRef } from "react";
import MaskingRectangle from "./maskingRectangle";

const Masking = ({ canvas }) => {
    const stageWrapperRef = useRef(null);
    const [stageWidth, setStageWidth] = useState(600);
    const [stageHeight, setStageHeight] = useState(400);
    const [maskingRectangles, setMaskingRectangles] = useState([]);
    const [shapes, setShapes] = useState([]);
    const [selectedId, selectShape] = useState(null);

    const [Stage, setStage] = useState(null);
    const [Layer, setLayer] = useState(null);
    const [Image, setImage] = useState(null);

    const addRectangle = e => {
        const getRandomInt = max => {
            return Math.floor(Math.random() * Math.floor(max));
        };
        let rectX = getRandomInt(100);
        let rectY = getRandomInt(100);
        if (e) {
            const { x, y } = e.currentTarget.getPointerPosition();
            rectX = x;
            rectY = y;
        }

        const rect = {
            x: rectX,
            y: rectY,
            width: 100,
            height: 100,
            fill: "rgba(255,0,0,0.4)",
            id: `rect${maskingRectangles.length + 1}`
        };
        const rects = maskingRectangles.concat([rect]);
        setMaskingRectangles(rects);
        const shs = shapes.concat([`rect${maskingRectangles.length + 1}`]);
        setShapes(shs);
    };

    const deleteActiveRectangle = () => {
        setMaskingRectangles(
            maskingRectangles.filter(rect => rect.id !== selectedId)
        );
        setShapes(shapes.filter(shape => shape !== selectedId));
        selectShape(null);
    };

    const onStageClick = e => {
        if (e.target.attrs.className !== "mask-rect") {
            selectShape(null);
        }
    };

    const onStageDblClick = e => {
        const stage = e.target.parent.parent;
        const elem = e.currentTarget;

        if (elem.clickStartShape.attrs.className !== "mask-rect") {
            addRectangle(e);
        }

        if (elem.clickStartShape.attrs.id === selectedId) {
            deleteActiveRectangle();
            stage.container().style.cursor = "crosshair";
        }
    };

    useEffect(() => {
        async function loadKonvaModules() {
            await import("react-konva").then(module => {
                setStage(() => module.Stage);
                setLayer(() => module.Layer);
                setImage(() => module.Image);
            });
        }
        loadKonvaModules();
        const scaleX = stageWrapperRef.current.clientWidth / canvas.width;
        const scaleY = stageWrapperRef.current.clientHeight / canvas.height;
        const scalingFactor = Math.min(scaleX, scaleY);
        setStageWidth(canvas.width * scalingFactor);
        setStageHeight(canvas.height * scalingFactor);
    }, []);

    return (
        <div>
            <div className="stage-wrapper" ref={stageWrapperRef}>
                <Stage
                    className="stage"
                    width={stageWidth}
                    height={stageHeight}
                    onClick={onStageClick}
                    onDblClick={onStageDblClick}
                >
                    <Layer className="layer1">
                        <Image
                            image={canvas}
                            width={stageWidth}
                            height={stageHeight}
                        />

                        {maskingRectangles.map((rect, i) => {
                            return (
                                <MaskingRectangle
                                    key={i}
                                    shapeProps={rect}
                                    isSelected={rect.id === selectedId}
                                    onSelect={() => {
                                        selectShape(rect.id);
                                    }}
                                    onChange={newAttrs => {
                                        const rects = maskingRectangles.slice();
                                        rects[i] = newAttrs;
                                        setMaskingRectangles(rects);
                                    }}
                                    onMouseEnter={e => {
                                        const stage = e.target.parent.parent;
                                        stage.container().style.cursor = "move";
                                    }}
                                    onMouseOut={e => {
                                        const stage = e.target.parent.parent;
                                        stage.container().style.cursor =
                                            "crosshair";
                                    }}
                                    stageProps={{
                                        width: stageWidth,
                                        height: stageHeight
                                    }}
                                />
                            );
                        })}
                    </Layer>
                </Stage>
            </div>
        </div>
    );
};

export default Masking;

我的MaskinRectangle组件看起来像这样:

import React from "react";
import { Rect, Transformer } from "react-konva";

const MaskingRectangle = ({
    shapeProps,
    isSelected,
    onSelect,
    onChange,
    stageProps,
    onMouseEnter,
    onMouseOver,
    onMouseOut,
    onMouseMove
}) => {
    const shapeRef = React.useRef();
    const trRef = React.useRef();

    React.useEffect(() => {
        if (isSelected) {
            trRef.current.setNode(shapeRef.current);
            trRef.current.getLayer().batchDraw();
        }
    }, [isSelected]);

    const dragBoundFunc = pos => {
        //Limit Min/Max x,y position
        const stageWidth = (stageProps && stageProps.width) || 800;
        const stageHeight = (stageProps && stageProps.height) || 600;
        const minX = 0;
        const minY = 0;
        const maxX = stageWidth - shapeRef.current.attrs.width;
        const maxY = stageHeight - shapeRef.current.attrs.height;
        const newX = pos.x < minX ? minX : pos.x > maxX ? maxX : pos.x;
        const newY = pos.y < minY ? minY : pos.y > maxY ? maxY : pos.y;

        return {
            x: newX,
            y: newY
        };
    };

    return (
        <>
            <Rect
                className="mask-rect"
                onClick={onSelect}
                onTap={onSelect}
                ref={shapeRef}
                {...shapeProps}
                draggable
                onTouchMove={null}
                onDragEnd={e => {
                    onChange({
                        ...shapeProps,

                        x: e.target.x(),
                        y: e.target.y()
                    });
                }}
                onTransformEnd={e => {
                    const node = shapeRef.current;
                    const scaleX = node.scaleX();
                    const scaleY = node.scaleY();
                    node.scaleX(1);
                    node.scaleY(1);
                    onChange({
                        ...shapeProps,
                        x: node.x(),
                        y: node.y(),
                        width: node.width() * scaleX,
                        height: node.height() * scaleY
                    });
                    e.evt.preventDefault();
                }}
                dragBoundFunc={dragBoundFunc}
                onMouseOver={onMouseOver}
                onFocus={onMouseOver}
                onMouseEnter={onMouseEnter}
                onMouseOut={onMouseOut}
                onBlur={onMouseOut}
                onMouseMove={onMouseMove}
            />
            {isSelected && <Transformer ref={trRef} rotateEnabled={false} />}
        </>
    );
};

export default MaskingRectangle;

一些想法/猜测:我想知道为什么它作为一个独立的应用程序工作得很好,但是当包含在现有的 HTML 页面中时会失败(顺便说一下,它还包括 jquery 和 Angular 1.x 等库)。

也许您可以给我一些提示如何搜索或回答以下问题之一:

  1. 在 React 应用程序本身之外的主体和其他元素上注册了几个事件处理程序(单击、鼠标移动),但它们不应该影响反应应用程序,还是我错了?
  2. 我看到错误中提到了default-passive-events。这可能与问题有什么关系(如果是,如何避免)?
  3. 是否更有可能是 Konva.js 库有问题(见附件截图)

提前感谢您提供的任何帮助、评论、建议在哪里/如何查看

4

0 回答 0