我在 React 16.8 中使用 Konva 4.0.18。应用程序,迄今为止在独立 (CRA) 中运行良好。当将此工作解决方案集成到现有的应用程序框架中时,我遇到了一个在转换矩形时出现的错误(即使再次单击时矩形转换停止,也会在移动鼠标时不断出现):
Transformer.js:316 未捕获的类型错误:无法在默认被动事件.js:6 处读取 e._handleMouseMove (Transformer.js:316) 处未定义的属性“getStage”
函数“findOne”的调试器屏幕截图,该函数返回“未定义”
有一个Masking
组件可以导入 Konva 的Stage
, Layout
andImage
以及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 等库)。
也许您可以给我一些提示如何搜索或回答以下问题之一:
- 在 React 应用程序本身之外的主体和其他元素上注册了几个事件处理程序(单击、鼠标移动),但它们不应该影响反应应用程序,还是我错了?
- 我看到错误中提到了
default-passive-events
。这可能与问题有什么关系(如果是,如何避免)? - 是否更有可能是 Konva.js 库有问题(见附件截图)
提前感谢您提供的任何帮助、评论、建议在哪里/如何查看