How to not use canvas clearRect() for multiple drawings? - javascript

I want to do multiple drawings on an image using canvas.
In my code, I use ctx.clearRect(0,0,canvas.width,canvas.height);
therefore, it does not allow me to do multiple drawings. If I did not use clearRect(), the program does not work correctly. Also, I've tried to change the place of clearRect(), but it also did not work for me.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas
ctx.beginPath();
var width = mousex-last_mousex;
var height = mousey-last_mousey;
ctx.rect(last_mousex,last_mousey,width,height);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.stroke();
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
var width = mousex - last_mousex;
var height = mousey - last_mousey;
ctx.rect(last_mousex, last_mousey, width, height);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.stroke();
}
//Output
$('#output').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
canvas {
cursor: crosshair;
border: 1px solid #000000;
background-image: url("kroki2v3.png");
background-repeat: no-repeat;
}
<html>
<head>
<meta charset="utf-8" />
<script src="https://code.jquery.com/jquery-2.1.3.js" integrity="sha256-goy7ystDD5xbXSf+kwL4eV6zOPJCEBD1FBiCElIm+U8=" crossorigin="anonymous"></script>
</head>
<body>
<canvas id="canvas" width="3200" height="1400"></canvas>
<div id="output"></div>
</body>
</html>

You have to store each rectangle position and size in array and print by looping.
jQuery(document).ready(function($) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas
ctx.beginPath();
var width = mousex-last_mousex;
var height = mousey-last_mousey;
ctx.rect(last_mousex,last_mousey,width,height);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.stroke();
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = 0;
var last_mousey = 0;
var mousex = 0;
var mousey = 0;
var mousedown = false;
var shapes = [];
var width;
var height;
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
const lastPos = {
lastMouseX : last_mousex,
lastMouseY : last_mousey,
rectWidth : width,
rectHeight : height
}
shapes.push(lastPos);
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
width = mousex - last_mousex;
height = mousey - last_mousey;
if (shapes.length > 0){
for(var i in shapes){
ctx.rect(shapes[i].lastMouseX, shapes[i].lastMouseY, shapes[i].rectWidth, shapes[i].rectHeight);
}
}
ctx.rect(last_mousex, last_mousey, width, height);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.stroke();
}
//Output
$('#output').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
});
canvas {
cursor: crosshair;
border: 1px solid #000000;
background-image: url("kroki2v3.png");
background-repeat: no-repeat;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" width="3200" height="1400"></canvas>
<div id="output"></div>

Related

Determine the distance between a straight line and a curve line drawn in a HTML canvas

I have a program in HTML, CSS and JavaScript where one can draw a from an initial point (Mousedown event )curved line(Mousemove event) and a straight line when the mouse click is lifted up(MouseUp event).
Now my problem is finding the distance of the curve line and as well as the straight line in two different labels.
My code goes below
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {
x: 0,
y: 0
};
var last_mouse = {
x: 0,
y: 0
};
/* Mouse Capturing Work */
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;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
initialPoint = {
x: mouse.x,
y: mouse.y
}
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
drawStraightLine()
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.strokeStyle = "#000000";
ctx.closePath();
ctx.stroke();
};
let initialPoint
const drawStraightLine = function() {
ctx.beginPath();
ctx.moveTo(initialPoint.x, initialPoint.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.strokeStyle = "#FF000077";
ctx.stroke();
}
html,
body {
width: 80%;
height: 50%;
}
#sketch {
border: 10px solid gray;
height: 100%;
}
<div id="sketch">
<canvas id="paint"></canvas>
<script src="1.js"></script>
</div>
<label id="StraightLineDistance"></label>
<label id="CurvedLineDistance"></label>
To find the length of a line you use Pythagoras
Eg the distance between two points A, B
function distanceBetween(A, B) {
return ((B.x - A.x) ** 2 + (B.y - A.y) ** 2) ** 0.5;
}
Or
function distanceBetween(A, B) {
const dx = B.x - A.x;
const dy = B.y - A.y;
return Math.sqrt(dx * dx + dy * dy);
}
Or
function distanceBetween(A, B) {
return Math.hypot(B.x - A.x, B.y - A.y);
}
To measure the drawn path you will need to accumulate the length each sub path (line) to get a total.
Example
The example accumulates the length as it is drawn. When the mouse down event happens the accumulated length is zeroed.
const canvas = document.querySelector('#paint');
const ctx = canvas.getContext('2d');
const sketch = document.querySelector('#sketch');
const sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var pathLength = 0;
var distance = 0;
const mouse = {x: 0, y: 0};
const last_mouse = {x: 0, y: 0};
const initialPoint = {x: 0, y: 0};
function distanceBetween(A, B) {
const dx = B.x - A.x;
const dy = B.y - A.y;
return (dx * dx + dy * dy) ** 0.5;
}
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
initialPoint.x = mouse.x = e.pageX - this.offsetLeft;
initialPoint.y = mouse.y = e.pageY - this.offsetTop;
pathLength = 0;
canvas.addEventListener('mousemove', onPaint);
}, false);
canvas.addEventListener('mouseup', function() {
drawStraightLine()
canvas.removeEventListener('mousemove', onPaint);
}, false);
function displayLengths() {
StraightLineDistance.textContent = "Distance: " + distance.toFixed(0) + "px";
CurvedLineDistance.textContent = "Traveled: " + pathLength.toFixed(0) + "px";
}
function onPaint(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.lineTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
pathLength += distanceBetween(last_mouse, mouse);
distance = distanceBetween(initialPoint, mouse);
displayLengths();
};
function drawStraightLine() {
ctx.strokeStyle = "#FF000077";
ctx.beginPath();
ctx.lineTo(initialPoint.x, initialPoint.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
distance = distanceBetween(initialPoint, mouse);
displayLengths();
}
html,
body {
width: 80%;
height: 50%;
}
#sketch {
border: 10px solid gray;
height: 100%;
}
<div id="sketch">
<canvas id="paint"></canvas>
<script src="1.js"></script>
</div>
<label id="StraightLineDistance"></label>
<label id="CurvedLineDistance"></label>
The JavaScript file
const canvas = document.querySelector('#paint');
const ctx = canvas.getContext('2d');
const sketch = document.querySelector('#sketch');
const sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var pathLength = 0;
var distance = 0;
const mouse = {x: 0, y: 0};
const last_mouse = {x: 0, y: 0};
const initialPoint = {x: 0, y: 0};
function distanceBetween(A, B) {
const dx = B.x - A.x;
const dy = B.y - A.y;
return (dx * dx + dy * dy) ** 0.5;
}
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
initialPoint.x = mouse.x = e.pageX - this.offsetLeft;
initialPoint.y = mouse.y = e.pageY - this.offsetTop;
pathLength = 0;
canvas.addEventListener('mousemove', onPaint);
}, false);
canvas.addEventListener('mouseup', function() {
drawStraightLine()
canvas.removeEventListener('mousemove', onPaint);
}, false);
function displayLengths() {
StraightLineDistance.textContent = "Distance: " + distance.toFixed(0) + "px";
CurvedLineDistance.textContent = "Traveled: " + pathLength.toFixed(0) + "px";
}
function onPaint(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
ctx.strokeStyle = "#000000";
ctx.beginPath();
ctx.lineTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
pathLength += distanceBetween(last_mouse, mouse);
distance = distanceBetween(initialPoint, mouse);
displayLengths();
};
function drawStraightLine() {
ctx.strokeStyle = "#FF000077";
ctx.beginPath();
ctx.lineTo(initialPoint.x, initialPoint.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
distance = distanceBetween(initialPoint, mouse);
displayLengths();
}
The HTML file
<link rel="stylesheet" href="1.css"/>
</head>
<body>
<div id="sketch">
<canvas id="paint"></canvas>
<script src="1.js"></script>
</div>
<label id="StraightLineDistance"></label><br/>
<label id="CurvedLineDistance"></label><br/>
<label id="Index"></label>
</body>
</html>
My new doubt is how can I show the realtime value of ratio of (distance/pathLength) in the label id="Index"
I have tried using Index.textContent = (distance/pathLength).toFixed(0); but that shows 1 and its constant in the output.
I would be pleased if I am helped with this

Drawing multiple rectangles on canvas without clearing the back image

I am trying to draw multiple rectangles on canvas. I am able to do it except its not clearing rectangles as the mouse moves.
And when i try to clear rectangle using clearRect then the back image on canvas is also gets cleared. So I have commented out //ctx.clearRect(0, 0, canvas.width, canvas.height); in the code below
I have gone through several SO posts with similar questions but doesn't seems work
$(function(){
var canvas = document.getElementById('myCanvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.fillText("Sample String", 20, 50);
}
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
//ctx.clearRect(0, 0, canvas.width, canvas.height);
var width = mousex - last_mousex;
var height = mousey - last_mousey;
ctx.beginPath();
ctx.rect(last_mousex, last_mousey, width, height);
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
}
//Output
$('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
Use mouse to draw multiple rectangles with in the canvas
</h3>
<canvas id="myCanvas"></canvas>
<div id="results">
</div>
your mistake was you cleared all the canvas:
ctx.clearRect(0, 0, canvas.width, canvas.height);
instead of clearing just the area you drew before:
ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);
I wrote the basic idea here, but you need to add some code to clear the area depends on the direction the mouse was, and moving to (try to move your mouse to each of the corners and see what happens).
$("#clear").click(function(){
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillText("Sample String", 20, 50);
});
$(function(){
var canvas = document.getElementById('myCanvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.fillText("Sample String", 20, 50);
}
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = w = h = 0;
var prev_x = prev_y = prev_w = prev_h = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
w = h = 0;
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
prev_x = last_mousex;
prev_y = last_mousey;
prev_w = w;
prev_h = h;
ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);
w = mousex - last_mousex;
h = mousey - last_mousey;
ctx.beginPath();
ctx.rect(last_mousex, last_mousey, w, h);
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
}
//Output
$('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
});
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
Use mouse to draw multiple rectangles with in the canvas
</h3>
<button id="clear">clear</button>
<br />
<canvas id="myCanvas"></canvas>
<div id="results">
</div>
I think you can come to another approach
By using mousedown event only then save all rectangle to an array variable
Then you can clear and redraw the whole canvas with the saved variable
var shapes = [];
canva.addEventListener('mousedown', mouseDownListener);
class Rectangle() {
public ctx, x, y, w, h;
public Rectangle(ctx, x, y, w, h) {
this.ctx = ctx;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public draw() {
// draw using ctx here
}
}
function mouseDownListener() {
// create rectable
var rectangle = new Rectangle(ctx, x, y, width, height);
// save rectangle to an array
shapes.push(rectangle);
// redraw canvas
redraw();
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw all rectangle
shapes.forEach(function(shape) {
// draw shape
shape.draw();
})
}

Stop OutSide Drag And Drop On HTML5 Canvas And Restrict Overlap Of Arc On Drag On Canvas

I have the following problems:
I want to stop drag and drop outside of the canvas.
Stop overlapping of circles on drag(stop drag a circle over another circle).
This is my code which can be found for testing purposes in this link
// get canvas related references
var mouseIsDown = false;
var lastX = 0;
var lastY = 0;
var circles = [];
var offsetX = 0;
var offsetY = 0;
var canvas = null;
var ctx = null;
var canvasWidth = 0;
var canvasHeight = 0;
var count = 0;
makeCircle(20, 20, "salmon");
function makeCircle(x, y, fill){
var i = 0;
for(i =0 ; i< 5 ;i++){
var circle = {
x: x,
y: y,
r: 20,
isDragging: false,
fill: fill
}
circles.push(circle);
y = y + 20;
}
}
var i =0;
for(i = 0; i < circles.length;i++){
updateCanvas();
}
addEventsToCanvas()
// an array of objects that define different rectangles
function drawImageScaled(img) {
var canvas = ctx.canvas;
offsetX = canvas.getBoundingClientRect().left;
offsetY = canvas.getBoundingClientRect().top;
canvasWidth = canvas.width;
canvasHeight = canvas.height;
var hRatio = canvas.width / img.width;
var vRatio = canvas.height / img.height;
var ratio = Math.min(hRatio, vRatio);
var centerShift_x = (canvas.width - img.width * ratio) / 2;
var centerShift_y = (canvas.height - img.height * ratio) / 2;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, img.width, img.height,
centerShift_x, centerShift_y, img.width * ratio, img.height * ratio);
if (circles) {
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
drawCircle(circle);
ctx.fillStyle = circle.fill;
ctx.fill();
ctx.stroke();
}
}
}
function drawCircle(circle) {
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.beginPath();
ctx.fillStyle = circle.fill;
ctx.strokeStyle = "black";
ctx.font = "20px Georgia";
ctx.lineWidth = 10;
ctx.arc(circle.x, circle.y, circle.r, 0, 2 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#ffffff";
ctx.fill();
}
function updateCanvas(){
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
let img = new Image();
img.onload = drawImageScaled(img);
img.setAttribute('crossOrigin', 'anonymous');
img.src = "https://images.unsplash.com/photo-1532619675605-1ede6c2ed2b0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80"
}
function addEventsToCanvas(){
// listen for mouse events
canvas.onmousedown = handleMouseDown;
canvas.onmouseup = handleMouseUp;
canvas.onmousemove = handleMouseMove;
}
function handleMouseDown(e){
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
let mouseX = parseInt(e.clientX - offsetX);
let mouseY = parseInt(e.clientY - offsetY);
// mousedown stuff here
lastX = mouseX;
lastY = mouseY;
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
var dx = circle.x - mouseX;
var dy = circle.y - mouseY;
if (dx * dx + dy * dy < circle.r * circle.r) {
circles[i].isDragging = true;
mouseIsDown = true;
}
}
}
function handleMouseUp(e){
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// mouseup stuff here
mouseIsDown = false;
for (var i = 0; i < circles.length; i++) {
circles[i].isDragging = false;
}
}
function handleMouseMove(e){
if (!mouseIsDown) {
return;
}
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
let mouseX = parseInt(e.clientX - offsetX);
let mouseY = parseInt(e.clientY - offsetY);
// mousemove stuff here
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
if (circle.isDragging) {
//move
circle.x += (mouseX - lastX);
circle.y += (mouseY - lastY);
}
}
lastX = mouseX;
lastY = mouseY;
updateCanvas()
}
This is the output
To stop drag and drop outside the canvas you simply need to handle the mouseLeave event. From your example i updated your addEventsToCanvas function like this :
function addEventsToCanvas(){
// listen for mouse events
canvas.onmousedown = handleMouseDown;
canvas.onmouseup = handleMouseUp;
canvas.onmousemove = handleMouseMove;
canvas.onmouseleave = function(event) {mouseIsDown = false;}
}
Then for collisions it is just some maths at drawing time. Here is the code to handle collisions with canvas border and others circle :
function drawCircle(circle) {
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.beginPath();
ctx.fillStyle = circle.fill;
ctx.strokeStyle = "black";
ctx.font = "20px Georgia";
ctx.lineWidth = 10;
//avoid outside canvas x and y
circle.x = Math.min(circle.x, canvas.width-circle.r);
circle.x = Math.max(circle.x, circle.r);
circle.y = Math.min(circle.y, canvas.height-circle.r);
circle.y = Math.max(circle.y, circle.r);
//then check if circles are not too close
if(circle.isDragging) {
circles.forEach(function(c) {
if(c!=circle) {
//calculate distance
let dist = Math.sqrt(Math.pow(Math.abs(c.x-circle.x), 2) + Math.pow(Math.abs(c.y-circle.y), 2));
if(dist<circle.r*2) {
let angle = Math.atan2(c.y - circle.y, c.x - circle.x);
circle.x = c.x - Math.cos(angle)*circle.r*2;
circle.y = c.y - Math.sin(angle)*circle.r*2;
}
}
});
}
ctx.arc(circle.x, circle.y, circle.r, 0, 2 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#ffffff";
ctx.fill();
}
You can test the whole code on JSFiddle
EDIT : I also modified the mouse move handler by replacing
circle.x += (mouseX - lastX);
circle.y += (mouseY - lastY);
by
circle.x = mouseX;
circle.y = mouseY;
It permit to place the circle center at mouse position everytime it is possible.

Replacing color with photo in html drawing tool

In this drawing tool for html I want to replace the color (#ddd) with a photo.
Instead of the current version I want to replace the grey rectangle with a photo. Any idea on how to do that? And it won't let me reposition the rectangle, any idea why?
(function() {
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "#ddd");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 25; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = true;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = false;
};
}
var container = document.getElementById('canvas');
init(container, 400, 400, '#ddd');
})();
You can achieve this by layering a solid canvas on top of another canvas. Erasing parts of the top canvas should reveal the canvas below.
The following reuses 99% of the code from two separate posts.
Loading the image onto the canvas.
Erasing the top canvas (layer).
// Borrowed from here: https://stackoverflow.com/a/4776378
var canvasWrapper = document.getElementsByClassName('layer-wrapper')[0];
var imageLayer = canvasWrapper.querySelector('.layer-image');
var drawLayer = canvasWrapper.querySelector('.layer-draw');
var img = new Image;
img.onload = function() {
imageLayer.width = drawLayer.width = img.width;
imageLayer.height = drawLayer.height = img.height;
var imageCtx = imageLayer.getContext('2d');
imageCtx.drawImage(img, 0, 0);
var drawCtx = drawLayer.getContext('2d');
drawCtx.fillStyle = '#7F7F7F';
drawCtx.fillRect(0, 0, img.width, img.height);
};
img.src = 'https://pbs.twimg.com/profile_images/462372073982025728/jTHaxsxd.jpeg';
// Borrowed from here: https://stackoverflow.com/a/25916334
var RADIUS = 32;
var canvas = canvasWrapper.querySelector('.layer-wrapper .layer-draw');
var ctx = canvas.getContext('2d');
var lastX;
var lastY;
var strokeColor = 'red';
var strokeWidth = 5;
var mouseX;
var mouseY;
var canvasOffset = $(canvas).offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var isMouseDown = false;
function handleMouseDown(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousedown stuff here
lastX = mouseX;
lastY = mouseY;
isMouseDown = true;
}
function handleMouseUp(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mouseup stuff here
isMouseDown = false;
}
function handleMouseOut(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mouseOut stuff here
isMouseDown = false;
}
function handleMouseMove(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousemove stuff here
if (isMouseDown) {
ctx.beginPath();
if (mode == "pen") {
ctx.globalCompositeOperation = "source-over";
ctx.moveTo(lastX, lastY);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
} else {
ctx.globalCompositeOperation = "destination-out";
ctx.arc(lastX, lastY, RADIUS, 0, Math.PI * 2, false);
ctx.fill();
}
lastX = mouseX;
lastY = mouseY;
}
}
$(canvas).mousedown(function(e) {
handleMouseDown(e);
}).mousemove(function(e) {
handleMouseMove(e);
}).mouseup(function(e) {
handleMouseUp(e);
}).mouseout(function(e) {
handleMouseOut(e);
});
var mode = 'eraser';
//$('#pen') .click(function() { mode = 'pen'; });
//$('#eraser').click(function() { mode = 'eraser'; });
.layer-wrapper {
position: relative;
width: 400px;
height: 300px;
}
.layer-wrapper canvas.layer {
position: absolute;
top: 0;
left: 0;
}
.layer-image {
z-index: 1;
}
.layer-draw {
z-index: 100;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="layer-wrapper">
<canvas class="layer layer-image"></canvas>
<canvas class="layer layer-draw"></canvas>
</div>

Moving a canvas from left to right is not smooth and fast

I want to move one canvas on top of another. when top canvas moves the base canvas displays its x and y. The event initially starts at mouse down. so press mouse and start moving the canvas moves smoothly from right to left but not left to right.
http://jsfiddle.net/happyomi/23PL3/3/
<head>
<style type="text/css">
body, html {
margin: 0;
}
canvas {
position: absolute;
/* top: 0;
left: 0;*/
}
#temp {
background-color: pink;
}
</style>
</head>
<body style="margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;">
<canvas id="myCanvas" style="display: block;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="temp" style="position: relative">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var hgap = 0;
var vgap = 0;
var rows, cols;
var annotation_x = 1;
var row = 0; var col = 0;
//ctx.font = "14px Arial";
c.width = $(document).width();
c.height = $(document).height();
var t = document.getElementById("temp");
tctx = t.getContext("2d");
// tctx.lineWidth = 10;
tctx.lineJoin = 'round';
tctx.lineCap = 'round';
tctx.strokStyle = 'red';
var mouse = { x: 0, y: 0 };
c.addEventListener('mousemove', function (evt) {
mouse.x = evt.pageX;
mouse.y = evt.pageY;
}, false);
c.addEventListener('mousedown', function (evt) {
// tctx.clearRect(0, 0, c.width, c.height);
evt.preventDefault();
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, c.width, c.height);
mouse.x = evt.pageX;
mouse.y = evt.pageY;
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
c.addEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function () {
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, t.width, t.height);
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
}
c.addEventListener('mouseup', function () {
c.removeEventListener('mousemove', onPaint, false);
}, false);
</script>
</body>
Heres A good Starting point for ya :) it does what your looking for. jsFiddle
/* Main Canvas */
var main = document.getElementById('main');
main.width = window.innerWidth;
main.height = window.innerHeight;
var mainCtx = main.getContext('2d');
var mainFill = '#000';
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
/* secondary canvas */
var cv = document.createElement('canvas');
cv.style.position = 'absolute';
cv.width = '200';
cv.height = '100';
cv.style.left = '0px';
cv.style.top = '0px';
var ctx = cv.getContext('2d');
var fillRect = '#ccc';
var fillText = '#000';
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
//draw this canvas to main canvas
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
var isHolding = false;
var mDown = function(e)
{
isHolding = true;
main.addEventListener('mousemove',mMove);
}
var mMove = function(e)
{
console.log('moving');
if(isHolding)
{
var xPos = e.pageX;
var yPos = e.pageY;
cv.style.left = (xPos-(cv.width/2))+'px';
cv.style.top = (yPos-(cv.height/2))+'px';
cv.width = cv.width; //clears canvas
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
ctx.fillStyle = fillText;
ctx.fillText('x: '+e.pageX,10,10);
ctx.fillText('y: '+e.pageY,50,10);
//draw temp canvas to main canvas
this.width = this.width;
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
}
}
var mUp = function(e)
{
isHolding = false;
main.removeEventListener('mousemove',mMove);
}
main.addEventListener('mousedown',mDown);
main.addEventListener('mouseup',mUp);
also it gets rid of the move event when not being used which will help have less event dispatches in memory and help with performance.

Categories

Resources