How to remove canvas background and display full background image - javascript

I am following this tutorial and trying to implement it on my website. I am struggling to remove the 'Black' background to show the full background image with the stars.
Here's jsFiddle: jFiddle
Here's the screen shot below.
Here's the jQuery for your inspection:
width = window.innerWidth,
height = 300;
// Add 2 shooting stars that just cycle.
entities.push(new ShootingStar());
entities.push(new ShootingStar());
//animate background
function animate() {
bgCtx.fillStyle = "black";
bgCtx.fillRect(0, 0, width, height);
bgCtx.fillStyle = '#fff';
bgCtx.strokeStyle = "#fff";
var entLen = entities.length;
while (entLen--) {
entities[entLen].update();
}
requestAnimationFrame(animate);
}
animate();
Any help would be great! thanks :)

In the animate()function, replace
bgCtx.fillStyle = "black";
bgCtx.fillRect(0, 0, width, height);
with
bgCtx.fillStyle = "rgba(0,0,0,0)";
bgCtx.clearRect(0, 0, width, height);
and remove this line bgCtx.fillRect(0, 0, width, height);(l80)
http://jsfiddle.net/aernk8kk/13/
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
// Terrain stuff.
var background = document.getElementById("bgCanvas"),
bgCtx = background.getContext("2d"),
width = window.innerWidth,
height = 300;
(height < 400) ? height = 400 : height;
background.width = width;
background.height = height;
function Terrain(options) {
options = options || {};
this.terrain = document.createElement("canvas");
this.terCtx = this.terrain.getContext("2d");
this.scrollDelay = options.scrollDelay || 90;
this.lastScroll = new Date().getTime();
this.terrain.width = width;
this.terrain.height = height;
this.fillStyle = options.fillStyle || "#f30";
this.mHeight = options.mHeight || height;
// generate
this.points = [];
var displacement = options.displacement || 140,
power = Math.pow(2, Math.ceil(Math.log(width) / (Math.log(2))));
// set the start height and end height for the terrain
this.points[0] = this.mHeight;//(this.mHeight - (Math.random() * this.mHeight / 2)) - displacement;
this.points[power] = this.points[0];
// create the rest of the points
for (var i = 1; i < power; i *= 2) {
for (var j = (power / i) / 2; j < power; j += power / i) {
this.points[j] = ((this.points[j - (power / i) / 2] + this.points[j + (power / i) / 2]) / 2) + Math.floor(Math.random() * -displacement + displacement);
}
displacement *= 0.6;
}
document.body.appendChild(this.terrain);
}
Terrain.prototype.update = function () {
// draw the terrain
this.terCtx.clearRect(0, 0, width, height);
this.terCtx.fillStyle = this.fillStyle;
if (new Date().getTime() > this.lastScroll + this.scrollDelay) {
this.lastScroll = new Date().getTime();
this.points.push(this.points.shift());
}
this.terCtx.beginPath();
for (var i = 0; i <= width; i++) {
if (i === 0) {
this.terCtx.moveTo(0, this.points[0]);
} else if (this.points[i] !== undefined) {
this.terCtx.lineTo(i, this.points[i]);
}
}
this.terCtx.lineTo(width, this.terrain.height);
this.terCtx.lineTo(0, this.terrain.height);
this.terCtx.lineTo(0, this.points[0]);
this.terCtx.fill();
}
// Second canvas used for the stars
bgCtx.fillStyle = "rgb(255,255,255)";
// stars
function Star(options) {
this.size = Math.random() * 2;
this.speed = Math.random() * .05;
this.x = options.x;
this.y = options.y;
}
Star.prototype.reset = function () {
this.size = Math.random() * 2;
this.speed = Math.random() * .05;
this.x = width;
this.y = Math.random() * height;
}
Star.prototype.update = function () {
this.x -= this.speed;
if (this.x < 0) {
this.reset();
} else {
bgCtx.fillRect(this.x, this.y, this.size, this.size);
}
}
function ShootingStar() {
this.reset();
}
ShootingStar.prototype.reset = function () {
this.x = Math.random() * width;
this.y = 0;
this.len = (Math.random() * 80) + 10;
this.speed = (Math.random() * 10) + 6;
this.size = (Math.random() * 1) + 0.1;
// this is used so the shooting stars arent constant
this.waitTime = new Date().getTime() + (Math.random() * 3000) + 500;
this.active = false;
}
ShootingStar.prototype.update = function () {
if (this.active) {
this.x -= this.speed;
this.y += this.speed;
if (this.x < 0 || this.y >= height) {
this.reset();
} else {
bgCtx.lineWidth = this.size;
bgCtx.beginPath();
bgCtx.moveTo(this.x, this.y);
bgCtx.lineTo(this.x + this.len, this.y - this.len);
bgCtx.stroke();
}
} else {
if (this.waitTime < new Date().getTime()) {
this.active = true;
}
}
}
var entities = [];
// init the stars
for (var i = 0; i < height; i++) {
entities.push(new Star({
x: Math.random() * width,
y: Math.random() * height
}));
}
// Add 2 shooting stars that just cycle.
entities.push(new ShootingStar());
entities.push(new ShootingStar());
//animate background
function animate() {
bgCtx.fillStyle = "rgba(0,0,0,0)";
bgCtx.clearRect(0, 0, width, height);
bgCtx.fillStyle = '#fff';
bgCtx.strokeStyle = "#fff";
var entLen = entities.length;
while (entLen--) {
entities[entLen].update();
}
requestAnimationFrame(animate);
}
animate();
body, html {
color: #fff;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: url(
http://cdn1.dottech.org/wp-content/uploads/2013/08/moon_clear_sky_wallpaper_2560x1440.jpg
) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
canvas {
position:absolute;
top:0;
left:0
}
<canvas id="bgCanvas"></canvas>
check clearRect

Related

Javascript particles are clipping over the edges

I have this small particle script that I adjusted to my liking, but I have one problem.
Once the particles come to the edge, they get clipped a bit (maybe 10 - 15px), is there any padding attribute for canvas that I could use to give them a bit of space?
I've created snippet bellow to show what's the problem if anyone is interested to help out?
let resizeReset = function() {
w = canvasBody.width = 800;
h = canvasBody.height = 460;
}
const opts = {
particleColor: "rgb(200,200,200)",
lineColor: "rgb(200,200,200)",
particleAmount: 8,
defaultSpeed: 0.05,
variantSpeed: 1,
defaultRadius: 5,
variantRadius: 10,
linkRadius: 500,
};
window.addEventListener("resize", function(){
deBouncer();
});
let deBouncer = function() {
clearTimeout(tid);
tid = setTimeout(function() {
resizeReset();
}, delay);
};
let checkDistance = function(x1, y1, x2, y2){
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
};
let linkPoints = function(point1, hubs){
for (let i = 0; i < hubs.length; i++) {
let distance = checkDistance(point1.x, point1.y, hubs[i].x, hubs[i].y);
let opacity = 1 - distance / opts.linkRadius;
if (opacity > 0) {
drawArea.lineWidth = 0.5;
drawArea.strokeStyle = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${opacity})`;
drawArea.beginPath();
drawArea.moveTo(point1.x, point1.y);
drawArea.lineTo(hubs[i].x, hubs[i].y);
drawArea.closePath();
drawArea.stroke();
}
}
}
Particle = function(xPos, yPos){
this.x = Math.random() * w;
this.y = Math.random() * h;
this.speed = opts.defaultSpeed + Math.random() * opts.variantSpeed;
this.directionAngle = Math.floor(Math.random() * 360);
this.color = opts.particleColor;
this.radius = opts.defaultRadius + Math.random() * opts. variantRadius;
this.vector = {
x: Math.cos(this.directionAngle) * this.speed,
y: Math.sin(this.directionAngle) * this.speed
};
this.update = function(){
this.border();
this.x += this.vector.x;
this.y += this.vector.y;
};
this.border = function(){
if (this.x >= w || this.x <= 0) {
this.vector.x *= -1;
}
if (this.y >= h || this.y <= 0) {
this.vector.y *= -1;
}
if (this.x > w) this.x = w;
if (this.y > h) this.y = h;
if (this.x < 0) this.x = 0;
if (this.y < 0) this.y = 0;
};
this.draw = function(){
drawArea.beginPath();
drawArea.arc(this.x, this.y, this.radius, 0, Math.PI*2);
drawArea.closePath();
drawArea.fillStyle = this.color;
drawArea.fill();
};
};
function setup(){
particles = [];
resizeReset();
for (let i = 0; i < opts.particleAmount; i++){
particles.push( new Particle() );
}
window.requestAnimationFrame(loop);
}
function loop(){
window.requestAnimationFrame(loop);
drawArea.clearRect(0,0,w,h);
for (let i = 0; i < particles.length; i++){
particles[i].update();
particles[i].draw();
}
for (let i = 0; i < particles.length; i++){
linkPoints(particles[i], particles);
}
}
const canvasBody = document.getElementById("canvas"),
drawArea = canvasBody.getContext("2d");
let delay = 200, tid,
rgb = opts.lineColor.match(/\d+/g);
resizeReset();
setup();
body {
background: #222;
margin: 0rem;
padding: 20px;
font-family: Futura, sans-serif;
display: flex;
justify-content: center;
}
#canvas {
// position: absolute;
display: block;
// top: 0;
// left: 0;
z-index: -1;
width: 80%;
}
<canvas id="canvas"></canvas>
Add the radius to the position on the edge detection
However I found a problem : if a circle start in an edge, it don't seems to move.
let resizeReset = function() {
w = canvasBody.width = 800;
h = canvasBody.height = 460;
}
const opts = {
particleColor: "rgb(200,200,200)",
lineColor: "rgb(200,200,200)",
particleAmount: 8,
defaultSpeed: 0.05,
variantSpeed: 1,
defaultRadius: 5,
variantRadius: 10,
linkRadius: 500,
};
window.addEventListener("resize", function(){
deBouncer();
});
let deBouncer = function() {
clearTimeout(tid);
tid = setTimeout(function() {
resizeReset();
}, delay);
};
let checkDistance = function(x1, y1, x2, y2){
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
};
let linkPoints = function(point1, hubs){
for (let i = 0; i < hubs.length; i++) {
let distance = checkDistance(point1.x, point1.y, hubs[i].x, hubs[i].y);
let opacity = 1 - distance / opts.linkRadius;
if (opacity > 0) {
drawArea.lineWidth = 0.5;
drawArea.strokeStyle = `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${opacity})`;
drawArea.beginPath();
drawArea.moveTo(point1.x, point1.y);
drawArea.lineTo(hubs[i].x, hubs[i].y);
drawArea.closePath();
drawArea.stroke();
}
}
}
Particle = function(xPos, yPos){
this.x = Math.random() * w;
this.y = Math.random() * h;
this.speed = opts.defaultSpeed + Math.random() * opts.variantSpeed;
this.directionAngle = Math.floor(Math.random() * 360);
this.color = opts.particleColor;
this.radius = opts.defaultRadius + Math.random() * opts. variantRadius;
this.vector = {
x: Math.cos(this.directionAngle) * this.speed,
y: Math.sin(this.directionAngle) * this.speed
};
this.update = function(){
this.border();
this.x += this.vector.x;
this.y += this.vector.y;
};
this.border = function(){
if (this.x + this.radius >= w || this.x - this.radius<= 0) { // Changes here
this.vector.x *= -1;
}
if (this.y + this.radius >= h || this.y - this.radius <= 0) { // And here
this.vector.y *= -1;
}
if (this.x > w) this.x = w;
if (this.y > h) this.y = h;
if (this.x < 0) this.x = 0;
if (this.y < 0) this.y = 0;
};
this.draw = function(){
drawArea.beginPath();
drawArea.arc(this.x, this.y, this.radius, 0, Math.PI*2);
drawArea.closePath();
drawArea.fillStyle = this.color;
drawArea.fill();
};
};
function setup(){
particles = [];
resizeReset();
for (let i = 0; i < opts.particleAmount; i++){
particles.push( new Particle() );
}
window.requestAnimationFrame(loop);
}
function loop(){
window.requestAnimationFrame(loop);
drawArea.clearRect(0,0,w,h);
for (let i = 0; i < particles.length; i++){
particles[i].update();
particles[i].draw();
}
for (let i = 0; i < particles.length; i++){
linkPoints(particles[i], particles);
}
}
const canvasBody = document.getElementById("canvas"),
drawArea = canvasBody.getContext("2d");
let delay = 200, tid,
rgb = opts.lineColor.match(/\d+/g);
resizeReset();
setup();
body {
background: #222;
margin: 0rem;
padding: 20px;
font-family: Futura, sans-serif;
display: flex;
justify-content: center;
}
#canvas {
// position: absolute;
display: block;
// top: 0;
// left: 0;
z-index: -1;
width: 80%;
background-color:white;
}
<canvas id="canvas"></canvas>

How to migrate a legacy a DOMContentLoaded function inside a Vue 3 component

I'm trying to refactor a website inside a Vue 3 single page app.
Everything is working but I cannot understand which is the best way to insert and execute some javascript functions...
In my homepage, that now is a component, I use this function to create a parallax star + mountain landscape
document.addEventListener('DOMContentLoaded', () => {
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
// Terrain stuff.
var background = document.getElementById("bg-canvas")
var backgroundHome = document.getElementById("bg-home")
var bgCtx = background.getContext("2d"),
width = window.innerWidth,
height = window.innerHeight;
(height < 400) ? height = 400: height;
background.width = width;
background.height = height;
function Terrain(options) {
options = options || {};
this.terrain = document.createElement("canvas");
this.terCtx = this.terrain.getContext("2d");
this.scrollDelay = options.scrollDelay || 90;
this.lastScroll = new Date().getTime();
this.terrain.width = width;
this.terrain.height = height;
this.fillStyle = options.fillStyle || "#494776";
this.mHeight = options.mHeight || height;
// generate
this.points = [];
var displacement = options.displacement || 140,
power = Math.pow(2, Math.ceil(Math.log(width) / (Math.log(2))));
// set the start height and end height for the terrain
this.points[0] = this.mHeight; //(this.mHeight - (Math.random() * this.mHeight / 2)) - displacement;
this.points[power] = this.points[0];
// create the rest of the points
for (var i = 1; i < power; i *= 2) {
for (var j = (power / i) / 2; j < power; j += power / i) {
this.points[j] = ((this.points[j - (power / i) / 2] + this.points[j + (power / i) / 2]) / 2) + Math.floor(Math.random() * -displacement + displacement);
}
displacement *= 0.6;
}
background.after(this.terrain);
}
Terrain.prototype.update = function() {
// draw the terrain
this.terCtx.clearRect(0, 0, width, height);
this.terCtx.fillStyle = this.fillStyle;
if (new Date().getTime() > this.lastScroll + this.scrollDelay) {
this.lastScroll = new Date().getTime();
this.points.push(this.points.shift());
}
this.terCtx.beginPath();
for (var i = 0; i <= width; i++) {
if (i === 0) {
this.terCtx.moveTo(0, this.points[0]);
} else if (this.points[i] !== undefined) {
this.terCtx.lineTo(i, this.points[i]);
}
}
this.terCtx.lineTo(width, this.terrain.height);
this.terCtx.lineTo(0, this.terrain.height);
this.terCtx.lineTo(0, this.points[0]);
this.terCtx.fill();
}
// Second canvas used for the stars
bgCtx.fillStyle = '#05004c';
bgCtx.fillRect(0, 0, width, height);
// stars
function Star(options) {
this.size = Math.random() * 2;
this.speed = Math.random() * .05;
this.x = options.x;
this.y = options.y;
}
Star.prototype.reset = function() {
this.size = Math.random() * 2;
this.speed = Math.random() * .05;
this.x = width;
this.y = Math.random() * height;
}
Star.prototype.update = function() {
this.x -= this.speed;
if (this.x < 0) {
this.reset();
} else {
bgCtx.fillRect(this.x, this.y, this.size, this.size);
}
}
function ShootingStar() {
this.reset();
}
ShootingStar.prototype.reset = function() {
this.x = Math.random() * width;
this.y = 0;
this.len = (Math.random() * 80) + 10;
this.speed = (Math.random() * 10) + 6;
this.size = (Math.random() * 1) + 0.1;
// this is used so the shooting stars arent constant
this.waitTime = new Date().getTime() + (Math.random() * 3000) + 500;
this.active = false;
}
ShootingStar.prototype.update = function() {
if (this.active) {
this.x -= this.speed;
this.y += this.speed;
if (this.x < 0 || this.y >= height) {
this.reset();
} else {
bgCtx.lineWidth = this.size;
bgCtx.beginPath();
bgCtx.moveTo(this.x, this.y);
bgCtx.lineTo(this.x + this.len, this.y - this.len);
bgCtx.stroke();
}
} else {
if (this.waitTime < new Date().getTime()) {
this.active = true;
}
}
}
var entities = [];
// init the stars
for (var i = 0; i < height; i++) {
entities.push(new Star({
x: Math.random() * width,
y: Math.random() * height
}));
}
// Add 2 shooting stars that just cycle.
entities.push(new ShootingStar());
entities.push(new ShootingStar());
entities.push(new Terrain({
displacement: 150,
scrollDelay: 20,
fillStyle: "#221445",
mHeight: height / 2
}));
entities.push(new Terrain({
displacement: 120,
scrollDelay: 50,
fillStyle: "#2e1f56",
mHeight: (height / 2) - 30
}));
entities.push(new Terrain({
mHeight: (height / 2) - 60
}));
//animate background
function animate() {
bgCtx.fillStyle = '#055e8f';
bgCtx.fillRect(0, 0, width, height);
bgCtx.fillStyle = '#ffffff';
bgCtx.strokeStyle = '#ffffff';
var entLen = entities.length;
while (entLen--) {
entities[entLen].update();
}
requestAnimationFrame(animate);
}
animate();
});
Which is the most efficient way to execute this when my homepage component is mounted?

html5-canvas background doesn't cover entire page

I'm currently using a canvas animation as the background of my new portfolio page. It works wonderfully until there's more content than can be displayed on a single page, but once you scroll down you'll find the canvas stops at the dimensions of the initial page display even though it's supposed to be the same size as the body element.
I apologize if this is a question that has been answered but I've been looking for a solution all morning and I'm coming up with nothing. Any help you can give is greatly appreciated.
My deployed page can be found here, and below is the JS.
Javascript:
var canvas,
ctx,
circ,
nodes,
mouse,
SENSITIVITY,
SIBLINGS_LIMIT,
DENSITY,
NODES_QTY,
ANCHOR_LENGTH,
MOUSE_RADIUS;
// how close next node must be to activate connection (in px)
// shorter distance == better connection (line width)
SENSITIVITY = 100;
// note that siblings limit is not 'accurate' as the node can actually have more connections than this value that's because the node accepts sibling nodes with no regard to their current connections this is acceptable because potential fix would not result in significant visual difference
// more siblings == bigger node
SIBLINGS_LIMIT = 10;
// default node margin
DENSITY = 50;
// total number of nodes used (incremented after creation)
NODES_QTY = 0;
// avoid nodes spreading
ANCHOR_LENGTH = 20;
// highlight radius
MOUSE_RADIUS = 200;
circ = 2 * Math.PI;
nodes = [];
canvas = document.querySelector("canvas");
resizeWindow();
mouse = {
x: canvas.width / 2,
y: canvas.height / 2
};
ctx = canvas.getContext("2d");
if (!ctx) {
alert("Ooops! Your browser does not support canvas :'(");
}
function Node(x, y) {
this.anchorX = x;
this.anchorY = y;
this.x = Math.random() * (x - (x - ANCHOR_LENGTH)) + (x - ANCHOR_LENGTH);
this.y = Math.random() * (y - (y - ANCHOR_LENGTH)) + (y - ANCHOR_LENGTH);
this.vx = Math.random() * 2 - 1;
this.vy = Math.random() * 2 - 1;
this.energy = Math.random() * 100;
this.radius = Math.random();
this.siblings = [];
this.brightness = 0;
}
Node.prototype.drawNode = function() {
var color = "rgba(216, 48, 168, " + this.brightness + ")";
ctx.beginPath();
ctx.arc(
this.x,
this.y,
2 * this.radius + (2 * this.siblings.length) / SIBLINGS_LIMIT,
0,
circ
);
ctx.fillStyle = color;
ctx.fill();
};
Node.prototype.drawConnections = function() {
for (var i = 0; i < this.siblings.length; i++) {
var color = "rgba(24, 168, 216, " + this.brightness + ")";
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.siblings[i].x, this.siblings[i].y);
ctx.lineWidth = 1 - calcDistance(this, this.siblings[i]) / SENSITIVITY;
ctx.strokeStyle = color;
ctx.stroke();
}
};
Node.prototype.moveNode = function() {
this.enbergy -= 2;
if (this.energy < 1) {
this.energy = Math.random() * 100;
if (this.x - this.anchorX < -ANCHOR_LENGTH) {
this.vx = Math.random() * 2;
} else if (this.x - this.anchorX > ANCHOR_LENGTH) {
this.vx = Math.random() * -2;
} else {
this.vx = Math.random() * 4 - 2;
}
if (this.y - this.anchorY < -ANCHOR_LENGTH) {
this.vy = Math.random() * 2;
} else if (this.y - this.anchorY > ANCHOR_LENGTH) {
this.vy = Math.random() * -2;
} else {
this.vy = Math.random() * 4 - 2;
}
}
this.x += (this.vx * this.energy) / 100;
this.y += (this.vy * this.energy) / 100;
};
function initNodes() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
nodes = [];
for (var i = DENSITY; i < canvas.width; i += DENSITY) {
for (var j = DENSITY; j < canvas.height; j += DENSITY) {
nodes.push(new Node(i, j));
NODES_QTY++;
}
}
}
function calcDistance(node1, node2) {
return Math.sqrt(
Math.pow(node1.x - node2.x, 2) + Math.pow(node1.y - node2.y, 2)
);
}
function findSiblings() {
var node1, node2, distance;
for (var i = 0; i < NODES_QTY; i++) {
node1 = nodes[i];
node1.siblings = [];
for (var j = 0; j < NODES_QTY; j++) {
node2 = nodes[j];
if (node1 !== node2) {
distance = calcDistance(node1, node2);
if (distance < SENSITIVITY) {
if (node1.siblings.length < SIBLINGS_LIMIT) {
node1.siblings.push(node2);
} else {
var node_sibling_distance = 0;
var max_distance = 0;
var s;
for (var k = 0; k < SIBLINGS_LIMIT; k++) {
node_sibling_distance = calcDistance(node1, node1.siblings[k]);
if (node_sibling_distance > max_distance) {
max_distance = node_sibling_distance;
s = k;
}
}
if (distance < max_distance) {
node1.siblings.splice(s, 1);
node1.siblings.push(node2);
}
}
}
}
}
}
}
function redrawScene() {
resizeWindow();
ctx.clearRect(0, 0, canvas.width, canvas.height);
findSiblings();
var i, node, distance;
for (i = 0; i < NODES_QTY; i++) {
node = nodes[i];
distance = calcDistance(
{
x: mouse.x,
y: mouse.y
},
node
);
if (distance < MOUSE_RADIUS) {
node.brightness = 1 - distance / MOUSE_RADIUS;
} else {
node.brightness = 0;
}
}
for (i = 0; i < NODES_QTY; i++) {
node = nodes[i];
if (node.brightness) {
node.drawNode();
node.drawConnections();
}
node.moveNode();
}
requestAnimationFrame(redrawScene);
}
function initHandlers() {
document.addEventListener("resize", resizeWindow, false);
canvas.addEventListener("mousemove", mousemoveHandler, false);
}
function resizeWindow() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function mousemoveHandler(e) {
mouse.x = e.clientX;
mouse.y = e.clientY;
}
initHandlers();
initNodes();
redrawScene();
})();
Set the canvas width property to document.body.scrollHeight, that's the full height of the document
Set the canvas height property to document.body.clientWidth, that's the full width of the document minus the scroll bar.
Change the height style of the canvas to fit-content or remove it. height: 100% will make it as high as the viewport.

HTML5 Canvas + JS Not Working on IOS/Safari

I've implemented a canvas element with a javascript particle effect. The effect is working on every browser but IOS/Safari. I've done a bit of research and IOS/Safari supports HTML5/Canvas: According to Browser Support Charts for HTML5/Canvas
$(function() {
var WIDTH = window.innerWidth * .9,
HEIGHT = window.innerHeight,
MAX_PARTICLES = 100,
DRAW_INTERVAL = 60,
canvas = document.querySelector('#pixies'),
context = canvas.getContext('2d'),
gradient = null,
pixies = new Array();
function setDimensions() {
WIDTH = window.outerWidth;
HEIGHT = window.innerHeight;
canvas.width = WIDTH;
canvas.height = HEIGHT;
}
setDimensions();
window.addEventListener('resize', setDimensions);
function Circle() {
this.settings = {ttl:8000, xmax:5, ymax:2, rmax:10, rt:1, xdef:960, ydef:540, xdrift:4, ydrift: 4, random:true, blink:true};
this.reset = function() {
this.x = (this.settings.random ? WIDTH*Math.random() : this.settings.xdef);
this.y = (this.settings.random ? HEIGHT*Math.random() : this.settings.ydef);
this.r = ((this.settings.rmax-1)*Math.random()) + 1;
this.dx = (Math.random()*this.settings.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.settings.ymax) * (Math.random() < .5 ? -1 : 1);
this.hl = (this.settings.ttl/DRAW_INTERVAL)*(this.r/this.settings.rmax);
this.rt = Math.random()*this.hl;
this.settings.rt = Math.random()+1;
this.stop = Math.random()*.2+.4;
this.settings.xdrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
this.settings.ydrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
}
this.fade = function() {
this.rt += this.settings.rt;
}
this.draw = function() {
if(this.settings.blink && (this.rt <= 0 || this.rt >= this.hl)) {
this.settings.rt = this.settings.rt*-1;
} else if(this.rt >= this.hl) {
this.reset();
}
var newo = 1-(this.rt/this.hl);
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
var cr = this.r*newo;
gradient = context.createRadialGradient(this.x, this.y, 0, this.x, this.y, (cr <= 0 ? 1 : cr));
gradient.addColorStop(0.0, 'rgba(255,255,255,'+newo+')');
gradient.addColorStop(this.stop, 'rgba(255,255,255,'+(newo*.6)+')');
gradient.addColorStop(1.0, 'rgba(255,255,255,0)');
context.fillStyle = gradient;
context.fill();
}
this.move = function() {
this.x += (this.rt/this.hl)*this.dx;
this.y += (this.rt/this.hl)*this.dy;
if(this.x > WIDTH || this.x < 0) this.dx *= -1;
if(this.y > HEIGHT || this.y < 0) this.dy *= -1;
}
this.getX = function() { return this.x; }
this.getY = function() { return this.y; }
}
for (var i = 0; i < MAX_PARTICLES; i++) {
pixies.push(new Circle());
pixies[i].reset();
}
function draw() {
context.clearRect(0, 0, WIDTH, HEIGHT);
for(var i = 0; i < pixies.length; i++) {
pixies[i].fade();
pixies[i].move();
pixies[i].draw();
}
}
setInterval(draw, DRAW_INTERVAL);
});
#particles {
position: absolute;
background: navy;
width: 200px;
height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="particles">
<canvas id="pixies"></canvas>
</div>
Any ideas why this isn't working in IOS/Safari? The actual site in question is this one: www.pjmaskslive.com
The issue appears to be that the canvas elements width is set 0 on the aforementioned website. So I would assume that the issue is setting the WIDTH variable at the start. This might be due to an ongoing bug with iOS 10 as mentioned in this question.
An alternative approach might be to use document.body.getBoundingClientRect().width as an alternative to window.innerWidth and/or window.outerWidth. screen.width could also be used, however, these could also have the same issues as your previous methods.
Seems like a safari issue rather than your code either way!

Why does my Javascript animation slowdown after a while

So I am in the process of making this rhythm game with canvas, all that it does up to this point is render the receivers (the point the blocks are going to collide with so the user can press the corresponding buttons and get points) and it renders the dancer animation. For some reason though after the page is open for a while the dancer slows down significantly and continues to gradually slow.
I can't figure out why or how to fix it. Anyone have any ideas?
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);
var spritesheet = null;
var dancer = {
time:0,
speed:0,
image:null,
x:0,
y:0,
currentFrame:0,
width:50,
height:100,
ready:false
}
function onload() {
spritesheet = new Image();
spritesheet.src = "danceSheet.png";
spritesheet.onload = initiate;
}
function initiate() {
game.startTime = new Date().getTime() / 1000;
dancer.x = (canvas.width / 2) - dancer.width;
dancer.y = 120;
game.initiateReceivers();
main();
}
var game = {
startTime:0,
currentTime:0,
receivers:[],
senders:[],
lanes:[],
drawDancer: function() {
ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0, dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height );
},
clearWindow: function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
initiateReceivers: function() {
var distanceRate = canvas.width / 4;
var position = 30;
for(initiates = 0; initiates < 4; initiates++) {
this.receivers[initiates] = new receivers;
this.receivers[initiates].x = position;
this.receivers[initiates].y = 300;
position += distanceRate;
}
}
}
var gameUpdates = {
updateMovement: function() {
game.currentTime = new Date().getTime() / 1000;
dancer.time = game.currentTime - game.startTime;
if(dancer.time >= 0.1) {
game.startTime = new Date().getTime() / 1000;
dancer.currentFrame += 1;
if(dancer.currentFrame == 12) dancer.currentFrame = 0;
}
},
collision: function(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2);
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
return true;
}
return false;
}
}
function receivers() {
this.x = 0;
this.y = 0;
this.width = 60;
this.height = 10;
}
function senders() {
this.x = 0;
this.y = 0;
this.width = 60;
this.height = 10;
this.lane = 0;
this.status = true;
}
function update() {
gameUpdates.updateMovement();
}
function render() {
game.clearWindow();
game.drawDancer();
game.receivers.forEach( function(receiver) {
ctx.rect(receiver.x,receiver.y,receiver.width,receiver.height);
ctx.fillStyle = "red";
ctx.fill();
}
)
}
function main() {
update();
render();
requestAnimationFrame(main);
}
I'm trying to get an idea of the slowness you're seeing so I adjusted your code to get a frames-per-second. Haven't found the cause yet for the drop.
Update
I found that the frames were dropping from drawing the rectangles. I've altered the code to use fillRect put the fill style outside of the loop. This seems to have fixed the frame drop.
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);
var spritesheet = null;
var dancer = {
time: 0,
speed: 0,
image: null,
x: 0,
y: 0,
currentFrame: 0,
width: 50,
height: 100,
ready: false
}
function onload() {
spritesheet = document.createElement('canvas');
spritesheet.width = (dancer.width * 12);
spritesheet.height = dancer.height;
var ctx = spritesheet.getContext('2d');
ctx.font = "30px Arial";
ctx.fillStyle = "black";
ctx.strokeStyle = "red";
for (var i = 0; i < 12; i++) {
var x = (i * dancer.width) + 10;
ctx.fillText(i,x,60);
ctx.beginPath();
ctx.rect(i*dancer.width,0,dancer.width,dancer.height);
ctx.stroke();
}
initiate();
}
function initiate() {
game.startTime = new Date().getTime() / 1000;
dancer.x = (canvas.width / 2) - dancer.width;
dancer.y = 120;
game.initiateReceivers();
main();
}
var game = {
startTime: 0,
currentTime: 0,
receivers: [],
senders: [],
lanes: [],
drawDancer: function() {
ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0, dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height);
//ctx.strokeStyle="red";
//ctx.beginPath();
//ctx.lineWidth = 3;
//ctx.rect(dancer.x,dancer.y,dancer.width,dancer.height);
//ctx.stroke();
},
clearWindow: function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
initiateReceivers: function() {
var distanceRate = canvas.width / 4;
var position = 30;
for (initiates = 0; initiates < 4; initiates++) {
this.receivers[initiates] = new receivers;
this.receivers[initiates].x = position;
this.receivers[initiates].y = 300;
position += distanceRate;
}
}
};
var gameUpdates = {
updateMovement: function() {
game.currentTime = new Date().getTime() / 1000;
dancer.time = game.currentTime - game.startTime;
if (dancer.time >= 0.1) {
game.startTime = new Date().getTime() / 1000;
dancer.currentFrame += 1;
if (dancer.currentFrame == 12) dancer.currentFrame = 0;
}
},
collision: function(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2);
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
return true;
}
return false;
}
}
function receivers() {
this.x = 0;
this.y = 0;
this.width = 60;
this.height = 10;
}
function senders() {
this.x = 0;
this.y = 0;
this.width = 60;
this.height = 10;
this.lane = 0;
this.status = true;
}
function update() {
gameUpdates.updateMovement();
}
function render() {
game.clearWindow();
game.drawDancer();
ctx.fillStyle = "red";
game.receivers.forEach(function(receiver) {
ctx.fillRect(receiver.x, receiver.y, receiver.width, receiver.height);
});
ctx.fillText(fps,10,10);
}
var fps = 0;
var frames = 0;
function getFps() {
fps = frames;
frames = 0;
setTimeout(getFps,1000);
}
getFps();
function main() {
update();
render();
frames++;
requestAnimationFrame(main);
}
onload();
canvas {
border:1px solid blue;
}

Categories