In canvas, how to draw 2 semi-transparent overlapping circles - html

I want to draw two circles on the gray rectangle in HTML canvas.
I attempted the following steps:
Fill rectangle gray
Change globalComposition lighter to mix two colors.
I want to mix only blue and red, not gray and gray rectangle.

You can easily achieve this property by fill style of the circles in rgba, where the last parameter will be alpha or opacity. The syntax will be something like this
circle.fillStyle = "rgba(255, 255, 255, 0.5)";
//can be used to fill as red object with opacity of 0.5
The complete code to achieve the desired effect will be something like this.
// JavaScript Code
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerleftX = canvas.width / 4;
var centerRightX = 3 * canvas.width / 4;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.rect(0, 0, 400, 200);
context.fillStyle = 'rgb(200,200,200)';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
context.beginPath();
context.arc(centerleftX + 50, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(0, 0,255,0.7)";
context.fill();
context.beginPath();
context.arc(centerRightX - 50, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(255, 0,0,0.7)";
context.fill();
<!-- HTML Code -->
<canvas id="myCanvas" width="400" height="200">

Related

Add gradient to HTML5 Circle from top to bottom

I'm trying to recreate my site's logo in HTML5 canvas for a bit of fun and to learn along the way. So far I've created the basic shapes, but I'm not sure how to add a gradient to the circle, so it goes from light orange at the top, to a darker orange at the bottom. This is what I have so far:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = canvas.width / 2 - 2;
// circle
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = '#FF9000';
context.fill();
context.lineWidth = 1;
context.strokeStyle = '#FF9000';
context.stroke();
// top line
context.beginPath();
context.moveTo(canvas.width / 2 - canvas.width / 4, canvas.height / 2 - canvas.height / 4);
context.lineTo(canvas.width / 2 + canvas.width / 4, canvas.height / 2 - canvas.height / 4);
context.lineWidth = canvas.width / 7;
context.strokeStyle = '#FFFFFF';
context.lineCap = 'round';
context.stroke();
// short middle line
context.beginPath();
context.moveTo(canvas.width / 2 - canvas.width / 8, canvas.height / 2);
context.lineTo(canvas.width / 2 + canvas.width / 8, canvas.height / 2);
context.lineWidth = canvas.width / 7;
context.strokeStyle = '#FFFFFF';
context.lineCap = 'round';
context.stroke();
// bottom line
context.beginPath();
context.moveTo(canvas.width / 2 - canvas.width / 4, canvas.height / 2 + canvas.height / 4);
context.lineTo(canvas.width / 2 + canvas.width / 4, canvas.height / 2 + canvas.height / 4);
context.lineWidth = canvas.width / 7;
context.strokeStyle = '#FFFFFF';
context.lineCap = 'round';
context.stroke();
Could someone perhaps guide me as to how to do this? HTML5 is a quite a leap in terms of my knowledge of html etc, so any help would be much appreciated.
When you do createLinearGradient think of it as drawing a line which the gradient will follow:
// imaginary line goes from x1,y1 to x2,y2 (the gradient will go there also)
var gradient=createLinearGradient( x1,y1, x2,y2 );
If you draw this line center-top to center-bottom, the gradient will go top to bottom.
var orangeGradient = context.createLinearGradient(
canvas.width/2, 0, canvas.width/2, canvas.height);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/LLGtc/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var context = canvas.getContext('2d');
context.arc(canvas.width/2, canvas.height/2, canvas.width/2-2, 0, Math.PI*2,false);
context.closePath();
var orangeGradient = context.createLinearGradient(canvas.width/2, 0, canvas.width/2, canvas.height);
orangeGradient.addColorStop(0, '#ffdd00');
orangeGradient.addColorStop(1, '#cc6600');
context.fillStyle = orangeGradient;
context.fill();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=400></canvas>
</body>
</html>

Animate a Fill Circle using Canvas

Basically I want to be able to Fill a Circle using canvas, but it animate to a certain percentage.
I.e only have the circle fill up 80% of the way.
My canvas knowledge isn't amazing, Here is an image i made in photoshop to display what i want.
I want the circle to start empty and then Fill up to say 70% of the circle.
Is this possible with Canvas, if so? can anyone shed some light on how to do it?
Here is a fiddle of what I've managed
http://jsfiddle.net/6Vm67/
var canvas = document.getElementById('Circle');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 80;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = '#13a8a4';
context.fill();
context.lineWidth = 10;
context.strokeStyle = '#ffffff';
context.stroke();
Any help would be massively appreciated
Clipping regions make this very easy. All you have to do is make a circular clipping region and then fill a rectangle of some size to get a "partial circle" worth of fill. Here's an example:
var canvas = document.getElementById('Circle');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 80;
var full = radius*2;
var amount = 0;
var amountToIncrease = 10;
function draw() {
context.save();
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.clip(); // Make a clipping region out of this path
// instead of filling the arc, we fill a variable-sized rectangle
// that is clipped to the arc
context.fillStyle = '#13a8a4';
// We want the rectangle to get progressively taller starting from the bottom
// There are two ways to do this:
// 1. Change the Y value and height every time
// 2. Using a negative height
// I'm lazy, so we're going with 2
context.fillRect(centerX - radius, centerY + radius, radius * 2, -amount);
context.restore(); // reset clipping region
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.lineWidth = 10;
context.strokeStyle = '#000000';
context.stroke();
// Every time, raise amount by some value:
amount += amountToIncrease;
if (amount > full) amount = 0; // restart
}
draw();
// Every second we'll fill more;
setInterval(draw, 1000);
http://jsfiddle.net/simonsarris/pby9r/
This is a little more dynamic, object-oriented version, so you can configure the options as the circle radius, border width, colors, duration and step of animation, you can also animate the circle to a certain percentage. It was quite fun to write this.
<canvas id="Circle" width="300" height="300"></canvas>
<script>
function Animation( opt ) {
var context = opt.canvas.getContext("2d");
var handle = 0;
var current = 0;
var percent = 0;
this.start = function( percentage ) {
percent = percentage;
// start the interval
handle = setInterval( draw, opt.interval );
}
// fill the background color
context.fillStyle = opt.backcolor;
context.fillRect( 0, 0, opt.width, opt.height );
// draw a circle
context.arc( opt.width / 2, opt.height / 2, opt.radius, 0, 2 * Math.PI, false );
context.lineWidth = opt.linewidth;
context.strokeStyle = opt.circlecolor;
context.stroke();
function draw() {
// make a circular clipping region
context.beginPath();
context.arc( opt.width / 2, opt.height / 2, opt.radius-(opt.linewidth/2), 0, 2 * Math.PI, false );
context.clip();
// draw the current rectangle
var height = ((100-current)*opt.radius*2)/100 + (opt.height-(opt.radius*2))/2;
context.fillStyle = opt.fillcolor;
context.fillRect( 0, height, opt.width, opt.radius*2 );
// clear the interval when the animation is over
if ( current < percent ) current+=opt.step;
else clearInterval(handle);
}
}
// create the new object, add options, and start the animation with desired percentage
var canvas = document.getElementById("Circle");
new Animation({
'canvas': canvas,
'width': canvas.width,
'height': canvas.height,
'radius': 100,
'linewidth': 10,
'interval': 20,
'step': 1,
'backcolor': '#666',
'circlecolor': '#fff',
'fillcolor': '#339999'
}).start( 70 );
</script>

Draw HTML5 Canvas with different background color than text?

I am looking to draw a canvas circle with text, however I want the canvas background color to be different from the color of the text in the circle. my code below uses the same color for both background and text ..
<canvas id="circlecanvas" width="50" height="50"></canvas>
<script>
var canvas = document.getElementById("circlecanvas");
var context = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
context.arc(centerX, centerY, 25, 0, Math.PI * 2, false);
context.fillStyle ="#dbbd7a";
context.fill()
context.font = 'bold 20pt Calibri';
context.textAlign = 'center';
context.fillText('34', centerX, centerY);
</script>
Try this:
context.arc(centerX, centerY, 25, 0, Math.PI * 2, false);
context.fillStyle ="#dbbd7a";
context.fill()
context.font = 'bold 20pt Calibri';
context.textAlign = 'center';
context.fillStyle ="#ff0000"; // <-- Text colour here
context.fillText('34', centerX, centerY);
So, basically, set the context.fillStyle for the text.
as you asked in the comments, the solution for centering the text vertically
is adding this
context.textBaseline = 'middle';
to Cerbrus's answer

html 5 canvas shadow just one border

i am trying to apply a blur shadow to a circle, but the thing is i just want the outer edge to have this blur/shadow affect, how can i do that? currently, the shadow is applied to all the borders
oh by the way, i am trying to animate...so the endingAngle below is supposed to keep changing to go from 0% circle to full circle..anyway that question is how i can specify just one side of the circle to have blur applied to...thanks
context.shadowBlur = 20;
context.shadowColor = "rgb(0, 255 , 0)";
context.beginPath();
context.arc(295, 295, 175, 1.5 * Math.PI, endingAngle, false);
context.lineWidth = 20;
context.strokeStyle = 'red';
context.stroke();
context.restore();
This isn't usually something you'd use a shadow for. You're better off with a radial gradient.
For example:
http://jsfiddle.net/NEntS/
The code:
var rg = context.createRadialGradient(295, 295, 175, 295, 295, 175+20);
rg.addColorStop(0, 'rgba(0,255,0,1)');
rg.addColorStop(0.8, 'rgba(0,255,0,.2)');
rg.addColorStop(1, 'rgba(255,255,255,0)');
// draw gradient behind
context.strokeStyle = rg;
context.beginPath();
context.arc(295, 295, 185, 1.5 * Math.PI, 2, false);
context.lineWidth = 25;
context.stroke();
context.restore();
// now stroke the red
context.beginPath();
context.arc(295, 295, 175, 1.5 * Math.PI, 2, false);
context.lineWidth = 20;
context.strokeStyle = 'red';
context.stroke();
context.restore();​
I'm drawing an arc with a larger radius and line width that has a green-to-transparent gradient (from center to outer). That gives the same effect you want but only on the outside.
Have you tried
ctx.shadowOffsetX
ctx.shadowOffsetY
to position your shadow?
Reference MDN

Draw text on top of rectangle

I'm trying to draw some text in the corner of a rectangle but I just started off drawing text on a rectangle before tackling the positioning. I can't seem to draw a rectangle, fill it with a color and then draw text over it. Even if i draw the text first, then rectangle, then fill in those orders, the rectangle just seems to overlap the text.
This code will show text and rectangles with no fill
context.beginPath();
for (var i = 0; i < 8; i++) {
context.font = "18pt Arial";
context.fillText("blah", 0, 0 + (i * 50));
context.rect(30, 0 + (i * 50), 50, 50);
}
context.lineWidth = 0.1;
context.strokeStyle = "black";
context.stroke();
This code will show me the text and filled in rectangles but the text seems to appear below the rectangles.
context.beginPath();
for (var i = 0; i < 8; i++) {
context.font = "18pt Arial";
context.fillText("blah", 0, 0 + (i * 50));
context.rect(30, 0 + (i * 50), 50, 50);
}
context.fillStyle = "#33cc00";
context.fill();
context.lineWidth = 0.1;
context.strokeStyle = "black";
context.stroke();
Any ideas what I'm doing wrong?
Every paint operation on an HTML5 Canvas draws on top of and (in general) obliterates whatever was underneath. If you want text to draw on top of the rectangles, you must call fillText() after you call fill() for the rects you have created.
It doesn't matter what order drawing commands are added to the path, it is when the fill() occurs that determines when the instantly-drying ink is applied. Since you do this after all your fillText() calls, the rectangles are drawn on top.
I would modify your code like this:
context.font = "18pt Arial";
context.strokeStyle = "#000";
context.lineWidth = 0.1;
for (var i=0; i<8; i++) {
context.fillStyle = "#3c0";
context.fillRect(30, 0 + (i * 50), 50, 50);
context.strokeRect(30, 0 + (i * 50), 50, 50);
context.fillStyle = "#fff";
context.fillText("blah", 0, 0 + (i * 50));
}
Alternatively, if you don't want to use fillRect()/strokeRect():
context.font = "18pt Arial";
context.strokeStyle = "#000";
context.lineWidth = 0.1;
for (var i=0; i<8; i++) {
context.beginPath();
context.fillStyle = "#3c0";
context.rect(30, 0 + (i * 50), 50, 50);
context.fill();
context.stroke();
context.fillStyle = "#fff";
context.fillText("blah", 0, 0 + (i * 50));
}