Я использую ограничивающий прямоугольник модуля NPM, чтобы нарисовать прямоугольники на изображении и определить, когда на них наводят курсор мыши. Большая часть логики c находится внутри самого модуля NPM. Программа полностью работоспособна, когда я импортирую изображение stati c для использования в качестве фона холста. Однако, если я сохраню изображение в состоянии, программа потеряет всю функциональность. Конечная цель - позволить фону холста динамически меняться без перезагрузки приложения.
Я обратился к автору пакета, но, к сожалению, он слишком занят, чтобы помочь. Исходный код довольно маленький, мне просто не хватает знаний React, чтобы полностью это исправить. Мне интересно, есть ли быстрое решение этой проблемы, если я должен просто написать это с нуля, или если по какой-то причине невозможно сохранить фон холста в состоянии.
Из того, что я Можно сказать, что компонент вызывает componentWillReceiveProps каждый раз, когда мышь перемещается, когда она функционирует должным образом. Однако, когда я использую изображение из состояния, движения мыши не обнаруживаются, и componentWillReceiveProps никогда не срабатывает. Это насколько я получил. Любая помощь будет принята с благодарностью! Соответствующий исходный код пакета ниже.
/* global Image */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import seedrandom from 'seedrandom';
class Boundingbox extends Component {
constructor(props) {
super(props);
this.state = {
canvasCreated: false,
hoverIndex: -1,
};
}
componentDidMount() {
console.log("MOUNTING")
const ctx = this.canvas.getContext('2d');
const background = new Image();
background.src = this.props.options.base64Image ?
'data:image/png;base64,' + this.props.image
:
this.props.image;
// Make sure the image is loaded first otherwise nothing will draw.
background.onload = (() => {
this.canvas.width = background.width;
this.canvas.height = background.height;
ctx.drawImage(background, 0, 0);
this.renderBoxes();
this.canvas.onmousemove = ((e) => {
// Get the current mouse position
console.log("mouse moving")
const r = this.canvas.getBoundingClientRect();
const scaleX = this.canvas.width / r.width;
const scaleY = this.canvas.height / r.height;
const x = (e.clientX - r.left) * scaleX;
const y = (e.clientY - r.top) * scaleY;
// ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
const selectedBox = { index: -1, dimensions: null };
if(this.props.boxes &&
this.props.boxes.length > 0) {
this.props.boxes.forEach((box, index) => {
if(!box || typeof box === 'undefined')
return null;
const coord = box.coord ? box.coord : box;
let [bx, by, bw, bh] = [0, 0, 0, 0]
if (
typeof coord.xmin !== 'undefined' &&
typeof coord.xmax !== 'undefined' &&
typeof coord.ymin !== 'undefined' &&
typeof coord.ymax !== 'undefined'
) {
// coord is an object containing xmin, xmax, ymin, ymax attributes
// width is absolute value of (xmax - xmin)
// height is absolute value of (ymax - ymin)
// absolute value takes care of various possible referentials:
// - sometimes 0,0 is top-left corner
// - sometimes 0,0 is bottom-left corner
[bx, by, bw, bh] = [
coord.xmin,
coord.ymax,
Math.abs(coord.xmax - coord.xmin),
Math.abs(coord.ymax - coord.ymin)
];
} else {
// coord is an array containing [x, y, width, height] values
[bx, by, bw, bh] = coord;
}
if (x >= bx && x <= bx + bw &&
y >= by && y <= by + bh) {
// The mouse honestly hits the rect
const insideBox = !selectedBox.dimensions || (
bx >= selectedBox.dimensions[0] &&
bx <= selectedBox.dimensions[0] + selectedBox.dimensions[2] &&
by >= selectedBox.dimensions[1] &&
by <= selectedBox.dimensions[1] + selectedBox.dimensions[3]
);
if (insideBox) {
selectedBox.index = index;
selectedBox.dimensions = box;
}
}
});
}
else if(this.state.pixelSegmentation &&
this.state.pixelSegmentation.length > 0) {
selectedBox.index = this.state.pixelSegmentation[x + this.canvas.width * y];
}
this.props.onSelected(selectedBox.index);
this.setState({ hoverIndex: selectedBox.index });
});
this.canvas.onmouseout = () => {
this.props.onSelected(-1);
this.setState({ hoverIndex: -1 });
// this.renderBoxes();
};
});
}
componentWillReceiveProps(nextProps) {
const ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
const background = new Image();
background.src = nextProps.options.base64Image ?
'data:image/png;base64,' + this.props.image
:
nextProps.image;
// Check canvas dimension with loaded image dimension
// in order to change canvas dimension if needed
background.onload = (() => {
console.log(this.canvas)
if(
this.canvas.width !== background.width &&
this.canvas.height !== background.height
) {
console.log("hit2")
this.canvas.width = background.width;
this.canvas.height = background.height;
ctx.drawImage(background, 0, 0);
this.renderBoxes(nextProps.boxes);
}
});
ctx.drawImage(background, 0, 0);
console.log("hit 3")
this.renderBoxes(nextProps.boxes);
this.setState({ hoverIndex: nextProps.selectedIndex });
return true;
}
componentDidUpdate() {
this.renderBoxes();
}
render() {
return <div className={this.props.className}>
<canvas
className="boundingBoxCanvas"
style={this.props.options.style}
ref={(canvas) => {
this.canvas = canvas;
}}
/>
</div>;
}
}
export default Boundingbox;