How to measure width and height of html5 graphic, including drop shadow - javascript

I am creating multiple html5 canvases, each one containing a single graphic (rectangle, circle etc), and they need to fit neatly into each canvas, including any drop shadow.
Without dropshadow parameters, and drawing, for example, a rectangle, you can know the exact width and height of the resulting graphic.
However, when you set dropshadow, and blur, how can you predict the width and height of the resulting graphic?
For example, using Javascript, how would I calculate the height and width of the rectangle and drop shadow, in the following code:
body
<canvas id="myCanvas" width="300" height="300"></canvas>
Javascript
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.rect(0, 0, 200, 100);
context.fillStyle = 'red';
context.shadowColor = '#999';
context.shadowBlur = 20;
context.shadowOffsetX = 20;
context.shadowOffsetY = 20;
context.fill();
JSfiddle example is here: http://jsfiddle.net/csu3vxk3/1/
thanks!

Related

Different html canvas coordinates

i made 2 deference size html canvas to drawing
First canvas = width : 400px,height:200px
Second canvas = width : 200px,height :100px
Now when i drawing in first html canvas i send that coordinates(x1,y1,x2,y2) to second canvas.
When first canvas coordinates send in second canvas it's not drawing in same place as first canvas.
is there way to equal first canvas coordinates to second one without changing canvas width and height .
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = "red";
ctx.moveTo(coord.x, coord.y);
ctx.lineTo(ncoord.x , ncoord.y);
ctx.stroke();
//SECOUND CANVAS
ctx2.beginPath();
ctx2.lineWidth = 5;
ctx2.lineCap = 'round';
ctx2.strokeStyle = "red";
ctx2.moveTo(coord.x, coord.y);
ctx2.lineTo(ncoord.x , ncoord.y);
ctx2.stroke();
when user drwaing in canvas 1 i send that coordinates to both canvas. but in second canvas not drawing in same place as canvas 1.
Note : canvas 1 and 2 have deferent width and height.
I need to slove this without changing width height of the both canvas.
I hope I have made the right assumptions to answer your question. I created two different canvases of two different sizes. The coordinates only fit on the first, bigger, canvas.
You can transform the 'big' coordinates to 'small' coordinates by dividing the width or height of the bigger smaller canvases by the bigger canvases.
For example, the height of the big canvas is 200 but the height of the smaller one is 100. If you divide 100 / 200 you get 0.5. The 'small' coordinates should be half as high as the original ones. See for yourself below:
//just for testing purposes
var coord = {
x: 320,
y: 125
};
var ncoord = {
x: 220,
y: 90
};
function drawBig() {
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = "red";
ctx.moveTo(coord.x, coord.y);
ctx.lineTo(ncoord.x, ncoord.y);
ctx.stroke();
}
function drawSmall() {
let bigCanvas = document.getElementById("canvas1");
let smallCanvas = document.getElementById("canvas2");
//Devide the dimensions of the big and small canvas in order to get the magnification factor:
let widthDimension = smallCanvas.width / bigCanvas.width;
let heightDimension = smallCanvas.height / bigCanvas.height
var ctx2 = smallCanvas.getContext("2d");
ctx2.beginPath();
ctx2.lineWidth = 5;
ctx2.lineCap = 'round';
ctx2.strokeStyle = "red";
//Transform the original coordinates to the right dimensions:
ctx2.moveTo(coord.x * widthDimension, coord.y * heightDimension);
ctx2.lineTo(ncoord.x * widthDimension, ncoord.y * heightDimension);
ctx2.stroke();
}
canvas {
border: 1px solid black;
}
<canvas id="canvas1" width="400" height="200"></canvas>
<hr>
<canvas id="canvas2" width="200" height="100"></canvas>
<button onclick="drawBig()">draw big canvas</button>
<button onclick="drawSmall()">draw small canvas</button>
Hope this helps! If not, please comment

Drawing flat shapes on HTML canvas creates blurry borders

I want to draw flat shapes, like rectangles, on an HTML canvas but whenever I use the fillRect or rect and then fill, the outcome is a shape with some kind of blurry inner glow and shadow. Is there any way to get rid of these “light effects”?
As an example, here’s a piece of code I used:
var canvas = document.getElementById('map');
var ctx = canvas.getContext("2d");
ctx.fillStyle = c;
ctx.fillRect(x, y, w, h);
and the produced outcome (with the glow and shadow):
probably just set the canvas.width and canvas.height to the same values you got the css style.
when some elements get scaled by css they normally get antialias (canvas and images).
image-rendering: auto;
image-rendering: crisp-edges;
image-rendering: pixelated;
some browsers also comply with these styles that remove the antialias
more about the css here
I use another method for drawing shapes:
var context = canvas.getContext("2d");
var rectX = 400, rectY = 300;
function draw() {
context.fillStyle = "#FFFF00"
context.fillRect(rectX, rectY, 100, 200);
}
draw();
Here's a fiddle with the result:
https://jsfiddle.net/Sufi2425/fnd5es9a/

HTML5 Canvas: How to border a fillRect?

In HTML5, I want to make a fillRect() (with a white fill color) and a border (black). I don't want to use strokeRect() unless I can fill that later. I'm making a game where you click on squares and they change color (it's more complex than that but that's what this focuses on).
<canvas id="canvas1" width="400" height="300" style="border:1px solid #000000;"></canvas>
<script>
var c=document.getElementById("canvas1");
var ctx=c.getContext("2d");
ctx.strokeStyle="rgba(0,0,0,1)";
ctx.strokeRect(0,0,100,100);
</script>
The border around the canvas is for reference.
I can use CSS too, but currently everything is in HTML.
you can not fill it later without a library. If you want to change something simply redraw.
You can use something like that:
ctx.fillStyle = 'blue';
ctx.strokeStyle = 'red';
var fillRect = false;
ctx.rect(20, 20, 150, 100);
if (fillRect) {
ctx.fill();
}
ctx.stroke();
it will draw only the border, if you change fillRect to true it will be filled. You can update your canvas on every requestAnimationFrame.
But maybe you want to use a library like paper.js. It makes things like clicking on objects much easier and it abstracts draws on canvas to objects you create once and update later, like what you asked for.
Work out the position you want to draw the square with the width and height. Once you have done that simply draw a bigger square first which has wider by 2 and higher by 2 but with the same center point. So you draw a square which is bigger and then you draw the normal square on top, this then gives you the illusion of the square has a border
HTML
<canvas id="canvas1" width="400" height="300" style="border:1px solid #000000;"></canvas>
CSS
#canvas1{
border: solid 1px black;
}
Javascript
var c=document.getElementById("canvas1");
var ctx=c.getContext("2d");
var rectXPos = 50;
var rectYPos = 50;
var rectWidth = 100;
var rectHeight = 100;
drawBorder(rectXPos, rectYPos, rectWidth, rectHeight)
ctx.fillStyle='#FFF';
ctx.fillRect(rectXPos, rectYPos, rectWidth, rectHeight);
function drawBorder(xPos, yPos, width, height, thickness = 1)
{
ctx.fillStyle='#000';
ctx.fillRect(xPos - (thickness), yPos - (thickness), width + (thickness * 2), height + (thickness * 2));
}
jsfiddle link : https://jsfiddle.net/jxgw19sh/2/
-- Update --
Add an extra parameter to drawBorder called thickness the default value is 1 but you can provide any other number for thickness into the function and it will use value instead of 1.
I tried on my own and it looks like this:
var x = 100;
var y = 100;
var width = 50;
var height = 50;
var borderWidth = 5;
var offset = borderWidth * 2;
c.beginPath();
c.fillStyle = 'black';
c.fillRect( x - borderWidth, y -borderWidth, width + offset, height + offset);
c.fillStyle = 'green';
c.fillRect( x, y, width, height);

Draw only shadows on html5-canvas

I'm trying to figure out how I can draw something on canvas and show only it's shadow, for example:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.shadowBlur=100;
ctx.shadowOffsetX = 150;
ctx.shadowColor="red";
ctx.fillStyle="rgba(0,0,0,0.7)";
ctx.fillRect(20,20,100,80);
Here I draw a black rectangle and add a red shadow with an offset, I'd like to see only the shadow without the rectangle.
As you can see on the example, I tried using rgba color but when I set opacity it affects the shadow as well.
here is a fiddle for this code: http://jsfiddle.net/YYvFw/
well the first thing that comes to mind is moving the rectangle out of the canvas and offsetting the shadow as far as you need it.
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d'),
width = 100,
height = 80,
posX = 100,
posY = 80;
context.rect(-width, -height, width, height);
context.shadowColor = 'red';
context.shadowBlur = 40;
context.shadowOffsetX = width+posX;
context.shadowOffsetY = height+posY;
context.fill();
that draws you the shadow at x:100 y:80
http://jsfiddle.net/S7WRx/2/
I don't know if there's an easy way to do it. The only thing I could think of is to getImageData for the shadowed area, and then clear the canvas and paste that imageData onto it.

How to prevent HTML5 canvas line width from changing when re-sizing the canvas.

Assuming that I have an <canvas> which contains a line (using lineTo function).
The canvas changes his dimensions (either both height and width, height or width) frequently.
During the canvas dimension change, I would like to keep the same visually width of the lines.
Thanks a lot.
The following snippet represents the current scenario when the dimensions of the canvas effects the visually width of the lines.
var index;
var canvas;
var context;
for (index = 1; index <= 2; index++) {
canvas = document.getElementById("canvas" + index);
context = canvas.getContext('2d');
context.beginPath();
context.moveTo(100, 150);
context.lineTo(450, 50);
context.lineWidth = 16;
context.stroke();
}
<h3>
As you can see, both canvas objects has the same line initialization
in JavaScript code. the only diff between them are the dimensions (in our case, the width).
</h3>
<canvas id="canvas1" style="width:100px"></canvas>
<canvas id="canvas2" style="width:300"></canvas>
So you have a couple things that are going to get weird on you... canvas needs to be sized outside of CSS. By setting size in css you are stretching the canvas vs using it's native sizing.
Notice the difference by switching the sizing on the elements.
The other thing is now that they are sized correctly you're starting the original point outside of the 100px canvas.
Further reading: https://www.w3.org/TR/html5/scripting-1.html#attr-canvas-width
here is a fiddle that shows what is really happening here - https://jsfiddle.net/bopjtwfe/
var index;
var canvas;
var context;
for (index = 1; index <= 2; index++) {
canvas = document.getElementById("canvas" + index);
context = canvas.getContext('2d');
context.beginPath();
context.moveTo(10, 10);
context.lineTo(150, 150);
context.lineWidth = 16;
context.stroke();
}
canvas {
display: block;
margin-bottom: 10px;
background-color: white;
}
<canvas id="canvas1" width='100px' height='100px' ></canvas>
<canvas id="canvas2" width='300px' height='300px'></canvas>

Categories