Add annotation to image with canvas on small screen without resizing - javascript

I hope you can help me with my problem. I am writing a mobile application with cordova and ionic and we need a function to annotate images before we upload them.
I want to be able to add annotations to an image (at the moment only lines) without resizing the image. But since the screenspace on phones is small i am now using 2 canvas directly placed above each other.
One the first one i render the scaled down image i want to annotate, on the 2nd one i make the annotations. Then i render the original image on 3 canvas and upscale the annotations to the size of the original image.
var finalcanvas = document.createElement('canvas');
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
var canvaslines = document.getElementById("canvasdraw");
ctxfinal.drawImage(canvaslines, 0, 0, imageObj.width, imageObj.height);
$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
This works fine, but the only downside is that the annotations are rather pixely. I assume there must be a library or something which should make things like this easier, but no matter how much i searched i could not find anything. But maybe i used the wrong keywords since i am not a very adept programmer and not a native speaker. Thanks for all your help in advance
Edit: Here is a link to a jsfiddle of my code http://jsfiddle.net/q97szydq/14/

One solution would be to store all your points into an array, then redraw them on your new canvas (after you rescaled the points) :
var drawnLines = [];
//in your start functions :
drawnLines.push(["m", x, y]);
//in your move functions :
drawnLines.push(["l", x, y]);
//then in your hideModal function :
var ratio = finalcanvas.width/document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3*ratio;
for(i=0; i<drawnLines.length; i++){
var xm = drawnLines[i][1]*ratio;
var ym = drawnLines[i][2]*ratio;
switch (drawnLines[i][0]){
case "l" : ctxfinal.lineTo(xm, ym);
case "m" : ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
ctx = document.getElementById("canvasdraw").getContext("2d");
ctx2 = document.getElementById("canvasimg").getContext("2d");
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 3;
var imageObj = new Image();
imageObj.onload = function() { //ion-header-bar
var MAX_WIDTH = 300;
var MAX_HEIGHT = 500;
tempW = imageObj.width;
tempH = imageObj.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
document.getElementById("canvasdraw").height = tempH;
document.getElementById("canvasdraw").width = tempW;
document.getElementById("canvasimg").height = tempH;
document.getElementById("canvasimg").width = tempW;
ctx2.drawImage(imageObj, 0, 0, tempW, tempH);
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
// setup to trigger drawing on mouse or touch
drawTouch();
drawPointer();
drawMouse();
var drawnLines = [];
//all draw functions have minus 50px height to adjust for header
// prototype to start drawing on touch using canvas moveTo and lineTo
function drawTouch() {
var start = function(e) {
ctx.beginPath();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("touchstart", start, false);
document.getElementById("canvasdraw").addEventListener("touchmove", move, false);
};
// prototype to start drawing on pointer(microsoft ie) using canvas moveTo and lineTo
function drawPointer() {
var start = function(e) {
e = e.originalEvent;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
e = e.originalEvent;
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("MSPointerDown", start, false);
document.getElementById("canvasdraw").addEventListener("MSPointerMove", move, false);
};
// prototype to start drawing on mouse using canvas moveTo and lineTo
function drawMouse() {
var clicked = 0;
var start = function(e) {
clicked = 1;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
if (clicked) {
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
}
};
var stop = function(e) {
clicked = 0;
};
document.getElementById("canvasdraw").addEventListener("mousedown", start, false);
document.getElementById("canvasdraw").addEventListener("mousemove", move, false);
document.addEventListener("mouseup", stop, false);
};
var hideModal = function() {
var finalcanvas = document.getElementById("finalcanvas");
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
ctxfinal.beginPath();
var ratio = finalcanvas.width / document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3 * ratio;
for (i = 0; i < drawnLines.length; i++) {
var xm = drawnLines[i][1] * ratio;
var ym = drawnLines[i][2] * ratio;
switch (drawnLines[i][0]) {
case "l":
ctxfinal.lineTo(xm, ym);
case "m":
ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
//I then generate a a image from this final canvas. So now i have the image in the original size + the sadly a bit pixely annotations
//$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
};
canvas {
border: 1px solid #000;
}
<div id="page">
<div class="buttons" style="height:50px;">
<button class="button button-clear" onclick="hideModal()">save</button>
</div>
<canvas id="canvasimg" style="position:absolute;z-index:1;"></canvas>
<canvas id="canvasdraw" style="position:absolute;background:transparent;z-index:99;"></canvas>
</div>
<div style="position:absolute;top:300px;">
<canvas id="finalcanvas"></canvas>

Related

How i can draw new lines with convas js

i want to draw lines with convas but my previous lines was deleted when i try create a new line. I wark with convas the first time and i will be happy if you can say me about my mistakes and solutions of the problem
const convas = document.querySelector(".v");
const ctx = convas.getContext("2d");
let startPositionLine = { x: 0, y: 0 };
let endPositionLine = { x: 0, y: 0 };
let { xStart, yStart } = startPositionLine;
let { xEnd, yEnd } = endPositionLine;
function moveMouseEvent(e) {
xEnd = e.offsetX;
yEnd = e.offsetY;
ctx.beginPath();
ctx.clearRect(0, 0, convas.width, convas.height);
ctx.moveTo(xStart, yStart);
ctx.lineTo(xEnd, yEnd);
ctx.stroke();
}
convas.onmousedown = (e) => {
ctx.beginPath();
xStart = e.offsetX;
yStart = e.offsetY;
ctx.stroke();
convas.onmousemove = (e) => moveMouseEvent(e);
};
convas.onmouseup = () => {
convas.onmousemove = null;
};
I mentioned this in my comment to your post above, but thought I would just give an example you can run and test here. So you are correct in what you are doing, but you just need to save each drawn line to an array AS YOU DRAW THEM. You will see the code for this in the mousedown event handler here. Then you need to redraw those saved lines each time after you clear the canvas in mousemove event handler.
const canvas = document.getElementById('canvas');
var canvasrect = canvas.getBoundingClientRect();
var Xstart = 0;
var Ystart = 0;
var Xend = 0
var Yend = 0
var isDrawing = false;
var linesArray = [{}];
// MOUSE CLICK / BUTTON DOWN LISTENER
canvas.addEventListener('mousedown', e => {
e.preventDefault();
e.stopPropagation();
canvasrect = canvas.getBoundingClientRect();
Xstart = e.clientX - canvasrect.left;
Ystart = e.clientY - canvasrect.top;
// We need to know if the user is actuallydrawing or not.
// Each time the user clicks their canvas we toggle whether to start or stop drawing.
if (isDrawing) {
// If this is the end of a line, save the end coordinates to the latest array element.
linesArray[linesArray.length - 1].xe = Xend;
linesArray[linesArray.length - 1].ye = Yend;
isDrawing = false;
} else {
// If this is the start of a new line, save the start coordinates in a new array element along with end coordinate placeholders.
linesArray.push({
xs: Xstart,
ys: Ystart,
xe: 0,
ye: 0
})
isDrawing = true;
}
});
// MOUSE MOVE
canvas.addEventListener('mousemove', e => {
e.preventDefault();
e.stopPropagation();
// get the current mouse x & y locations along with any scrolling and window resizing offsets.
Xend = e.clientX - canvasrect.left;
Yend = e.clientY - canvasrect.top;
if (isDrawing === true) {
var ctx = canvas.getContext('2d');
//clear the canvas
ctx.clearRect(0, 0, canvasrect.width, canvasrect.height);
// Draw a line from the initial click coordinates to the current mouse pointer coordinates.
ctx.strokeStyle = '#fe0101';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(Xstart, Ystart);
ctx.lineTo(Xend, Yend);
ctx.stroke();
// now redraw the previous lines saved in the linesArray
if (linesArray.length >= 1) {
for (let i = 0; i < linesArray.length; i++) {
if (linesArray[i].xe != 0) {
ctx.strokeStyle = '#fe0101';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(linesArray[i].xs, linesArray[i].ys);
ctx.lineTo(linesArray[i].xe, linesArray[i].ye);
ctx.stroke();
}
}
}
}
});
<canvas id="canvas" width="500" height="500" style="background-color:lightGray"></canvas>

Double image background on canvas not sharing the same size

I'm trying to make a section on a website have two background images that will reveal the bottom one as the pointer moves across the screen.
I'm still new to javascript, and my code is made up of bits and pieces that I've found on google, but I can't seem to get the top image to share the same resolution and image size for whatever reason as the bottom image.
Here is the link to my codepen: https://codepen.io/Awktopus/pen/zYwKOKO
And here is my code:
HTML:
<canvas id="main-canvas" id="canvas-size" class="background-size"></canvas>
<image src="https://i.imgur.com/PbGAAIy.jpg" id="upper-image" class="hidden-bg"></img>
<image src="https://i.imgur.com/Gx14sKW.jpg" id="lower-image" class="hidden-bg"></img>
CSS:
.hidden-bg {
display: none;
}
JS:
var can = document.getElementById('main-canvas');
var ctx = can.getContext('2d');
can.width = window.innerWidth;
can.height = window.innerWidth / 2;
var upperImg = document.getElementById("upper-image");
var lowerImg = document.getElementById("lower-image");
var pat = ctx.createPattern(upperImg, "no-repeat");
var canvas = ctx.canvas ;
var hRatio = canvas.width / lowerImg.width ;
var vRatio = canvas.height / lowerImg.height ;
var ratio = Math.max ( hRatio, vRatio );
var centerShift_x = ( canvas.width - lowerImg.width*ratio ) / 2;
var centerShift_y = ( canvas.height - lowerImg.height*ratio ) / 2;
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
can.width = can.width;
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.drawImage(lowerImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
ctx.beginPath();
ctx.rect(0,0,can.width,can.height);
ctx.arc(mouse.x, mouse.y, 250, 0, Math.PI*2, true)
ctx.clip();
ctx.fillStyle = pat;
ctx.fillRect(0, 0, lowerImg.width, lowerImg.height, centerShift_x, centerShift_y, lowerImg.width*ratio, lowerImg.height*ratio);
}
var img = new Image();
img.onload = function() {
redraw({x: -500, y:-500})
}
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
If I understood this right you will want to set the width and height and draw the upper image using drawImage(). Just use the same ratios as the lowerImage. No need to use createPattern for this.
codepen: https://codepen.io/jfirestorm44/pen/BaRLoxX
var can = document.getElementById('main-canvas');
var ctx = can.getContext('2d');
can.width = window.innerWidth;
can.height = window.innerWidth / 2;
var upperImg = document.getElementById("upper-image");
var lowerImg = document.getElementById("lower-image");
//var pat = ctx.createPattern(upperImg, "no-repeat");
var canvas = ctx.canvas ;
var hRatio = canvas.width / lowerImg.width ;
var vRatio = canvas.height / lowerImg.height ;
var ratio = Math.max ( hRatio, vRatio );
var centerShift_x = ( canvas.width - lowerImg.width*ratio ) / 2;
var centerShift_y = ( canvas.height - lowerImg.height*ratio ) / 2;
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
can.width = can.width;
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.drawImage(lowerImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
ctx.beginPath();
ctx.rect(0,0,can.width,can.height);
ctx.arc(mouse.x, mouse.y, 250, 0, Math.PI*2, true)
ctx.clip();
ctx.drawImage(upperImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
}
var img = new Image();
img.onload = function() {
redraw({x: -500, y:-500})
}
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
.hidden-bg {
display: none;
}
<canvas id="main-canvas" id="canvas-size" class="background-size"></canvas>
<image src="https://i.imgur.com/PbGAAIy.jpg" id="upper-image" class="hidden-bg"></img>
<image src="https://i.imgur.com/Gx14sKW.jpg" id="lower-image" class="hidden-bg"></img>

draw an rectangle on a pdf inside canvas using pdf.js

I should draw a rectangle inside a pdf document in canvas, but it cleans the background of document.
I want a way to draw a rectangle in it without cleaning the background. Please can anyone help me with this.
Below is the code i am using:
$("#div").mouseover(function () {
$("canvas").on('click', function (e) {
console.log(nr)
id = ($(this).attr("id"));
console.log(id)
const baseImage = loadImage("");
var canvas = document.getElementById(id);
var ctx = canvas.getContext('2d');
Canvas = ctx;
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var prev_x = prev_y = prev_w = prev_h = 0;
var mousex = mousey = 0;
var mousedown = false;
$(canvas).on('mousedown', function (e) {
if (rectanglearray.length < 2) {
last_mousex = parseInt(e.clientX - canvasx);
last_mousey = parseInt(e.clientY - canvasy);
mousedown = true;
}
});
$(canvas).on('mouseup', function (e) {
mousedown = false;
});
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
//if (rectanglearray.length < 2) {
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);
a = last_mousex;
b = last_mousey;
c = last_mousex + width;
d = last_mousey + height;
gjer = width;
lart = height;
t = a;
h = b;
gjere = gjer;
larte = lart;
nfq = id.substring(3, 4);
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.stroke();
rectanglearray.push(ctx);
//}
}
});
execute++;
});
});
so when i click in one of the pages of pdf it takes pages id and allows to only draw a rectangle in that page, but when i draw it cleans the background.

Show rectangle on canvas when mouse move

I want to draw rectangle on canvas. Below code is working fine except when i draw rectangle it does't show path when mouse is moving. When i left the mouse then rectangle is visible on canvas.
Please help,
Thanks
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
currShape = 'rectangle',
mouseIsDown = 0,
startX, endX, startY, endY,
dot_flag = false;
var x = "white",
y = 2;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
var imageObj = new Image(); //Canvas image Obj
imageObj.onload = function() {
ctx.drawImage(imageObj, 69, 50); //Load Image on canvas
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image
w = canvas.width; // Canvas Width
h = canvas.height; // Canvas Height
//Check Shape to be draw
eventListener();
}
function eventListener(){
if(currShape=='rectangle'){
canvas.addEventListener("mousedown",function (e) {
mouseDown(e);
}, false);
canvas.addEventListener("mousemove",function (e){
mouseXY(e);
}, false);
canvas.addEventListener("mouseup", function (e){
mouseUp(e);
}, false);
}
}
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
if(currShape=='rectangle')
{
drawSquare(); //update on mouse-up
}
}
}
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
if(currShape=='rectangle')
{
drawSquare(); //update on mouse-up
}
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
//drawSquare();
}
}
function drawSquare() {
// creating a square
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);
ctx.beginPath();
ctx.globalAlpha=0.7;
ctx.rect(startX + offsetX, startY + offsetY, width, height);
ctx.fillStyle = x;
ctx.fill();
ctx.lineWidth = y;
ctx.strokeStyle = x;
ctx.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
.colortool div {
width: 15px;
height: 15px;
float: left;
margin-left: 2px;
}
.clear {
clear: both;
}
<!DOCTYPE HTML>
<html>
<body onload="init()">
<div class="canvasbody">
<canvas id="can" width="400" height="400" style="border:1px dotted #eee;"></canvas>
</div>
</body>
</html>
Here is you new JavaScript
var canvas, cnvHid, cnvRender, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
currShape = 'rectangle',
mouseIsDown = 0,
startX, endX, startY, endY,
dot_flag = false;
var x = "white",
y = 2;
function init() {
canvas = document.getElementById('can');
cnvHid = document.getElementById( "canHid" );
cnvRender = document.getElementById( "canRend" );
ctx = canvas.getContext("2d");
var imageObj = new Image(); //Canvas image Obj
imageObj.onload = function() {
ctx.drawImage(imageObj, 69, 50); //Load Image on canvas
renderAllCanvas();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image
w = canvas.width; // Canvas Width
h = canvas.height; // Canvas Height
//Check Shape to be draw
eventListener();
}
function eventListener(){
if(currShape=='rectangle'){
cnvRender.addEventListener("mousedown",function (e) {
mouseDown(e);
renderAllCanvas();
}, false);
cnvRender.addEventListener("mousemove",function (e){
mouseXY(e);
renderAllCanvas();
}, false);
cnvRender.addEventListener("mouseup", function (e){
mouseUp(e);
renderAllCanvas();
}, false);
}
}
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
if(currShape=='rectangle')
{
drawSquare( canvas ); //update on mouse-up
cnvHid.getContext( "2d" ).clearRect( 0, 0, cnvHid.width, cnvHid.height );
}
}
}
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
if(currShape=='rectangle')
{
drawSquare( canvas ); //update on mouse-up
}
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare( cnvHid, true );
}
}
function drawSquare( cnv, clear ) {
var ctx = cnv.getContext( "2d" );
if( clear && clear === true ){
ctx.clearRect( 0, 0, cnv.width, cnv.height );
}
// creating a square
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);
ctx.beginPath();
ctx.globalAlpha=0.7;
ctx.rect(startX + offsetX, startY + offsetY, width, height);
ctx.fillStyle = x;
ctx.fill();
ctx.lineWidth = y;
ctx.strokeStyle = x;
ctx.stroke();
ctx.closePath();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function renderAllCanvas(){
var cnxRender = cnvRender.getContext( "2d" );
cnxRender.drawImage(
canvas
,0,0
,cnvRender.width,cnvRender.height
);
cnxRender.drawImage(
cnvHid
,0,0
,cnvRender.width,cnvRender.height
);
}
And here is you new HTML
<!DOCTYPE HTML>
<html>
<body onload="init()">
<div class="canvasbody">
<canvas id="can" width="400" height="400" style="display: none;"></canvas>
<canvas id="canHid" width="400" height="400" style="display: none;"></canvas>
<canvas id="canRend" width="400" height="400" style="border:1px dotted #eee;"></canvas>
</div>
</body>
</html>
In some way, you would need to keep track on the changes you make to a shape you draw on the canvas. In your case, you would start by creating a very small rectangle and then scale it according to your mouse position during your dragmove.
Currently, you only have a function which draws an entirely new rectangle but does not take any previous "state" into consideration.
I found this blogpost which could be helpful. It doesn't explain scaling in particular but it could help with the basic concepts behind so I think this would be a good way for you to find a suitable solution.
Since we are finding the canvas tag in the DOM using it’s id and then setting the drawing context of the canvas to 2D. Two things is importent here is store the information as we draw the recatangle and a bolean to check user is drawing the rectangleor not.
You can reffer these links:Drawing a rectangle using click, mouse move, and click
Draw on HTML5 Canvas using a mouse
Check the js fiddle in the given link.
Hope this will help you..
Your current code has the redraw commented out on the mouse move, which would be required to update the canvas. However your code is also destroying the image the way the rectangle is being drawn. If you retain the image as shown below and redraw it on each frame before drawing the rectangle, it might have the desired effect.
var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
currShape = 'rectangle',
mouseIsDown = 0,
startX, endX, startY, endY,
dot_flag = false;
var x = "white",
y = 2,
image = null;
function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
var imageObj = new Image(); //Canvas image Obj
imageObj.onload = function() {
image = imageObj;
ctx.drawImage(image, 69, 50); //Load Image on canvas
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image
w = canvas.width; // Canvas Width
h = canvas.height; // Canvas Height
//Check Shape to be draw
eventListener();
}
function eventListener(){
if(currShape=='rectangle'){
canvas.addEventListener("mousedown",function (e) {
mouseDown(e);
}, false);
canvas.addEventListener("mousemove",function (e){
mouseXY(e);
}, false);
canvas.addEventListener("mouseup", function (e){
mouseUp(e);
}, false);
}
}
function mouseUp(eve) {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
if(currShape=='rectangle')
{
drawSquare(); //update on mouse-up
}
}
}
function mouseDown(eve) {
mouseIsDown = 1;
var pos = getMousePos(canvas, eve);
startX = endX = pos.x;
startY = endY = pos.y;
if(currShape=='rectangle')
{
drawSquare(); //update on mouse-up
}
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
var pos = getMousePos(canvas, eve);
endX = pos.x;
endY = pos.y;
drawSquare();
}
}
function drawSquare() {
// draw background image
if(image) {
ctx.drawImage(image, 69, 50);
}
// creating a square
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);
ctx.beginPath();
ctx.globalAlpha=0.7;
ctx.rect(startX + offsetX, startY + offsetY, width, height);
ctx.fillStyle = x;
ctx.fill();
ctx.lineWidth = y;
ctx.strokeStyle = x;
ctx.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
.colortool div {
width: 15px;
height: 15px;
float: left;
margin-left: 2px;
}
.clear {
clear: both;
}
<!DOCTYPE HTML>
<html>
<body onload="init()">
<div class="canvasbody">
<canvas id="can" width="400" height="400" style="border:1px dotted #eee;"></canvas>
</div>
</body>
</html>

Is the canvas empty?

I'm trying to make a scratch card using canvas with JS. my question is:
can I know if the user have "erased" all the canvas?
I have two images one on top the other, and I managed to make the user "erase" the on-top canvas image. I want to fire up a function when the canvas is empty\completly erased.
Thanks
var offsetT;
var offsetL;
var canvas = document.createElement('canvas');
canvas.id = "canvas";
var canvasWidth = 290;
var canvasheight = 269;
canvas.width = canvasWidth;
canvas.height = canvasheight;
var context = canvas.getContext("2d");
var scratcher = document.getElementById("scratcher");
var radius = 20; //Brush Radius
context.drawImage(scratcher,0,0);
// set image as pattern for fillStyle
context.globalCompositeOperation = 'destination-out';
context.fillStyle = context.createPattern(scratcher, "repeat");
// for demo only, reveals image while mousing over canvas
canvas.onmousemove = function (e) {
var r = this.getBoundingClientRect(),
x = e.clientX - r.left,
y = e.clientY - r.top;
context.beginPath();
context.moveTo(x + radius, y);
context.arc(x, y, radius, 0, 2 * Math.PI);
context.fill();
};
document.body.appendChild(canvas);
document.addEventListener('touchmove', function(e){
var touchobj = e.changedTouches[0]; // reference first touch point (ie: first finger)
var x = touchobj.clientX;
var y = touchobj.clientY;
offsetT = canvas.offsetTop;
offsetL = canvas.offsetLeft;
context.beginPath();
context.moveTo(x-offsetL + radius, y-offsetT);
context.arc(x-offsetL,y-offsetT, radius, 0, 2 * Math.PI);
context.fill();
var cursor = document.getElementById('cursor');
cursor.style.display = 'block';
cursor.style.left = x+ "px";
cursor.style.top = y+ "px";
e.preventDefault();
}, false);
The only way is to check the imageData of the canvas :
var data = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data;
var isEmpty = !Array.prototype.some.call(data, function(p){return p>0;});
var ctx = c.getContext('2d');
var isEmpty = function(ctx){
var data = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data;
return !Array.prototype.some.call(data, function(p){return p>0;});
}
//first check before drawing
log.innerHTML += isEmpty(ctx)+' ';
//no more empty
ctx.fillRect(0,0,10,10);
// recheck
log.innerHTML += isEmpty(ctx);
/*
we could also have used a for loop :
//in Function
for(var i=0; i<data.length; i++){
if(data[i]>0){
return false;
}
return true;
}
*/
<canvas id="c"></canvas>
<p id="log"></p>

Categories