Heys guys,
I am testing some stuff out with the native accelometer on my android phone, I want to draw rectangles, which works but I want them to be a different color everytime one is drawn.
Thank you in advance :)
function onSuccess(acceleration) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.width = window.innerWidth;
context.height = window.innerHeight;
context.save();
context.beginPath();
context.rect(acceleration.x*10+150, acceleration.y*10+100, acceleration.z*10, acceleration.y*10);
context.fillStyle = '#FF0000';
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
context.restore();
}
function onError() {
alert('onError!');
}
fillStyle should have random color instead of '#FF0000'
You can use random color by Paul Irish
function onSuccess(acceleration) {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.width = window.innerWidth;
context.height = window.innerHeight;
context.save();
context.beginPath();
context.rect(acceleration.x * 10 + 150, acceleration.y * 10 + 100, acceleration.z * 10, acceleration.y * 10);
context.fillStyle = '#' + Math.floor(Math.random() * 16777215).toString(16);
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
context.restore();
}
function onError() {
alert('onError!');
}
Edit: As suggested by Morten Olsen, provided approach may fail sometimes, You can refer this SO answer
Just take a function for it.
function randomColor() {
var c = "#";
for (var i = 0; i < 6; i++) {
c += (Math.random() * 16 | 0).toString(16);
}
return c;
}
var a = document.getElementById("id1").style;
a.color = randomColor();
<h1 id="id1">stackoverflow</h1>
Assign a random color to fillStyle.
context.fillStyle = "#"+((1<<24)*Math.random()|0).toString(16);
From this post
Use this:
'#'+Math.floor(Math.random()*16777215).toString(16);
For more information: http://www.paulirish.com/2009/random-hex-color-code-snippets/
Related
I have a moving object and so it doesn't leave a trail behind I am using the clearRect(). However I can't remove everything in the canvas because that would remove my other object (which is the goal for the player to collect.)
var playerX = 350;
var playerY = 450;
function coin(posX, posY, width, height) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'gold';
ctx.fillRect(posX, posY, width, height); //this is what I don't want to clear
}
function player() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.fillStyle = "gray";
ctx.fillRect(playerX, playerY, 50, 50);
ctx.closePath();
}
function random(min, max) {
var x = Math.floor(Math.random() * max) + min;
return x;
}
function moveLeft() {
playerX -= 5;
player();
window.requestAnimationFrame(moveLeft);
}
function moveRight() {
playerX += 5;
player();
window.requestAnimationFrame(moveLeft);
}
player();
coin(random(5, 650), random(5, 250), 50, 50);
</script>
Any help would be greatly appreciated.
One thing you can try is make a single animation function that would call itself recursively.
function animate(){
canvas.clearRect()
// draw everything here
window.requestanimationframe(animate)
}
animate()
I want to change a line width but why all lines width in canvas is also changed?
Bellow is my code snippet
let c_canvas = document.getElementById("c");
let context = c_canvas.getContext("2d");
let gradientFill = context.createLinearGradient(400, 0, 95, 305);
gradientFill.addColorStop(0, "rgba(195, 42, 28, 1.000)");
gradientFill.addColorStop(0.6, "rgba(252, 239, 55, 1.000)");
gradientFill.addColorStop(1, "rgba(12, 151, 206, 1.000)");
context.fillStyle = gradientFill;
context.fillRect(0, 0, 500, 500);
context.beginPath();
for (let x = 0.5; x <= 501; x += 100) {
context.moveTo(x, 0);
context.lineTo(x, 500);
}
for (let y = 0.5; y <= 501; y += 100) {
context.moveTo(0, y);
context.lineTo(500, y);
}
context.lineWidth = 1;
context.stroke(); // Draw it
let frectx = 100;
let frecty = 450;
let lrectx = 250;
let lrecty = 340;
let radius = 15; // for example
let font = "bold " + radius + "px serif";
let text = "1";
let rand =[];
for(let i=0; i<5; i++)
{
rand[i] = Math.floor((Math.random() * 6) + 1);
}
rand.forEach(function(entry,i) {
text = i+1;
frectx = entry*70;
frecty = Math.floor((Math.random() * 9) + 1)*50;
context.moveTo(frectx, frecty);
context.lineTo(lrectx, lrecty);
context.lineWidth = 8;
context.strokeStyle = "#ddd";
context.stroke();
context.fillStyle = "white";
context.beginPath();
context.arc(frectx, frecty, 10, 0, 2 * Math.PI);
context.stroke();
context.closePath();
context.fill();
context.fillStyle = "black"; // font color to write the text with
context.font = font;
context.textBaseline = "top";
context.fillText(text, frectx - radius / 4, frecty - radius / 2);
context.fillStyle = "white";
context.beginPath();
context.arc(lrectx, lrecty, 10, 0, 2 * Math.PI);
context.stroke();
context.closePath();
context.fill();
context.fillStyle = "black"; // font color to write the text with
context.font = font;
context.textBaseline = "top";
context.fillText(text, lrectx - radius / 4, lrecty - radius / 2);
})
<canvas id="c" width="501px" height="501px"></canvas>
or you can see in jsfiddle:
https://jsfiddle.net/dyaskur/t4fgLs73/
How to only change width in that lines inside the box?
My second question is how to make my line and circle transform to glow/change color when i hover on it?
A context.beginPath() is missing between
context.lineWidth = 1;
context.stroke(); // Draw it
and
context.lineTo(lrectx, lrecty);
context.lineWidth = 8;
context.strokeStyle = "#ddd";
context.stroke();
Without the beginPath call you are simply re-stroking all or the paths and subpaths already defined with the new stroke style and width.
The general answer to the second part of your question is that you don't get to do this.
Painting a canvas is equivalent to drawing an image. You can work out where the mouse is over the image, but you would then need to work out (in your program) if the mouse is over some pixels you want to change and redraw the canvas if it is.
If you want to use CSS :hover pseudo classes to change presentation you will need to construct the source code of an SVG element for the graphic, create the element from the source code generated, and supply appropriate CSS for the SVG element's child nodes that will be affected by mouse position.
I'm using Canvas to play and learn with Javascript. Currently I'm creating a circle and have it display in random areas on the screen. I was able to complete that exercise completely; everything ran smoothly in one function.
Now I would like to create an object for the circle and call it in the for loop. I created the object, but something is still wrong. I'm only seeing one circle instead of 40. I banged my head on this for awhile before coming here for help. Take a look at the code below.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (!ctx) {
alert('HTML5 Canvas is not supported in you browser');
}
function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
this.posX = posX;
this.posY = posY;
this.radius = radius;
this.startAngle = startAngle;
this.endAngle = endAngle;
this.anticlockwise = anticlockwise;
this.test = function() {
ctx.beginPath();
ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
ctx.fill();
}
}
var cir = new Circle(
(Math.random() * canvas.width),
(Math.random() * canvas.height),
20,
0,
Math.PI*2,
true
);
function drawCircle() {
for(var i = 0; i < 40; i++){
cir.test();
}
}
/*setInterval(drawCircle, 400)*/
drawCircle();
You are calling cir.test() 40 times without having 40 instances of Circle. It is the same circle being drawn 40 times on top of itself.
This might be an immediate fix to your problem:
function drawCircle() {
for(var i = 0; i < 40; i++){
// Mind you that doing this
// Will not allow you to reference
// your circles after they are
// created. The best method is
// to put them in an array
// of circles
var cir = new Circle(
(Math.random() * canvas.width),
(Math.random() * canvas.height),
20,
0,
Math.PI*2,
true
);
cir.test();
}
}
/*setInterval(drawCircle, 400)*/
drawCircle();
However, I would recommend the following changes to your code:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (!ctx) {
alert('HTML5 Canvas is not supported in you browser');
}
function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
this.posX = posX;
this.posY = posY;
this.radius = radius;
this.startAngle = startAngle;
this.endAngle = endAngle;
this.anticlockwise = anticlockwise;
// Using better function names
// is always a good idea
this.testDraw = function() {
ctx.beginPath();
ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
ctx.fill();
}
}
// Create an array to fill
// with Circle instances
var circlesArray = []
// Changed drawCircle to drawCircles
// it is clearer
function drawCircles() {
for(var i = 0; i < 40; i++){
// Create new Circle objects
// and add them to the circlesArray
// this will allow you to have a
// each circle later on
circlesArray.push(new Circle(
(Math.random() * canvas.width),
(Math.random() * canvas.height),
20,
0,
Math.PI*2,
true
));
// Go through each item of the array
// and call the test function
circlesArray[i].testDraw();
}
}
/*setInterval(drawCircle, 400)*/
drawCircles();
Currently your drawCircle() function is running a single test function on the same 'cir' variable 40 times. What you want to do is to fill an array with 40 new items using the for-loop. Then, use another for-loop to define those items as new Circle objects and call the test function on each new circle.
Here is the code I would use:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (!ctx) {
alert('HTML5 Canvas is not supported in you browser');
}
function Circle(posX, posY, radius, startAngle, endAngle, anticlockwise) {
this.posX = posX;
this.posY = posY;
this.radius = radius;
this.startAngle = startAngle;
this.endAngle = endAngle;
this.anticlockwise = anticlockwise;
this.test = function() {
ctx.beginPath();
ctx.arc(posX, posY, radius, startAngle, endAngle, anticlockwise);
ctx.fill();
}
}
/*Create an array to hold your circles*/
var circleArray = [];
function drawCircle() {
for (var i = 0; i < 40; i++) {
circleArray.push('cirlce' + i); /*Push circle variable into circleArray*/
}
for (var i = 0; i < circleArray.length; i++) {
/*Create a new circle object for every iteration of the circleArray*/
circleArray[i] = new Circle(
(Math.random() * canvas.width), (Math.random() * canvas.height),
20,
0,
Math.PI * 2,
true
);
circleArray[i].test(); /*Run the test function for every item in the circle array*/
}
}
/*setInterval(drawCircle, 400)*/
drawCircle();
<canvas id='canvas'></canvas>
Please read the comments, if you need more help understanding this just comment below.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
if (!ctx) {
alert('HTML5 Canvas is not supported in you browser');
}
//The only thing I can see perhaps changing is radius so use radius as parameter
function Circle(radius) {
this.posX = Math.random() * canvas.width; //This is always going to be the same so no need to pass as an argument
this.posY = Math.random() * canvas.height; //So will this
this.test = function() {
ctx.beginPath();
ctx.arc(this.posX, this.posY, radius, 0, Math.PI*2, true); //So will Math.PI*2, and true
ctx.fill();
}
this.test();
}
function drawCircle() {
for(var i = 0; i < 40; i++){
new Circle(i); //This passes i as the radius so you can see the differences
}
}
drawCircle();
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>
I am trying to draw circles using a for loop. It works just fine accept it double draws the last circle.
See this jsfiddle for the example.
If I comment out the last
context.stroke();
in the second 'for' loop the circles display correctly. If I leave it in it double draws the last circle making it look bold.
What am I doing wrong?
Ken
The duplicate is caused by the extension lines you are drawing after the circles. Add a context.beginPath() call in the last for loop:
for(var j = 0; j < circle_Count + 1; j++) {
context.beginPath();
...
Working fiddle: http://jsfiddle.net/kwwqw5n2/3/
You have to close paths.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var box_Height = 50;
// Make Top Rect
context.fillStyle = "#F3E2A9";
context.fillRect(1, 1, canvas.width-1, box_Height-1);
context.strokeRect(0.5, 0.5, canvas.width-1, box_Height);
//Define the circles
var centerY = 25;
var radius = 10;
var circle_Count = 3;
var distance_Between = canvas.width / (circle_Count+1);
//Draw three white circles.
for(var i=0;i<circle_Count;i++){
context.beginPath();
context.arc(distance_Between * (i+1), centerY, radius, 0, 2 * Math.PI, true);
context.fillStyle = 'white';
context.lineWidth = 1;
context.strokeStyle = '#000000';
context.fill();
context.stroke();
context.closePath();
}
//Define the Extension Lines
var Ext_Line_Start_X = 0;
var Ext_Line_Start_Y = box_Height + 4; //The plus is the Gap
var Ext_Line_Length = 60;
//Draw Extension Lines
for(var j=0;j<circle_Count+1;j++){
context.beginPath();
context.moveTo(distance_Between * j + 0.5, Ext_Line_Start_Y);
context.lineTo(distance_Between * j + 0.5, Ext_Line_Start_Y + Ext_Line_Length);
context.stroke();
context.closePath();
}