Stop canvas clearing on lineWidth change - reactjs

I have a react app that allows you to draw and select different line widths.
Code:
const [sliderVal, setSliderVal] = useState(1)
const canvasRef = useRef(null)
useEffect(() => {
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
/* Mouse Capturing Work */
var mouse = {x: 0, y: 0};
var last_mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
canvas.style.cursor = "crosshair";
}, false);
/* Drawing on Paint App */
ctx.lineWidth = sliderVal;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'blue';
canvas.addEventListener('mousedown', function() {
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
};
}, [sliderVal])
I'm trying to make it so if sliderVal changes the whole canvas wont re-render only the line width will. Right now it works but if I select a new lineWidth the whole canvas gets cleared.

I recommend you not to use the eventListener in that way, canvas in ReactJS already has some methods to which you can access and pass a function. This new way of handling the canvas solves your problem:
const [sliderVal, setSliderVal] = useState(1);
const [mouse, setMouse] = useState({
x: 0,
y: 0,
lastX: 0,
lastY: 0,
click: false
});
const canvasRef = useRef(null);
const paint = (e) => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
const bounds = canvas.getBoundingClientRect();
setMouse({
...mouse,
x: e.pageX - bounds.left - window.scrollX,
y: e.pageY - bounds.top - window.scrollY,
lastX: mouse.x,
lastY: mouse.y
});
ctx.lineWidth = sliderVal;
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.strokeStyle = "blue";
if (mouse.click) {
ctx.beginPath();
ctx.moveTo(mouse.lastX, mouse.lastY);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
}
};
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
canvas.style.cursor = "crosshair";
}, []);
return (
<canvas
onMouseDown={() => setMouse({ ...mouse, click: true })}
onMouseMove={(e) => paint(e)}
onMouseUp={() => setMouse({ ...mouse, click: false })}
ref={canvasRef}
/>
I share a codesandbox with the functional solution

Related

How to use canvas HTML5 on smartphone

I have code written on react js, using canvas html 5. It is image eraser: it should properly erase front image and when only some persent of it left, it trigger another action(i haven not done another action yet). It works fine in browser, but when i choose adaptive for any smatphone, it stops working. I tried to change mouse events to touch events but it didn't help.
Here is the code:
import './DrawingCanvas.css';
import {useEffect, useRef, useState} from 'react';
const DrawingCanvas = () => {
const canvasRef = useRef(null);
const contextRef = useRef(null);
const [isDrawing, setIsDrawing] = useState(false);
const [persent, setPersent] = useState(100);
useEffect(() => {
const url = require('../../images/one.jpg');
const canvas = canvasRef.current;
const img = new Image();
img.src = url;
const context = canvas.getContext("2d");
img.onload = function () {
let width = Math.min(500, img.width);
let height = img.height * (width / img.width);
canvas.width = width;
canvas.height = height;
context.drawImage(img, 0, 0, width, height);
contextRef.current = context;
context.lineCap = "round";
context.lineWidth = 350;
contextRef.current.globalCompositeOperation = 'destination-out';
};
}, []);
useEffect(() => {
console.log(persent);
if(persent<=0.1) return alert('hello')
}, [persent]);
const startDrawing = ({nativeEvent}) => {
const {offsetX, offsetY} = nativeEvent;
contextRef.current.beginPath();
contextRef.current.moveTo(offsetX, offsetY);
contextRef.current.lineTo(offsetX, offsetY);
// contextRef.current.stroke();
setIsDrawing(true);
nativeEvent.preventDefault();
};
const draw = ({nativeEvent}) => {
if (!isDrawing) {
return;
}
const {offsetX, offsetY} = nativeEvent;
contextRef.current.lineTo(offsetX, offsetY);
contextRef.current.stroke();
nativeEvent.preventDefault();
let pixels = contextRef.current.getImageData(0, 0, canvasRef.current.width, canvasRef.current.height);
let transPixels = [];
for (let i = 3; i < pixels.data.length; i += 4) {
transPixels.push(pixels.data[i]);
}
let transPixelsCount = transPixels.filter(Boolean).length;
setPersent((transPixelsCount / transPixels.length) * 100);
};
const stopDrawing = () => {
contextRef.current.closePath();
setIsDrawing(false);
};
return (
<div>
<canvas className="canvas-container"
ref={canvasRef}
onMouseDown={startDrawing}
onMouseMove={draw}
onMouseUp={stopDrawing}
onMouseLeave={stopDrawing}
>
</canvas>
</div>
)
}
export default DrawingCanvas;
.canvas-container {
background-image: url("https://media.istockphoto.com/id/1322277517/photo/wild-grass-in-the-mountains-at-sunset.jpg?s=612x612&w=0&k=20&c=6mItwwFFGqKNKEAzv0mv6TaxhLN3zSE43bWmFN--J5w=");
}
Maybe it all can be done through touch events, but idk how to do that properly

How to properly load images to Canvas in React

I have an array of image urls. I want to display one image at a time on canvas. I've setup useEffect to be triggered when index of current image is changed.
I've researched online and found out that images load async and i must use onload callback to draw new image on canvas (Why won't my image show on canvas?).
I've setup effect and callback like this:
const [image, setImage] = useState<HTMLImageElement>()
useEffect(() => {
const image = new Image()
image.onload = () => update
image.src = images[imageState.imageIndex]?.url
setImage(image)
}, [imageState.imageIndex, images, update])
const update = useCallback(() => {
if (!canvasRef.current) return
const ctx = canvasRef.current.getContext('2d')
if (!ctx || !image) return
ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height)
canvasRef.current.width = image.width
canvasRef.current.height = image.height
ctx.drawImage(image, 0, 0)
}, [image])
canvas is setup like this:
export const ImageGallery = (props: ImageGalleryProps) => {
const classes = useImageGalleryStyles()
return (
<div className={classes.outerContainer}>
<canvas
style={{
left: `${imageState.position.x}px`,
top: `${imageState.position.y}px`,
transform: `rotate(${imageState.rotate}deg) scale(${imageState.scale})`,
}}
ref={canvas.ref}
className={classes.image}
/>
</div>
)
}
Images are changed like this:
Callback never called and canvas remains blank. What is proper way to update canvas?
Ended up with this:
useEffect(() => {
const image = new Image()
image.onload = function() {
if (!canvasRef.current) return
const ctx = canvasRef.current.getContext('2d')
if (!ctx || !image) return
ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height)
canvasRef.current.width = image.width
canvasRef.current.height = image.height
ctx.drawImage(image, 0, 0)
coordinates.map(c => {
switch (c.coordinates.$type) {
case DefectCoordinatesType.WideSide:
c.coordinates.WideSides.map(ws => {
if (image) {
ctx.beginPath()
ctx.imageSmoothingEnabled = false
ctx.moveTo(ws[0].x * image.width, ws[0].y * image.height)
ctx.lineTo(ws[1].x * image.width, ws[1].y * image.height)
ctx.closePath()
ctx.strokeStyle = 'red'
ctx.lineWidth = 2
ctx.stroke()
}
})
}
})
}
image.src = images[imageState.imageIndex]?.url
}, [checkBoundaries, coordinates, imageState.imageIndex, images, prevIndex, zoomOut])

Cannot stop useEffect() from executing

My application, pulls data ( text, numbers) from a database and then places them in a canvas image. This is working as expected, and the data is being displayed along with a few lines of the final diagram. However the useEffect() function is not stopping and continues to display the same image, which I would not have realised had I not placed an alert.
I have seen the documentation and other questions that have discussed this problem. I understand that I need to put a variable whose value will not change. But I am simply unable to do this. I am sharing my code. Will be grateful if someone can help.
import React, { useEffect, useState, useRef } from "react";
import { useParams } from "react-router";
import './cindex.css';
export default function GetChartData() {
const params = useParams();
const [dbdata, setData] = useState('empty52');
const canvas = useRef();
let ctx = null;
let name = null
let Lalong = null
let T1 = { text: 'dummy', x: 180, y: 100 }
let T2 = { text: 'dummy', x: 180, y: 200 }
useEffect(() => {
async function getData() {
const response = await fetch(`http://localhost:5000/getchartdata/${params.id.toString()}`);
//const response = await fetch(`http://khona21.cleverapps.io/getchartdata/${params.id.toString()}`);
if (!response.ok) {
const message = `An error occurred: ${response.statusText}`;
window.alert(message);
return;
}
const dbdata = await response.json();
setData(dbdata);
}
getData();
return;
},[dbdata]);
// initialize the canvas context
useEffect(() => {
// dynamically assign the width and height to canvas
const canvasEle = canvas.current;
canvasEle.width = canvasEle.clientWidth;
canvasEle.height = canvasEle.clientHeight;
// get context of the canvas
ctx = canvasEle.getContext("2d");
//}, []);
}, [T1,T2]);
useEffect(() => {
let pid = dbdata.pid;
let spid = JSON.stringify(pid);
if (typeof spid !== 'undefined'){
name = dbdata.pid.name;
Lalong = dbdata.GLon.La
if (T1.text === 'dummy') {
T1.text = name
T2.text = Lalong.toString()
}
}
else {
//window.alert('undefined')
}
drawLine({ x: 150, y: 20, x1: 150, y1: 450 });
drawLine({ x: 300, y: 20, x1: 300, y1: 450 });
writeText(T1);
writeText(T2);
window.alert('finished drawing')
//}, []);
//}, [[]]);
}, [T1]);
const drawLine = (info, style = {}) => {
const { x, y, x1, y1 } = info;
const { color = 'black', width = 1 } = style;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x1, y1);
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.stroke();
}
// write a text
const writeText = (info, style = {}) => {
const { text, x, y } = info;
const { fontSize = 20, fontFamily = 'Arial', color = 'black', textAlign = 'left', textBaseline = 'top' } = style;
ctx.beginPath();
ctx.font = fontSize + 'px ' + fontFamily;
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.fillStyle = color;
ctx.fillText(text, x, y);
ctx.stroke();
}
return (
<div>
<h3>Chart Positions</h3>
<p>{JSON.stringify(dbdata)}</p>
<hr></hr>
<canvas ref={canvas}></canvas>
</div>
);
}
I have tried to ensure that that the text in T1 changes only once and hence should stop the loop. But it is not. What should I do?
the TRICK was to use [dbdata.length] instead of simply [dbdata] as the stopping condition in the useEffect() function. dbdata was being set each time as new, but dbdata.length was not changing.
import React, { useEffect, useState, useRef } from "react";
import { useParams } from "react-router";
import './cindex.css';
//let T1 = { text: 'dummy', x: 180, y: 100 }
//let T2 = { text: 'dummy', x: 180, y: 200 }
export default function GetChartData() {
const canvas = useRef();
let ctx = null;
const params = useParams();
const [dbdata, setData] = useState('empty52');
let name = null
let Lalong = null
const T1 = { text: 'dummy', x: 180, y: 100 }
const T2 = { text: 'dummy', x: 180, y: 200 }
useEffect(() => {
async function getData() {
const response = await fetch(`http://localhost:5000/getchartdata/${params.id.toString()}`);
//const response = await fetch(`http://khona21.cleverapps.io/getchartdata/${params.id.toString()}`);
if (!response.ok) {
const message = `An error occurred: ${response.statusText}`;
window.alert(message);
return;
}
const dbdata = await response.json();
setData(dbdata);
// *********************************************************************
let pid = dbdata.pid;
let spid = JSON.stringify(pid);
if (typeof spid !== 'undefined'){
name = dbdata.pid.name;
Lalong = dbdata.GLon.La
T1.text = name
T2.text = Lalong.toString()
}
else {
//window.alert('undefined')
}
// dynamically assign the width and height to canvas
const canvasEle = canvas.current;
canvasEle.width = canvasEle.clientWidth;
canvasEle.height = canvasEle.clientHeight;
// get context of the canvas
ctx = canvasEle.getContext("2d");
drawLine({ x: 150, y: 20, x1: 150, y1: 450 });
drawLine({ x: 300, y: 20, x1: 300, y1: 450 });
writeText(T1);
writeText(T2);
window.alert('image drawn')
// **********************************************************************
}
getData();
return;
},[dbdata.length]);
const drawLine = (info, style = {}) => {
const { x, y, x1, y1 } = info;
const { color = 'black', width = 1 } = style;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x1, y1);
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.stroke();
}
// write a text
const writeText = (info, style = {}) => {
const { text, x, y } = info;
const { fontSize = 20, fontFamily = 'Arial', color = 'black', textAlign = 'left', textBaseline = 'top' } = style;
ctx.beginPath();
ctx.font = fontSize + 'px ' + fontFamily;
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.fillStyle = color;
ctx.fillText(text, x, y);
ctx.stroke();
}
return (
<div>
<h3>Chart Positions</h3>
<p>{JSON.stringify(dbdata)}</p>
<hr></hr>
<canvas ref={canvas}></canvas>
</div>
);
}

React - How to get client coordinates on canvas properly? (drawing a straight line with mouse)

I got to make "drawing a line" works, but this line wouldn't start from where my mouse starts, rather it'd start from very beginning {x: 0, y:0}. How to draw a line starting from where my mouse clicks?
I already used e.nativeEvent.offsetX and e.nativeEvent.offsetY for getting client X and Y, and this is used for just drawing feature, but I'm stuck how I can utilize it for drawing line, or changing my draw a line code for making it work. Thank you in advanced!
const canvasRef = useRef(null);
const ctxRef = useRef(null);
const [isDrawing, setIsDrawing] = useState(false);
const [lineWidth, setLineWidth] = useState(5);
const [lineColor, setLineColor] = useState("black");
let startPosition = {x: 0, y: 0};
let lineCoordinates = {x: 0, y: 0};
const getClientOffset = (e) => {
const {pageX, pageY} = e.touches ? e.touches[0] : e;
const x = pageX - canvasRef.offsetLeft;
const y = pageY - canvasRef.offsetTop;
return {
x,
y
}
}
const drawLine = () => {
ctxRef.current.beginPath();
ctxRef.current.moveTo(startPosition.x, startPosition.y);
ctxRef.current.lineTo(lineCoordinates.x, lineCoordinates.y);
ctxRef.current.stroke();
}
useLayoutEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.strokeStyle = lineColor;
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctxRef.current = ctx;
}, [lineColor, lineWidth]);
const handleMouseDown = (e) => {
setIsDrawing(true);
// const posX = e.nativeEvent.offsetX;
// const posY = e.nativeEvent.offsetY;
// ctxRef.current.beginPath();
// ctxRef.current.moveTo(
// posX,
// posY
// );
startPosition = getClientOffset(e);
}
const handleMouseMove = (e) => {
if (!isDrawing) {
return;
}
ctxRef.current.lineTo(
e.nativeEvent.offsetX,
e.nativeEvent.offsetY
);
ctxRef.current.stroke();
lineCoordinates = getClientOffset(e);
drawLine();
}
const handleMouseUp = () => {
ctxRef.current.closePath();
setIsDrawing(false);
}
The issue is let startPosition and let lineCoordinates – on each render update React will reinitialize these variables with {x: 0, y:0}. In order to remember any value you must use useState().
I tried it out in a demo
https://codesandbox.io/s/crazy-breeze-xj26c?file=/src/App.js

drawing 4 circles in a canvas in reactjs

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
});
}
}
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.

Resources