I come here for a clean canvas issue in HTML/Javascript. In this canvas, it's use for a signature (like this).
If i use these lines of code :
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
function save() {
var canvas = document.getElementById("can");
var dataURL = canvas.toDataURL("image/png");
document.getElementById('source').value = dataURL;
var fd = new FormData(document.forms["general"]);
var xhr = new XMLHttpRequest();
xhr.open('Get', 'convertToPdf.php', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
console.log(percentComplete + '% uploaded');
alert('Succesfully uploaded');
}
};
xhr.onload = function() {
};
xhr.send(fd);
}
function color(obj) {
switch (obj.id) {
case "green":
x = "green";
break;
case "blue":
x = "blue";
break;
case "red":
x = "red";
break;
case "yellow":
x = "yellow";
break;
case "orange":
x = "orange";
break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display = "none";
}
var conv = new ActiveXObject("pdfServMachine.converter");
conv.convert("http://www.google.com", "google.pdf", false);
WScript.Echo("finished conversion");
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
<p align="center">
<canvas id="can" width="700" height="200" style="border:2px solid;"></canvas>
</p>
<table align="center">
<tr align="left">
<td align="right">
<input type="submit" name="ss" value="Submit" id="btn" onclick="save();return validateBeforeSubmit(); ">
</td>
<td align="right">
<input type="button" name="ss" value="clear" id="btn" onclick="erase()">
</td>
</tr>
</table>
The clear, works, but if I have a scrollbar in my page, we can't see anything in the canvas!!
So, I was looking for an function init() that will be able to write in the canvas wherever you are in the webpage and found this :
function init(){
var canvas = document.getElementById('can');
var ctx = canvas.getContext('2d');
w = canvas.width;
h = canvas.height;
var x = null;
var y;
canvas.onmousedown = function(e){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
ctx.beginPath();
ctx.moveTo(x,y);
}
canvas.onmouseup = function(e){
x = null;
}
canvas.onmousemove = function(e){
if (x==null) return;
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
ctx.lineTo(x,y);
ctx.stroke();
}
}
But know, the canvas take all 'signature' for where you are in the page, so, if the webpage have a scroll bar, no problem, the canvas still show something if you draw something, but the clear won't work on it.
So, my issue it's that I want to be able to write in the canvas, no matter where it is, and be able, if a click on my button who have the function clear, to clear the canvas.
EDIT
Here what my webpage look like:
My page
Right now, I put it without scrollbar to show, but, at the original size, the page have a scroll. My canvas it's at the bottom of the page, so, when I scroll down, I can't draw in it, but in a page without scroll, I can draw in it and erase it!!
There was the reason that I put the second init function, that if there a scrollbar or not, I'm still able to draw in it, that I scroll or not the page, but not for clean it!!
Thanks for you're help
https://jsfiddle.net/we242fmt/3/
(In the example I purposely moved the canvas down the page using CSS to better demonstrate. You can remove the CSS I've added in to get back to where you were)
What's happening is that you're getting the offset of the canvas element but the offset doesn't take into account how far you've scrolled down the page.
All we need to do is simply adjust the code to incorporate the distance that the user has scrolled:
currX = e.clientX - canvas.offsetLeft + window.scrollX;
currY = e.clientY - canvas.offsetTop + window.scrollY;
In your example you don't need to use scrollX because you're not scrolling horizontally, but I included it for the sake of being thorough.
Related
The aim is to able to write using mouse movement on video on pause.
I am using an HTML5 Video tag to play video.
I am able to play the video without any issue, apart from playing video I need to write able to draw on video on the pause of the video
I am able to write on canvas. But when I have a video tag in canvas, I am NOT able to view any of my drawings.
Can you please let me know, what I am doing wrong?
Below is the code:
<html>
<!-- <body onload="init()"> -->
<body>
<canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;">
</canvas>
<video id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;">
<source src="Test.mp4" type="video/mp4">
</video>
</body>
<script type="text/javascript">
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
//# must await page load via JS (before using JS functions)...
addEventListener("load", init );
function init()
{
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
canvas.addEventListener("mousemove", function (e) { findxy('move', e)}, false);
canvas.addEventListener("mousedown", function (e) { findxy('down', e) }, false);
canvas.addEventListener("mouseup", function (e) { findxy('up', e)}, false);
canvas.addEventListener("mouseout", function (e) { findxy('out', e)}, false);
}
function draw()
{
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase()
{
var m = confirm("Want to clear");
if (m)
{
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display = "none";
}
}
function save()
{
document.getElementById("canvasimg").style.border = "2px solid";
//var dataURL = canvas.toDataURL();
//document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").src = canvas.toDataURL();
document.getElementById("canvasimg").style.display = "inline";
}
function findxy(res, e)
{
if (res == 'down')
{
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
flag = true;
dot_flag = true;
if (dot_flag)
{
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out")
{ flag = false; }
if (res == 'move')
{
if (flag)
{
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
function color(obj)
{
switch (obj.id)
{
case "green": x = "green"; break;
case "blue": x = "blue"; break;
case "red": x = "red"; break;
case "yellow": x = "yellow"; break;
case "orange": x = "orange"; break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
</script>
</html>
I have a canvas in which, is drawn an element svg (example a circle), the user is responsible for drawing with the mouse through this figure, I save the dots x and y drawn by the user in an array, but I dont know how to get the dots only from svg stroke.
My problem is:
Using isPointInStroke() I can see if the point is in the stroke but If I don't have the total points array of the stroke, it's impossible to know if the user has drawn 100% of the SVG figure. In the previous way if the user draws half of the drawing but correctly, it would give me 100% success.
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
var svgPathCirculo=" M125,200a75,75 0 1,0 150,0a75,75 0 1,0 -150,0";
var circulo = new Path2D(svgPathCirculo);
ctx.lineWidth = 5;
ctx.setLineDash([5, 15]);
ctx.stroke(circulo);
// Just example to check if it works
if(ctx.isPointInStroke(circulo, 125, 200)){
ctx.arc(200,200,3,0,2*Math.PI);
ctx.fill();
};
canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
}
I use the canvas to draw on it and svg to display predefined shapes for the user to follow as a template while drawing (such as drawing booklets for young children).
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
if(!arrayCoordenadas.includes({x:currX,y:currY})){
arrayCoordenadas.push({x:currX,y:currY});
}
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
if(!arrayCoordenadas.includes({x:currX,y:currY})){
arrayCoordenadas.push({x:currX,y:currY});
}
draw();
}
}
}
I need to know each of the x and y coordinates of the svg stroke path.
Example: Example of what I mean
I've added a function to detect the mouse position in the canvas and now currX became curr.x ... etc
If you are using Path2Dthis is how you detect if a point {x,y} is in the stroke:
ctx.isPointInStroke(the_path, x, y)
Next comes my code. The user can draw only inside the stroke.
Now the code is working but I don't think you may know if the user has drawn 100% of the SVG figure. You may push the points inside the array of points and calculate the length of the path, and compare it with the length of the circle, but I don't think this would do.
let prev = {},
curr = {};
let flag = false;
let circulo;
function init() {
canvas = document.getElementById("can");
ctx = canvas.getContext("2d");
w = canvas.width = 400;
h = canvas.height = 400;
var svgPathCirculo = "M125,200a75,75 0 1,0 150,0a75,75 0 1,0 -150,0";
circulo = new Path2D(svgPathCirculo);
ctx.lineWidth =10;
ctx.setLineDash([5, 15]);
ctx.stroke(circulo);
canvas.addEventListener("mousemove", move, false);
canvas.addEventListener("mousedown", down, false);
canvas.addEventListener("mouseup", up, false);
canvas.addEventListener("mouseout", up, false);
}
function draw(prev, curr, trazado) {
ctx.setLineDash([]); //unset linedash
ctx.lineCap = "round";
ctx.strokeStyle = "gold"
ctx.lineWidth =5;
if (
ctx.isPointInStroke(trazado, curr.x, curr.y) &&
ctx.isPointInStroke(trazado, prev.x, prev.y)
) {
ctx.beginPath();
ctx.moveTo(prev.x, prev.y);
ctx.lineTo(curr.x, curr.y);
ctx.stroke();
}
}
function down(e) {
prev = oMousePos(canvas, e);
curr = oMousePos(canvas, e);
flag = true;
}
function up(e) {
flag = false;
}
function move(e) {
if (flag) {
curr = oMousePos(canvas, e);
draw(prev, curr, circulo);
prev = { x: curr.x, y: curr.y };
}
}
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return {
//objeto
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
};
}
init();
canvas{border:1px solid}
<canvas id="can"></canvas>
I have used the following code draw on canvas during the mouse move.
<script type="text/javascript">
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
}
function color(obj) {
switch (obj.id) {
case "green":
x = "green";
break;
case "blue":
x = "blue";
break;
case "red":
x = "red";
break;
case "yellow":
x = "yellow";
break;
case "orange":
x = "orange";
break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display =
"none";
}
}
function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
</script>
<div class="content-wrapper" onmousemove="init()" style="width: 50%;
float: left;">
<canvas id="can" width="400" height="200" style="border:2px solid;">
</canvas>
</div>
It doesn't draw exactly at the mouse point when I have scrolled down the web page. That is it draws something, but not at the mouse point if I have scrolled down through the web page.
I want to avoid that, and it should draw at the mouse point even after I have scrolled down.
Can someone figure out what the issue is ?
You should use offsetX and offsetY property of MouseEvent, instead of e.clientX - canvas.offsetLeft and e.clientY - canvas.offsetTop respectively, to draw the line exactly at the mouse point even after the web page is scrolled.
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
canvas.addEventListener("mousemove", function(e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function(e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function(e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function(e) {
findxy('out', e)
}, false);
}
function color(obj) {
switch (obj.id) {
case "green":
x = "green";
break;
case "blue":
x = "blue";
break;
case "red":
x = "red";
break;
case "yellow":
x = "yellow";
break;
case "orange":
x = "orange";
break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display =
"none";
}
}
function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.offsetX;
currY = e.offsetY;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.offsetX;
currY = e.offsetY;
draw();
}
}
}
<div class="content-wrapper" onmousemove="init()" style="width: 50%;
float: left;">
<canvas id="can" width="400" height="500" style="border:2px solid;"></canvas>
</div>
I'm currently trying to achieve the following.
I have a HTML5 Canvas, where you can draw in. The code is this:
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "black",
y = 2;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
}
function color(obj) {
switch (obj.id) {
case "green":
x = "green";
break;
case "blue":
x = "blue";
break;
case "red":
x = "red";
break;
case "yellow":
x = "yellow";
break;
case "orange":
x = "orange";
break;
case "black":
x = "black";
break;
case "white":
x = "white";
break;
}
if (x == "white") y = 14;
else y = 2;
}
function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
ctx.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display = "none";
}
}
function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
}
function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
<html>
<body onload="init()">
<canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>
<div style="position:absolute;top:12%;left:43%;">Choose Color</div>
<div style="position:absolute;top:15%;left:45%;width:10px;height:10px;background:green;" id="green" onclick="color(this)"></div>
<div style="position:absolute;top:15%;left:46%;width:10px;height:10px;background:blue;" id="blue" onclick="color(this)"></div>
<div style="position:absolute;top:15%;left:47%;width:10px;height:10px;background:red;" id="red" onclick="color(this)"></div>
<div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:yellow;" id="yellow" onclick="color(this)"></div>
<div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:orange;" id="orange" onclick="color(this)"></div>
<div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:black;" id="black" onclick="color(this)"></div>
<div style="position:absolute;top:20%;left:43%;">Eraser</div>
<div style="position:absolute;top:22%;left:45%;width:15px;height:15px;background:white;border:2px solid;" id="white" onclick="color(this)"></div>
<img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
<input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:55%;left:10%;">
<input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:55%;left:15%;">
</body>
</html>
So basically just drawing lines from one point to another.
Now I'm wondering about the following. Most of you should know OneNote, which has a feature that you can draw something, and then you see "whoops, this was drawn much to big or to small in comparison to the other things I have drawn" and then you can just mark it and grab the corner and make the rectangle you marked smaller or bigger.
I'm currently thinking about the same solution in a canvas. So people can draw something in that canvas, and there's a resize button, when you click on it, you can "draw" a rectangle (like with a dotted border and transparet fill) and everything in that rectangle is then marked. Then you can grab one of the corners and make the marked drawings smaller or bigger, and move that content as well.
But honestly, I have no idea how to get started with that.
Anybody has an idea on how to do that?
Not that difficult:
Create a button, attach an event listener, call a function. I’ll call it resize for the purpose of my guide
Create the dotted border overlay over your canvas. Just make it a div, wrap the canvas into a wrapper, apply a bit of CSS. Voilà.
Attach event handlers to the div to make it resizable or search the web for a library that can do that.
Then you’ll have to redraw the canvas as image with CanvasRenderingContext2D.drawImage().
It’s worth noting that canvases are raster-graphics. The canvas will become unsharp with enlarging.
I am trying to create a simple canvas program where the user can consistently create new shapes. This one is just a basic rectangle creator (I am hoping to expand it more to circles, lines, and maybe even other stuff). Right now though I have created something that is working in a really weird way.
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
function init() {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
document.body.addEventListener("mouseup", mouseUp, false);
}
function mouseUp() {
mouseIsDown = 0;
//mouseXY();
}
function mouseDown() {
mouseIsDown = 1;
startX = event.clientX;
startY = event.clientY;
mouseXY();
}
function mouseXY(eve) {
if (!eve) {
var eve = event;
}
endX = event.pageX - canvas.offsetLeft;
endY = event.pageY - canvas.offsetTop;
drawSquare();
}
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
</script>
</head>
<body onload="init()">
<canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas>
</body>
</html>
Sorry about the slightly weird formatting when I copy and pasted my code. I think the problem is my mouseXY function. What I want is the user to click somewhere on the canvas a drag the mouse to create a rectangle, when the user lets go that is the end of that operation and they can create a whole new rectangle right after. At this point the program kind of just lets me click and create a new rectangle but if I let go of the mouse button it doesn't stop, in fact I have to click again to make it stop which then creates a new rectangle. I am still very new to this and I am having a lot of trouble with this, I will continue to work on this and if I figure it out I will let the site know. Thank you and have a great day!
Well I got this to work (thanks to #Ken) but now I am trying to solve a new problem. I want to be able to put multiple rectangles on the canvas. I created a function that represents the Rectangle and then created a draw function within the rectangle function to draw out a rectangle. I created a new function called addShape() that ideally creates the rectangle object and pushes into an array called square and drawShapes() that is supposed to erase everything on the canvas and redraws everything. Here is what I have so far:
<html>
<head>
<meta chartset="utf-8">
<title>Dragging a square</title>
<script type="text/javascript">
function Rectangle(canvas, x, y, width, height,color) {
//this.context = canvas.getContext("2d");
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.draw = function() {
this.context.globalAlpha = 0.85;
this.context.beginPath();
this.context.rect(this.x, this.y, this.width, this.height);
this.context.fillStyle = this.color;
this.context.strokeStyle = "black";
this.context.lineWidth = 1;
this.context.fill();
this.context.stroke();
};
};
// hold the canvas and context variable, as well as the
// starting point of X and Y and the end ones
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
// An array that holds all the squares
var squares = [];
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
canvas.addEventListener("mouseup", mouseUp, false);
}
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square(); //update on mouse-up
addShape(); // Update on mouse-up
}
}
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
// Square(); //update
addShape();
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//Square();
addShape();
}
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function addShape() {
var w = endX - startX;
var h = endY - startY;
var offsetX = (w < 0) ? w : 0;
var offsetY = (h < 0) ? h : 0;
var width = Math.abs(w);
var height = Math.abs(h);
var s = new Rectangle(startX + offsetX, startY + offsetY, width, height, "yellow");
squares.push(s);
// Update the display
drawShapes();
}
function drawShapes() {
context.clearRect(0,0,canvas.width,canvas.height);
for (var i = 0; i < squares.length; i++) {
var shape = squares[i];
shape.draw();
};
}
function clearCanvas() {
squares = [];
drawShapes();
}
</script>
</head>
<body onload="addShape()">
<canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas><br>
<button onclick="clearCanvas()">Clear Canvas</button>
</body>
</html>
I am pretty sure I broke the original code... thank you for any help!
You need to modify a couple of things in the code: (edit: there are many issues with this code. I went through some of them inline here, but haven't tested. If you put it in a fiddle it's easier for us to check)..
Fiddle
When mouse down occur initialize both start and end points. Call a common draw function that is not dependent on the event itself:
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
drawSquare(); //update
}
At mouse up, only register if isMouseDown is true, else this function will handle all incoming up-events (as you have attatched it to document, which is correct - window could have been used too):
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare(); //update on mouse-up
}
}
Only draw if mouseisdown is true:
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare();
}
}
In addition you will need to clear the previous area of the rectangle before drawing a new or else it won't show when you draw a bigger rectangle and then move the mouse back to draw a smaller one.
For simplicity you can do:
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.clearRect(0, 0, context.width, context.height);
//or use fillRect if you use a bg color
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
Use this for mouse position:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}