diff --git a/src/AnnotationDrawing.js b/src/AnnotationDrawing.js index a7ec0469faefefe066e85e3141a803fd5a1be985..0b9f49601599b8294e7e094d704cb4c9ec2d3566 100644 --- a/src/AnnotationDrawing.js +++ b/src/AnnotationDrawing.js @@ -76,7 +76,7 @@ class AnnotationDrawing extends Component { return; } - console.log('selected shape id', selectedShapeId); + if (!selectedShapeId) { return; } @@ -138,99 +138,133 @@ class AnnotationDrawing extends Component { handleMouseDown = (e) => { - try{ + try { + + const pos = e.target.getStage().getPointerPosition(); + console.log('mouse down', this.props.activeTool); + let shape = null; + switch (this.props.activeTool) { + case 'rectangle': + case 'ellipse': + this.setState({ + isDrawing: true, + currentShape: { + type: this.props.activeTool, + x: pos.x, + y: pos.y, + width: 0, + height: 0, + strokeColor: this.props.strokeColor, + strokeWidth: this.props.strokeWidth, + fill: this.props.fillColor, + id: uuidv4(), + }, + },() => { + // Add global key press event listener + window.addEventListener('keydown', this.handleKeyPress); + }); + break; + case "text": - const pos = e.target.getStage().getPointerPosition(); - console.log('mouse down', this.props.activeTool); - let shape = null; - switch (this.props.activeTool) { - case 'rectangle': - case 'ellipse': - this.setState({ - isDrawing: true, - currentShape: { - type: this.props.activeTool, + shape = { + type: 'text', x: pos.x, y: pos.y, - width: 0, - height: 0, - stroke: this.props.strokeColor, - strokeWidth: this.props.strokeWidth, + fontSize: 20, fill: this.props.fillColor, + text: 'text', id: uuidv4(), - }, - }); - break; - case "text": + }; + + + this.setState({ + + shapes: [...this.state.shapes, shape], + selectedShape: shape, + selectedShapeId: shape.id, + newShape: shape, + currentShape: shape, + },() => { + // Add global key press event listener + window.addEventListener('keydown', this.handleKeyPress); + }); + console.log('text', shape); + break; + + + case "line": + shape = { + type: 'line', + x: pos.x, + y: pos.y, + with: 10, + height: 10, + fill: this.props.fillColor, + points: [0, 0, 0, 0, 0, 0], + id: uuidv4(), + }; + + this.setState({ + + shapes: [...this.state.shapes, shape], + selectedShape: shape, + selectedShapeId: shape.id, + newShape: shape, + currentShape: shape, + },() => { + // Add global key press event listener + window.addEventListener('keydown', this.handleKeyPress); + }); + break; - shape = { - type: 'text', - x: pos.x, - y: pos.y, - fontSize: 20, - fill: this.props.fillColor, - text: 'text', - id: uuidv4(), - }; - - this.setState({ newShape: shape }, () => { - // Add global key press event listener - window.addEventListener('keydown', this.handleKeyPress); - }); - this.setState({ - shapes: [...this.state.shapes, shape], - selectedShape: shape, - selectedShapeId: shape.id, - newShape: shape, - currentShape: shape, - }); - console.log('text', shape); - break; case "freehand": - const points = [pos.x, pos.y]; + const points = [pos.x, pos.y]; - shape = { - type: 'freehand', - x: pos.x, - y: pos.y, - with:1920, - height:1080, - fill: this.props.fillColor, - points: points, - id: uuidv4(), - }; + shape = { + type: 'freehand', + x: pos.x, + y: pos.y, + with: 1920, + height: 1080, + fill: this.props.fillColor, + points: points, + id: uuidv4(), + }; - this.setState({ + this.setState({ - shapes: [...this.state.shapes, shape], - selectedShape: shape, - selectedShapeId: shape.id, - newShape: shape, - currentShape: shape, - }); - - // other cases - } + shapes: [...this.state.shapes, shape], + selectedShape: shape, + selectedShapeId: shape.id, + newShape: shape, + currentShape: shape, + },() => { + // Add global key press event listener + window.addEventListener('keydown', this.handleKeyPress); + }); + // other cases + } - if( this.state.currentShape===null ) return; - // Check if the current shape is a freehand object - if (this.state.selectedShapeId && this.state.currentShape.type === 'freehand') { - // Start drawing - this.setState({ - isDrawing: true, - shapes: this.state.shapes.map(shape => shape.id === this.state.selectedShapeId - ? { ...shape, points: [...shape.points, e.evt.clientX, e.evt.clientY] } - : shape) - }); - } - }catch(e){ - console.log('error',e); + if (this.state.currentShape === null) return; + // Check if the current shape is a freehand object + if (this.state.selectedShapeId && this.state.currentShape.type === 'freehand') { + // Start drawing + this.setState({ + isDrawing: true, + shapes: this.state.shapes.map(shape => shape.id === this.state.selectedShapeId + ? { ...shape, points: [...shape.points, e.evt.clientX, e.evt.clientY] } + : shape) + }); + } + + } catch (e) { + console.log('error', e); } }; @@ -240,46 +274,72 @@ class AnnotationDrawing extends Component { // // Add the new point to the current shape - + // }; handleMouseMove = (e) => { - try{ - console.log('mouse move', this.props.activeTool); - if (!this.state.isDrawing) return; - - - if(this.state.currentShape===null ) return; - const pos = e.target.getStage().getPointerPosition(); - - switch (this.props.activeTool) { - case 'rectangle': - case 'ellipse': - this.setState({ - currentShape: { - ...this.state.currentShape, - width: pos.x - this.state.currentShape.x, - height: pos.y - this.state.currentShape.y, - }, - }); - - break; - case "freehand": - this.setState({ - shapes: this.state.shapes.map(shape => shape.id === this.state.selectedShapeId - ? { ...shape, points: [...shape.points, e.evt.clientX, e.evt.clientY] } - : shape) - }); - break; - - default: - break; - } + try { + console.log('mouse move', this.props.activeTool); + if (!this.state.isDrawing) return; + + + if (this.state.currentShape === null) return; + const pos = e.target.getStage().getPointerPosition(); + + switch (this.props.activeTool) { + case 'rectangle': + case 'ellipse': + + // prevent negative radius for ellipse + + if (this.state.currentShape.type === 'ellipse') { + if (pos.x < this.state.currentShape.x) { + pos.x = this.state.currentShape.x; + } + if (pos.y < this.state.currentShape.y) { + pos.y = this.state.currentShape.y; + } + } + + + + this.setState({ + currentShape: { + ...this.state.currentShape, + width: pos.x - this.state.currentShape.x, + height: pos.y - this.state.currentShape.y, + }, + }); - }catch(e){ - console.log('error',e); + break; + case "line": + // update ponts + + + + + this.setState({ + currentShape: { + ...this.state.currentShape, + points: [0, 0, 0, 0, pos.x, pos.y], + }, + }); + case "freehand": + this.setState({ + shapes: this.state.shapes.map(shape => shape.id === this.state.selectedShapeId + ? { ...shape, points: [...shape.points, e.evt.clientX, e.evt.clientY] } + : shape) + }); + break; + + default: + break; + } + + } catch (e) { + console.log('error', e); } }; @@ -287,19 +347,43 @@ class AnnotationDrawing extends Component { handleMouseUp = () => { // Stop drawing - try{ - console.log('mouse up', this.props.activeTool); - if (!this.state.isDrawing) return; - if (!this.state.currentShape) return; + try { + console.log('mouse up', this.props.activeTool); + if (!this.state.isDrawing) return; + if (!this.state.currentShape) return; + + switch (this.props.activeTool) { + + case 'rectangle': + case 'ellipse': + + this.setState((prevState) => ({ + isDrawing: false, + shapes: [...prevState.shapes, prevState.currentShape], + currentShape: null, + })); + break; + case "line": + this.setState((prevState) => ({ + isDrawing: false, + shapes: [...prevState.shapes, prevState.currentShape], + currentShape: null, + })); + break; + case "freehand": + this.setState((prevState) => ({ + isDrawing: false, + shapes: [...prevState.shapes, prevState.currentShape], + currentShape: null, + })); + break; + default: - this.setState((prevState) => ({ - isDrawing: false, - shapes: [...prevState.shapes, prevState.currentShape], - currentShape: null, - })); + + } } - catch(e){ - console.log('error',e); + catch (e) { + console.log('error', e); } }; @@ -336,11 +420,11 @@ class AnnotationDrawing extends Component { > - { <ParentComponent shapes={shapes} + {<ParentComponent shapes={shapes} onShapeClick={this.onShapeClick} activeTool={this.props.activeTool} selectedShapeId={this.state.selectedShapeId} - /> } + />} <Layer> diff --git a/src/shapes/LineNode.js b/src/shapes/LineNode.js new file mode 100644 index 0000000000000000000000000000000000000000..64be1cf5707ccf227b368c3978fa2f92f04648d2 --- /dev/null +++ b/src/shapes/LineNode.js @@ -0,0 +1,68 @@ +import React, { Component, useState } from 'react'; +import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; + +import { + Stage, Layer, Star, Text, Circle, Rect + , Ellipse, Transformer,Shape, Line, + +} from 'react-konva'; + + + + + +class LineNode extends React.Component { + + constructor(props) { + super(props); + this.shapeRef = React.createRef(); + this.trRef = React.createRef(); + } + + componentDidMount() { + if (this.trRef.current) { + this.trRef.current.nodes([this.shapeRef.current]); + this.trRef.current.getLayer().batchDraw(); + } + } + + handleClick = () => { + this.props.onShapeClick(this.props.shape); + + }; + + render() { + const { activeTool } = this.props; + const isSelected = this.props.selectedShapeId === this.props.shape.id + + return ( + <React.Fragment> + <Line + // map props to konva + ref={this.shapeRef} + x={this.props.x || 0} + y={this.props.y || 0} + + points={this.props.points || [0, 0, 0, 0, 100, 100]} + fill={this.props.fill } + stroke={this.props.fill } + strokeWidth={this.props.strokeWidth || 1} + id={this.props._id} + draggable={activeTool === 'cursor' || activeTool === 'edit'} + onClick={this.handleClick} + + /> + + <Transformer ref={this.trRef} + + visible={activeTool === 'edit' && isSelected} + /> + + </React.Fragment> + ); + } +} + + +export default LineNode; \ No newline at end of file diff --git a/src/shapes/ParentComponent.js b/src/shapes/ParentComponent.js index a57324b5fbe4d6105a4b3f14cf13d092959912dc..933f48c8c100f9e772c26f4b6db5776941445fc3 100644 --- a/src/shapes/ParentComponent.js +++ b/src/shapes/ParentComponent.js @@ -8,6 +8,7 @@ import Rectangle from './Rectangle'; import EllipseNode from './EllipseNode'; import TextNode from './TextNode'; +import LineNode from './LineNode'; import { Stage, Layer, Star, Text, Circle, Rect , Ellipse, Transformer,Shape @@ -183,6 +184,32 @@ class ParentComponent extends React.Component { /> ); break; + case 'line': + return ( + <LineNode + + shape={shape} + selectedShapeId={selid} + selectedShape={selectedShape} + onShapeClick={this.handleShapeClick} + activeTool={this.props.activeTool} + selected={selected} + + _id={shape.id} + key={i} + x={shape.x} + y={shape.y} + points={shape.points} + fill={shape.fill} + stroke={shape.strokeColor} + strokeWidth={shape.strokeWidth} + draggable={this.props.activeTool === 'cursor'} + onClick={this.props.activeTool === 'cursor' ? () => this.setState({ currentShape: shape }) : null} + // onDragEnd={this.handleDragEnd(shape.id)} // Add this line + onDblClick={this.handleShapeDblClick} + /> + ); + } })} </Layer>