Trying to make 2 happy/sad faces with canvas - javascript

I'm currently trying to make 1 happy face and 1 sad face with canvas but the problem is I can't get 2 faces to appear, only one.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Site's Title</title>
</head>
<body>
<canvas id="myDrawing" width="800" height="200" style="border:1px solid #EEE">
</canvas>
<script>
var canvas = document.getElementById("myDrawing");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0;
var endAngle = 2 * Math.PI;
function drawFace() {
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.stroke();
ctx.fillStyle = "yellow";
ctx.fill();
}
function drawSmile(){
var x = canvas.width / 2;
var y = 150
var radius = 40;
var startAngle = 1.1 * Math.PI;
var endAngle = 1.9 * Math.PI;
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.lineWidth = 7;
// line color
ctx.strokeStyle = 'black';
ctx.stroke();
}
function drawEyes(){
var centerX = 40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
//left eye
var centerX = -40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
}
drawFace()
function drawHappyFace(){
drawFace();
drawEyes();
drawSmile();
}
drawHappyFace();
// SECOND FACE - HAPPY FACE
<canvas id="canvas" width="200" height="200" style="border:1px solid #EEE">
</canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0;
var endAngle = 2 * Math.PI;
function drawFace() {
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.stroke();
ctx.fillStyle = "yellow";
ctx.fill();
}
function drawSmile(){
var x = canvas.width / 2;
var y = 150
var radius = 40;
var startAngle = 1.9 * Math.PI;
var endAngle = 1.1 * Math.PI;
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.lineWidth = 7;
// line color
ctx.strokeStyle = 'black';
ctx.stroke();
}
function drawEyes(){
var centerX = 40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
//left eye
var centerX = -40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
}
drawFace()
function drawHappyFace(){
drawFace();
drawEyes();
drawSmile();
}
drawHappyFace();
</script>
</body>
</html>
</body>
</html>
I cna only get one of the faces to appear at once, for some reason, but I want both at the same time!

you can't have multiple functions with the same name because the second one overrides (hides) the first one; doesn't matter if they are in the same <script> tag or not (they can even be in different files)
change the name of the functions for the second face if you are such a beginner, but you should provide arguments to the function which will let you choose between multiple canvases and shapes using single function
it can look like this:
http://jsfiddle.net/Y5rUH/2/

Related

How to reduce canvas stroke with animation

I am trying to add some animation on changing the endAngle of a canvas arc like this but it is not working. How can I do this?
var steps =30;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.5 * Math.PI;
var endAngle = 1.4999 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
context.strokeStyle = 'black';
context.stroke();
setTimeout(function(){
endAngle = endAngle - 1;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.stroke();
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="250" height="250"></canvas>
new answer
Whenever you draw something on the canvas it doesn't erase what was previously drawn on it. You have to do that manually like this:
context.fillStyle="#ffffff";
context.fillRect(0,0,250,250);
//draw here
full solution:
<html>
<body>
<canvas id="myCanvas" width="250" height="250"></canvas>
<script language=javascript>
var steps =30;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.5 * Math.PI;
var endAngle = 1.49 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
context.strokeStyle = 'black';
context.stroke();
setInterval(function(){
context.fillStyle="#ffffff";
context.fillRect(0,0,250,250);
endAngle = endAngle - 0.01;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.stroke();
}, 10);
</script>
</body>
</html>
old answer
Well there are a few things. You've got your clockwise and counterclockwise mixed up causing the circle to be completely full before your "animation" starts.
if you want it clockwise then put the end angle ahead like this:
var startAngle = 1.5 * Math.PI;
var endAngle = 1.51 * Math.PI;
And then increase the angle in your animation timeout instead of decrease:
endAngle = endAngle+1;
and finally, your timeout should be an interval, not a timeout. The timeout will only run once. simple as changing it to
setInterval(function(){...
You also don't need jquery for this code by the way.

HTML 5 Canvas, rotate everything

I made a cylinder gauge, very similar to this one:
It is drawn using about 7 or so functions... mine is a little different. It is very fleixble in that I can set the colors, transparency, height, width, whether there is % text shown and a host of other options. But now I have a need for the same thing, but all rotated 90 deg so that I can set the height long and the width low to generate something more like this:
I found ctx.rotate, but no mater where it goes all the shapes fall apart.. ctx.save/restore appears to do nothing, I tried putting that in each shape drawing function. I tried modifying, for example, the drawOval function so that it would first rotate the canvas if horizontal was set to one; but it appeared to rotate it every single iteration, even with save/restore... so the top cylinder would rotate and the bottom would rotate twice or something. Very tough to tell what is really happening. What am I doing wrong? I don't want to duplicate all this code and spend hours customizing it, just to produce something I already have but turned horizontal. Erg! Help.
Option 1
To rotate everything just apply a transform to the element itself:
canvas.style.transform = "rotate(90deg)"; // or -90 depending on need
canvas.style.webkitTransform = "rotate(90deg)";
Option 2
Rotate context before drawing anything and before using any save(). Unlike the CSS version you will first need to translate to center, then rotate, and finally translate back.
You will need to make sure width and height of canvas is swapped before this is performed.
ctx.translate(ctx.canvas.width * 0.5, ctx.canvas.height * 0.5); // center
ctx.rotate(Math.PI * 0.5); // 90°
ctx.translate(-ctx.canvas.width * 0.5, -ctx.canvas.height * 0.5);
And of course, as an option 3, you can recalculate all your values to go along the other axis.
Look at the rotate function in this example. You want to do a translation to the point you want to rotate around.
example1();
example2();
function rotate(ctx, degrees, x, y, fn) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(degrees * (Math.PI / 180));
fn();
ctx.restore();
}
function rad(deg) {
return deg * (Math.PI / 180);
}
function example2() {
var can = document.getElementById("can2");
var ctx = can.getContext('2d');
var w = can.width;
var h = can.height;
function drawBattery() {
var percent = 60;
ctx.beginPath();
ctx.arc(35,50, 25,0,rad(360));
ctx.moveTo(35+percent+25,50);
ctx.arc(35+percent,50,25,0,rad(360));
ctx.stroke();
ctx.beginPath();
ctx.fillStyle = "rgba(0,255,0,.5)";
ctx.arc(35,50,25,0,rad(360));
ctx.arc(35+percent,50,25,0,rad(360));
ctx.rect(35,25,percent,50);
ctx.fill();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "#666666";
ctx.moveTo(135,25);
ctx.arc(135,50,25, rad(270), rad(269.9999));
//ctx.moveTo(35,75);
ctx.arc(35,50,25,rad(270),rad(90), true);
ctx.lineTo(135,75);
ctx.stroke();
}
drawBattery();
can = document.getElementById("can3");
ctx = can.getContext('2d');
w = can.width;
h = can.height;
rotate(ctx, -90, 0, h, drawBattery);
}
function example1() {
var can = document.getElementById('can');
var ctx = can.getContext('2d');
var color1 = "#FFFFFF";
var color2 = "#FFFF00";
var color3 = "rgba(0,155,255,.5)"
var text = 0;
function fillBox() {
ctx.save();
ctx.fillStyle = color3;
ctx.fillRect(0, 0, can.width / 2, can.height);
ctx.restore();
}
function drawBox() {
ctx.save();
ctx.beginPath();
ctx.strokeStyle = ctx.fillStyle = color1;
ctx.rect(10, 10, 50, 180);
ctx.font = "30px Arial";
ctx.fillText(text, 25, 45);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = color2;
ctx.lineWidth = 10;
ctx.moveTo(10, 10);
ctx.lineTo(60, 10);
ctx.stroke();
ctx.restore();
}
fillBox();
rotate(ctx, 90, can.width, 0, fillBox);
text = "A";
drawBox();
color1 = "#00FFFF";
color2 = "#FF00FF";
text = "B";
rotate(ctx, 90, can.width, 0, drawBox);
centerRotatedBox()
function centerRotatedBox() {
ctx.translate(can.width / 2, can.height / 2);
for (var i = 0; i <= 90; i += 10) {
var radians = i * (Math.PI / 180);
ctx.save();
ctx.rotate(radians);
ctx.beginPath();
ctx.strokeStyle = "#333333";
ctx.rect(0, 0, 50, 50)
ctx.stroke();
ctx.restore();
}
}
}
#can,
#can2,
#can3 {
border: 1px solid #333333
}
<canvas id="can" width="200" height="200"></canvas>
<canvas id="can2" width="200" height="100"></canvas>
<canvas id="can3" width="100" height="200"></canvas>

Draw vertical line between circles in canvas

I want draw a vertical line between circles in my project.
and these are my codes:
html:
<div id="ways" style="width:1000px;margin:0 auto;height:100%;">
<div id="row1">
<div id="col11" class="r1"><canvas id="col111" width="578" height="200"></canvas></div>
<div id="col12" class="r1"><canvas id="col112" width="578" height="200"></canvas></div>
<div id="col13" class="r1"><canvas id="col113" width="578" height="200"></canvas></div>
</div>
<div id="row2">
<div id="col21" class="r1"><canvas id="col221" width="578" height="200"></canvas></div>
<div id="col22" class="r1"><canvas id="col222" width="578" height="200"></canvas></div>
<div id="col23" class="r1"><canvas id="col223" width="578" height="200"></canvas></div>
</div>
<div id="row3">
<div id="col31" class="r1"><canvas id="col331" width="578" height="200"></canvas></div>
<div id="col32" class="r1"><canvas id="col332" width="578" height="200"></canvas></div>
<div id="col33" class="r1"><canvas id="col333" width="578" height="200"></canvas></div>
</div>
</div>
and theses are js code:
var canvas = document.getElementById('col111');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
var canvas = document.getElementById('col112');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
var canvas = document.getElementById('col113');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
var canvas = document.getElementById('col221');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
var canvas = document.getElementById('col222');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
var canvas = document.getElementById('col223');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
How I can draw a vertical line between circles? when I tried to do this become this image:
and this is my js code:
var canvas = document.getElementById('col221');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(290, -100);
context.lineTo(290, 80);
context.stroke();
please help for this problem!
thank u!
I'm not sure why you're opting to use multiple canvases but I have implemented a more generic solution in my fiddle here.
It uses two loops defined as:
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
...
}
}
This makes it more flexible as you can specify the rows and columns in the script. The rest is just knowing what your offsets are!
The code to implement the circle is largely untouched, but the fun is when to draw a line:
if (j != cols - 1) {
// Draw horizontal line
var hLineX = x + radius;
var hLineY = y;
context.moveTo(hLineX, hLineY);
context.lineTo(hLineX + distance + lineWidth, hLineY);
}
if (i > 0) {
// Draw vertical line
var vLineY = y - radius - distance - lineWidth;
context.moveTo(x, vLineY);
context.lineTo(x, vLineY + distance + lineWidth);
}
All this is saying is that you should draw a horizontal line on every column except for the last one. This works pretty well, even when you have one row by one column. You also want to draw a vertical line when there is more than one row, and offset it so it looks like it joins onto the previous row.
EDIT: Noticed you have different x and y distances, so I modified the fiddle to account for this.

Adding alert to canvas faces

I'm currently trying to make so that when you click on one of the happy face you get an alert box which says "thanks for the feed back", but I'm currently not sure to to incoperate that in tho my code! Thanks! Here is the fiddle http://jsfiddle.net/bsjs9/
<html lang="en">
<head>
<meta charset="utf-8" />
<title>SmileMore</title>
</head>
<body>
<h1>
Bring your Charts to life with HTML5 Canvas</h1>
</hgroup>
<p>
Rendering Dynamic charts in JS
</p>
<div class="smile">
<canvas id="myDrawing" width="200" height="200" style="border:1px solid #EEE"></canvas>
<canvas id="canvas" width="200" height="200" style="border:1px solid #EEE"></canvas>
</div>
<script>
var FacePainter = function(canvasName)
{
var canvas = document.getElementById(canvasName);
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 0;
var endAngle = 2 * Math.PI;
function drawFace() {
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.stroke();
ctx.fillStyle = "yellow";
ctx.fill();
}
function drawSmile(startAngle, endAngle)
{
var x = canvas.width / 2;
var y = 150;
var radius = 40;
ctx.beginPath();
ctx.arc(x, y, radius, startAngle * Math.PI, endAngle * Math.PI);
ctx.lineWidth = 7;
// line color
ctx.strokeStyle = 'black';
ctx.stroke();
}
function drawEyes() {
var centerX = 40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
//left eye
var centerX = -40;
var centerY = 0;
var radius = 10;
// save state
ctx.save();
// translate context so height is 1/3'rd from top of enclosing circle
ctx.translate(canvas.width / 2, canvas.height / 3);
// scale context horizontally by 50%
ctx.scale(.5, 1);
// draw circle which will be stretched into an oval
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// restore to original state
ctx.restore();
// apply styling
ctx.fillStyle = 'black';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'black';
ctx.stroke();
}
this.drawHappyFace = function() {
drawFace();
drawEyes();
drawSmile(1.1, 1.9);
}
this.drawSadFace = function() {
drawFace();
drawEyes();
drawSmile(1.9, 1.1);
;
}
}
new FacePainter('canvas').drawHappyFace();
new FacePainter('myDrawing').drawSadFace();
</script>
</body>
</html>
</body>
</html>
As an extra assignment I would like to know if anyone knows how to fix the "happy" smile, its kinda way off! Thanks all!
Since you draw the happy face on its own canvas, you can simple put an onclick handler on the canvas.
<canvas id="myDrawing" width="200" height="200" style="border:1px solid #EEE" onclick="alert('thanks');"></canvas>
Regarding the smiles, I added a new ofsy parameter to drawSmile, which offsets the arc origin vertically.
Here is the updated fiddle.
If you only want to show the alert, when the user clicks inside the face, you need to get the click coordinates and hittest it against the circle. You can see this in this fiddle.

building a color wheel in html5

I am just learning some details about html5 canvas, and in the progress, I am trying to build a simple color wheel by wedges (build a 1 degree wedge at a time and add it up to 360 degree). However, I am getting some weird marks on the gradient as shown in the following image:
.
Here is the fiddle that produced the colorwheel: http://jsfiddle.net/53JBM/
In particular, this is the JS code:
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 100;
var counterClockwise = false;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-1)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.closePath();
context.fillStyle = 'hsl('+angle+', 100%, 50%)';
context.fill();
}
If anyone can point out what I am doing wrong or if there is a better way to accomplish what I am attempting to do it would be much appreciated :)
Is this enough to you, please check
var startAngle = (angle-2)*Math.PI/180;
Try this it looks great.
Thanks by the way this is exactly what I was trying to make.
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 100;
var counterClockwise = false;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-2)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.closePath();
var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
gradient.addColorStop(0,'hsl('+angle+', 10%, 100%)');
gradient.addColorStop(1,'hsl('+angle+', 100%, 50%)');
context.fillStyle = gradient;
context.fill();
}
<body>
<canvas id="picker"></canvas>
</body>
Similar approach, just for the color
var canvas = document.getElementById("picker");
var context = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 50;
var thickness = 0.6;
for(var angle=0; angle<=360; angle+=1){
var startAngle = (angle-2)*Math.PI/180;
var endAngle = angle * Math.PI/180;
context.beginPath();
context.arc(x, y, (1-thickness/2)*radius, startAngle, endAngle, false);
context.lineWidth = thickness*radius;
context.strokeStyle = 'hsl('+angle+', 100%, 50%)';
context.stroke();
}
<body>
<canvas id="picker"></canvas>
</body>
Edit: full project here: https://github.com/dersimn/jquery-colorwheel

Categories

Resources