Draw only shadows on html5-canvas - javascript

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.

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

Why do stroked rectangles tend to go outside the canvas?

I've been experimenting with the <canvas> recently, and I noticed a strange behaviour when stroking rectangles near the origin (0, 0) of the canvas.
// canvas context
var ctx = document.querySelector('#screen').getContext('2d');
// draw a rectangle
ctx.fillStyle = 'orange';
ctx.fillRect(0, 0, 100, 100);
// stroke a border for the rectangle
ctx.lineWidth = 20;
ctx.strokeRect(0, 0, 100, 100);
<canvas id="screen"></canvas>
What went wrong?
In the example above, the rectangle itself was drawn at (0, 0) as intended, but its border (the stroked rectangle) seems to be drawn at an offset.
Generally, when stroking a rectangle at a position away from the origin, this effect is omitted —
Meaning that the stroked rectangles aren't being drawn starting at the position specified, but at an offset, I suppose.
Why is that?
The stroke is centered around the coordinates that your primitve is defined at. In the case of your rectangle with stroke width of 20, drawing this at the top left of the canvas will cause half of the strokes width to be drawn outside of the canvas boundary.
Adjusting the coordinates of strokeRect() to 10,10,.. causes the rectangle to be offset from the canvas origin, meaning that the full stroke of 20 pixels will be visible from the top-left of the canvas:
ctx.lineWidth = 20;
ctx.strokeRect(10, 10, 100, 100);
Consider the following adjustments, made to ensure the stroke is fully visible around the drawn rectangle:
var canvas = document.querySelector('#screen');
// Set the width and height to specify dimensions of canvas (in pixels)
// Choosing a 100x100 square matches the strokeRect() drawn below and
// therefore achieves the appearance of a symmetric stroke
canvas.width = 100;
canvas.height = 100;
// canvas context
var ctx = canvas.getContext('2d');
// draw a rectangle
ctx.fillStyle = 'orange';
ctx.fillRect(10, 10, 90, 90);
// stroke a border for the rectangle
ctx.lineWidth = 20;
var halfStroke = ctx.lineWidth * 0.5;
ctx.strokeRect(halfStroke, halfStroke, 100 - (halfStroke * 2), 100 - (halfStroke * 2));
<canvas id="screen"></canvas>
Update
Here is a visualisation of the stroke in relation to the line/rectangle edge provided by Ibrahim Mahrir:

How to Style Images in a canvas?

I'm using node-canvas and I was wonder how style an imported image in canvas similar to how you would an image in CSS.
For example, how would I crop a square image in canvas to a circle. In CSS, all you need to do is set border radius to 50%.
Well obviously you cannot use CSS in this case since CSS is applied to the DOM and not the the pixel based content of a Canvas element.
However the Canvas element has its own set of draw functions which allow to you replicate or at least approximate CSS rules.
Since you mentioned cropping an image to a circle I'll focus on this example. To achieve this effect you want to specify a clipping region before drawing the image. Every pixel outside of the clipped region will not be drawn. Effectively this will crop the image to the clipped region.
In code:
// Retrieve canvas and get context
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// Save the context so we can undo the clipping region at a later time
context.save();
// Define the clipping region as an 360 degrees arc at point x and y
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
// Clip!
context.clip();
// Draw the image at imageX, imageY.
context.drawImage(image, imageX, imageY);
// Restore context to undo the clipping
context.restore();
I'd advice taking a look at this page to give you an idea of what you can do with the Canvas element and the 2D rendering context.
I don't know if this would work in node, However you can do this with canvas;
The simplest way of doing it is using, as you intended, border-radius:
canvas{border-radius:50%;}
An other way of doing it is by using the ctx.clip() method.
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(125,120,100,0,2*Math.PI);
// you clip the context
ctx.clip();
let img = document.querySelector("#testImg");
ctx.drawImage(img, 0, 20);
<canvas width="250" height="240" >
<img id="testImg" src="theImage.jpg">
</canvas>
Yet an other way of doing it is by using ctx.globalCompositeOperation = "destination-atop"in this way:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = canvas.width = 400,
cx = cw / 2;
let ch = canvas.height = 400,
cy = ch / 2;
ctx.globalCompositeOperation = "destination-atop";
let img = document.querySelector("#testImg");
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.fillStyle = "#f00";
ctx.arc(cx, cx, 100, 0, 2 * Math.PI);
ctx.fill();

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

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!

canvas draw circle with quadratic curve

I know I can draw arc with arc function of canvas but when I increase the size of that arc it changes its start and end x,y points. So I was thinking if we can draw arc with some other way keeping its start end points fixed while increasing it size.
Edit
Below is the images showing what I am looking for. First image shows a rectangle. when its side is stretched it changed to circle(2nd image). when side is stretched further it changed to big circle. At in all images you can see that end points of circle are joined to corners of rectangle. This is what I want to do.
1st Image
2nd Image
3rd Image
Or you can see this video to understand what I am looking to do.
What I have done
This fiddle shows result of my work.
To draw rectangle just click and drag your mouse.
Here is the code
I believe you're looking for something like this:
draw(0);
$('#range').on('change', function(){
range = parseInt($(this).val());
draw(range)
})
function draw(val){
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d'),
x = 100,
y = 50,
d;
context.clearRect(0, 0, canvas.width, canvas.height);
d = Math.sqrt(Math.pow(val,2) + Math.pow(50,2));
context.beginPath();
context.lineWidth = 1;
context.arc(x,y+val,d,0,2*Math.PI);
// line color
context.strokeStyle = 'black';
context.stroke();
// Cut off the top of the circle.
context.clearRect(0, 0, canvas.width, y);
// This stuff's just to show some dots
context.fillStyle = 'red';
context.fillRect(x-1,y-1,2,2); // Middle
context.fillRect(x-52,y-2,4,4);//Target point 1
context.fillRect(x+48,y-2,4,4);// Target point 2
context.fillRect(x-2,y+d+val-2,4,4); // Point on circle
context.fillStyle = 'black';
}
Working sample
There are a couple disadvantages to this is that it gets "slower" the closer you get to the circle, because the circle's getting exponentially larger in the hidden section (The slider's controlling it's size), and that it doesn't work for diagonal lines as it is right now.
Other than that, it works like expected.
Check this : http://jsfiddle.net/KZBzq/4/
Updated answer with bezierCurveTo
HTML
<label>Range :</label>
<input type="range" name="points" value="0" min="0" step="1" max="100" id="range">
<canvas id="myCanvas" width="578" height="250"></canvas>
JS
draw(100);
$('#range').on('change', function(){
range = parseInt($(this).val());
draw(100-range)
})
function draw(val){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d'),
x = 100,
y = 100,
cp1x = x/2,
cp2x = y/2,
cp1y = val,
cp2y = val;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.lineWidth = 1;
context.moveTo(25 , x);
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
// line color
context.strokeStyle = 'black';
context.stroke();
}
Now x and Y are fixed. Is this was your requirement?

Categories