Javascript fillRect on canvas with absolute position inside a relative container - javascript

I have two canvases inside a container like this:
<div class="canvasContainer">
<canvas class="drawCanvas" style="z-index: 0;"></canvas>
<canvas class="drawCanvas" height="150" width="300" style="z-index: 1;"></canvas>
</div>
The first canvas (z-index 0) contains an image and the second canvas is for drawing. Both canvas have a position absolute and the canvasContainer has a relative position, but for some reason the fillRect function on the canvas context does not work when I apply the relative postion to the canvasContainer. When I remove the relative postion the fillRect function in Javascript does work, but then my canvas is positioned absolute to the body tag. Why does the fillRect function not work inside my canvasContainer when its postion is relative?
This is how I draw on my canvas
let canvas = document.createElement('canvas');
canvas.style.zIndex = "0";
canvas.className = "drawCanvas";
let context = canvas.getContext("2d");
img.onload = function() {
context.drawImage(img, 0, 0);
}
canvasContainer.appendChild(canvas);
let canvas2 = document.createElement('canvas');
canvas2.className = "drawCanvas";
canvas2.style.zIndex = "1";
canvas2.height = canvas.height;
canvas2.width = canvas.width;
canvas2.md = false;
canvas2.addEventListener('mousedown', function(event){
this.md = true;
});
canvas2.addEventListener('mouseup', function(event){
this.md = false;
});
canvas2.addEventListener('mousemove', function(event){
let mouseX = event.clientX - this.offsetLeft;
let mouseY = event.clientY - this.offsetTop;
if(this.md){
let ctx = this.getContext('2d');
ctx.fillStyle = "blue";
ctx.fillRect(mouseX, mouseY, 4, 4);
}
}
});
imageContainer.appendChild(canvas2);
}

Related

Draw an rectangle between html elements

I'm trying to draw a rectangle between 2 tag by javascript but i couldn't have any achievement. The things i´m trying to do is something like this:
Screenshot
i tried to draw a rectangle by giving X, Y but the size changes when the page size changes:
var x = 100;
var y = 111;
var width = 200;
var height = 40
var canvas = document.createElement('canvas'); //Create a canvas element
//Set canvas width/height
canvas.style.width = '100%';
canvas.style.height = '100%';
//Set canvas drawing area width/height
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//Position canvas
canvas.style.position = 'absolute';
canvas.style.left = 0;
canvas.style.top = 0;
canvas.style.zIndex = 100000;
canvas.style.pointerEvents = 'none'; //Make sure you can click 'through' the canvas
document.body.appendChild(canvas); //Append canvas to body element
var context = canvas.getContext('2d');
//Draw rectangle
context.rect(x, y, width, height);
context.fillStyle = 'yellow';
context.fill();
function getOffset(el) {
el = el.getBoundingClientRect();
return {
left: el.left + window.scrollX,
top: el.top + window.scrollY
}
}

Alter the dimensions of the canvas image permanently and NOT keep the aspect ratio

I am creating a gradient on a canvas, generating a PNG file, and then downloading it. I want a radial gradient which is an ellipse. Since canvas gradients must be circles, I am generating the gradient as a circle and then resizing the canvas element to create the ellipse. This works fine and the visually generated image is the ellipse I want.
When I go to download the generated canvas, it is using the full size of the canvas, not the css styled size and so I get the original full sized circle. Is there a way to actually alter the dimensions of the canvas image and NOT keep the aspect ratio? All the SO posts that show up on the topic want to keep the aspect ratio.
makeCanvas();
scaled();
var input = document.createElement("input");
input.type = "button";
input.style.display = "block";
input.value = "Download Canvas to PNG";
input.onclick = function() {
var canvas = document.getElementById("canvas");
downloadURI(canvas.toDataURL("image/png"), "gradient.png");
}
document.body.appendChild(input);
var input = document.createElement("input");
input.type = "button";
input.style.display = "block";
input.value = "Download Scaled";
input.onclick = function() {
var canvas = document.getElementById("scaled");
downloadURI(canvas.toDataURL("image/png"), "gradient.png");
}
document.body.appendChild(input);
function makeCanvas() {
var canvasGradient;
var ctx;
width = 200;
height = 200;
var canvas = document.createElement("canvas");
canvas.id = "canvas";
canvas.style.width = width + "px";
canvas.style.height = height + "px";
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
var gradient;
// both circles have to share the center of the canvas
var coords = {
x1: 0,
y1: 0,
x2: 0,
y2: 0
};
coords.x1 = (width / 2);
coords.x2 = coords.x1;
coords.y1 = (height / 2);
coords.y2 = coords.y1;
// inner circle is just the center - a point
coords.r1 = 0;
// outer circle is the edge
coords.r2 = Math.min(height, width);
gradient = ctx.createRadialGradient(coords.x1, coords.y1, coords.r1, coords.x2, coords.y2, coords.r2);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
canvas.style.width = width / 2 + "px";
document.body.append(canvas);
can = alter(canvas, ctx);
//document.body.append(can);
}
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
function alter(canvas, ctx) {
var can = document.createElement("canvas");
can.id = "can";
can.width = Math.floor(canvas.width / 2);
can.height = canvas.height;
can.ctx = can.getContext("2d");
can.ctx.drawImage(canvas, 0, 0, can.width, can.height);
canvas.width = can.width;
canvas.height = can.height;
ctx.drawImage(can, 0, 0);
return can;
}
function scaled() {
var canvas = document.createElement("canvas");
canvas.id = "scaled";
canvas.style.width = "200px";
canvas.style.height = "200px";
canvas.width = 200;
canvas.height = 200;
ctx = canvas.getContext('2d');
var gradient;
var g = ctx.createRadialGradient(100, 100, 0, 100, 100, 100);
g.addColorStop(0, "white")
g.addColorStop(1, "red")
ctx.fillStyle = g
ctx.scale(0.5, 1) // scale x axis 0.5
ctx.fillRect(0, 0, 200, 200) // gradient circle squashed along x
document.body.append(canvas);
}
Use transformations to change shape of gradients.
For your info gradient circles can be transformed to a ellipse.
var g = ctx.createRadialGradient(200,200,0,200,200,200)
g.addColorStop(0,"red")
g.addColorStop(1,"white")
ctx.fillStyle = g
ctx.scale(0.5,1) // scale x axis 0.5
ctx.fillRect(0,0,400,400) // gradient circle squashed along x
Scaling a canvas
Create a second canvas
// assuming canvas , ctx is the original canvas and context
var can = document.createElement("canvas");
Set the resolution
can.width = Math.floor(canvas.width / 2);
can.height = canvas.height;
Get context and draw original on new canvas
can.ctx = can.getContext("2d");
can.ctx.drawImage(canvas,0,0,can.width,can.height);
Set the original canvas to the new size
canvas.width = can.width;
canvas.height = can.height;
Draw on the scaled can onto the original canvas
ctx.drawImage(can,0,0);
can = undefined; // reference to dump temp canvas
You now have the canvas scale yet keeping the content. You could also just replace the old canvas with the new one

JS canvas resizing in all sides

I am trying to resize a canvas in all directions the way Photoshop does.
I tried with JS but it's not matching the output I got from the Photoshop CC canvas size feature.
Original Image (600 x 439): http://i.imgur.com/rXURSWC.jpg
Resized with JS code (580 x 430): http://i.imgur.com/fwUiHyF.png
Resized with Photoshop CC (Image->Canvas Size) (580 x 430): http://i.imgur.com/smXTNv2.jpg
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 580;
var height = 430;
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, x, y, width, height);
};
imageObj.src = 'https://i.imgur.com/rXURSWC.jpg';
<body>
<canvas id="myCanvas" width="580" height="430"></canvas>
</body>
So, any idea how I can resize canvas in all directions the way photoshop CC does so that it can match to output of Photoshop CC.
JSFiddle: https://jsfiddle.net/f2L4b942/
What you are asking for is just to crop your image, but keep the anchor point in the middle.
This is easily implemented :
Set the x and y parameters of drawImage to the difference between the required size and the original one, divided by 2.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var requiredWidth = canvas.width = 580;
var requiredHeight = canvas.height = 430;
var img = new Image();
img.onload = function() {
// all you need is here
var offsetX = (requiredWidth - img.naturalWidth) / 2;
var offsetY = (requiredHeight - img.naturalHeight) / 2;
context.drawImage(img, offsetX, offsetY, img.naturalWidth, img.naturalHeight);
};
img.src = 'http://i.imgur.com/rXURSWC.jpg';
<canvas id="myCanvas" width="580" height="430"></canvas>
You could accomplish this by redefining the canvas width and height upon image load ...
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var imageObj = new Image();
imageObj.onload = function() {
canvas.width = this.width;
canvas.height = this.height;
context.drawImage(imageObj, x, y);
};
imageObj.src = 'http://i.imgur.com/rXURSWC.jpg';
body {
margin: 0px;
padding: 0px;
}
#myCanvas {
border: 1px solid black;
}
<canvas id="myCanvas" width="580" height="430"></canvas>

JavaScript canvas - clearImage() - canvas.getBoundingClientRect

I cannot clear the cursor image (canvas.getBoundingClientRect) after the cursor moves across the canvas element! I am left with a trail of appended images on the canvas.
How can I clear the trail of appended images and still keep my customized cursor (canvas.getBoundingClientRect) visible each time the canvas is cleared?
See my code :
<script>
window.addEventListener("load", CanvasProperties, false);
//Global Variables
var canvas, context;
// Canvase Element - 2D Properties
function CanvasProperties(){
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
window.addEventListener("mousemove", CustomCursor, false);};
// Customized Cursor for Game's Canvas
function CustomCursor(e){
var canvasRect = canvas.getBoundingClientRect();
var xPosition = e.clientX - 5 - canvasRect.left;
var yPosition = e.clientY - 5 - canvasRect.top;
var img = new Image();
img.src = "hero.png";
context.drawImage(img, xPosition, yPosition, 80, 80);};
</script>
Yeah, this one was really hard to google. The answer I like the best: https://stackoverflow.com/a/2142549/607407
function CustomCursor(e){
var canvasRect = canvas.getBoundingClientRect();
var img = new Image();
img.src = "https://crossorigin.me/https://www.gravatar.com/avatar/5a061a72feb5b6580dadd5dcbc92d3b5?s=64&d=identicon&r=PG";
var xPosition = e.clientX - 5 - canvasRect.left-img.naturalWidth/2;
var yPosition = e.clientY - 5 - canvasRect.top- img.naturalHeight/2;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, xPosition, yPosition, 80, 80);
};
Snippet:
//Global Variables - which is wrong
var canvas, context;
// Canvase Element - 2D Properties
function CanvasProperties(){
canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context = canvas.getContext("2d");
window.addEventListener("mousemove", CustomCursor, false);
}
// Customized Cursor for Game's Canvas
function CustomCursor(e){
var canvasRect = canvas.getBoundingClientRect();
var img = new Image();
img.src = "https://crossorigin.me/https://www.gravatar.com/avatar/5a061a72feb5b6580dadd5dcbc92d3b5?s=64&d=identicon&r=PG";
var xPosition = e.clientX - 5 - canvasRect.left-img.naturalWidth/2;
var yPosition = e.clientY - 5 - canvasRect.top- img.naturalHeight/2;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, xPosition, yPosition, 80, 80);
};
CanvasProperties();
<canvas width="300" height="300" id="canvas" />
Customized Canvas Cursor - Works! :)
<!DOCTYPE html>
<html>
<body id="body" style="background-color:gray;">
<canvas id="canvas" width="600" height="400" style="background-color:white;
display:block; margin:1 auto;"> </canvas>
<script>
window.addEventListener("load", CanvasProperties, false);
//JavaScript Variables
var canvas, context;
// Canvase Element - 2D Properties
function CanvasProperties(){
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
window.addEventListener("mousemove", CustomCursor, false);
}
// Customized Cursor for Game's Canvas
function CustomCursor(e){
var canvasRect = canvas.getBoundingClientRect();
var img = new Image(); img.src = "hero.png";
var xPosition = e.clientX - 5 - canvasRect.left;
var yPosition = e.clientY - 5 - canvasRect.top;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, xPosition, yPosition, 80, 80);
};
CanvasProperties();
</script>
</body>
</html>
You could just use css for this very easily, as the above stated in the comments, don't reinvent the wheel, javascript is still a lot slower than the native client the browser is running on. check out this https://davidwalsh.name/css-custom-cursor and you can use the canvas:hover to make it so it uses your custom cursor whenever the mouse is over it.

draw on image using canvas

I have a picture which which is loaded like this:
<img src="map/racetrack.jpg" id="map">
And here is my drawing function:
this.drawRoute = function(){
var pos = [];
var canvas = $('<canvas/>')[0];
var img = $('#map')[0];
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
$(window).on('mousedown', function(e){
pos.push({
x: e.clientX,
y: e.clientY
});
});
if (positions.length > 1) {
ctx.beginPath();
ctx.moveTo(pos[0].x, pos[0].y);
for (var i = 1; i < pos.length; i++) {
ctx.lineTo(pos[i].x, pos[i].y);
}
ctx.stroke();
}
}
But nothing is drawn on the picture. I can't see where the mistake is. I know usually I'm supposed to use <canvas> element, but I only need this particular part done in canvas, nothing else.
Here's the fiddle
Well a few things first you have no canvas element. Secondly I didnt see where you were calling the draw portion.
Live Demo
What I ended up doing was adding a canvas element, hiding the image, and then every time you draw it draws the image to the canvas, and then draws the points over it. This should hopefully be enough to get you started.
var pos = [];
var canvas = $('#canvas')[0];
var img = $('#map')[0];
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
function render() {
ctx.drawImage(img, 0, 0);
if (pos.length > 1) {
ctx.beginPath();
ctx.moveTo(pos[0].x, pos[0].y);
for (var i = 1; i < pos.length; i++) {
ctx.lineTo(pos[i].x, pos[i].y);
}
ctx.stroke();
}
}
$(window).on('mousedown', function (e) {
pos.push({
x: e.clientX,
y: e.clientY
});
render();
});
render();

Categories

Resources