HTML5 Canvas context fill doesn't work on Chrome - html

I have created a circular pattern generator using HTML5 canvas. I have used the arc to create circles and have placed them randomly on the canvas. Also, I have the circles filled with a random color generated on mousedown. The arc fill works on Firefox but doesnt show on Chrome. I am using Latest Chrome ver 18.
context.save();
context.scale(1, 1);
context.beginPath();
context.arc(nextX, nextY, radius, 0, 2 * Math.PI, false);
context.closePath();
context.fillStyle = color;
context.lineWidth = 1;
context.strokeStyle = color;
context.stroke();
context.fill();
context.restore();
Here is the live working link - http://www.riaxe.com/html5cirpattern/

Related

Canvas rectangle with 3D effect border

(Refer to image)
First part of image shows div with raised borders(using -webkit-box-shadow,box-shadow properties). I want to give same effect to rectangle drawn using HTML5 canvas element.
Is it any way to acieve this??
That's possible, try something like this:
context.rect(50, 50, 100, 100);
context.fillStyle = 'white';
context.shadowColor = 'black';
context.shadowBlur = 25;
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.fill();
Working Example

A smooth circle in Html5

I'm trying to draw a circle with a canvas in HTML5. I use an example from w3schools, but the result is ugly, not smooth. Is it possible to have a smooth circle ? (I tried this with Chrome and IE9)
The code I use :
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.arc(125,120,100,0,2*Math.PI);
ctx.stroke();
=> http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_canvas_tut_path2 : the original example
=> http://jsfiddle.net/jPeKk/ : my try, bigger
On chrome, this is a known issue that has been discussed here - Can I turn off antialiasing on an HTML <canvas> element?
and here - How to anti-alias clip() edges in html5 canvas under Chrome Windows?
Try
ctx.webkitImageSmoothingEnabled=true;
to make your line smoother.
Another solution that works for me (though I think it's more of a hack than a proper solution) is to draw a line around the circle with the same color. For some reason this is going to be very smooth.
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.beginPath();
context.arc(100, 100, 60, 0, 2 * Math.PI, false);
context.fillStyle = '#775599';
context.fill();
context.beginPath();
context.arc(200, 200, 60, 0, 2 * Math.PI, false);
context.fillStyle = '#775599';
context.fill();
context.lineWidth = 2;
context.strokeStyle = '#775599';
context.stroke();

Canvas Chart fill the space between lines

I'm developing a simple chart using html5 Canvas. The idea is to draw two lines - one for min values and another one for max values, which I managed to do AND fill the space between those two line with some colour. Wonder how do I do the last part?
to fill the space you have to:
//get the context of the canvas
var context = canvas.getContext("2d");
//begin to draw
context.beginPath();
//draw all the lines you need to do the path....
context.moveTo(x, y);
context.lineTo(x1,y1);
context.lineTo(x2,y2);
//end of draw
context.closePath();
//to fill the space in the shape
context.fillStyle = "#FF00FF";
context.fill();
//to draw a border
context.lineWidth = 5;
context.strokeStyle = "#FF0000";
context.stroke();
UPDATE: to fill the space between 2 lines, is drawing a square:
I asume the lines are defined as:
line1: from (x1,y1) to (x2,y2)
line2: from (x3,y3) to (x4,y4)
then the square to draw to fill the space:
from (x1,y1) -> (x2,y2) -> (x3,y3) -> (x4,y4) and closepath();
then:
context.beginPath();
context.moveTo(x1,y1); //go to first point
context.lineTo(x2,y2); //draw to second point
context.lineTo(x3,y3); //draw to third point
context.lineTo(x4,y4); //draw to last point
context.closePath(); //draw to first point
context.fill(); //fill the area

HTML5 - Canvas Shape Stroke

I have created 2 shapes, circle and rectangle, one on top of the other to resemble a key lock. I then try to apply a stroke but its stroking both shapes. What I want it to do is just stroke the merged pattern and not any of the intersections.
context.beginPath();
context.fillStyle = "#ccc";
context.arc(115, 550, 12, 0, 2 * Math.PI, false);
context.moveTo(105, 555);
context.fillStyle = "#999";
context.rect(105, 555, 20, 30);
context.fill();
context.stroke();
context.closePath();
If I try to draw the rect first, then the arc on top there are extra line paths when you stroke, its like I have to close Path and then draw it again.
You can't use a rect and a whole circle if you want the path to do without the intersecting part.
Instead you have to draw only part of the circle and only part of the rectangle. This should do it for you:
context.beginPath();
context.fillStyle = "#ccc";
context.arc(115, 550, 12, 2.5, 2.2 * Math.PI, false);
context.moveTo(105+20, 555);
context.fillStyle = "#999";
// instead of a rect, we really want three lines
context.lineTo(105+20,555+30);
context.lineTo(105,555+30);
context.lineTo(105,555);
context.fill();
context.stroke();
context.closePath();
While working on my own irregular shape answer, I discovered a lab project by Professor Cloud that solved my problem.
This page, SVG-to-Canvas, parses an SVG graphic to Canvas code. So if you have an application like Illustrator with which you can draw and save the graphic as SVG, then you can parse the usable canvas codes and just plug them in.
You can use compositing and temporary canvas. Something like that:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var tempCanvas = document.getElementById('tempCanvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.save();
// clear temp context
tempContext.clearRect(0, 0, canvas.width, canvas.height);
// draw all rects with strokes
tempContext.beginPath();
tempContext.strokeStyle='red';
tempContext.lineWidth=3;
tempContext.arc(100, 100, 60, 0, 2 * Math.PI, false);
tempContext.rect(20,150,100,200);
tempContext.stroke();
// set compositing to erase existing drawings
// where the new drawings are drawn
tempContext.globalCompositeOperation='destination-out';
// fill all rects
// This "erases" all but the outline stroke
tempContext.beginPath();
tempContext.fillStyle='blue';
tempContext.arc(100, 100, 60, 0, 2 * Math.PI, false);
tempContext.rect(20,150,100,200);
tempContext.fill();
// draw outlines from tempcanvas into canvas
ctx.drawImage(tempCanvas, 0, 0);
// draw into canvas
ctx.beginPath();
ctx.fillStyle='green';
ctx.globalAlpha = 0.2;
ctx.rect(20,150,100,200);
ctx.arc(100, 100, 60, 0, 2 * Math.PI, false);
ctx.fill();
tempContext.restore();
And a jsfiddle: https://jsfiddle.net/EvaF/8to68dtd/2/

Canvas 'Clip' reverse action?

Assuming I have:
var context = document.getElementById('test').getContext('2d');
// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);
// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
context.closePath();
context.globalCompositeOperation = 'destination-out';
// 'P' hole
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.fillStyle = '#ffffff';
context.fill();
context.closePath();
This works, except as you can see the 'hole' isn't a clip, so if the background isn't solid, you simply can't set the 'fill' color of the hole to match the background.
Therefore I need to clip the hole instead. When I do that however, the only part of the 'P' that shows is the part bound by the clip 'hole'. I need the reverse. I need the 'P' to show, but clip the part with the 'hole' so any background will show through.
Here is as far as I got, but not quite there:
var context = document.getElementById('test').getContext('2d');
// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);
// 'P' hole clip
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.clip();
context.closePath();
// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
context.closePath();
Thank you for your help!
I understand you asked this a while ago but I have an answer for you.
Your first example was half-correct. Using destination-out will work, however in order not to disturb the canvas you want to draw on, we create a new canvas and draw it in that.
Then once we've drawn our shape on there with our cutaways, we then draw the entire canvas onto the original. Since the new canvas has no background it will keep transparency.
var canvas = document.getElementById('test'),
context = canvas.getContext('2d'),
// New canvas - we will draw the letter P on here
newCanvas = document.createElement('canvas'),
newContext = newCanvas.getContext('2d');
// Make sure you have enough room on your new canvas
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;
with(newContext) {
// 'P'
beginPath();
moveTo(90,89);
lineTo(161,89);
quadraticCurveTo(200,89,200,127);
quadraticCurveTo(200,166,148,166);
lineTo(115,166);
lineTo(108,210);
lineTo(69,210);
lineTo(90,89);
fillStyle = "#eee";
fill();
closePath();
globalCompositeOperation = 'destination-out';
// 'P' hole
beginPath();
moveTo(124,117);
lineTo(146,117);
quadraticCurveTo(160,117,160,127);
quadraticCurveTo(160,145,146,145);
lineTo(120,145);
lineTo(124,117);
fillStyle = '#000';
fill();
closePath();
}
with(context) {
// Background
fillStyle = '#000';
fillRect(0,0,300,300);
// Simply reference the canvas element when drawing
drawImage(newCanvas, 0, 0);
}
I know this is very old but... you are not using clip correctly in your second try. Everything that comes after clip will be drawn only on the clipped area.
so you could either:
Clip the hole and redraw the background
var context = document.getElementById('test').getContext('2d');
// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);
// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
// 'P' hole clip
context.beginPath();
context.moveTo(124,117);
context.lineTo(146,117);
context.quadraticCurveTo(160,117,160,127);
context.quadraticCurveTo(160,145,146,145);
context.lineTo(120,145);
context.lineTo(124,117);
context.clip();
// Redraw Background in the clipped area
context.fillStyle = '#000';
context.fillRect(0,0,300,300);
<canvas id="test" width="300" height="300">
clip the outside part of the hole and draw the P
var context = document.getElementById('test').getContext('2d');
// Background
context.fillStyle = '#000';
context.fillRect(0,0,300,300);
// inverse 'P' hole clip
context.beginPath();
context.rect(0, 0, 300, 300);
context.lineTo(124,117);
context.lineTo(120,145);
context.lineTo(146,145);
context.quadraticCurveTo(160,145,160,127);
context.quadraticCurveTo(160,117,146,117);
context.lineTo(124,117);
context.clip();
// 'P'
context.beginPath();
context.moveTo(90,89);
context.lineTo(161,89);
context.quadraticCurveTo(200,89,200,127);
context.quadraticCurveTo(200,166,148,166);
context.lineTo(115,166);
context.lineTo(108,210);
context.lineTo(69,210);
context.lineTo(90,89);
context.fillStyle = "#eee";
context.fill();
<canvas id="test" width="300" height="300">
Also, you don't need to use closePath here.