How to have two layers of Canvas one over another - javascript

I am making a canvas, where there is a large image and behind it there is another image. then by using mouse coordinate I made a circle around the cursor. This circle will work as a hole to reveal the hidden image under the background. I made it kinda but I cannot set the front image.
Have a look at my code please: JSFiddle
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
//var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
context.fillStyle = 'black';
context.fill();
Can someone tell me please how to have an image as big as the canvas to cover it?
Thanks

It looks like you are on the right track. The easiest way to have an image where the circle is not in your setup, would be to set a background image on the canvas element, and use background-size: cover to make it fill the canvas area.
Working Example (see CSS in second block):
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>
To get the foreground image to fill the canvas, and take care of the edge, you need to resize the image in another canvas.
Working Example:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
//Create another canvas to darw a resized image to.
var imageResized = document.createElement('canvas');
imageResized.width = width;
imageResized.height = height;
//Wait for the original image to low to draw the resize.
imageObj.onload = function() {
//Find hoe mauch to scale the image up to cover.
var scaleX = width / imageObj.width;
var scaleY = height / imageObj.height;
var scaleMax = Math.max(scaleX, scaleY);
var ctx = imageResized.getContext('2d');
ctx.scale(scaleMax, scaleMax);
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>

Related

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

HTML5 Canvas why fillText() method clears everything after clearRect()

When i call writeTextToCanvas method before clearCanvas method, it works perfectly,
if i call clearCanvas method first than writeTextToCanvas, it doesn't works, drawing functions etc. all works after clearCanvas but fillText doesn't work and also clears all canvas when i call fillText
when i set context.globalAlpha = 0.5 before fillText, i can barely see text on the canvas but anything in canvas erased somehow
var canvas;
var context;
var selectedRole = DRAW_TOOLS.PENCIL;
function initDrawingCanvas(index) {
var question = document.getElementsByClassName('question').item(index);
canvas = question.getElementsByClassName('questionDrawingCanvas').item(0);
context = canvas.getContext("2d");
canvasWidth = canvas.width;
canvasHeight = canvas.height;
compositeOperation = context.globalCompositeOperation;
canvas.addEventListener("touchmove", onCanvasTouchMove, false);
canvas.addEventListener("touchstart", onCanvasTouchStart, false);
canvas.addEventListener("touchstop", onCanvasTouchStop, false);
}
var startX = 0;
var startY = 0;
var endX = 0;
var endY = 0;
var compositeOperation;
function onCanvasTouchMove(event){
endX = event.changedTouches[0].clientX - $(canvas).offset().left;
endY = event.changedTouches[0].clientY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.PENCIL){
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(endX, endY);
context.strokeStyle = $('.colorPicker').css('background-color');
context.lineWidth = parseInt($('#pencilSize').attr("data-size"));
context.stroke();
}else if(selectedRole == DRAW_TOOLS.ERASER){
context.save();
context.globalCompositeOperation = "destination-out";
context.arc(endX,endY,25,0,Math.PI*2,false);
context.fill();
context.restore();
}
startX = endX;
startY = endY;
}
function onCanvasTouchStart(event){
$("#colorPicker").css("display", "none");
$("#pencilSize").css("display", "none");
$("#textColorPicker").css("display", "none");
$("#canvas_textSize").css("display", "none");
startX = event.changedTouches[0].pageX - $(canvas).offset().left;
startY = event.changedTouches[0].pageY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.TEXT){
showConfirmDialog('<textarea id="canvasTextArea" class="canvasTextArea"></textarea>', RESOURCES.CANVAS_TEXT_TITLE, {positiveButton: RESOURCES.OKAY, negativeButton: RESOURCES.CANCEL}, function(){
var text = $("#canvasTextArea").val();
if(isNullOrUndefined(text)) return;
writeTextToCanvas(text);
hideDialog();
}, function(){
hideDialog();
});
$("#canvasTextArea").focus();
$("#canvasTextArea").css("font-size", $('#textSizePicker').attr("data-size") + "px");
$("#canvasTextArea").css("color", $('.textColorPicker').css("background-color"));
}
}
function onCanvasTouchStop(event){
console.log(event);
}
function clearCanvas(){
context.clearRect(0, 0, canvas.width, canvas.height);
}
function getCanvasContent(){
return canvas.toDataURL();
}
function writeTextToCanvas(text) {
context.globalCompositeOperation = "source-over";
context.textBaseline = "top";
context.font = $('#textSizePicker').attr("data-size") + 'px sans-serif';
context.fillStyle = $('.textColorPicker').css("background-color");
context.fillText(text, startX, startY);
}
What should i use to clear canvas or clear some parts like eraser then i can fillText normally?
Your call to clearRect() is stopping the entire script because it throws an error (check the console). You're not passing in a rectangle to the call.
It needs to be called like:
context.clearRect(0, 0, canvas.width, canvas.height);
Here's a working example: http://jsfiddle.net/pe19L15m

Drawing a filled circle in a canvas on mouseclick

I want to draw a filled (or not filled) circle in a canvas on mouseclick, but I can't get my code to work properly, I've tried pretty much everything!
This is my HTML:
<div id="images"></div>
<canvas style="margin:0;padding:0;position:relative;left:50px;top:50px;" id="imgCanvas" width="250" height="250" onclick="draw(e)"></canvas>
and my current script:
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function createImageOnCanvas(imageId) {
canvas.style.display = "block";
document.getElementById("images").style.overflowY = "hidden";
var img = new Image(300, 300);
img.src = document.getElementById(imageId).src;
context.drawImage(img, (0), (0)); //onload....
}
function draw(e) {
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = "#000000";
context.arc(posx, posy, 50, 0, 2 * Math.PI);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
The code works just fine if and only if I remove the "use strict";, but in this assignment I have to make a code that works even with it, which is my problem.
Here is the jsFiddle
Solved it myself.
function draw(e) {
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect();
var posx = e.clientX - rect.left;
var posy = e.clientY - rect.top;
context.fillStyle = "#000000";
context.beginPath();
context.arc(posx, posy, 50, 0, 2 * Math.PI);
context.fill();
}
This script works fine for me.

Drawing a circle in a canvas on mouseclick

I want to draw a filled (or not filled) circle in a canvas on mouseclick, but I can't get my code to work properly, I've tried pretty much everything!
This is my HTML:
<div id="images"></div>
<canvas style="margin:0;padding:0;position:relative;left:50px;top:50px;" id="imgCanvas" width="250" height="250" onclick="draw(e)"></canvas>
and my current script:
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function createImageOnCanvas(imageId) {
canvas.style.display = "block";
document.getElementById("images").style.overflowY = "hidden";
var img = new Image(300, 300);
img.src = document.getElementById(imageId).src;
context.drawImage(img, (0), (0)); //onload....
}
function draw(e) {
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = "#000000";
context.arc(posx, posy, 50, 0, 2 * Math.PI);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
I think my problem is with function draw(e), even though I feel pretty confident about that part.
Here is the jsFiddle
I have forked and updated your fiddle to make a working example: http://jsfiddle.net/ankr/ds9s7/161/
Besides referencing the event incorrectly - as stated by others - you also did not begin nor end your path when drawing. Added context.beginPath() and context.fill() calls
Here's the relevant JS code
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function draw(e) {
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = "#000000";
context.beginPath();
context.arc(posx, posy, 50, 0, 2*Math.PI);
context.fill();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}

HTML5 Canvas drawing ellipse increasingly

I am writing on whiteboard using HTML5 drawing.
The problem is when I am trying to draw ellipse, so press down and drag, many ellipse are drawn.
ctx.moveTo(startX, startY + (y-startY)/2);
ctx.bezierCurveTo(startX, startY, x, startY, x, startY + (y-startY)/2);
ctx.bezierCurveTo(x, y, startX, y, startX, startY + (y-startY)/2);
ctx.stroke();
I want to show only one ellipse every time.
Any help?
This might help - this is my version of drawing an ellipse using only arc and scaling.
https://jsfiddle.net/richardcwc/wdf9cocz/
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var scribble_canvasx = $(canvas).offset().left;
var scribble_canvasy = $(canvas).offset().top;
var scribble_last_mousex = scribble_last_mousey = 0;
var scribble_mousex = scribble_mousey = 0;
var scribble_mousedown = false;
//Mousedown
$(canvas).on('mousedown', function(e) {
scribble_last_mousex = parseInt(e.clientX-scribble_canvasx);
scribble_last_mousey = parseInt(e.clientY-scribble_canvasy);
scribble_mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
scribble_mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function(e) {
scribble_mousex = parseInt(e.clientX-scribble_canvasx);
scribble_mousey = parseInt(e.clientY-scribble_canvasy);
if(scribble_mousedown) {
ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas
//Save
ctx.save();
ctx.beginPath();
//Dynamic scaling
var scalex = 1*((scribble_mousex-scribble_last_mousex)/2);
var scaley = 1*((scribble_mousey-scribble_last_mousey)/2);
ctx.scale(scalex,scaley);
//Create ellipse
var centerx = (scribble_last_mousex/scalex)+1;
var centery = (scribble_last_mousey/scaley)+1;
ctx.arc(centerx, centery, 1, 0, 2*Math.PI);
//Restore and draw
ctx.restore();
ctx.strokeStyle = 'black';
ctx.lineWidth = 5;
ctx.stroke();
}
//Output
$('#output').html('current: '+scribble_mousex+', '+scribble_mousey+'<br/>last: '+scribble_last_mousex+', '+scribble_last_mousey+'<br/>mousedown: '+scribble_mousedown);
});
canvas {
cursor: crosshair;
border: 1px solid #000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="800" height="500"></canvas>
<div id="output"></div>

Categories

Resources