How to make a scrolling starfield - javascript

I want to write a simple scrolling right to left starfield. I have printed out the stars randomly. Now, how do I target each star and randomly give it a speed (say 1-10) and begin moving it? I also need to put each star back on the right edge after it reaches the left edge.
Following is my code written so far:
<!DOCTYPE html>
<html>
<head>
<script>
function stars()
{
canvas = document.getElementById("can");
if(canvas.getContext)
{
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect (0, 0, 400, 400);
ctx.fill();
starfield();
}
}
//print random stars
function starfield()
{
for (i=0; i<10; i++)
{
var x = Math.floor(Math.random()*399);
var y = Math.floor(Math.random()*399);
var tempx = x;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
}
</script>
</head>
<body onload="stars()">
<h1>Stars</h1>
<canvas id="can" width="400" height="400"style="border:2px solid #000100" ></canvas>
</body >
</html>

Here's a quick demo on Codepen. After saving the stars in an array, I'm using requestAnimationFrame to run the drawing code and update the position on every frame.
function stars() {
canvas = document.getElementById("can");
console.log(canvas);
if (canvas.getContext) {
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect(0, 0, 400, 400);
ctx.fill();
starfield();
}
}
// Create random stars with random velocity.
var starList = []
function starfield() {
for (i = 0; i < 20; i++) {
var star = {
x: Math.floor(Math.random() * 399),
y: Math.floor(Math.random() * 399),
vx: Math.ceil(Math.random() * 10)
};
starList.push(star);
}
}
function run() {
// Register for the next frame
window.requestAnimationFrame(run);
// Reset the canvas
ctx.fillStyle = "black";
ctx.rect(0, 0, 400, 400);
ctx.fill();
// Update position and draw each star.
var star;
for(var i=0, j=starList.length; i<j; i++) {
star = starList[i];
star.x = (star.x - star.vx + 400) % 400;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(star.x, star.y, 3, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
stars();
run();

Put your x,y coordinates in an array, and then make a function that draws the array.
var stars = [
{x:110, y:80},
{x:120, y:20},
{x:130, y:60},
{x:140, y:40}
]
Then make a function to alter the x,y coordinates (for example increment y=y+1) each time before using the draw function.
Bonus:
This array solution allows you to have each star move at its own speed, you could store a delta (say 1 upto 3) in that array, and do y=y+delta instead. This looks 3D.
You could even go further and have a seperate x and y delta, and have stars fly out from the middle, which is even more 3D!
Or even simpler/faster could be to have the render function accept an x,y offset. It could then even wrap around, so that what falls off the screen on one side comes back on the other. It looks like you are rotating in space.

I simple way to imitate star movement towards a point(like a center) is simply divide both X and Y by Z coordinate.
nx = x / z
ny = y / z
And simply decrease z value as you iterate. As z is big, your points will be around a point and as z decreases the result will be bigger and bigger which imitates "moving" of a stars.

Just providing a solution which uses jQuery because using it you can get the output with lesser lines of code compared to complete canvas solution.It uses two canvas divs to get the desired output:
Check this fiddle
Little updated code from the code posted in the question
<script>
function stars(){
canvas = document.getElementById("can1");
canvasCopy = document.getElementById("can2");
if(canvas.getContext){
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.rect (0, 0, 400, 400);
ctx.fill();
starfield();
var destCtx = canvasCopy.getContext('2d');
destCtx.drawImage(canvas, 0, 0);
}
}
//print random stars
function starfield(){
for (i=0;i<10;i++){
var x = Math.floor(Math.random()*399);
var y = Math.floor(Math.random()*399);
var tempx = x;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
}
</script>
<body onload="stars()">
<h1>Stars</h1>
<div id="starBlocks">
<canvas id="can1" width="400" height="400"style="border:2px solid #000100" ></canvas>
<canvas id="can2" width="400" height="400"style="border:2px solid #000100" ></canvas>
</div>
</body >
jQuery
function playStars()
{
$('#starBlocks').animate({
scrollLeft : 400
},10000,'linear',function(){
$('#starBlocks').scrollLeft(0);
playStars();
});
}
playStars();
CSS
#starBlocks{
white-space:nowrap;
font-size:0px;
width:400px;
overflow:hidden;
}

Related

Canvas Javascript Looping

I'm trying to loop my animation, but no matter what I do, it won't loop. I'm pretty new to canvas, javascript and code in general.
var canvas = document.getElementById("fabrication");
var ctx = canvas.getContext("2d");
var background = new Image();
background.src =
"C:/Users/dylan/Desktop/ProjectTwo/Images/fabricationbackground.jpg";
background.onload = function(){
}
//Loading all of my canvas
var posi =[];
posi[1] = 20;
posi[2] = 20;
var dx=10;
var dy=10;
var ballRadius = 4;
//Variables for drawing a ball and it's movement
function drawballleft(){
posi =xy(posi[1],posi[2])
}
function xy(x,y){
ctx.drawImage(background,0,0);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#FFFFFFF";
ctx.fill();
ctx.closePath();
var newpos=[];
newpos[1]= x +dx;
newpos[2]= y +dy;
return newpos;
//Drawing the ball, making it move off canvas.
if (newpos[1] > canvas.width) {
newpos[1] = 20;
}
if (newpos[2] > canvas.height) {
newpos[2] = 20;
}
//If statement to detect if the ball moves off the canvas, to make it return to original spot
}
setInterval(drawballleft, 20);
//Looping the function
Please let me know if I've done something wrong, I really want to learn what I'm doing here. The ball is supposed to go off the canvas, and loop back onto itself, but it goes off the canvas and ends.
Thanks in advance!
I have made a few changes to your code.
First I am using requestAnimationFrame instead of setInterval. http://www.javascriptkit.com/javatutors/requestanimationframe.shtml
Second I am not using an image because I didn't want to run into a CORS issue. But you can put your background image back.
I simplified your posi array to use indexes 0 and 1 instead of 1 and 2 to clean up how you create your array.
I moved your return from before the two ifs to after so the ball will move back to the left or top when it goes off the side. I think that was the real problem you were seeing
var canvas = document.getElementById("fabrication");
var ctx = canvas.getContext("2d");
//Loading all of my canvas
var posi =[20,20];
var dx=10;
var dy=10;
var ballRadius = 4;
//Variables for drawing a ball and it's movement
function drawballleft(){
posi = xy(posi[0],posi[1])
requestAnimationFrame(drawballleft);
}
function xy(x,y){
ctx.fillStyle = '#FFF';
ctx.fillRect(0,0,400,300);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
var newpos=[x+dx,y+dy];
//Drawing the ball, making it move off canvas.
if (newpos[0] > canvas.width) {
newpos[0] = 20;
}
if (newpos[1] > canvas.height) {
newpos[1] = 20;
}
//If statement to detect if the ball moves off the canvas, to make it return to original spot
return newpos;
}
requestAnimationFrame(drawballleft);
canvas {
outline: 1px solid red;
}
<canvas width="400" height="300" id="fabrication"></canvas>
To make it all even simpler...
Use an external script for handling the canvas.
A really good one ;) :
https://github.com/GustavGenberg/handy-front-end#canvasjs
Include it with
<script type="text/javascript" src="https://gustavgenberg.github.io/handy-front-end/Canvas.js"></script>
Then it's this simple:
// Setup canvas
const canvas = new Canvas('my-canvas', 400, 300).start(function (ctx, handyObject, now) {
// init
handyObject.Ball = {};
handyObject.Ball.position = { x: 20, y: 20 };
handyObject.Ball.dx = 10;
handyObject.Ball.dy = 10;
handyObject.Ball.ballRadius = 4;
});
// Update loop, runs before draw loop
canvas.on('update', function (handyObject, delta, now) {
handyObject.Ball.position.x += handyObject.Ball.dx;
handyObject.Ball.position.y += handyObject.Ball.dy;
if(handyObject.Ball.position.x > canvas.width)
handyObject.Ball.position.x = 20;
if(handyObject.Ball.position.y > canvas.height)
handyObject.Ball.position.y = 20;
});
// Draw loop
canvas.on('draw', function (ctx, handyObject, delta, now) {
ctx.clear();
ctx.beginPath();
ctx.arc(handyObject.Ball.position.x, handyObject.Ball.position.y, handyObject.Ball.ballRadius, 0, Math.PI * 2);
ctx.fillStyle = '#000';
ctx.fill();
ctx.closePath();
});
I restructured your code and used the external script, and now it looks much cleaner and easier to read and toubleshoot!
JSFiddle: https://jsfiddle.net/n7osvt7y/

Trying to animate shapes in canvas, it shows up, but doesn't move

I'm trying to animate polygons made using lineTo in canvas. It shows up, but won't move. I tried to follow the object approach, but it didn't seem to do anything.
Help?
<!doctype html>
<html>
<head>
<style>
canvas {
border: 1px solid black;
}
</style>
<script>
"use strict";
var canvas;
var ctx;
var timer;
var shapes;
var x;
var y;
function degreesToRadians(degrees) {
return (degrees*Math.PI)/180;
}
//to rotate stuff, not currently in use
function rotateStuff() {
roTimer = setInterval(ctx.rotate(degreesToRadians(60)),100);
}
//constructor for Shape object, not currently in use
function Shape() {
//this.x = canvas.width/2 + Math.random()*10-5;
//this.y = canvas.height/2 + Math.random()*10-5;
this.r = Math.random()*20-5;
this.vx = Math.random()*10-5;
this.vy = Math.random()*10-5;
var colors = ['red','green','orange','purple','blue','aqua','pink','gold'];
this.color = colors[Math.floor(Math.random()*colors.length)];
}
//pushes the shapes to an array, not currently in use
function makeShapes() {
shapes = [];
for (var i = 0; i<2; i++){
shapes.push(new Shape());
}
}
//fills and resets background
function fillBackground() {
ctx.globalCompositeOperation = 'source-over';
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.globalCompositeOperation = 'lighter';
}
//draws the shape
function drawShapes(r, p, m) {
//canvas, x position, y position, radius, number of points, fraction of radius for inset
fillBackground();
x = 350;
y = 350;
r = Math.random()*20-5;
//for (var i = 0; i < shapes.length; i++) {
//var s = shapes[i];
ctx.save();
ctx.beginPath();
ctx.translate(x, y);
ctx.moveTo(0,0-r);
//}
for (var i2 = 0; i2 < p; i2++) {
ctx.rotate(Math.PI / p);
ctx.lineTo(0, 0 - (r*m));
ctx.rotate(Math.PI / p);
ctx.lineTo(0, 0 - r);
}
ctx.fillStyle = "yellow";
ctx.fill();
var vx = Math.random()*10-5;
var vy = Math.random()*10-5;
x += vx;
y += vy;
r -=8
ctx.restore();
}
//}
window.onload = function() {
canvas = document.getElementById('animCanvas');
ctx = canvas.getContext('2d');
//makeShapes();
//console.log(shapes);
timer = setInterval(drawShapes(40, 5, 0.5), 100);
//timer2 = setInterval(makeShapes, 4500);
}
</script>
</head>
<body>
<canvas width='700' height='700' id='animCanvas'></canvas>
</body>
</html>
A coding hint: Separate your code into discrete duties. This separation lets you concentrate your coding focus on simpler tasks. And once you've got that task running correctly you can move onto another task without worrying that a previous task has become broken.
Here are the tasks for your "rotate stars" project
1. Draw a star and
2. Rotate that star using animation.*
... and their descriptions
drawShapes() draws one star at a specified [x,y] position at a specified currentAngle
animate() runs an animation loop that:
Clears the canvas.
Fills the background.
Draws the star (or many stars) with `drawShapes`.
Changes the `currentAngle` rotation for the next loop.
Requests another animation loop.
About rotating
Rotating your shape is a simple 2 step process:
1. Move to the shape's centerpoint: `.translate(centerX,centerY)'
2. Rotate the canvas to the currently desired angle: `rotate(currentAngle)`
Since translate and rotate are not automatically undone, you must "clean up" after your transformations. An easy way to do that is to do this: context.setTransform(1,0,0,1,0,0). This sets the internal transformation matrix to its default state (==fully untransformed).
So your rotation process becomes:
1. Move to the shape's centerpoint: `.translate(centerX,centerY)'
2. Rotate the canvas to the currently desired angle: `.rotate(currentAngle)`
3. Reset the canvas: `.setTransform(1,0,0,1,0,0)`
Here's annotated code and a Demo:
var canvas;
var ctx;
canvas = document.getElementById('animCanvas');
ctx = canvas.getContext('2d');
var cw=canvas.width;
var ch=canvas.height;
var shapes=[];
var star1={ x:50, y:100, r:40, currentAngle:0, p:5, m:.5, fill:'yellow',angleChange:Math.PI/60}
var star2={ x:150, y:100, r:25, currentAngle:0, p:55, m:5, fill:'blue',angleChange:-Math.PI/360}
var star3={ x:250, y:100, r:25, currentAngle:0, p:15, m:3, fill:'red',angleChange:Math.PI/120}
requestAnimationFrame(animate);
function drawShapes(star) {
ctx.save();
// translate to the star's centerpoint
ctx.translate(star.x,star.y);
// rotate to the current angle
ctx.rotate(star.currentAngle)
// draw the star
ctx.beginPath();
ctx.moveTo(0,0-star.r);
for (var i2 = 0; i2 < star.p; i2++) {
ctx.rotate(Math.PI / star.p);
ctx.lineTo(0, 0 - (star.r*star.m));
ctx.rotate(Math.PI / star.p);
ctx.lineTo(0, 0 - star.r);
}
ctx.fillStyle =star.fill;
ctx.fill();
ctx.restore();
}
function fillBackground() {
ctx.globalCompositeOperation = 'source-over';
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.globalCompositeOperation = 'lighter';
}
function animate(time){
// clear the canvas
ctx.clearRect(0,0,cw,ch);
// fill the background
fillBackground();
// draw the stars
// If you put star1,star2,star3 in a stars[] array then
// you could simply the following demo code by looping
// through the array
//
// draw the star1
drawShapes(star1);
// increase star1's current rotation angle
star1.currentAngle+=star1.angleChange;
// draw the star2
drawShapes(star2);
// increase star2's current rotation angle
star2.currentAngle+=star2.angleChange;
// draw the star3
drawShapes(star3);
// increase star3's current rotation angle
star3.currentAngle+=star2.angleChange;
// request another animation loop
requestAnimationFrame(animate);
}
<canvas width='700' height='700' id='animCanvas'></canvas> </body>

Update HTML5 canvas rectangle on hover?

I've got some code which draws a rectangle on a canvas, but I want that rectangle to change color when I hover the mouse over it.
The problem is after I've drawn the rectangle I'm not sure how I select it again to make the adjustment.
What I want to do:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();
$('c.[rectangle]').hover(function(this){
this.fillStyle = 'red';
this.fill();
});
You can't do this out-of-the-box with canvas. Canvas is just a bitmap, so the hover logic has to be implemented manually.
Here is how:
Store all the rectangles you want as simple object
For each mouse move on the canvas element:
Get mouse position
Iterate through the list of objects
use isPointInPath() to detect a "hover"
Redraw both states
Example
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
rects = [
{x: 10, y: 10, w: 200, h: 50},
{x: 50, y: 70, w: 150, h: 30} // etc.
], i = 0, r;
// render initial rects.
while(r = rects[i++]) ctx.rect(r.x, r.y, r.w, r.h);
ctx.fillStyle = "blue"; ctx.fill();
canvas.onmousemove = function(e) {
// important: correct mouse position:
var rect = this.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top,
i = 0, r;
ctx.clearRect(0, 0, canvas.width, canvas.height); // for demo
while(r = rects[i++]) {
// add a single rect to path:
ctx.beginPath();
ctx.rect(r.x, r.y, r.w, r.h);
// check if we hover it, fill red, if not fill it blue
ctx.fillStyle = ctx.isPointInPath(x, y) ? "red" : "blue";
ctx.fill();
}
};
<canvas/>
This is a stable code in base of #K3N answer. The basic problem of his code is because when one box is over the another the two may get mouse hover at same time. My answer perfectly solves that adding a 'DESC' to 'ASC' loop.
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
var map = [
{x: 20, y: 20, w: 60, h: 60},
{x: 30, y: 50, w: 76, h: 60}
];
var hover = false, id;
var _i, _b;
function renderMap() {
for(_i = 0; _b = map[_i]; _i ++) {
ctx.fillStyle = (hover && id === _i) ? "red" : "blue";
ctx.fillRect(_b.x, _b.y, _b.w, _b.h);
}
}
// Render everything
renderMap();
canvas.onmousemove = function(e) {
// Get the current mouse position
var r = canvas.getBoundingClientRect(),
x = e.clientX - r.left, y = e.clientY - r.top;
hover = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for(var i = map.length - 1, b; b = map[i]; i--) {
if(x >= b.x && x <= b.x + b.w &&
y >= b.y && y <= b.y + b.h) {
// The mouse honestly hits the rect
hover = true;
id = i;
break;
}
}
// Draw the rectangles by Z (ASC)
renderMap();
}
<canvas id="canvas"></canvas>
You may have to track the mouse on the canvas using JavaScript and see when it is over your rectangle and change the color then. See code below from my blog post
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="700" height="500" style="border:1px solid #c3c3c3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
var myRect={x:150, y:75, w:50, h:50, color:"red"};
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = myRect.color;
ctx.fillRect(myRect.x, myRect.y, myRect.w, myRect.h);
c.addEventListener("mousemove", function(e){
if ((e.clientX>=myRect.x)&(e.clientX<=myRect.x+myRect.w)&(e.clientY>=myRect.y)&(e.clientY<=myRect.y+myRect.h)){
myRect.color = "green";}
else{
myRect.color = "red";}
updateCanvas();
}, false);
function updateCanvas(){
ctx.fillStyle = myRect.color;
ctx.fillRect(myRect.x, myRect.y, myRect.w, myRect.h);
}
</script>
</body>
</html>
I believe this is a slightly more in-depth answer that would work better for you, especially if you are interested in game design with the canvas element.
The main reason this would work better for you is because it focuses more on an OOP (object orientated programming) approach. This allows for objects to be defined, tracked and altered at a later time via some event or circumstance. It also allows for easy scaling of your code and in my opinion is just more readable and organized.
Essentially what you have here is two shapes colliding. The cursor and the individual point / object it hovers over. With basic squares, rectangles or circles this isn't too bad. But, if you are comparing two more unique shapes, you'll need to read up more on Separating Axis Theorem (SAT) and other collision techniques. At that point optimizing and performance will become a concern, but for now I think this is the optimal approach.
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width = window.innerWidth;
const height = canvas.height = window.innerHeight;
const cx = width / 2;
const cy = height / 2;
const twoPie = Math.PI * 2;
const points = []; // This will be the array we store our hover points in later
class Point {
constructor(x, y, r) {
this.x = x;
this.y = y;
this.r = r || 0;
}
}
class HoverPoint extends Point {
constructor(x, y, r, color, hoverColor) {
super(x, y, r);
this.color = color;
this.hoverColor = hoverColor;
this.hovered = false;
this.path = new Path2D();
}
draw() {
this.hovered ? ctx.fillStyle = this.hoverColor : ctx.fillStyle = this.color;
this.path.arc(this.x, this.y, this.r, 0, twoPie);
ctx.fill(this.path);
}
}
class Cursor extends Point {
constructor(x, y, r) {
super(x, y, r);
}
collisionCheck(points) {
// This is the method that will be called during the animate function that
// will check the cursors position against each of our objects in the points array.
document.body.style.cursor = "default";
points.forEach(point => {
point.hovered = false;
if (ctx.isPointInPath(point.path, this.x, this.y)) {
document.body.style.cursor = "pointer";
point.hovered = true;
}
});
}
}
function createPoints() {
// Create your points and add them to the points array.
points.push(new HoverPoint(cx, cy, 100, 'red', 'coral'));
points.push(new HoverPoint(cx + 250, cy - 100, 50, 'teal', 'skyBlue'));
// ....
}
function update() {
ctx.clearRect(0, 0, width, height);
points.forEach(point => point.draw());
}
function animate(e) {
const cursor = new Cursor(e.offsetX, e.offsetY);
update();
cursor.collisionCheck(points);
}
createPoints();
update();
canvas.onmousemove = animate;
There is one more thing that I would like to suggest. I haven't done tests on this yet but I suspect that using some simple trigonometry to detect if our circular objects collide would preform better over the ctx.IsPointInPath() method.
However if you are using more complex paths and shapes, then the ctx.IsPointInPath() method would most likely be the way to go. if not some other more extensive form of collision detection as I mentioned earlier.
The resulting change would look like this...
class Cursor extends Point {
constructor(x, y, r) {
super(x, y, r);
}
collisionCheck(points) {
document.body.style.cursor = "default";
points.forEach(point => {
let dx = point.x - this.x;
let dy = point.y - this.y;
let distance = Math.hypot(dx, dy);
let dr = point.r + this.r;
point.hovered = false;
// If the distance between the two objects is less then their combined radius
// then they must be touching.
if (distance < dr) {
document.body.style.cursor = "pointer";
point.hovered = true;
}
});
}
}
here is a link containing examples an other links related to collision detection
I hope you can see how easily something like this can be modified and used in games and whatever else. Hope this helps.
Below code adds shadow to canvas circle on hovering it.
<html>
<body>
<canvas id="myCanvas" width="1000" height="500" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
</body>
<script>
var canvas = document.getElementById("myCanvas"),
ctx = canvas.getContext("2d"),
circle = [{
x: 60,
y: 50,
r: 40,
},
{
x: 100,
y: 150,
r: 50,
} // etc.
];
// render initial rects.
for (var i = 0; i < circle.length; i++) {
ctx.beginPath();
ctx.arc(circle[i].x, circle[i].y, circle[i].r, 0, 2 * Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
}
canvas.onmousemove = function(e) {
var x = e.pageX,
y = e.pageY,
i = 0,
r;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < circle.length; i++) {
if ((x > circle[i].x - circle[i].r) && (y > circle[i].y - circle[i].r) && (x < circle[i].x + circle[i].r) && (y < circle[i].y + circle[i].r)) {
ctx.beginPath();
ctx.arc(circle[i].x, circle[i].y, circle[i].r, 0, 2 * Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.shadowBlur = 10;
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgb(255,255,255)';
ctx.shadowColor = 'grey';
ctx.stroke();
ctx.shadowColor = 'white';
ctx.shadowBlur = 0;
} else {
ctx.beginPath();
ctx.arc(circle[i].x, circle[i].y, circle[i].r, 0, 2 * Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.shadowColor = 'white';
ctx.shadowBlur = 0;
}
}
};
</script>
</html>
I know this is old, but I am surprised no one has mentioned JCanvas. It adds to the simplicity of animating canvas on events. More documentation here https://projects.calebevans.me/jcanvas/docs/mouseEvents/
<html lang="en">
<head>
<!-- css and other -->
</head>
<body onload="draw();">
<canvas id = "canvas" width="500" height="500" style= border:1px solid #000000;"> </canvas>
<script>
function draw() {
$('canvas').drawRect({
layer: true,
fillStyle:'#333',
x:100, y: 200,
width: 600,
height: 400,
mouseover: function(layer) {
$(this).animateLayer(layer, {
fillStyle: 'green'
}, 1000, 'swing');
}
});
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jcanvas/21.0.1/jcanvas.js" crossorigin="anonymous"></script>
</body>
</html>
Consider this following code:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();
c.addEventListener("mouseover", doMouseOver, false);//added event to canvas
function doMouseOver(e){
ctx.fillStyle = 'red';
ctx.fill();
}
DEMO
You could use canvas.addEventListener
var canvas = document.getElementById('canvas0');
canvas.addEventListener('mouseover', function() { /*your code*/ }, false);
It worked on google chrome
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();
$(c).hover(function(e){
ctx.fillStyle = 'red';
ctx.fill();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="myCanvas"/>

Having trouble with canvas, I've followed online tutorials but nothing shows in browser window

I've been learning how to use html5 recently and one aspect that really interests me is the canvas's ability to create animations. I have followed some online tutorials to some success but recently I found "thecodeplayer" where there are some awesome tutorials (if your in to it, check it out). I've got to the point where I've gone through it various times but still with no luck. The canvas does not show in my browser window when I load it up in chrome. Ive even turned off extensions like adblocker as suggested from some answers on this site. Its probably something obvious but I cant find where I seem to have gone wrong. Anyone who can point me in the right direction, thanks
Heres the code.
<html>
<head>
<script type="text/javascript">
//Initializing the canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//Canvas dimensions
var W = 500; var H = 500;
//create an array of particles
var particles = [];
for(var i = 0; i < 50; i++)
{
//This will add 50 particles to the array with random positions
particles.push(new create_particle());
}
//function to create multiple particles
function create_particle()
{
//Random position on the canvas
this.x = Math.random()*W;
this.y = Math.random()*H;
//add random velocity to each particle
this.vx = Math.random()*20-10;
this.vy = Math.random()*20-10;
//Random colors
var r = Math.random()*255>>0;
var g = Math.random()*255>>0;
var b = Math.random()*255>>0;
this.color = "rgba("+r+", "+g+", "+b+", 0.5)";
//Random size
this.radius = Math.random()*20+20;
}
var x = 100; var y = 100;
//animate the particle
function draw()
{
//paint canvas black, remove particle trails
ctx.globalCompositeOperation = "source-over";
//reduce the opacity of the BG paint to give the final touch
ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
ctx.fillRect(0, 0, W, H);
//blend the particle with the BG
ctx.globalCompositeOperation = "lighter";
//draw particles from the array now
for(var t = 0; t < particles.length; t++)
{
var p = particles[t];
ctx.beginPath();
//colors
var gradient = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.radius);
gradient.addColorStop(0, "white");
gradient.addColorStop(0.4, "white");
gradient.addColorStop(0.4, p.color);
gradient.addColorStop(1, "black");
ctx.fillStyle = gradient;
ctx.arc(p.x, p.y, p.radius, Math.PI*2, false);
ctx.fill();
//velocity
p.x += p.vx;
p.y += p.vy;
//Stops balls moving out of canvas
if(p.x < -50) p.x = W+50;
if(p.y < -50) p.y = H+50;
if(p.x > W+50) p.x = -50;
if(p.y > H+50) p.y = -50;
}
}
setInterval(draw, 33);
</script>
</head>
<body>
<canvas id="canvas"width="500"height="500"></canvas>
</body>
</html>
Place the code in a function, and add a script tag below the body HTML, calling the canvas drawing function. The canvas element is not yet created when you want to use it for drawing on.
Result:
<html>
<head>
<script type="text/javascript">
function doCanvasStuff () {
//Initializing the canvas
var canvas = document.getElementById("canvas");
...
setInterval(draw, 33);
}
</script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<script>
doCanvasStuff();
</script>
</html>

Moving Objects on html5 Canvas

I placed an text on html5 canvas object using fillText option, question is I need to move the text position or change the color of the text that is already rendered.
Shortly I need to know how to Manipulate particular child of canvas element
This will move a small circle over your canvas
var can = document.getElementById('canvas');
can.height = 1000; can.width = 1300;
var ctx = can.getContext('2d');
var x = 10, y = 100;
ctx.fillStyle = "black";
ctx.fillRect(700, 100, 100, 100);
function draw() {
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(250,0,0,0.4)';
ctx.fill();
x += 2;
ctx.fillStyle = "rgba(34,45,23,0.4)";
ctx.fillRect(0, 0, can.width, can.height);
requestAnimationFrame(draw);
//ctx.clearRect(0,0,can.width,can.height);
}
draw();
<canvas id="canvas" style="background:rgba(34,45,23,0.4)"></canvas>
I think there is no object model behind the canvas, so you cannot access a "child object" like a "text object" and change it.
What you can do is that you draw the text again with a different color that overwrites the "pixels" of the canvas.
If you want to move the text, first you have to either clear the canvas or re-draw the text with a background/transparent color to get rid of the text in the previous position. Then you can draw the text in the new position.
I've never tried it but I think this would be the way to do it.
var canvas = document.getElementById("canvas"); //get the canvas dom object
var ctx = canvas.getContext("2d"); //get the context
var c = { //create an object to draw
x:0, //x value
y:0, //y value
r:5; //radius
}
var redraw = function(){ // this function redraws the c object every frame (FPS)
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear the canvas
ctx.beginPath(); //start the path
ctx.arc(c.x, c.y, c.r, 0, Math.PI*2); //draw the circle
ctx.closePath(); //close the circle path
ctx.fill(); //fill the circle
requestAnimationFrame(redraw);//schedule this function to be run on the next frame
}
function move(){ // this function modifies the object
var decimal = Math.random() // this returns a float between 0.0 and 1.0
c.x = decimal * canvas.width; // mulitple the random decimal by the canvas width and height to get a random pixel in the canvas;
c.y = decimal * canvas.height;
}
redraw(); //start the animation
setInterval(move, 1000); // run the move function every second (1000 milliseconds)
Here is a fiddle for it.
http://jsfiddle.net/r4JPG/2/
If you want easing and translations, change the move method accordingly.
Hope it is allowed to advertise somebody's project.
Take a look at http://ocanvas.org/ you can get inspiration there.
It is object like canvas library. Allows you to handle events, make animations etc.
<html>
<head>
<title>Canvas Exam</title>
</head>
<body>
<canvas id="my_canvas" height="500" width="500" style="border:1px solid black">
</canvas>
<script>
var dom=document.getElementById("my_canvas");
var ctx=dom.getContext("2d");
var x1=setInterval(handler,1);
var x=50;
var y=50;
r=40;
function handler()
{
ctx.clearRect(0,0,500,500);
r1=(Math.PI/180)*0;
r2=(Math.PI/180)*360;
ctx.beginPath();
//x=x*Math.random();
x=x+2;
r=r+10*Math.random();
ctx.arc(x,y,r,r1,r2);
ctx.closePath();
ctx.fillStyle="blue";
ctx.fill();
ctx.stroke();
if(x>400)
{
x=50;
y=y+10;
}
r=40;
}
</script>
</body>
</html>

Categories

Resources