Я использую Konva 4.0.18 в React 16.8. Приложение, которое хорошо работает до сих пор в автономном режиме (CRA). При интеграции этого рабочего решения в существующий фрейм приложения я сталкиваюсь с ошибкой, которая появляется при преобразовании прямоугольника (и постоянно появляется при перемещении мыши, даже если преобразование прямоугольника прекращается при повторном нажатии):
Transformer. js: 316 Uncaught TypeError: Невозможно прочитать свойство 'getStage' undefined в e._handleMouseMove (Transformer. js: 316) при событиях по умолчанию-пассивных. js: 6
Снимок экрана отладчика в функции 'findOne', который возвращает 'undefined'
Существует компонент Masking
, который импортирует Stage
, Layout
и * 1014 Конвы * а также 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
componeht выглядит следующим образом:
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).
Может быть, вы можно г Вот несколько советов, как искать или отвечать на один из этих вопросов:
- Существует несколько обработчиков событий (click, mousemove), зарегистрированных на теле и других элементах вне самого React App, но они не должно влиять на приложение реакции, или я здесь не прав?
- Я вижу упоминание
default-passive-events
в ошибке. Как это может быть связано с проблемой (и если да, то как этого можно избежать)? - Вероятность возникновения проблемы в библиотеке Konva. js (см. Скриншот прилагается)
Заранее спасибо за любую помощь, комментарии, предложения, где / как искать