lost-sia
Version:
Single Image Annotation Tool
283 lines (261 loc) • 6.2 kB
JSX
import React, { Component } from "react";
import "./Annotation.scss";
import * as modes from "../types/modes";
import * as cursorstyles from "../types/cursorstyles";
class Node extends Component {
/*************
* LIFECYCLE *
**************/
constructor(props) {
super(props);
this.state = {
haloCss: "node-halo-off",
selAreaCss: "sel-area-off",
// anno: undefined,
nodeSelected: false,
style: {},
};
}
componentDidMount() {
this.setState({
// anno: this.props.anno,
style: {
...this.props.style,
cursor: this.getCursorStyle(this.props.mode),
},
});
// switch (this.props.mode){
// case modes.CREATE:
// if (this.props.idx !== 0){
// this.turnSelAreaOn()
// }
// default:
// break
// }
}
componentDidUpdate(prevProps) {
switch (this.props.mode) {
case modes.CREATE:
if (this.props.idx !== 0 || this.props.isPoint) {
this.turnSelAreaOn();
}
break;
case modes.EDIT:
this.turnSelAreaOn();
break;
default:
break;
}
//on mode change
if (prevProps.mode !== this.props.mode) {
this.setState({
style: {
...this.state.style,
cursor: this.getCursorStyle(this.props.mode),
},
});
}
if (prevProps.style !== this.props.style) {
this.setState({
style: {
...this.state.style,
...this.props.style,
cursor: this.getCursorStyle(this.props.mode),
},
});
}
}
/*************
* EVENTS *
**************/
onClick(e) {
this.turnHaloOn();
if (this.props.onClick) {
this.props.onClick(e, this.props.idx);
}
}
onMouseMove(e) {
if (this.props.onMouseMove) {
this.props.onMouseMove(e, this.props.idx);
}
// switch (this.props.mode){
// case modes.CREATE:
// let newAnno = [...this.state.anno]
// const mousePos = mouse.getMousePosition(e, this.props.svg)
// newAnno[this.props.idx].x = mousePos.x
// newAnno[this.props.idx].y = mousePos.y
// this.setState({
// anno: newAnno
// })
// if (this.props.onAnnoUpdate){
// this.props.onAnnoUpdate(e, this.props.idx, newAnno)
// }
// default:
// break
// }
}
onContextMenu(e) {
e.preventDefault();
}
onMouseUp(e) {
switch (this.props.mode) {
case modes.EDIT:
switch (e.button) {
case 0:
this.turnSelAreaOff();
break;
default:
break;
}
break;
default:
break;
}
if (this.props.onMouseUp) {
this.props.onMouseUp(e, this.props.idx);
}
}
onMouseDown(e) {
e.stopPropagation();
if (this.props.onMouseDown) {
this.props.onMouseDown(e, this.props.idx);
}
switch (this.props.mode) {
case modes.CREATE:
switch (e.button) {
case 0:
this.turnSelAreaOff();
break;
case 2:
this.turnSelAreaOff();
break;
default:
break;
}
// case modes.EDIT:
// switch (e.button){
// case 0:
// this.turnSelAreaOn()
// break
// default:
// break
// }
break;
default:
break;
}
}
onMouseOver(e) {
if (this.props.isSelected) {
this.turnHaloOn();
}
}
onMouseLeave(e) {
if (this.props.isSelected) {
this.turnHaloOff();
}
}
onDoubleClick(e) {
if (this.props.onDoubleClick) {
this.props.onDoubleClick(e, this.props.idx);
}
}
handleMouseLeave(e) {
if (this.props.onMouseLeave) {
this.props.onMouseLeave(e, this.props.idx);
}
}
/*************
* LOGIC *
**************/
getCursorStyle(mode) {
switch (mode) {
case modes.CREATE:
return cursorstyles.CREATE_NODE;
case modes.EDIT:
return cursorstyles.EDIT_NODE;
case modes.VIEW:
return cursorstyles.NORMAL_NODE;
default:
break;
}
}
turnSelAreaOn() {
if (this.state.selAreaCss !== "sel-area-on") {
this.setState({
selAreaCss: "sel-area-on",
});
}
}
turnSelAreaOff() {
if (this.state.selAreaCss !== "sel-area-off") {
this.setState({
selAreaCss: "sel-area-off",
});
}
}
turnHaloOn() {
this.setState({
haloCss: "node-halo-on",
});
}
turnHaloOff() {
this.setState({
haloCss: "node-halo-off",
});
}
/*************
* RENDERING *
**************/
renderHalo() {
if (this.state.haloCss === "node-halo-off") return null;
const data = this.props.anno[this.props.idx];
return (
<circle
cx={data.x}
cy={data.y}
r={this.props.style.r * 3}
className={this.state.haloCss}
onMouseLeave={(e) => this.onMouseLeave(e)}
/>
);
}
renderNodes() {
const data = this.props.anno[this.props.idx];
if (data === undefined) {
return;
}
return (
<g
onClick={(e) => this.onClick(e)}
onMouseMove={(e) => this.onMouseMove(e)}
onContextMenu={(e) => this.onContextMenu(e)}
onMouseUp={(e) => this.onMouseUp(e)}
onMouseDown={(e) => this.onMouseDown(e)}
onDoubleClick={(e) => this.onDoubleClick(e)}
onMouseLeave={(e) => this.handleMouseLeave(e)}
>
<circle
cx={data.x}
cy={data.y}
r={"100%"}
className={this.state.selAreaCss}
/>
{this.renderHalo()}
<circle
cx={data.x}
cy={data.y}
r={3}
fill="red"
style={this.state.style}
className={this.props.className}
onMouseOver={(e) => this.onMouseOver(e)}
/>
</g>
);
}
render() {
return <g>{this.renderNodes()}</g>;
}
}
export default Node;