I'm dabbling with html5 and javascript (I know nothing of both). I found an example of some html5, copied it, and started experimenting. Heres some code. The idea is that when any key is pressed, two squares start moving left (doesn't clean up behind it yet). What I don't understand is why I cant change colour (Ive indicated below). Any ideas? Im obviously doing something very wrong.
<!doctype html>
<!-- this source copied from http://www.xanthir.com/blog/b48B0 -->
<canvas width=800 height=800>
</canvas>
<script>
var canvas = document.getElementsByTagName("canvas")[0];
var context = canvas.getContext('2d');
var x = 230;
var y = 380;
// First, we'll paint the whole canvas black.
context.fillStyle = "black";
context.fillRect(0,0,800,800);
context.fillStyle = "red";
context.fillRect(0,0,30,30);
context.fillRect(0,100,30,30);
context.fillStyle = "green";
context.fillRect(0,200,30,30);
// Now we'll draw some shapes
// circle
context.fillStyle = "#06c";
context.strokeStyle = "white";
// These can be any CSS color.
context.lineWidth = 3;
context.beginPath();
context.moveTo(450,250);
context.arc(375,250,75,0,2*Math.PI,false)
context.closePath();
context.fill();
context.stroke();
// A triangle! And a rainbow!
context.beginPath();
context.moveTo(150,50);
context.lineTo(90,150);
context.lineTo(210,150);
context.lineTo(150,50);
context.closePath();
var rainbow = context.createLinearGradient(150,50,150,150);
rainbow.addColorStop(.1,"red");
rainbow.addColorStop(.3,"orange");
rainbow.addColorStop(.5,"yellow");
rainbow.addColorStop(.7,"lime");
rainbow.addColorStop(.9,"blue");
context.fillStyle = rainbow;
context.fill();
// Some text! And a shadow!
context.shadowOffsetX = -2;
context.shadowOffsetY = 2;
context.shadowColor = "#f88";
context.shadowBlur = .01;
context.fillStyle = "red";
context.font = "bold 72px monospace";
context.fillText("Foo Bar",30,400);
context.fillStyle = "blue";
context.fillRect(0,300,30,30);
// ???????????? end of main. The current context now seems to remain (blue fillstyle with some shadow )
// routine here : press any key to animate two new blocks over writing ----------------
document.onkeydown = function(e) {
context.fillstyle = "red"; // <-- ???????? this doesnt work (remains same colour as last one in main )
context.fillRect(x,y,50,50); // <-- ???????? draws a square in blue, not red
x = x - 5;
context.fillstyle = "white"; // <-- ???????? this doesnt work (remains same colour as last one in main )
context.fillRect(x -100,y ,50,50); // <-- ???????? draws a square in blue, not white
}
Because you wrote fillstyle and not fillStyle. You need to capitalize the S.
It is valid in Javascript because you are just attaching a new fillstyle field (which does not exist and is meaningless) to that context.
So you gotta be careful. Typos can cause lots of trouble, because the resulting code isn't technically an error, but its certainly not what you want!
Related
I'm trying to make a fade out effect with JavaScript on the Canvas element. I'm currently have two sollutions for this. In theory, both should work fine, but in practice, only one does, and I wonder why.
The not working code is the following:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = 1;
requestAnimationFrame(test);
function test(){
i-=0.01;
ctx.fillStyle = "white";
ctx.fillRect(20, 20, 75, 50);
ctx.globalAlpha = i;
ctx.fillStyle = "red";
ctx.fillRect(20, 20, 75, 50);
requestAnimationFrame(test);
}
What I wanted to achieve, is to gradually change the alpha value of the current context, in order to fade it to white. After a while, it should have full transparency, but it does not. It stops right before reaching that state. Here it is in JSFiddle: https://jsfiddle.net/bq75v1mm/
The working code is the following:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = 1;
requestAnimationFrame(test);
function test(){
i-=0.01;
ctx.fillStyle = "white";
ctx.fillRect(20, 20, 75, 50);
ctx.fillStyle = "rgba("+255+","+0+","+0+","+i+")";
ctx.fillRect(20, 20, 75, 50);
requestAnimationFrame(test);
}
With this code, I'm just simply changing the alpha value of the given fillStyle for the upcoming rectangle, and it works like a charm, and makes the square vanish into thin air. Here it is in JSFiddle: https://jsfiddle.net/mxtynwwd/
I would like to understand why doesn't the first sollution work? Why can't I lower the globalAlpha value after a given minimum? Or is the problem in the code?
In your second example, you reset fillStyle every time before drawing the white rectangle.
You're not doing the same with globalAlpha in your first example.
Not all values will be accepted by the globalAlpha property. Quoting MDN:
A number between 0.0 (fully transparent) and 1.0 (fully opaque). The default value is 1.0 Values outside the range, including Infinity and NaN will not be set and globalAlpha will retain its previous value.
Due to precision loss in floating pointer math, when i becomes negative, globalAlpha gets stuck on 0.009999999999999247 (may vary across machines).
To fix both of the above, reset globalAlpha before drawing the white rectangle:
ctx.globalAlpha = 1;
and before drawing the red one, make sure i is >= 0:
i = i < 0 ? 0 : i;
Your first example can accordingly be updated to behave exactly like your second one:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var i = 1;
requestAnimationFrame(test);
function test() {
i -= 0.01;
i = i < 0 ? 0 : i;
ctx.globalAlpha = 1;
ctx.fillStyle = "white";
ctx.fillRect(20, 20, 75, 50);
ctx.globalAlpha = i;
ctx.fillStyle = "red";
ctx.fillRect(20, 20, 75, 50);
requestAnimationFrame(test);
}
[ Updated fiddle ]
context.font = '20pt Calibri';
context.fillStyle = 'rgba(225,225,225,0.5)';
var width = context.measureText(message2).width;
context.fillRect(xIndent, yIndent+100, width, 60);
context.fillStyle = 'rgba(255,85,0,1.0)';
context.fillText(message3, xIndent, yIndent+100);
I want the context.fillText to have no transparency and the context.fillRect to have some transparency
For some reason, I can make both transparent or both opague
The result is both TEXT and Background color are of the same transparency
You need to reset everything after the first text is written. Because you can set fillStyle after you have drawn or written something, it will still fill it. So, if you want to have to things drawn or written after each other you need to reset everything, so that the next fillStyle doesn't change it's fillStyle too. You need to use context.beginPath() after you have wriite the first text. Here is your code corrected :
context.font = '20pt Calibri';
context.fillStyle = 'rgba(225,225,225,0.5)';
var width = context.measureText(message2).width;
context.fillRect(xIndent, yIndent+100, width, 60);
context.beginPath();
context.fillStyle = 'rgba(255,85,0,1.0)';
context.fillText(message3, xIndent, yIndent+100);
It is best to use context.beginPath() each time you want to draw or write something else.... I hope this helped.....
I'm currently making a website, and have recently discovered the wonders of HTML5 canvas.
I have made a triangle using HTML5 canvas and JavaScript (simple, I know).
I will be placing a triangle after each section of the webpage to indicate the user should continue to scroll down. I will be using multiple triangles on the webpage, each in a different colour (yes, I spell it that way).
So, I want to make a function that uses an array of the canvas elements on the page to change the colour of each of the triangles. For example the first will be blue, the second red, and the third yellow.
Here is the code so far.
Problem: it does not work! Where have I gone wrong? Do you have a better solution? I am new to Stack Overflow.
// declare all global variables
var allCanvasElements = document.getElementsByClassName('canvas');
var canvasArrayLength = allCanvasElements.length;
function canvasLoop() {
// create canvas
var c = allCanvasElements[i];
var ctx = c.getContext("2d");
for (i = 0; i < canvasArrayLength; i++) {
// canvas code
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(60,0);
ctx.lineTo(30,30);
// selects current canvas, gives colour
if (c == allCanvasElements[i]) {
ctx.strokeStyle = "red";
ctx.fillStyle = "red";
}
// fills and strokes the canvas
ctx.fill();
ctx.stroke();
}
}
window.addEventListener("load", canvasLoop(), false);
literally just read through the code again after posting, and found that I was using using 'i' to find the current element in the canvas array before I had even declared the loop that uses 'i'. Silly me! A quick change, now it works just fine. Now, on to the rest of the Canvas elements! Here is the corrected code if you're interested -
// declare all global variables
var allCanvasElements = document.getElementsByClassName('canvas');
var canvasArrayLength = allCanvasElements.length;
function canvasLoop() {
// create canvas
var c = allCanvasElements[i];
var ctx = c.getContext("2d");
for (i = 0; i < canvasArrayLength; i++) {
// canvas code
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(60,0);
ctx.lineTo(30,30);
// selects current canvas, gives colour
if (c == allCanvasElements[i]) {
ctx.strokeStyle = "red";
ctx.fillStyle = "red";
}
// fills and strokes the canvas
ctx.fill();
ctx.stroke();
}
}
window.addEventListener("load", canvasLoop(), false);
I have this example in canvas. I would like to know how I can add text in shapes.
I have looked into the code that draws shapes but not really sure how to add text. I was able to add text but it doesn't move with balls?
function draw()
{
context.clearRect(0, 0, stageWidth, stageHeight);
var i = balls.length;
while(--i > -1)
{
context.fillStyle = balls[i].color;
context.beginPath();
context.arc(balls[i].x,balls[i].y,balls[i].size,0,Math.PI*2,true);
context.closePath();
context.fill();
}
}
You just have to use the ball's x and y value to make sure the text follow the ball, and use textAlign and textBaseline to easily align the text.
function draw()
{
context.clearRect(0, 0, stageWidth, stageHeight);
// Align once an for all.
context.textAlign = 'center'; // Set text align to center.
context.textBaseline = 'middle'; // Set text vertical align to middle.
var i = balls.length;
while(--i > -1)
{
context.fillStyle = balls[i].color;
context.beginPath();
context.arc(balls[i].x,balls[i].y,balls[i].size,0,Math.PI*2,true);
context.closePath();
context.fill();
// Easier to see the text.
context.fillStyle = 'black';
// Draw text `Ball # i` centered at position (x, y),
// with the width of the text equal to ball's size * 2.
context.fillText('Ball #' + i, balls[i].x ,balls[i].y, balls[i].size * 2);
}
}
See altered jsfiddle, is that what you want?
P.S : When playing with canvas, it's always best to keep HTML5 Canvas Cheat Sheet handy.
How I clean text from canvas shape ?
this my code:
<div id="ways" style="width:1000px;margin:0 auto;height:100%;">
<canvas id="canvas" width="1000" height="1000"></canvas>
and fiddle
Just refactor the code a bit -
Extract the lines which draws the circle into a single function which takes one of those circle objects as an argument:
function drawCircle(circle) {
context.beginPath();
context.arc(circle.x, circle.y, circle.radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = lineWidth;
context.strokeStyle = '#003300';
context.stroke();
}
Then replace those lines which they came from originally, in the loop with this line (after the circle object has been pushed):
drawCircle(circles[circles.length-1]); // draw last added circle
Now you can use this function in your click events by modifying the code (here, it toggles text on and off):
if (context.isPointInPath(x, y)) {
if (circle.clicked) {
drawCircle(circle); // now we can reuse this function to clear the text
circle.clicked = false;
}
else {
circle.clicked = true;
context.fillStyle = "blue";
context.font = "bold 34px Arial";
context.textAlign="center";
context.fillText("Yeah", circle.x, circle.y);
}
break;
}
Modified fiddle
Just a note with this approach: this will redraw the circles on top of each other. Over time the lines will start to look jaggy due to the added anti-aliasing on the edges. For this reason a full clear of the canvas is better, and then redraw them all. But I'll leave that as an exercise for you.. :-)