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>
Related
I am using canvas to draw a progress loader for a mobile application. The arc looks fuzzy in low resolution devices.
The android app is rendered using Web View. There is a significant difference in the canvas and the other normal text in the app which is not looking good on devices.
The code for creating the canvas goes as below:
function drawProgressBar(degrees) {
var canvas = document.getElementById('canvasProgress');
if (canvas) {
var ctx = canvas.getContext('2d');
var canvasWidth = canvas.width *.5;
var canvasHeight = canvas.height *.5;
var radians = 0;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// backgroud circle
ctx.beginPath();
ctx.strokeStyle = circleColor;
ctx.lineWidth = lineWidth;
ctx.shadowBlur = 5;
ctx.shadowColor = "#9fa0a4";
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 1;
ctx.arc(canvasHeight / 2, canvasWidth / 2, canvasWidth / 3, 0, Math.PI * 4, false);
ctx.imageSmoothingEnabled = true;
ctx.closePath();
ctx.stroke();
radians = degrees * Math.PI / 50;
// progressBar
ctx.beginPath();
ctx.strokeStyle = progressColor;
ctx.lineWidth = lineWidth;
ctx.arc(canvasHeight / 2, canvasWidth / 2, canvasWidth / 3, 0 - 90 * Math.PI / 180, radians - 90 * Math.PI / 180, false);
ctx.stroke();
// progress update text
ctx.fillStyle = "#333333";
ctx.font = '22pt headerCustomFont';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.textAlign = "center";
ctx.fillText('%', canvasWidth / 2 + 30, canvasHeight / 2 - 3);
var outputTextPerc = degrees;
if (degrees === 100) {
ctx.fillText(outputTextPerc, canvasWidth / 2 - 8, canvasHeight / 2 - 3);
} else {
ctx.fillText(outputTextPerc, canvasWidth / 2 - 4, canvasHeight / 2 - 3);
}
ctx.font = '12pt headerCustomFont';
ctx.fillText("Complete", canvasWidth / 2, canvasHeight / 2 + 28);
}
}
Please find the fiddle for the same: http://jsfiddle.net/8ayv5xdk/1/
What could be done to make the edges smooth
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">
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>
I am using canvas element to draw curve along with text. It is working fine in chrome, Firefox, IE 9. But in IE 8,7 this is not working. Showing the error like:
SCRIPT438: Object doesn't support property or method 'getContext'
I searched in Google then i found Excanvas.js will figure out this problem, but I am getting the same error.
Thank you.
<head><!--[if IE]><script src="js/excanvas.js"></script><![endif]--></head>
My html canvas code:
<canvas id="myCanvas" width="679" height="290"></canvas>
My js code:
function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
var len = str.length, s;
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / len) / 2);
for(var n = 0; n < len; n++) {
context.rotate(angle / len);
context.save();
context.translate(0, -1 * radius);
s = str[n];
context.fillText(s, 0, 0);
context.restore();
}
context.restore();
}
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d'),
centerX = canvas.width / 2,
centerY = canvas.height + 40,
angle = Math.PI * 0.8,
radius = 250;
context.font = 'bold 30pt Ubuntu';
context.textAlign = 'center';
context.fillStyle = 'orange';
context.strokeStyle = '#336699';
context.lineWidth = 10;
drawTextAlongArc(context, 'Sustainable Skill Solutions', centerX, centerY, radius, angle);
// draw circle underneath text
context.arc(centerX, centerY, radius +70, 0, 2 * Math.PI, false);
context.stroke();
You need to run your JS only when document is ready.
This may not be necessary for browsers supporting <canvas>, but for IE<9, excanvas.js works after document loaded, so you'll need to run your JS after that.
Change your JS to:
function drawTextAlongArc()
{
/* ... */
}
function onLoad()
{
var canvas=document.getElementById("myCanvas"),
context=canvas.getContext("2d");
/* ... */
}
if(window.addEventListener)
{
window.addEventListener("load",onLoad,false);
}
else if(window.attachEvent)
{
window.attachEvent("onload",onLoad);
}
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