I'm unable to get the text on the canvas. What am I doing wrong here ?
JSFiddle - http://jsfiddle.net/qHpt6/
var el = document.getElementById('mycanvas');
var context = el.getContext('2d');
context.globalAlpha = 0.95;
context.beginPath();
context.rect(0, 0, el.width, el.height);
context.fillStyle = "#435a6b";
context.fillText('Hello World',0,0);
context.fill();
You're trying to draw 40 point text into a little teeny box. Make the box bigger or the text a lot smaller.
You're also drawing the text at the upper left corner of the box. The text goes up from the baseline.
If you change the box size to something like 350 wide and 250 high, and change the code to
context.fillText("Hello World", 0, 200);
then you'll see the text.
Forked and fixed fiddle.
There is multiple issues:
The canvas is too small too correctly draw the text.
The text has the same fillStyle as the rectangle, so one cannot see it.
You draw the rectangle after the text, so the text is covered.
You may try this code:
context.globalAlpha = 0.95;
context.rect(0, 0, el.width, el.height);
context.fillStyle = "#435a6b";
context.fill();
context.font = 'italic 40pt Calibri';
context.fillStyle = "black";
context.fillText('Hello World',50,50);
http://jsfiddle.net/qHpt6/
Related
I cannot seem to to copy image data from a specific area on a canvas.
I can paint a rectangle around the area but when I use getImageData it caputures a different area.
I am trying to capture the grey box labelled click using
let sweepImgData = ctx.getImageData(300,250 ,100, 20);
But when I then use:
ctx.putImageData(sweepImgData, 75, 75);
It shows a blank box.
Can anyone please put me out of my misery?
https://jsfiddle.net/piersheriotwalker/67eLvg1t/53/
var ctx = document.getElementById("canv").getContext("2d");
let sweepImgData = ctx.getImageData(300,250 ,100, 20);
ctx.fillStyle = "blue";
ctx.fillRect(0, 0 , ctx.canvas.width, ctx.canvas.height);
ctx.putImageData(sweepImgData, 75, 75);
I just started working with Javascript and the Canvas tag and was having a lot of fun with it till I hit this snag... Basically I have three different objects being drawn on the canvas. The back ground on big black rectangle, then two shapes a rectangle and text. I want them to be two different colors, and so I use fillstyle() before drawing each. the problem is the the browser seems to ignore every call to fillstyle() after the first and sticks with the first color I choose. I've tried with and with out the beginPath() closePath(), fill() statements it seems to work with or with out these so I'm not if sure if there required I had seen it used while I was researching this issue. I've tried using RGB values instead of the color names. No luck.
//background
context.fillStyle = "Black";
context.beginPath();
context.fillRect(0, 0, 500, 300);
context.closePath();
context.fill();
//text
context.fillStyle = "Red";
context.font = "20px Sans-Serif";
context.textBaseline = "top";
context.beginPath();
context.fillText ("TEXT", x, y );
context.closePath();
context.fill();
//Test block
context.fillstyle = "Green";
context.beginPath();
context.fillRect(0,0,30,20);
context.closePath();
context.fill();
It looks like you have an error with your test block:
context.fillstyle = "Green";
Should be
context.fillStyle = "Green";
I'm currently drawing an image to an HTML5 Canvas and masking it with an arc, calling clip() before I draw the image so that only the portion that's in the arc is shown. How can I feather the edges of this arc? I know from googling around that there is no simple way to simply apply a "feather" to a shape drawn with canvas. What abut going in on the pixel data for the image where its edges touch the arc? Thanks for any help.
Here is the relevant portion of my code:
ctx.arc(canvas.width/2, canvas.height/2, 250, 0, 6.28, false);//draw the circle
ctx.restore();
ctx.save();
ctx.drawImage(background, 0, 0,
background.width * scale, background.height * scale);
ctx.clip();//call the clip method so the next render is clipped in last path
ctx.drawImage(img, 0, 0,
img.width * scale, img.height * scale);
ctx.closePath();
ctx.restore();
UPDATE
Thanks for the thorough answer and very helpful code/comments Ken!! I spent a few hours last night trying to work this solution in my particular use case and I'm having trouble. It seems that if I clip an image with the second-canvas technique you describe I can't redraw it on transforms the same way that I can with an arc() and clip() routine. Here's a JS Fiddle of what I'm trying to accomplis, minus the feathering on the arc, notice the click and drag events on the two layered images.
http://jsfiddle.net/g3WkN/
I tried replacing the arc() with your method, but I'm having a hard time getting that to be responsive to the transforms that happen on mouse events.
Update 2017/7
Since this answer was given there are now a new option available in newer browsers, the filter property on the context. Just note that not all browsers currently supports it.
For browsers which do we can cut down the code as well as remove temporary canvas like this:
var ctx = demo.getContext('2d');
ctx.fillStyle = '#f90';
ctx.fillRect(0, 0, demo.width, demo.height);
clipArc(ctx, 200, 200, 150, 40);
function clipArc(ctx, x, y, r, f) {
ctx.globalCompositeOperation = 'destination-out';
ctx.filter = "blur(25px)"; // "feather"
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
// reset comp. mode and filter
ctx.globalCompositeOperation = 'destination-out';
ctx.filter = "none";
}
body {background:#07c}
<canvas id="demo" width=400 height=400></canvas>
Old answer
Technique
You can achieve this by combining the following steps:
Use off-screen canvas
Use the shadow feature (the secret ingredient)
Use composite modes
The concept is based on having the browser make the feather internally by utilizing the blurred shadow. This is much faster than blurring in JavaScript. As we can make shadow for any object you can make complex feathered masks.
The off-screen canvas is used to draw the shadow only. We achieve this by moving the actual shape outside the canvas and then offset the shadow accordingly. The result is that shadow is drawn on the off-screen canvas while the actual shape is "invisible".
Now that we have a feathered version of our shape we can use that as a mask for composite mode. We choose destination-out to cleat where the shadow is drawn, or destination-in to invert the mask.
Example
Lets create a wrapper function that do all the steps for us
ONLINE DEMO HERE
function clipArc(ctx, x, y, r, f) { /// context, x, y, radius, feather size
/// create off-screen temporary canvas where we draw in the shadow
var temp = document.createElement('canvas'),
tx = temp.getContext('2d');
temp.width = ctx.canvas.width;
temp.height = ctx.canvas.height;
/// offset the context so shape itself is drawn outside canvas
tx.translate(-temp.width, 0);
/// offset the shadow to compensate, draws shadow only on canvas
tx.shadowOffsetX = temp.width;
tx.shadowOffsetY = 0;
/// black so alpha gets solid
tx.shadowColor = '#000';
/// "feather"
tx.shadowBlur = f;
/// draw the arc, only the shadow will be inside the context
tx.beginPath();
tx.arc(x, y, r, 0, 2 * Math.PI);
tx.closePath();
tx.fill();
/// now punch a hole in main canvas with the blurred shadow
ctx.save();
ctx.globalCompositeOperation = 'destination-out';
ctx.drawImage(temp, 0, 0);
ctx.restore();
}
That's all there is to it.
USAGE
clipArc(context, centerX, centerY, radius, featherSize);
With demo background (see fiddle):
ctx.fillStyle = '#ffa';
ctx.fillRect(0, 0, demo.width, demo.height);
clipArc(ctx, 200, 200, 150, 40);
Result:
If you want to keep center intact just replace composite mode with destination-in.
Demo for inverted feathered mask
When I place a square on the canvas at 0,0 coords the top left is cut off:
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = 'blue';
context.rect(0, 0, 200, 100);
context.fillStyle = 'yellow';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
<canvas id="c" width="500" height="500"></canvas>
Why is this?
It's because half the stroke is inside the rect.fill and the other half of the stroke is outside the rect.fill.
Kind of like css borders, you must account for them when sizing/positioning.
In canvas's case, the stroke is always half-in / half-out the object.
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.