For one of my application i am creating circular time range selector widget.I have created the clock dial using html canvas.I need help to select time range by touch and drag on the dial as shown in the imageCircular clock dial. When clicked on the "Add" button, the previous selection should be cleared. Next time i should be able to set new range. this continues. The range value should be stored in a variable. It should work on the mobile device. Your help would be appreciated. http://codepen.io/harish_s/pen/ggpoBq
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = 180;
drawClock();
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.strokeStyle = "rgb(207,207,207)";
ctx.arc(0, 0, radius, 0, 2*Math.PI);
ctx.lineWidth = 60;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 150, 0, 2*Math.PI);
ctx.fillStyle = "rgb(243,244,244)";
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, 50, 0, 2*Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
ctx.font = '25pt Calibri';
ctx.fillStyle = 'white';
ctx.fillText('SET', -25, 10);
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius*0.20 + "px arial";
ctx.fillStyle = '#000';
ctx.textBaseline="middle";
ctx.textAlign="center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius*1);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius*1);
ctx.rotate(-ang);
}
}
#canvas{
position: absolute;
width: 50%;
left: 35%;
top:5%;
}
<canvas id="canvas" width="1000" height="500">
</canvas>
Related
In the W3 Schools HTML Canvas Clock drawing tutorial, the clock numbers are translated around the canvas using a static multiplier (.85, shown below).
ctx.translate(0, -radius*0.85);
If you didn't want to use the hardcoded/static .85 value to position the numeral, how would you find the correct position using Sin, or Cos, or other means?
I think here is the answer:
function drawNumerals() {
var numerals = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
angle = 0,
numeralWidth = 0;
numerals.forEach(function(numeral) {
angle = Math.PI/6 * (numeral-3);
numeralWidth = context.measureText(numeral).width;
context.fillText(numeral,
canvas.width/2 + Math.cos(angle)*(HAND_RADIUS) - numeralWidth/2,
canvas.height/2 + Math.sin(angle)*(HAND_RADIUS) + FONT_HEIGHT/3);
});
}
You just have to edit it to your needs.
I found it on Github Gist Draw circle with clock numbers
Seems to scale up correctly when i tried.
Are you removing or omitting the height attribute on the canvas element like this?
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas"
style="background-color:#333">
</canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
drawClock();
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2*Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius*0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius*0.1, 0, 2*Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius*0.15 + "px arial";
ctx.textBaseline="middle";
ctx.textAlign="center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius*0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius*0.85);
ctx.rotate(-ang);
}
}
</script>
</body>
</html>
The code determines the height it should use for the clock from the elements actual dimensions. If you dont constrain the height and width it will look wrong.
If you see you can double the size of the clock by modifying the height and width attributes of the canvas
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" height="800px" width="800px"
style="background-color:#333">
</canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
drawClock();
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2*Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius*0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius*0.1, 0, 2*Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius*0.15 + "px arial";
ctx.textBaseline="middle";
ctx.textAlign="center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius*0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius*0.85);
ctx.rotate(-ang);
}
}
</script>
</body>
</html>
I want to create a clock using HTML5, canvas and JavaScript.
However I don't understand why when I run the following code with Sublime I can't see anything. I tried to see something using both Internet Explorer and Google Chrome.
Maybe the error is in the code?
This is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Clock</title>
<!--<script src="clockJS.js" ></script>-->
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<img id="myImage" />
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.strokeStyle = '28d1fa';
ctx.linewidth = 17;
ctx.lineCap = "round";
ctx.shadowBlur = 15;
ctx.shadowColor = '28d1fa';
function degToRad(degree) {
var factor = Math.PI / 180;
return degree * factor;
}
function renderTime() {
var now = new Date();
var today = now.toDateString();
var time = today.toLocaleTimeString();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds();
var milliseconds = now.getMilliseconds();
var newSeconds = seconds + (milliseconds/1000);
//Background
gradient = ctx.createRadioGradient(250, 250, 5, 250, 250, 300);
gradient.addColorStop(0, '09303a');
gradient.addColorStop(1, 'black');
ctx.fillStyle = gradient;
//ctx.fillStyle = '333333';
ctx.fillRect(0, 0, 500, 500);
//Hours
ctx.beginPath();
ctx.arc(250, 250, 200, degToRad(270), degToRad((hours*15)-90));
ctx.stroke();
//Minutes
ctx.beginPath();
ctx.arc(250, 250, 170, degToRad(270), degToRad((minutes*6)-90));
ctx.stroke();
//Seconds
ctx.beginPath();
ctx.arc(250, 250, 140, degToRad(270), degToRad((newSeconds*6)-90));
ctx.stroke();
//Date
ctx.font = "23px Arial bold";
ctx.fillStyle = '28d1fa';
ctx.fillText(today, 175, 250);
//Time
ctx.font = "23px Arial";
ctx.fillStyle = '28d1fa';
ctx.fillText(time, 175, 280);
var dataUrl = canvas.toDataUrl();
document.getElementById('myImage').src = dataUrl;
}
setInterval(renderTime, 40);
</script>
</body>
</html>
Can someone help me?
Change this lines:
var time = today.toLocaleTimeString();
gradient = ctx.createRadioGradient(250, 250, 5, 250, 250, 300);
var dataUrl = canvas.toDataUrl();
To this:
var time = now.toLocaleTimeString();
gradient = ctx.createRadialGradient(250, 250, 5, 250, 250, 300);
var dataUrl = canvas.toDataURL();
That should get you something into the screen. I recommend you using Chrome's developer console to see all the JavaScript errors.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90
setInterval(drawClock, 1000);
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2*Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius*0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius*0.1, 0, 2*Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius*0.15 + "px arial";
ctx.textBaseline="middle";
ctx.textAlign="center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius*0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius*0.85);
ctx.rotate(-ang);
}
}
function drawTime(ctx, radius){
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
//hour
hour=hour%12;
hour=(hour*Math.PI/6)+
(minute*Math.PI/(6*60))+
(second*Math.PI/(360*60));
drawHand(ctx, hour, radius*0.5, radius*0.07);
//minute
minute=(minute*Math.PI/30)+(second*Math.PI/(30*60));
drawHand(ctx, minute, radius*0.8, radius*0.07);
// second
second=(second*Math.PI/30);
drawHand(ctx, second, radius*0.9, radius*0.02);
}
function drawHand(ctx, pos, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0,0);
ctx.rotate(pos);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.rotate(-pos);
}
<canvas id="canvas" width="400" height="400"
style="background-color:#333">
</canvas>
I am attempting to animate an emoticon that was previously drawn in canvas. I am attempting to do a draw and clear using frames following a tutorial but am not getting results. I have 6 frames of the emoticon coded and am unsure how to include this within the code. This is what I have so far:
<!DOCTYPE html>
<html>
<head>
<title>Adding Animation</title>
<style>
canvas {
border: 3px #CCC solid;
}
</style>
</head>
<body>
<div id="container">
<canvas id="myCanvas" height="1200" width="900"></canvas>
</div>
<script>
var mainCanvas = document.querySelector("#myCanvas");
var mainContext = mainCanvas.getContext("2d");
var canvasWidth = mainCanvas.width;
var canvasHeight = mainCanvas.height;
function drawCircle() {
mainContext.clearRect(0, 0, canvasWidth, canvasHeight);
// color in the background
mainContext.fillStyle = "#EEEEEE";
mainContext.fillRect(0, 0, canvasWidth, canvasHeight);
// draw the circle
ctx.beginPath();
ctx.strokeStyle = "000000";
ctx.lineWidth = 5;
ctx.fillStyle = "yellow";
ctx.arc(600, 450, 150, 0, Math.PI * 2, true);
ctx.stroke();
ctx.closePath();
ctx.fill();
//The smile
ctx.beginPath();
ctxstrokeStyle = "black";
ctx.lineWidth = 2;
ctx.arc(600, 475, 75, .1 * Math.PI, Math.PI * .9, false)
ctx.stroke();
ctx.closePath();
//The eyes
//Left
ctx.save();
ctx.scale(0.65, 1);
ctx.beginPath();
ctx.arc(850, 405, 40, 0 * Math.PI, Math.PI * 2, false);
ctx.fillStyle="black";
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
//Right
ctx.save();
ctx.scale(0.65, 1);
ctx.beginPath();
ctx.arc(1000,405,40, 0*Math.PI, Math.PI*2, false);
ctx.fillStyle="black";
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore()
}
drawCircle();
</script>
</body>
</html>
I am unsure if I am even on the right track as I have a difficult time with animation. Does anyone have any suggestions they can give me guidance on?
You have 2 names for the context: mainContext & ctx.
Change it to a single name and your face is "smiley" ! :-)
...
To animate:
Use a requestAnimationFrame loop to change the scaleY value in scale(scaleX,scaleY) over time.
Here's annotated code and a Demo:
var mainCanvas = document.querySelector("#myCanvas");
var ctx = mainCanvas.getContext("2d");
var canvasWidth = mainCanvas.width;
var canvasHeight = mainCanvas.height;
ctx.translate(-425,-275);
drawCircle(1);
// global var to hold pct the left eye is open
// 1==fully open, 0==fully closed
var scaley=1;
var direction=-1;
// request 1 animate() loop
requestAnimationFrame(animate);
function animate(time){
// draw smiley with the specified eye openness
drawCircle(scaley);
scaley+=.02*direction;
if(scaley<0){
scaley=0;
direction=1;
}
if(scaley>1){
scaley=1;
direction=-1;
}
requestAnimationFrame(animate);
}
function drawCircle(scaleY) {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// color in the background
ctx.fillStyle = "#EEEEEE";
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// draw the circle
ctx.beginPath();
ctx.strokeStyle = "000000";
ctx.lineWidth = 5;
ctx.fillStyle = "yellow";
ctx.arc(600, 450, 150, 0, Math.PI * 2, true);
ctx.stroke();
ctx.closePath();
ctx.fill();
//The smile
ctx.beginPath();
ctxstrokeStyle = "black";
ctx.lineWidth = 2;
ctx.arc(600, 475, 75, .1 * Math.PI, Math.PI * .9, false)
ctx.stroke();
//The eyes
//Left
ctx.save();
// move the [0,0] origin to the left eye's centerpoint
ctx.translate(550,405);
// close the left eye by the specified scaleY
ctx.scale(0.65, scaleY);
ctx.beginPath();
// draw the left eye (arc) at 0,0 because
// we translated the origin to [550,405] earlier
ctx.arc(0, 0, 40, 0 * Math.PI, Math.PI * 2, false);
ctx.fillStyle="black";
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
//Right
ctx.save();
ctx.scale(0.65, 1);
ctx.beginPath();
ctx.arc(1000,405,40, 0*Math.PI, Math.PI*2, false);
ctx.fillStyle="black";
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore()
}
<canvas id="myCanvas" height="1200" width="900"></canvas>
You never declared a ctx variable.
Change all your mainContext by ctx and it should be working fine.
I want to draw one circle and a character with shadow on a canvas in a HTML page while loading the page and recreate the image on a button click. I am using this code:
window.onload = function() {
draw();
};
function draw(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
var width = c.width;
var height = c.height;
//DRAW A CIRCLE
var centerX = Math.floor((Math.random() * width));
var centerY = Math.floor((Math.random() * height));
var radius = Math.floor(Math.random() * 50);
var color = '#f11';
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
//DRAW A CHARACTER WITH SHADOW
var c = "S";
ctx.font = "300% Verdana";
ctx.shadowBlur = 20;
ctx.shadowColor = "black";
ctx.shadowOffsetX = 20;
ctx.shadowOffsetY = 20;
ctx.fillStyle = "#111";
ctx.fillText(c, 10, 90);
}
In HTML I am calling draw function onclick() event of a button named Refresh.
For the first time it is giving desired output by drawing one circle and a character with shadow. As I click on the Refresh button it is drawing both the objects with shadow. I dont want to draw shadow of the circle. Can anyone please tell me the mistake I'm doing here.
You may want to use the CanvasRenderingContext2D.save() method :
window.onload = function() {
draw();
};
document.getElementById("canvas").addEventListener('click', draw);
function draw(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
var width = c.width;
var height = c.height;
//DRAW A CIRCLE
var centerX = Math.floor((Math.random() * width));
var centerY = Math.floor((Math.random() * height));
var radius = Math.floor(Math.random() * 50);
var color = '#f11';
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
//DRAW A CHARACTER WITH SHADOW
//save the actual context
ctx.save();
var c = "S";
ctx.font = "300% Verdana";
ctx.shadowBlur = 20;
ctx.shadowColor = "black";
ctx.shadowOffsetX = 20;
ctx.shadowOffsetY = 20;
ctx.fillStyle = "#111";
ctx.fillText(c, 10, 90);
//restore it
ctx.restore();
}
canvas{border:1px solid;}
<canvas id="canvas" width="400" height="200"></canvas>
The problem is demonstrated in the image below
In other words, how to exactly compute the x and y coordinates for every frame?
ctx.arc(x,y,radius,0,pi*2,false)
because after incrementing one coordinate, I have a problem how to compute the other
I tried this but doesn't work
var step=2,x=100,y=100,r=50,coordinates=[[x,y-r]];
for(var i=1;i <r;i+=step){
bx=x;
x+=step;
y=y-Math.sqrt(Math.pow(r,2)-Math.pow(bx-x,2))
coordinates[i]=[x,y];
}
a jsfiddle will be appreciated.
var canvas = document.querySelector("#c");
var ctx = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var speed = 10; // Lower is faster
function animate(t){
ctx.save();
ctx.clearRect (0 , 0 ,canvas.width ,canvas.height );
ctx.translate(canvas.width/2, canvas.height/2);
// First circle
ctx.beginPath();
ctx.arc(0, 0, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
// rotate + move along
ctx.rotate((t/speed)/100);
ctx.translate(100,0);
// Orbiting cirle
ctx.beginPath();
ctx.arc(0, 0, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
ctx.restore();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
canvas {
border: 1px solid black;
}
<canvas id="c" width="512" height="512"></canvas>