Related
I'm creating a pixel art app and when I want to save the image from the canvas the image is so small, so it seems pixelated when I want to resize it.
I want to resize it to bigger dimensions, but I don't know how.
This is the code example:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(0, 0, 50, 50);
ctx.fillStyle = 'red';
ctx.fill();
document.write('<img style="width:300px;" src="'+c.toDataURL("image/png")+'"/>');
// This is an image with dimensions 108x108px and it seems very bad when i resize it to 300x300px
// I want to download the canvas image with more resolution
<canvas id="myCanvas" width="108" height="108" style="width: 300px; height:300px;">
</canvas>
you can create a canvas and put the imageData in it.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(0, 0, 25, 25);
ctx.fillStyle = 'red';
ctx.fill();
ctx.beginPath();
ctx.rect(0, 25, 25, 25);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.beginPath();
ctx.rect(25, 0, 25, 25);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.beginPath();
ctx.rect(25, 25, 25, 25);
ctx.fillStyle = 'green';
ctx.fill();
var c2 = document.createElement("canvas");
c2.width = 50;
c2.height = 50;
var ctx2 = c2.getContext("2d");
var imageData = ctx.getImageData(0, 0, 50, 50);
ctx2.putImageData(imageData, 0, 0);
document.write('<img style="width:300px;" src="' + c2.toDataURL("image/png") + '"/>');
//Selectors
canvas = document.querySelector('.canvas');
canvas.setAttribute("tabindex", 0);
canvas.focus();
pointerImg = document.querySelector('.pointer');
//Variables
const pi = Math.PI;
const c = canvas.getContext('2d');
var grid = {
'x':60,
'y':20,
'size':20,
}
var pointerValues = {
37: {'x':-1, 'y':0},
38: {'x':0, 'y':-1},
39: {'x':1, 'y':0},
40: {'x':0, 'y':1},
}
//Event Listeners
window.addEventListener('resize', function() {
//init();
})
var cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
//Functions
function init() {
resizeGrid();
initCells();
}
init();
function update(){
requestAnimationFrame(update)
}
update();
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function() {
this.draw();
}
this.draw = function() {
c.beginPath();
c.rect(this.x*this.size, this.y*this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle=this.color; c.fill();
c.closePath();
}
this.resetCell = function() {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
}
function resizeGrid() {
let windowX = window.innerWidth;
windowX -= windowX*0.1;
grid.size = windowX/grid.x;
let canvasX = windowX, canvasY = grid.y * grid.size;
canvas.width = canvasX;
canvas.height = canvasY;
}
function initCells() {
cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
for(let i=0;i<grid.x;i++) {
for(let j=0;j<grid.y;j++) {
cells[i][j] = new Cell(i, j, grid.size);
cells[i][j].update();
}
}
}
<html>
<head>
<link rel="stylesheet" href="assets/css/main.css">
<div style="display:none;">
<img class='pointer' src="assets/img/pointer.svg">
</div>
<div class='nav'>
</div>
</head>
<body>
<div class="content">
<canvas class='canvas'></canvas>
</div>
<script src='assets/js/canvas.js'></script>
</body>
</html>
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function () {
this.draw();
}
this.draw = function () {
c.beginPath();
c.rect(this.x * this.size, this.y * this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle = this.color;
c.fill();
c.closePath();
}
this.resetCell = function () {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
This is my code for a single cell in a grid. After I draw it a single time, when I call resetCell(), it draws the cell just a little bit bigger.
In this picture, I call Update for the very first cell and it becomes a tiny bit bigger than the rest.
I've tried pretty much everything but nothing seems to work.
Also can someone recommend better way to draw and control grid.
I need it to demonstrate BFS algorithm.
You were tricked by the thickness of the border
The border has a thickness, which is easy to forget. If you draw a box which is X wide, its left and right border are in addition to the width of X.
So if you do NOT fill the interior, you get this nice appearance (left), but if you FILL, you get this ugly appearance (right).
When you draw a grid of these squares, each one covers over the right-hand and bottom sides of previous squares, so that it is not obvious what is happening.
Unless you redraw one that is not the last of the list, as I have done here (bottom-middle). Then it becomes obvious that something is wrong.
Here is the code to reproduce the above figures, and below I recommend a solution.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// With NO fill, it looks fine
ctx.beginPath();
ctx.rect(40, 40, 40, 40);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.rect(80, 80, 40, 40);
ctx.stroke();
ctx.closePath();
// With white fill, the inner half of each box gets covered up by the white fill.
ctx.beginPath();
ctx.rect(140, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(180, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Make Grid. This part looks OK initially.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(240, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(240, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Redraw one: this will look messed up.
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="400" height="150" ></canvas>
</body>
</html>
Solution 1. Don't fill the interiors
This is the neatest solution, if you can get away with it, and it works regardless of any (non-zero) border thickness.
Solution 2. Shrink the width to allow for border thickness
This is complicated because you need to manually set the border thickness, and realise that it is in addition to the numerical values you specify for the rectangle's size.
Look at this messy business at CSS-tricks, even when they are trying to make borders interesting! https://css-tricks.com/almanac/properties/b/border/
Here I had a problem with my 2048 game that I am making in HTML and Javascript and I am having trouble again. This time, I am trying to make a for/in loop that can check to see if the squares to the left, right, top and bottom are filled. What I need is a way to refer to the numbers of the squares while still being able to refer to the properties of the objects. I am doing my best to explain what I am trying to do. I hope the comments in my code explain what each block does. Thank you for your help.
/*
Math.floor(Math.random()*(1-16+1)+1) <------
|
this code picks a random number between 1 and 16___|
switch ()
*/
//this function creates a method to create objects
function square(full, color, number) {
this.full = full;
this.color = color;
this.number = number;
}
//this block creates objects for each square
var sq1 = new square(true, "black", 2);
var sq2 = new square(false, "grey", 2);
var sq3 = new square(false, "grey", 2);
var sq4 = new square(false, "grey", 2);
var sq5 = new square(false, "grey", 2);
var sq6 = new square(false, "grey", 2);
var sq7 = new square(false, "grey", 2);
var sq8 = new square(false, "grey", 2);
var sq9 = new square(false, "grey", 2);
var sq10 = new square(false, "grey", 2);
var sq11 = new square(false, "grey", 2);
var sq12 = new square(false, "grey", 2);
var sq13 = new square(false, "grey", 2);
var sq14 = new square(false, "grey", 2);
var sq15 = new square(false, "grey", 2);
var sq16 = new square(false, "grey", 2);
//creates a board with the .full properties of the squares
board = [sq1.full, sq2.full, sq3.full, sq4.full, sq5.full, sq6.full, sq7.full, sq8.full, sq9.full, sq10.full, sq11.full, sq12.full, sq13.full, sq14.full, sq15.full, sq16.full];
//creates var sq_num to help check if items to left, up, right and down are full
var sq_num =
//this giant code block conducts all movement
function movement() {
document.addEventListener('keydown', function(event) {
/*for (sq_num in board)
{
if sq_num */
if (event.keyCode == 37) //left
{
if (sq4.full == true) {
sq4.color = sq1.color
sq4.color = "grey"
sq1.color = true
}
if (sq8.full == true) {
sq8.color = sq7.color
sq7.color = "black"
}
if (sq12.full == true) {
sq12.color = sq11.color
sq11.color = "black"
}
if (sq16.full == true) {
sq16.color = sq15.color
sq15.color = "black"
}
} else if (event.keyCode == 38) //up
{
sq13.color = sq9.color
sq9.color = "black"
sq14.color = sq10.color
sq10.color = "black"
sq15.color = sq11.color
sq11.color = "black"
sq16.color = sq12.color
sq12.color = "black"
} else if (event.keyCode == 39) //right
{
if (sq1.full == true) {
sq1.color = sq2.color
sq2.color = "black"
sp2.full = true
}
if (sq2.full == true) {
sq2.color = sq3.color
sq3.color = "black"
sq3.full = true
}
if (sq5.full == true) {
sq5.color = sq6.color
sq6.color = "black"
}
if (sq9.full == true) {
sq9.color = sq10.color
sq10.color = "black"
}
if (sq13.full = true) {
sq13.color = sq14.color
sq14.color = "black"
}
} else if (event.keyCode == 40) //down
{
sq1.color = sq5.color
sq5.color = "black"
sq2.color = sq6.color
sq6.color = "black"
sq3.color = sq7.color
sq7.color = "black"
sq4.color = sq8.color
sq8.color = "black"
}
})
};
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//this function draws each square where it should be in the formation of a board.
function draw() {
ctx.clearRect(0, 0, c.width, c.height); // clear the canvas so the old rectangles are gone
// board
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "grey";
ctx.rect(5, 5, 610, 610);
ctx.stroke();
// sq1
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq1.color;
ctx.fill();
//sq2
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq2.color;
ctx.fill();
//sq3
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq3.color;
ctx.fill();
//sq4
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 10, 150, 150);
ctx.stroke();
ctx.fillStyle = sq4.color;
ctx.fill();
//sq5
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq5.color;
ctx.fill();
//sq6
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq6.color;
ctx.fill();
//sq7
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq7.color;
ctx.fill();
//sq8
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 160, 150, 150);
ctx.stroke();
ctx.fillStyle = sq8.color;
ctx.fill();
//sq9
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq9.color;
ctx.fill();
//sq10
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq10.color;
ctx.fill();
//sq11
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq11.color;
ctx.fill();
//sq12
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 310, 150, 150);
ctx.stroke();
ctx.fillStyle = sq12.color;
ctx.fill();
//sq13
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(10, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq13.color;
ctx.fill();
//sq14
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(160, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq14.color;
ctx.fill();
//sq15
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(310, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq15.color;
ctx.fill();
//sq16
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "black";
ctx.rect(460, 460, 150, 150);
ctx.stroke();
ctx.fillStyle = sq16.color;
ctx.fill();
}
window.setInterval(draw, 100) // repeat game loop function forever, 10 times per second(that value is measured in ms)
body {
background-color: lightgrey;
}
<canvas id="myCanvas" width="620" height="620" style="border:1px solid #d3d3d"></canvas>
Basically I want to draw a slime from Dragon Quest (it looks like a water drop). I have done the following, but I'd like to know if there is a better way to do it. Maybe using Bezier curves or something like that?
Update:
I actually got everything to look like how I want it, except for the gradient for the glow spots (white)
Slime.prototype.drawEye = function(x,y,w,h)
{
ctx.save();
ctx.lineWidth = 3;
ctx.beginPath();
var c = [];
c.push("sclera");
//c.push("iris");
c.push("pupil");
var wScale = [1,2.2,3];
var hScale = [1,2,1.3];
for (var i = 0; i < c.length; i++)
{
w /= wScale[i];
h /= hScale[i];
ctx.beginPath();
ctx.ellipse(x,y,w,h,0,degreesToRadians(360),false);
ctx.fillStyle = this.colors[c[i]];
ctx.fill();
ctx.stroke();
}
ctx.restore();
}
Slime.prototype.drawMouth = function()
{
ctx.save();
ctx.beginPath();
var x = this.x+this.w/30;
var y = this.y+this.h/8;
var w = this.w;
var h = this.h/8;
var start = [x-w/3,y];
var end = [x+w/8,y+h/5];
// mouth
bezierCurve(start,[x-w/3.3,y+h*2.3],[x+w/8,y+h*1.8],end);
bezierCurveTo([x-w/10,y+h*0.6],[x-w/6,y+h*0.6],start);
ctx.lineCap = "round";
ctx.lineWidth = 8;
ctx.stroke();
ctx.clip();
ctx.fillStyle = this.colors["mouth"];
ctx.fill();
start = [x-w/3.5,y+h*1];
// tongue
ctx.beginPath();
bezierCurve(start,[x-w/5,y+h*2.5],[x+w/6.5,y+h*1.6],[x+w/9,y+h*0.75]);
bezierCurveTo([x+w/10,y+h/4],[x-w/5,y],start);
ctx.fillStyle = this.colors["tongue"];
ctx.fill();
//ctx.stroke();
ctx.restore();
}
Slime.prototype.drawHealthBar = function()
{
ctx.beginPath();
ctx.rect(this.x-this.w,this.y+this.h/2+30,this.w*2*this.health/this.maxHealth,20);
ctx.fillStyle = "#00ff00";
ctx.fill();
ctx.beginPath();
ctx.rect(this.x-this.w+(this.w*2*this.health/this.maxHealth),this.y+this.h/2+30,(this.maxHealth-this.health)/this.maxHealth*this.w*2,20);
ctx.fillStyle = "#ff0000";
ctx.fill();
ctx.beginPath();
ctx.rect(this.x-this.w,this.y+this.h/2+30,this.w*2,20);
ctx.strokeStyle = "#000000";
ctx.stroke();
}
Slime.prototype.drawBody = function()
{
ctx.save();
ctx.fillStyle = this.colors["body"];
ctx.beginPath();
var x = this.x;
var y = this.y+this.h*0.4;
var w = this.w/2;
var h = this.h;
var left = [x-w*0.97,this.y+h/11];
var bottom = [x,this.y+h*0.495];
var right = [x+w*0.97,this.y+h/15];
var top = [x+this.w/30,this.y-h/2+this.topOffset];
bezierCurve(left,[x-w,y+h/10],[x-w/7,y+h/12],bottom);
bezierCurveTo([x+w*0.8,y+h/10],[x+w*1.05,y-h/7],right);
y = this.y - (y - this.y);
bezierCurveTo([x+w*0.75,y+h/15],[x+w*0.2,y+h/4.5],top);
bezierCurveTo([x-w*0.2,y+h/5],[x-w*0.8,y+h/10],left);
ctx.lineWidth = 3;
ctx.fill();
ctx.strokeStyle = this.colors["bodyOutline"];
ctx.stroke();
ctx.clip();
ctx.shadowColor = "#000033";
ctx.shadowBlur = 40;
ctx.shadowOffsetX = ctx.shadowBlur/4;
ctx.shadowOffsetY = ctx.shadowOffsetX*-0.8;
ctx.lineWidth = 4;
for (var i = 0; i < 7; i++)
{
if (i%2==0)
{
ctx.shadowColor = "#000033";
}
else
{
ctx.shadowColor = "rgba(0,0,80,0.5)";
}
ctx.stroke();
}
ctx.restore();
}
Slime.prototype.drawGlow = function(x,y,r1,r2)
{
ctx.save();
var g = ctx.createRadialGradient(x,y,r1,x,y,r2);
g.addColorStop(0.0,"#ffffff");
g.addColorStop(1.0,this.colors["body"]);
ctx.beginPath();
ctx.arc(x,y,r2,0,degreesToRadians(360),false);
ctx.fillStyle = g;
ctx.fill();
ctx.restore();
}
Slime.prototype.draw = function()
{
ctx.lineWidth = 2;
this.drawBody();
this.drawMouth();
var w = this.w/10;
var h = this.h/10;
var x = this.x;
var y = this.y;
this.drawEye(x-this.w/4.5,y-h/2.5,w,h);
this.drawEye(this.x+this.w/13,y-h/10,w,h);
this.drawGlow(this.x-this.w/2.5,this.y+this.h/12,this.w/50,this.w/16);
this.drawGlow(this.x+this.w/2*0.7,this.y+this.h/10,this.w/50,this.w/16);
}
End update
Yes, you can draw the droplet outline using just 4 cubic Bezier curves.
Here's a proof-of-concept using just 4 C-Bez curves:
Why! Why! Why! .......... Did I enjoy creating a Slime Man??
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
drawDropletMan(20,20,'rgb(63,187,255)');
drawDropletMan(255,55,'rgb(255,180,155)');
function drawDropletMan(x,y,fill){
ctx.translate(x,y);
drawBody(fill);
circularGlow(158,111,3,18,fill);
circularGlow(32,107,3,18,fill);
eye(65,87,17,10);
eye(120,90,17,10);
mouth(33,130);
ctx.translate(-x,-y);
}
//
function drawBody(fillcolor){
ctx.save();
ctx.beginPath();
ctx.moveTo(109,0);
ctx.bezierCurveTo(111,64,199,35,198,123);
ctx.bezierCurveTo(199,139,183,192,99,190);
ctx.bezierCurveTo(66,193,-4,167,1,110);
ctx.bezierCurveTo(9,47,97,45,109,1);
ctx.fillStyle=fillcolor;
ctx.fill();
ctx.strokeStyle='black';
ctx.lineWidth=2;
ctx.stroke();
ctx.clip();
ctx.shadowColor='black';
ctx.shadowBlur=15;
ctx.lineWidth=1;
for(var i=0;i<8;i++){ctx.stroke();}
ctx.restore();
}
//
function circularGlow(x,y,r1,r2,fillcolor){
var g=ctx.createRadialGradient(x,y,r1,x,y,r2);
g.addColorStop(0.00,'white');
g.addColorStop(1.00,fillcolor);
ctx.beginPath();
ctx.arc(x,y,r2,0,Math.PI*2);
ctx.fillStyle=g;
ctx.fill();
}
//
function eye(x,y,r1,r2){
ctx.beginPath();
ctx.arc(x,y,r1,0,Math.PI*2);
ctx.fillStyle='white';
ctx.strokeStyle='black';
ctx.fill();
ctx.lineWidth=2;
ctx.stroke();
//
ctx.beginPath();
ctx.arc(x,y,r2,0,Math.PI*2);
ctx.fillStyle='black';
ctx.fill();
}
//
function mouth(){
ctx.save();
ctx.translate(5,5);
ctx.beginPath();
ctx.moveTo(44,120);
ctx.bezierCurveTo(56,136,112,132,128,123);
ctx.bezierCurveTo(138,123,143,123,132,138);
ctx.bezierCurveTo(113,165,49,169,39,127);
ctx.bezierCurveTo(41,128,32,122,44,120);
ctx.closePath();
ctx.fillStyle='black';
ctx.fill();
ctx.clip();
ctx.beginPath();
ctx.arc(90,200,56,0,Math.PI*2);
ctx.fillStyle='coral';
ctx.fill();
ctx.restore();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=500 height=300></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.