html canvas drew far from actual drew point - javascript

I have a image inside canvas. When I paint it draw the line far from the actual point. I can't figure out why this is happening and how to fix it.
This is the script and it is taken from here. When I click in one point it draw in another point.
Draw on HTML5 Canvas using a mouse
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);
base_image = new Image();
base_image.src = document.getElementById("editable_image_path").src
base_image.onload = function() {
ctx.drawImage(base_image, 0, 0, 800, 400);
};
}
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();
}
}
}
<div class="snap-field col-sm-12" style="height: 800px;">
<body onload="init()">
<canvas id="can" width="1000" height="500"
style="border:1px solid;position:absolute;">
</canvas>
</body>
</div>

Instead of using canvas.offsetX and canvas.offsetY in the findXY function, use canvas.getBoundingClientRect().left and canvas.getBoundingClientRect().top. It will give you more reliable absolute coordinates for the canvas as the reference point for drawing.

Related

how to make drawable on dynamic canvas

I have display canvas dynamically based on records in db. Currently I have
two records in db and it shows two canvas in page.Now i should able to draw
on both cannvas however I can only draw on last canvas not on the both canvas.
Please check the image https://ibb.co/n7rvdk5 for more.
I am getting id 609 and 610.It can be 1,2 etc. This id are passed on canvas id to make it unique.
<div class="snap-field col-sm-12" style="height: 450px;">
loop here
<canvas data-fieldid="{{$draw->id}}"
id="image-canvas-{{$draw->id}}"
width="400" height="200"
class="image-canvas"
style="position:absolute;">
</canvas>
</div>
This is my js part and within document.ready function i have loaded the canvas . initEditableImageCanvas takes unique id. for example in this case it takes 609 and 610.I can draw on canvas with id 610 but not on 609.Maybe I need to make some changes here and I am not sure what should I do
<script>
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "red",
y = 2;
function initEditableImageCanvas(fieldId) {
canvas = document.getElementById('image-canvas-' + fieldId);
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 findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.getBoundingClientRect().left;
currY = e.clientY - canvas.getBoundingClientRect().top;
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.getBoundingClientRect().left;
currY = e.clientY - canvas.getBoundingClientRect().top;
draw();
}
}
}
$(document).ready(function() {
$(".image-canvas").each(function(canvas) {
//get id
initEditableImageCanvas($(this).data("fieldid"));
});
});
</script>
I am looking for help to fix it. I want draw in all canvas.
Any help? Thanks
In order to draw on a canvas, you can store it in a variable so that you are able to apply your logic.
let canvas = document.getElementById('canvasId');
let ctx = canvas.getContext('2d')
/*
Logic
*/
However, in your case, it turns out that since canvas and ctx are global variables, they get reassigned each time initEditableImageCanvas() is called within jQuery's each().
So even though the function findxy() is called whenever one event (i.e. mousemove) happens, it's not sufficient to draw on the right places. You
have to check if it is pointing to the right canvas.
This said, to prevent unexpected behaviors, prefer using local variables defined with let statement instead of global ones when working with multiple drawable canvas. One solution follows:
Change var -> let
Add a third parameter (c) to findxy()
Add an parameter (ctx) to draw()
// get rid of global canvas and ctx
var flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "red",
y = 2;
function initEditableImageCanvas(fieldId) {
// use let
let canvas = document.getElementById('editable-image-canvas-' + fieldId);
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
/*
Attach this to each findxy
*/
canvas.addEventListener("mousemove", function(e) {
findxy('move', e, this)
}, false);
canvas.addEventListener("mousedown", function(e) {
findxy('down', e, this)
}, false);
canvas.addEventListener("mouseup", function(e) {
findxy('up', e, this)
}, false);
canvas.addEventListener("mouseout", function(e) {
findxy('out', e, this)
}, false);
}
function draw(ctx) {
// added parameter ctx
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
function findxy(res, e, c) {
// added parameter c and local ctx
let ctx = c.getContext('2d')
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - c.getBoundingClientRect().left;
currY = e.clientY - c.getBoundingClientRect().top;
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 - c.getBoundingClientRect().left;
currY = e.clientY - c.getBoundingClientRect().top;
draw(ctx); // added argument
}
}
}
$(document).ready(function() {
$(".editable-image-canvas").each(function(canvas) {
// alert($(this).data("fieldid")) //give id 609 and 610
initEditableImageCanvas($(this).data("fieldid"));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="snap-field col-sm-12" style="height: 450px;"> <div style="display:grid;"> <span>609</span> <canvas data-fieldid="609" id="editable-image-canvas-609" width="200" height="150" class="editable-image-canvas" style="position:relative;top:10%;border:1px dotted; margin-bottom:30px;"> </canvas> <span>610</span> <canvas data-fieldid="610" id="editable-image-canvas-610" width="200" height="150" class="editable-image-canvas" style="position:relative;top:10%;border:1px dotted;"> </canvas> </div><input type="hidden" name="field_{{$draw->id}}" id="editable-image-hidden-{{$draw->id}}"></div>

unable to draw on multiple canvas

How to load multiple canvas and enable drawing on it. Currently, It shows two canvas on my page but I can only draw in one canvas.
I have two records in database. foreach loop below make two canvas but I can only draw in only one canvas not on the both canvas. I should able to draw on both canvas and that is the things I want. I am looking for any help or any tips on how should I do so that I can draw on all canvas generated dynamically.
<body onload="init()">
<canvas id="can_{{$draw->id}}" width="1200" height="400"
style="position:absolute;top:10%;left:10%;border:2px solid;">
</canvas>
</body>
Below is the js code that allows user to draw on image of canvas
<script type="text/javascript">
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var x = "red",
y = 2;
function init() {
for(let i=1;i<3;i++){
canvas = document.getElementById('can_'+i);
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);
}//end of for
}
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.getBoundingClientRect().left;
currY = e.clientY - canvas.getBoundingClientRect().top;
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.getBoundingClientRect().left;
currY = e.clientY -canvas.getBoundingClientRect().top;
draw();
}
}
}
</script>
Try something similar to this. Add the context to an array and see if you can draw to both. Not exactly sure the context thing is your problem but I think it is.
let canvas1 = document.getElementById("c1");
let canvas2 = document.getElementById("c2");
let ctx1 = canvas1.getContext("2d");
let ctx2 = canvas2.getContext("2d");
let ctx = [ctx1, ctx2];
function draw() {
ctx.forEach((ctx, i) => {
ctx.fillStyle = "lightblue";
ctx.fillRect(10, 10, 100, 100)
});
}
draw()
<canvas id='c1'></canvas>
<canvas id='c2'></canvas>
Adding what #Kaiido said for performance
let canvas1 = document.getElementById("c1");
let canvas2 = document.getElementById("c2");
let ctx1 = canvas1.getContext("2d");
let ctx2 = canvas2.getContext("2d");
ctx1.fillStyle = "lightblue";
ctx1.fillRect(50, 50, 100, 100)
ctx2.drawImage(canvas1, 0, 0)
<canvas id='c1'></canvas>
<canvas id='c2'></canvas>
Here's a solution that makes use of the fact we know which canvas generated a mouse event. Since we know that, we can use it to get the context of the correct canvas.
I show a message for mousemove and mousedown, indicating which canvas triggered the event.
<!doctype html>
<html>
<head>
<script>
"use strict";
var canvas, ctx, flag = false,
prevx = 0,
curx = 0,
prevy = 0,
cury = 0,
dot_flag = false;
var x = "red",
y = 2;
window.addEventListener('load', onLoaded, false);
function onLoaded(evt)
{
let canvasElems = document.querySelectorAll('canvas');
canvasElems.forEach(
can => {
can.addEventListener('mousemove', function(evt){ findxy('move', evt, this);}, false);
can.addEventListener('mousedown', function(evt){ findxy('down', evt, this);}, false);
can.addEventListener('mouseup', function(evt){ findxy('up', evt, this);}, false);
can.addEventListener('mouseout', function(evt){ findxy('out', evt, this);}, false);
} );
}
function findxy(reason, evt, elem)
{
if (reason=='up' || reason=='out')
flag = false;
if (reason == 'down')
{
document.querySelector('#output').textContent = elem.getAttribute('name') + ' was clicked';
prevx = curx;
prevy = cury;
curx = evt.clientX - elem.getBoundingClientRect().left;
cury = evt.clientY - elem.getBoundingClientRect().top;
flag = true;
dot_flag = true;
//if (dot_flag)
//{
let ctx = elem.getContext('2d');
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(curx, cury, 2, 2);
ctx.closePath();
dot_flag = false;
//}
}
else if (reason == 'move')
{
document.querySelector('#output').textContent = elem.getAttribute('name') + ' was moved over';
if (flag)
{
prevx = curx;
prevy = cury;
curx = evt.clientX - elem.getBoundingClientRect().left;
cury = evt.clientY - elem.getBoundingClientRect().top;
draw(elem);
}
}
}
function draw(tgtCanvas)
{
let ctx = tgtCanvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(prevx, prevy);
ctx.lineTo(curx, cury);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}
</script>
<style>
canvas
{
margin: 4px;
border: solid 1px #333;
}
</style>
</head>
<body>
<canvas name='canvas1'></canvas><canvas name='canvas2'></canvas>
</br>
<span id='output'></span>
</body>
</html>

How to add dynamic labels to the dynamically added shapes on the Canvas?

I am trying to create a free-form drawing tool which allows to draw a shape (rectangle/triangle/line) and add the unique labels for each drawn shape. I got the free-form drawing tool code here: https://jsfiddle.net/k70m5qvh/.
Code:
<html>
<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 "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();
//clear background
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 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>
<body onload="init()">
<style>
.eraser {
cursor: cell;
}
</style>
<canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:1px solid black;"></canvas>
<div style="position:absolute;top:17%;left:67%;width: 40px; height:15px;border: 1px solid black; padding: 10px 5px;" id="black" onclick="color(this)">Draw</div>
<div style="position:absolute;top:37%;left:67%;width: 40px; height:15px;border: 1px solid black; padding: 10px 5px;" id="white" class="eraser" onclick="color(this)">Erase</div>
<img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
</body>
</html>
But need a solution for the second part, that is adding dynamic labels for drawn objects.
Does anyone have experience of adding dynamic labels for dynamically added free-form shapes on canvas? Appreciate the help!

Mouse Position In canvas not correct when page scrolls down

I've got a page where I added a canvas which will be used by a technician or client for their signatures. I've managed to get it working and able to draw inside the canvas. However, when the page is scrolled a bit downwards the positioning of where the drawing starts is higher than the mouse point. When I scroll the page back to the top again, the position of the where the drawing starts is directly on the mouse point again.
How do I get the correct position of X and Y irrespective of whether the page is scrolled or not?
This is what I've done:
HTML:
<body onload="init();">
<div id="dialogSignature" runat="server" style="padding-top:10px; display:none; ">
<canvas id="myCanvas" width="400" height="200" style="border:2px solid;"></canvas>
<img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
</body>
<table>
<tr>
<td>
<input type="button" value="Clear" id="clr" size="23" onclick="erase()" class="myButton" >
</td>
<td>
<button class="myButton" onclick="javascript:UploadPic();return false;">Sumbit</button>
</td>
</tr>
</table>
<asp:Label ID="lblText" runat="server" Text="Label" Visible="false"></asp:Label>
<asp:Label ID="lblScopeIdentity" runat="server" Text="sss" Visible="false"></asp:Label>
</div>
Javascript:
<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('myCanvas');
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);
canvas.addEventListener("touchstart", function (e) {
mousePos = getTouchPos(canvas, e);
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousedown", {
clientX: touch.clientX,
clientY: touch.clientY
});
canvas.dispatchEvent(mouseEvent);
}, false);
canvas.addEventListener("touchend", function (e) {
var mouseEvent = new MouseEvent("mouseup", {});
canvas.dispatchEvent(mouseEvent);
}, false);
canvas.addEventListener("touchmove", function (e) {
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousemove", {
clientX: touch.clientX,
clientY: touch.clientY
});
canvas.dispatchEvent(mouseEvent);
}, false);
// Prevent scrolling when touching the canvas
document.body.addEventListener("touchstart", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, false);
document.body.addEventListener("touchend", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, false);
document.body.addEventListener("touchmove", function (e) {
if (e.target == canvas) {
e.preventDefault();
}
}, false);
}
function getTouchPos(canvasDom, touchEvent) {
var rect = canvasDom.getBoundingClientRect();
return {
x: touchEvent.touches[0].clientX - rect.left,
y: touchEvent.touches[0].clientY - rect.top
};
}
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();
}
}
}
var scopeIdentityUse = "<%=scopeIdentityJS1%>";
var Pic = document.getElementById("myCanvas").toDataURL("image/png");
Pic = Pic.replace(/^data:image\/(png|jpg);base64,/, "")
$.ajax({
type: 'POST',
url: 'Save_Picture.aspx/UploadPic',
data: '{ "imageData" : "' + Pic + '", "param" : "' + scopeIdentityUse + '" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
document.location.href = 'CreatePDFReport.aspx'
//alert("Done, Picture Uploaded.");
}
});
</script>
Below is a better version of the correct position of mouse pointer. (styling needs to be redone though in stylesheet)....
Javascript:
<script type="text/javascript">
var canvas, ctx;
var mouseX, mouseY, mouseDown = 0;
var touchX, touchY;
var lastX, lastY = -1;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext('2d');
w = canvas.width;
h = canvas.height;
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
canvas.addEventListener('mouseup', sketchpad_mouseUp, false);
canvas.addEventListener('touchstart', sketchpad_touchStart, false);
canvas.addEventListener('touchend', sketchpad_touchEnd, false);
canvas.addEventListener('touchmove', sketchpad_touchMove, false);
function drawLine(ctx, x, y, size) {
if (lastX == -1) {
lastX = x;
lastY = y;
}
r = 0; g = 0; b = 0; a = 255;
ctx.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + (a / 255) + ")";
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.lineWidth = size;
ctx.stroke();
ctx.closePath();
lastX = x;
lastY = y;
}
function sketchpad_mouseDown() {
mouseDown = 1;
drawLine(ctx, mouseX, mouseY, 6);
}
function sketchpad_mouseUp() {
mouseDown = 0;
lastX = -1
lastY = -1
}
function sketchpad_mouseMove(e) {
getMousePos(e);
if (mouseDown == 1) {
drawLine(ctx, mouseX, mouseY, 6);
}
}
function getMousePos(e) {
if (!e)
var e = event;
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
}
function sketchpad_touchStart() {
getTouchPos();
drawLine(ctx, touchX, touchY, 6);
event.preventDefault();
}
function sketchpad_touchEnd() {
lastX = -1;
lastY = -1;
}
function sketchpad_touchMove(e) {
getTouchPos(e);
drawLine(ctx, touchX, touchY, 6);
event.preventDefault();
}
function getTouchPos(e) {
if (!e)
var e = event;
if (e.touches) {
if (e.touches.length == 1) {
var touch = e.touches[0];
touchX = touch.pageX - touch.target.offsetLeft;
touchY = touch.pageY - touch.target.offsetTop;
}
}
}
function fd_erase(elem1) {
ctx.clearRect(0, 0, w, h);
if (typeof elem1 != 'undefined') {
document.getElementById(elem1).style.display = "none";
document.getElementById(elem1).value = '';
}
}
function fd_save() {
canvas = document.getElementById('can');
ctx = canvas.getContext('2d');
var dataURL = canvas.toDataURL();
document.getElementById('Signature1_img').src = dataURL;
document.getElementById('Signature1').value = dataURL;
document.getElementById('Hidden1').value = dataURL;
document.getElementById('Signature1_img').style.display = "inline";
}
And on html:
<div style="position: absolute; width:794px; height:1122px; background-color:#FFFFFF;">
<form runat="server" id="form1">
<canvas id="can" Width="300px" Height="300px" style="top:108px;left:96px;color:#000000;background-color:#FFFFFF;border:1px solid #000;"></canvas>
<input type="hidden" id="Signature1" name="Signature1" value="" >
<input type="text" id="Hidden1" name="hndText" runat="server" value="" >
<img id="Signature1_img" name="Signature1_img" Width="300px" Height="300px" style="color:#000000;background-color:#FFFFFF;border-style:solid;border-width:1px;border-color:#000000;display:none;">
</form>
</div>

Offset all Canvas Lines

I have the following canvas code:
<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 "blue":
x = "blue";
break;
case "red":
x = "red";
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>
However because of CSS having margin/padding/width/height on my parent elements, the canvas is returning an offset to the left and bottom, is there any way to forcefully apply a negative offset back to the mouse location or is it possible to just get the MOUSE location instead.
Use .getBoundingClientRect which accounts for CSS styling & repositioning:
var BB=canvas.getBoundingClientRect();
var BBoffsetX=BB.left;
var BBoffsetY=BB.top;
var mouseX=parseInt(e.clientX-BBoffsetX);
var mouseY=parseInt(e.clientY-BBoffsetY);

Categories