Ad

Drawing 4 Circles In A Canvas In Reactjs

- 1 answer

I am trying to draw multi color circles in a canvas image. When I draw one circle previous circle was deleted.So I make a function to replicate the previous circle but there I was unable to get the exact coordinate of the center of the circle and a straight line is created. I am sharing my code. In the draw circle function I need the proper centerx and centery.


class Circle extends Component {
    constructor(props) {
        super(props);
        //added state 
        this.state = {
            isDown: false,
            previousPointX: '',
            previousPointY: '',
            base_image: {},
            circleConfig: {
                maxCircle: 4,
                color: ["red", "blue", "#ffa500", "green"]
            },
            circles: [],
            canvasId: this.props.canvasid,
            rotate:this.props.rotate
        }
        this.handleMouseDown = this.handleMouseDown.bind(this);
        this.handleMouseMove = this.handleMouseMove.bind(this);
        this.handleMouseUp = this.handleMouseUp.bind(this);
    }

    render() {
        return (
            <div>
                <canvas  ref="canvas" className="CursorCanvas"
                    width={400}
                    height={390}
                    onMouseDown={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseDown(nativeEvent);
                        }}
                    onMouseMove={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseMove(nativeEvent);
                        }}
                    onMouseUp={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseUp(nativeEvent);
                        }}
                />
                <pre hidden>{JSON.stringify(this.state.lines, null, 2)}</pre>
            </div>
        );
    }

    drawCircle(circles, ctx) {
        console.log('draw circle',circles)
        circles.forEach((item) => {
            var r=(item.endx-item.startx)/2;
            var centerx=(item.endx-item.startx)/2;
            var centery=(item.endy-item.starty)/2;
            ctx.arc(centerx, centery, r, 0, 2 * Math.PI);
           ctx.strokeStyle = item.color ;


        })
    }

    handleMouseDown(event) {
        if (this.state.circles.length >= this.state.circleConfig.maxCircle) return;

        this.setState({
            isDown: true,
            previousPointX: event.offsetX,
            previousPointY: event.offsetY
        },()=>{
          console.log('mousedown',this.state)
        })
    }

    handleMouseMove(event){
      if (this.state.isDown) {
        event.preventDefault();
        event.stopPropagation();
        const canvas = ReactDOM.findDOMNode(this.refs.canvas);
            var x = event.offsetX;
            var y = event.offsetY;
            var ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(this.state.base_image, 0, 0);
            //Save
            ctx.save();
            ctx.beginPath();
            this.drawCircle(this.state.circles,ctx);
            var circleLength = this.state.circles.length || 0;

            //Dynamic scaling
            var scalex = (x-this.state.previousPointX)/2;
            var scaley = (y-this.state.previousPointY)/2;
            ctx.scale(scalex,scaley);
            //Create ellipse
            var centerx = (this.state.previousPointX/scalex)+1;
            var centery = (this.state.previousPointY/scaley)+1;
            ctx.arc(centerx, centery, 1, 0, 2*Math.PI);
            ctx.restore();
            ctx.stroke();     
            ctx.strokeStyle = this.state.circleConfig.color[circleLength];;

      }

    }
    handleMouseUp(event) {
        if (this.state.circles.length >= this.state.circleConfig.maxCircle) return;
        this.setState({
            isDown: false
        });
        console.log('mouseup',this.state)
        const canvas = ReactDOM.findDOMNode(this.refs.canvas);
        var x = event.offsetX;
        var y = event.offsetY;
        var ctx = canvas.getContext("2d");
        var circleLength = this.state.circles.length || 0;

        if (this.state.previousPointX !== x && this.state.previousPointY !== y) {
            this.setState({
                circles: this.state.circles.concat({
                    startx: this.state.previousPointX,
                    starty: this.state.previousPointY,
                    endx: x,
                    endy: y,
                    color: this.state.circleConfig.color[circleLength]
                })
            },
                () => {
                    ctx.stroke();
                    ctx.closePath();
                    this.props.drawCircleToStore(this.state.circles, this.state.canvasId, this.props.imgSrc,this.state.rotate)
                }
            );
        }
    }
    componentDidMount(){
        const canvas = ReactDOM.findDOMNode(this.refs.canvas);
        const ctx = canvas.getContext("2d");
        const base_image = new Image();
        base_image.src = this.props.imgSrc
        base_image.onload = function (){
            ctx.drawImage(base_image, 0, 0);
        }
        this.setState({
            base_image: base_image
        });
    }
}

Ad

Answer

In the drawCircle metho the center coordinate wil be

var r = (item.endx - item.startx) / 2;
centerx = (r + item.startx);
centery = (r + item.starty);
ctx.arc(centerx, centery, r, 0, 2 * Math.PI);

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


class CircleMultiple extends Component {
    constructor(props) {
        super(props);
        //added state 
        this.state = {
            isDown: false,
            previousPointX: '',
            previousPointY: '',
            base_image: {},
            circleConfig: {
                maxCircle: 4,
            },
            circles: [],
            canvasId: this.props.canvasid,
            rotate: this.props.rotate
        }
        this.handleMouseDown = this.handleMouseDown.bind(this);
        this.handleMouseMove = this.handleMouseMove.bind(this);
        this.handleMouseUp = this.handleMouseUp.bind(this);
    }

    render() {
        return (
            <div>
                <canvas ref="canvas" className="CursorCanvas" width="300" height="300"
                    onMouseDown={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseDown(nativeEvent);
                        }}
                    onMouseMove={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseMove(nativeEvent);
                        }}
                    onMouseUp={
                        e => {
                            let nativeEvent = e.nativeEvent;
                            this.handleMouseUp(nativeEvent);
                        }}
                />
                <pre hidden>{JSON.stringify(this.state.circles, null, 2)}</pre>
            </div>
        );
    }

    drawCircle(circles, ctx) {
        circles.forEach((item) => {
            ctx.beginPath();
            var r = (item.endx - item.startx) / 2;
            var centerx = (r + item.startx);
            var centery = (r + item.starty);
            ctx.arc(centerx, centery, r, 0, 2 * Math.PI);
            ctx.stroke();
            ctx.closePath();
        })
    }

    handleMouseDown(event) {
        if (this.state.circles.length >= this.state.circleConfig.maxCircle) return;

        this.setState({
            isDown: true,
            previousPointX: event.offsetX,
            previousPointY: event.offsetY
        }, () => {
            //   console.log('mousedown',this.state)
        })
    }

    handleMouseMove(event) {
        if (this.state.isDown) {
            event.preventDefault();
            event.stopPropagation();
            const canvas = ReactDOM.findDOMNode(this.refs.canvas);
            var x = event.offsetX;
            var y = event.offsetY;
            var ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            // ctx.drawImage(this.state.base_image, 0, 0);
            ctx.drawImage(this.state.base_image,
                canvas.width / 2 - this.state.base_image.width / 2,
                canvas.height / 2 - this.state.base_image.height / 2
            );
            //Save
            ctx.save();
            ctx.beginPath();
            this.drawCircle(this.state.circles, ctx);
            // var circleLength = this.state.circles.length || 0;

            //Dynamic scaling
            var scalex = (x - this.state.previousPointX) / 2;
            var scaley = (y - this.state.previousPointY) / 2;
            ctx.scale(scalex, scaley);
            //Create ellipse
            var centerx = (this.state.previousPointX / scalex) + 1;
            var centery = (this.state.previousPointY / scaley) + 1;
            ctx.beginPath();
            ctx.arc(centerx, centery, 1, 0, 2 * Math.PI);
            ctx.restore();
            ctx.stroke();
            // ctx.strokeStyle = this.state.circleConfig.color[circleLength];
            // console.log('centerx',centerx,'centery',centery)
        }

    }
    handleMouseUp(event) {
        if (this.state.circles.length >= this.state.circleConfig.maxCircle) return;
        this.setState({
            isDown: false
        });
        // console.log('mouseup',this.state)
        var x = event.offsetX;
        var y = event.offsetY;

        if (this.state.previousPointX !== x && this.state.previousPointY !== y) {
            this.setState({
                circles: this.state.circles.concat({
                    startx: this.state.previousPointX,
                    starty: this.state.previousPointY,
                    endx: x,
                    endy: y,
                    r: (x - this.state.previousPointX) / 2,
                    centerx: (((x - this.state.previousPointX) / 2) + this.state.previousPointX),
                    centery: (((x - this.state.previousPointX) / 2) + this.state.previousPointY)
                    // color: this.state.circleConfig.color[circleLength]
                })
            },
                () => {
                    //console.log('mouseup', this.state);
                }
            );
        }
    }
    componentDidMount() {
        const canvas = ReactDOM.findDOMNode(this.refs.canvas);
        const ctx = canvas.getContext("2d");
        const base_image = new Image();
        base_image.src = this.props.imgSrc
        base_image.onload = function () {
            // ctx.drawImage(base_image, 0, 0);
            ctx.drawImage(base_image,
                canvas.width / 2 - base_image.width / 2,
                canvas.height / 2 - base_image.height / 2
            );
        }
        this.setState({
            base_image: base_image
        });
    }
}

export default CircleMultiple;

To remove the connecting line between circles need to add

            ctx.beginPath();

before calling drawCircle() method.

Ad
source: stackoverflow.com
Ad