Using Canvas layers to draw shapes on top of one another - javascript

I'm trying to create an interactive app to enable users to select the shape they want by clicking on the different buttons for the shapes and then enable them to draw the shape wherever they will click on the canvas.
This part is okay but when i click on a different button to draw a shape it seems that the previous shape comes along with the new shape and seems to be overlapped.
Here's the pic:
As you see, the rectangle and the round shape becomes overlapped.
I've tried to use layers of canvas to fix it but now the rectangle button is not working and the rounded shape is not appearing where the user clicks, rather like 30px away from it.
Here's the codes:
<!DOCTYPE html>
<html>
<head>
<script>
function initiateCanvasRectangle()
{
var ctx = document.getElementById('myCanvas1').getContext('2d');
ctx.canvas.addEventListener('mousemove', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
});
ctx.canvas.addEventListener('click', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
ctx.fillRect(mouseX,mouseY,100,50);
ctx.fillStyle = "purple";
});
}
function initiateCanvasCircle()
{
var ctx = document.getElementById('myCanvas2').getContext('2d');
ctx.canvas.addEventListener('mousemove', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
});
ctx.canvas.addEventListener('click', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
ctx.beginPath();
ctx.arc(mouseX, mouseY, 30, 0, 2 * Math.PI, false);
ctx.fillStyle = 'pink';
ctx.fill();
});
}
function rect(){
window.addEventListener('click', function(event) {
initiateCanvasRectangle();
});
}
function drawRect()
{
rect();
}
function circle(){
window.addEventListener('click', function(event) {
initiateCanvasCircle();
});
}
function drawCircle()
{
circle();
}
</script>
<style>
BUTTON.rect {
padding: 8px 8px 8px 32px;
font-family: Arial, Verdana;
background-color: white;
border:2px solid black;
}
#tbl {
border-collapse:collapse;
}
</style>
</head>
<body>
<table border="1" id="tbl">
<tr><td><button class="circle" onclick="drawCircle(); return true;" style="padding:20px 40px 20px 40px;">Circle</button>
</td>
<td>
<button class="rect" onclick="drawRect(); return true;" style="padding:20px 40px 20px 40px;"></button>
</td></tr>
</table>
<p>
<div style="position: relative;">
<canvas id="myCanvas1" width="1100" height="400" style="position: absolute; left: 0; top: 0; z-index: 0; border:1px solid black"></canvas>
<canvas id="myCanvas2" width="1100" height="400" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
</body>
</html>
Can you tell me how to fix it? Any help will be much appreciated. Thanks.

Related

Replicate Canvas resize in a Div

There's any way to replicate this scale behavior in a div ?
Here's an example of the behavior I wanted to reproduce within the div. I already have the movement part, and I just wanted to know about the resizing.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<style>
body {
margin: 0px;
padding: 0px;
}
#wrapper {
position: relative;
border: 1px solid #9C9898;
width: 578px;
height: 200px;
}
#buttonWrapper {
position: absolute;
width: 30px;
top: 2px;
right: 2px;
}
input[type="button"] {
padding: 5px;
width: 30px;
margin: 0px 0px 2px 0px;
}
</style>
<script>
function draw(scale, translatePos) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.translate(translatePos.x, translatePos.y);
context.scale(scale, scale);
context.beginPath(); // begin custom shape
context.moveTo(-119, -20);
context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
context.bezierCurveTo(131, 50, 131, 20, 101, 0);
context.bezierCurveTo(141, -60, 81, -70, 51, -50);
context.bezierCurveTo(31, -95, -39, -80, -39, -50);
context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
context.closePath(); // complete custom shape
var grd = context.createLinearGradient(-59, -100, 81, 100);
grd.addColorStop(0, "#8ED6FF"); // light blue
grd.addColorStop(1, "#004CB3"); // dark blue
context.fillStyle = grd;
context.fill();
context.lineWidth = 5;
context.strokeStyle = "#0000ff";
context.stroke();
context.restore();
}
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var translatePos = {
x: canvas.width / 2,
y: canvas.height / 2
};
var scale = 1.0;
var scaleMultiplier = 0.8;
var startDragOffset = {};
var mouseDown = false;
// add button event listeners
document.getElementById("plus").addEventListener("click", function() {
scale /= scaleMultiplier;
draw(scale, translatePos);
}, false);
document.getElementById("minus").addEventListener("click", function() {
scale *= scaleMultiplier;
draw(scale, translatePos);
}, false);
// add event listeners to handle screen drag
canvas.addEventListener("mousedown", function(evt) {
mouseDown = true;
startDragOffset.x = evt.clientX - translatePos.x;
startDragOffset.y = evt.clientY - translatePos.y;
});
canvas.addEventListener("mouseup", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseover", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseout", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mousemove", function(evt) {
if (mouseDown) {
translatePos.x = evt.clientX - startDragOffset.x;
translatePos.y = evt.clientY - startDragOffset.y;
draw(scale, translatePos);
}
});
draw(scale, translatePos);
};
jQuery(document).ready(function() {
$("#wrapper").mouseover(function(e) {
$('#status').html(e.pageX + ', ' + e.pageY);
});
})
</script>
</head>
<body onmousedown="return false;">
<div id="wrapper">
<canvas id="myCanvas" width="578" height="200">
</canvas>
<div id="buttonWrapper">
<input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
</div>
</div>
<h2 id="status">
0, 0
</h2>
</body>
</html>
I tried to use css scale, but it resizes the div too, I want to modify only the space and the elements inside it.

How do I change X-Y positions of an circle on a canvas

I'm trying out canvas for the first time. After creating a circle I want to be able to change the position of the center of this circle at the click of a button. But I am unable to figure how to do so. Can someone suggest a method for it?
#button{
height: 25px;
width:125px;
border: 1px solid black;
text-align: center;
cursor: pointer;
}
<html>
<head></head>
<body>
<div id="button" onclick="changePosition()">Click here</div>
<canvas id="testCanvas" width="500px" height="500px"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("testCanvas");
var a = canvas.getContext("2d");
a.fillStyle = "#b22222";
a.beginPath();
a.arc(100,100,25,0,2*Math.PI);
a.fill();
function changePosition(){
//what do I put here??
}
</script>
</body>
</html>
You need to redraw the scene. Create a function that resets the canvas and then draws the circle
var canvas = document.getElementById("testCanvas");
var ctx = canvas.getContext("2d");
var circlePos = {
left: 100,
top: 100,
}
function renderCircle( circlePos ) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#b22222";
ctx.beginPath();
ctx.arc(circlePos.left, circlePos.top, 25, 0, 2 * Math.PI);
ctx.fill();
}
function changePosition() {
circlePos.left += 10;
if ( circlePos.left > canvas.width ) {
circlePos.left = 0;
}
renderCircle( circlePos );
}
changePosition();
#button {
height: 25px;
width: 125px;
border: 1px solid black;
text-align: center;
cursor: pointer;
}
<button onclick="changePosition()">Click here</button>
<canvas id="testCanvas" width="500" height="200"></canvas>

How do I add a onClick event handler to a canvas element and control mouse movement actions?

I have an image within a canvas, I want to be to click the image and drag the image(without lifting the left mouse button) and the image at the position where the left mouse button was released. For now as soon as the mouse icon hovers over the canvas, the image moves with it, I tried to add an onclick listener event but I am sure my newbie-ness got in the way of my progress.
Here is what I had come up with so far. How can I make this work with my existing code?
var canvas = document.getElementById('customCanvas');
var context = canvas.getContext('2d');
make_base();
function make_base()
{
upload_image = new Image();
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
canvas.addEventListener('click', canvas.onmousemove = function(e) {
/// correct mouse position so its relative to canvas
var rect = canvas.getBoundingClientRect(),
constantX = 0, constantY = 0,
x = e.clientX - rect.left,
y = e.clientY - rect.top;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(upload_image, x, y);
});
}
}
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
}
.sidepane {
height: 100%;
background: #E8E8EA;
}
.sidepane .form {
height: 80px;
margin: 10px 0;
}
.sidepane .assets {
width: 100%;
}
#assetText {
font-size: 24px;
}
.assets .text, .assets .image {
margin: 10px 0;
}
.assets .image ul li {
width: 50px;
height: 50px;
margin-right: 5px;
float: left;
overflow: hidden;
}
.assets .image ul li img {
width: 100%;
height: 100%;
}
.canvas .block {
position: relative;
width: 600px; height: 600px;
margin: 10px;
border: 1px solid;
box-shadow: 0px 0px 5px black;
}
.item {
border: 1px solid transparent;
position: absolute;
}
.item.selected {
border-color: blue;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="sidepane col-sm-2 col-md-2 col-lg-2">
<form method="post" action="/images" enctype="multipart/form-data">
<!--<div class="form">-->
<h3>Form</h3>
<input type="file" class="form-control" placeholder="Upload Your Images" name="filefield">
<button id="submit" class="btn btn-default">upload</button>
<!-- Upload Form here -->
<!--</div>-->
<hr />
<div class="assets">
<h3>Assets</h3>
<div class="text">
<h4>Text</h4>
<input type="text" name="textfield">
<button id="addText" class="btn btn-default">Add Text</button>
</div>
<div class="image">
<h4>Images</h4>
<ul class="list-unstyled">
<!-- List of images here -->
<!-- <li><img src="images/sample.jpeg" class="img-rounded" /></li> -->
</ul>
</div>
</div>
<input type="submit" >
</form>
</div>
<!-- canvas -->
<div class="canvas col-sm-8 col-md-8 col-lg-8">
<div class="block">
<!-- Add images and texts to here -->
<canvas id="customCanvas" width="598" height="598" style="border: 1px solid #000000">
</canvas>
</div>
</div>
First, you have to check if your mouse is on the image, and then check if you are trying to drag the image. To do that, you need some events, mousedown, mouseup and mousemove. To check if your mouse pointer is on the image, you have to get the X, Y, width, height of that image. Final code below.
Edit
Some more changes. Image class has no X and Y properties so I had to define variables that will store that data and make some changes to isInside function.
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
var context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
var upload_image;
var imageX, imageY;
var mouseX, mouseY;
var imageDrag = false;
make_base();
canvas.addEventListener("mousemove", function (evt) {
var mousePos = getMousePos(canvas, evt);
mouseX = mousePos.x;
mouseY = mousePos.y;
});
function getMousePos(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
function isInsideImage(rect) {
var pos = { x: mouseX, y: mouseY };
return pos.x > imageX && pos.x < imageX + rect.width && pos.y < imageY + rect.height && pos.y > imageY;
}
function make_base()
{
upload_image = new Image();
imageX = 0;
imageY = 0;
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
}
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
}
canvas.addEventListener("mousedown", function (evt) {
if(isInsideImage(upload_image)) {
imageDrag = true;
}
});
canvas.addEventListener("mouseup", function (evt) {
if(imageDrag)
imageDrag = false;
});
setInterval(function() {
if(imageDrag) {
context.clearRect(0, 0, canvas.width, canvas.height);
imageX = mouseX;
imageY = mouseY;
context.drawImage(upload_image, imageX, imageY);
}
}, 1000/30);
The event you're looking for would be https://developer.mozilla.org/en/docs/Web/Events/mousedown - AFAIK (correct me if I'm wrong) but the click event would only fire when a complete click event has completed (both down and up).
Here's some sample code for this;
var mouseX;
var mouseY; // Accessible outside the function. Easier access to canvas drawing.
var canvas = ''; // Complete this to get canvas element
canvas.addEventListener("mousedown", function(mouse){
// Get mouse co-ordinates
})
Inside this event listener, you can check for your current mouse position...
var canvasElement = element.getBoundingClientRect()
mouseX = mouse.pageX - canvasElement.left;
mouseY = mouse.pageY - canvasElement.top;
Use these variables when drawing your image to the canvas to determine the image's x and y position. These should change as your mouse moves around the canvas. I.e, pass them to your make_base() function;
make_base(mouseX, mouseY)
Update your drawing function to account for them;
function make_base(mouseX, mouseY)
{
upload_image = new Image();
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
canvas.addEventListener('click', canvas.onmousemove = function(e) {
/// correct mouse position so its relative to canvas
var rect = canvas.getBoundingClientRect(),
constantX = 0, constantY = 0,
x = mouseX,
y = mouseY
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(upload_image, x, y);
});
}
}
PLEASE NOTE that the code above is not complete, for example, the X and Y will be based on where your mouse is on the PAGE, not the CANVAS. there are separate calculations needed to account for this.
Or, you can just embed an external link under the image to take you to wherever you want!

HTML Canvas and a little issue displaying correctly?

I'm trying to adjust the size to correctly be position more in the middle and a larger div. I would like it to be 500x500. What I'm trying to do is do a classic version of what Windows Paint is.
The issue is adjusting the 'canvas' to the middle stops the paint brush to 'draw'.
Here is the code, I have so far.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
width: 500px;
height: 500px;
margin: auto;
top: 50%;
left: 50%;
width: 90%;
border: 3px solid #73AD21;
padding: 10px;
}
</style>
</head>
<body>
<div id="paint" >
<canvas id="myCanvas"></canvas>
</div>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var painting = document.getElementById('paint');
var paint_style = getComputedStyle(painting);
canvas.width = parseInt(paint_style.getPropertyValue('width'));
canvas.height = parseInt(paint_style.getPropertyValue('height'));
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineWidth = 10;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#00CC99';
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
</script>
</body>
</html>
Get rid of the styling on body and replace it with this:
#paint {
height: 500px;
margin: auto;
width: 90%; /* you also had width: 500px, which one did you want? */
border: 3px solid #73AD21;
padding: 10px;
}
Fiddle - Looks like it's working okay with that change.

Unable to use the full space of canvas

I need to use the full space of canvas to draw. But here unable to use the top and left of the canvas to draw. I try make some changes in css, still no luck. Please help.
p.s. By clicking the button the canvas will popup.
<button onClick="openPopup();">click here</button>
<div id="test" class="popup">
<div class="cancel" onclick="closePopup();"></div>
<canvas id="canvas1" width="750" height="720" style="border: 1px solid black"></canvas>
</div>
<style>
.popup{
position:absolute;
top:0px;
left:0px;
margin:0px;
width: 900px;
height: 750px;
font-family:verdana;
font-size:13px;
padding:2px;
background-color:white;
border:2px solid grey;
z-index:100000000000000000;
display:none;
opacity:0.6;
filter:alpha(opacity=60);
margin-left: 300px;
margin-top: 90px;
overflow: auto;
}
.cancel{
display:relative;
cursor:pointer;
margin:0;
float:right;
height:10px;
width:14px;
padding:0 0 5px 0;
background-color:red;
text-align:center;
font-weight:bold;
font-size:11px;
color:white;
border-radius:3px;
z-index:100000000000000000;
}
.cancel:hover{
background:rgb(255,50,50);
}
</style>
<script>
function openPopup() {
document.getElementById('test').style.display = 'block';
}
function closePopup() {
document.getElementById('test').style.display = 'none';
}
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
var isPressed = false;
var mx = 4, my = 4;
function move(e) {
getMouse(e);
if (isPressed) {
ctx.lineTo(mx, my);
ctx.stroke()
}
}
function up(e) {
getMouse(e);
isPressed = false;
}
function down(e) {
getMouse(e);
ctx.beginPath();
ctx.moveTo(mx, my);
isPressed = true;
}
can.onmousemove = move;
can.onmousedown = down;
can.onmouseup = up;
// waaaay oversimplified:
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX;
my = e.pageY;
}
</script>
The drawing point is not synced with mouse pointer.
That is the reason why you can't draw at the left part and the top part of the canvas, because the mouse is already out of the canvas if you try to draw something nearby the left edge.
Notice that how you get the current position of the drawing point:
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX;
my = e.pageY;
}
the variable e refers to mouseEvent object. and e.pageX means the distance between the mouse and the left side of the page, NOT YOUR CANVAS. So you should minus the left offset of the canvas from mx and do the same to my, so that the drawing point is right on where you want.
One simple solution:
set the canvas's margin, border and padding to 0;
.popup{
//everything else..
boder: 0;
margin-left: 0px;
margin-top: 0px;
}
Better solution:
minus the left offset to mx and my
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX - 305;
my = e.pageY - 95;
//Dynamically getting those padding and margin and border would be better!
}

Categories