I manage a few websites and for some reason I am having trouble getting the falling snow effect to work in Google Chrome. The code works perfectly in IE 11 but the same exact code in Google Chrome just puts a snowflake in the upper left corner of the page. Is my code wrong for it to work in Chrome?
CSS
.snowflakeContainer {
position: absolute;
left: 0px;
top: 0px;
}
.snowflake {
padding-left: 15px;
font-family: Cambria, Georgia, serif;
font-size: 14px;
line-height: 24px;
position: fixed;
color: #008B8B;
user-select: none;
z-index: 1000;
}
.snowflake:hover {
cursor: default;
}
HTML
<script src="js5/fallingsnow_v6.js"></script>
JavaScript
// The star of every good animation
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var transforms = ["transform",
"msTransform",
"webkitTransform",
"mozTransform",
"oTransform"];
var transformProperty = getSupportedPropertyName(transforms);
// Array to store our Snowflake objects
var snowflakes = [];
// Global variables to store our browser's window size
var browserWidth;
var browserHeight;
// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 25;
// Flag to reset the position of the snowflakes
var resetPosition = false;
//
// It all starts here...
//
function setup() {
window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
window.addEventListener("resize", setResetFlag, false);
}
setup();
//
// Vendor prefix management
//
function getSupportedPropertyName(properties) {
for (var i = 0; i < properties.length; i++) {
if (typeof document.body.style[properties[i]] != "undefined") {
return properties[i];
}
}
return null;
}
//
// Constructor for our Snowflake object
//
function Snowflake(element, radius, speed, xPos, yPos) {
// set initial snowflake properties
this.element = element;
this.radius = radius;
this.speed = speed;
this.xPos = xPos;
this.yPos = yPos;
// declare variables used for snowflake's motion
this.counter = 0;
this.sign = Math.random() < 0.5 ? 1 : -1;
// setting an initial opacity and size for our snowflake
this.element.style.opacity = .1 + Math.random();
this.element.style.fontSize = 12 + Math.random() * 50 + "px";
}
//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function () {
// using some trigonometry to determine our x and y position
this.counter += this.speed / 5000;
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
// setting our snowflake's position
setTranslate3DTransform(this.element, Math.round(this.xPos), Math.round(this.yPos));
// if snowflake goes below the browser window, move it back to the top
if (this.yPos > browserHeight) {
this.yPos = -50;
}
}
//
// A performant way to set your snowflake's position
//
function setTranslate3DTransform(element, xPosition, yPosition) {
var val = "translate3d(" + xPosition + "px, " + yPosition + "px" + ", 0)";
element.style[transformProperty] = val;
}
//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {
// get our snowflake element from the DOM and store it
var originalSnowflake = document.querySelector(".snowflake");
// access our snowflake element's parent container
var snowflakeContainer = originalSnowflake.parentNode;
// get our browser's size
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeCopy = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeCopy);
// set our snowflake's initial position and related properties
var initialXPos = getPosition(50, browserWidth);
var initialYPos = getPosition(50, browserHeight);
var speed = 5+Math.random()*40;
var radius = 4+Math.random()*10;
// create our Snowflake object
var snowflakeObject = new Snowflake(snowflakeCopy,
radius,
speed,
initialXPos,
initialYPos);
snowflakes.push(snowflakeObject);
}
// remove the original snowflake because we no longer need it visible
snowflakeContainer.removeChild(originalSnowflake);
// call the moveSnowflakes function every 30 milliseconds
moveSnowflakes();
}
//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.update();
}
// Reset the position of all the snowflakes to a new value
if (resetPosition) {
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.xPos = getPosition(50, browserWidth);
snowflake.yPos = getPosition(50, browserHeight);
}
resetPosition = false;
}
requestAnimationFrame(moveSnowflakes);
}
//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
return Math.round(-1*offset + Math.random() * (size+2*offset));
}
//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
resetPosition = true;
}
Any help would be appreciated. Again the code works well in IE11 but the same exact code will not work in Chrome.
Related
I have a function that craeates divs with a circle.
Now they are all created and appear at the beginning of the page and go further in order.
Next, I need each circle to appear in a random place. I did this.
Now I need all of them to move randomly across the entire page, I have difficulties with this.
Here is an example of how everything works for one element that is already on the page.
https://jsfiddle.net/quej8wko/
But when I add this code, all my created circles don't move.
I get an error:
"message": "Uncaught TypeError: Cannot set properties of null (setting 'willChange')",
This is probably due to the fact that initially there are no circles on the page. How can I connect the code so that all created circles move?
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createDiv(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createDiv(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
clip-path: circle(50%);
height: 40px;
width: 40px;
margin: 20px;
position: absolute;
}
I have modified the snippet which works as you expected.
There was a mistake where you were initializing and creating the object instance only once and none of the div elements that you created inside the setInterval function never got Instantiated.
I think you are just starting out with JavaScript with this sample project.
Below are few suggestions:
Learn to debug the code. You should be using dev tools by making use of debugger statement where it takes you to the source code to analyze the variable scope and stack during the runtime. console.log also helps in few situations.
I could see a lot of confusing naming convention (You have named the create div parameter as id but creating a div class using that id)
Try using ES6 features (class syntax is really good when writing OOP in JS although it's just a syntactic sugar for prototype)
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createAndInitializeDivObject(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
var x = new RandomObjectMover(document.querySelector(`.${id}`), window);
x.start();
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createAndInitializeDivObject(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
width: 35px;
height: 35px;
border-radius: 35px;
background-color: #ffffff;
border: 3px solid purple;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="circle"></div>
<script src="app.js"></script>
</body>
</html>
I am using code from https://www.kirupa.com/html5/the_falling_snow_effect.htm and well as it turns out the snow is falling all over my page and not just the banner div...
// Array to store our Snowflake objects
var snowflakes = [];
// Global variables to store our browser's window size
var browserWidth;
var browserHeight;
// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 50;
// Flag to reset the position of the snowflakes
var resetPosition = false;
// Handle accessibility
var enableAnimations = false;
var reduceMotionQuery = matchMedia("(prefers-reduced-motion)");
// Handle animation accessibility preferences
function setAccessibilityState() {
if (reduceMotionQuery.matches) {
enableAnimations = false;
} else {
enableAnimations = true;
}
}
setAccessibilityState();
reduceMotionQuery.addListener(setAccessibilityState);
//
// It all starts here...
//
function setup() {
if (enableAnimations) {
window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
window.addEventListener("resize", setResetFlag, false);
}
}
setup();
//
// Constructor for our Snowflake object
//
function Snowflake(element, speed, xPos, yPos) {
// set initial snowflake properties
this.element = element;
this.speed = speed;
this.xPos = xPos;
this.yPos = yPos;
this.scale = 1;
// declare variables used for snowflake's motion
this.counter = 0;
this.sign = Math.random() < 0.5 ? 1 : -1;
// setting an initial opacity and size for our snowflake
this.element.style.opacity = (.9 + Math.random()) / 3;
}
//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function() {
// using some trigonometry to determine our x and y position
this.counter += this.speed / 5000;
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
this.scale = .5 + Math.abs(10 * Math.cos(this.counter) / 20);
// setting our snowflake's position
setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element);
// if snowflake goes below the browser window, move it back to the top
if (this.yPos > browserHeight) {
this.yPos = -50;
}
}
//
// A performant way to set your snowflake's position and size
//
function setTransform(xPos, yPos, scale, el) {
el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`;
}
//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {
// get our snowflake element from the DOM and store it
var originalSnowflake = document.querySelector(".snowflake");
// access our snowflake element's parent container
var snowflakeContainer = originalSnowflake.parentNode;
snowflakeContainer.style.display = "block";
// get our browser's size
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeClone = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeClone);
// set our snowflake's initial position and related properties
var initialXPos = getPosition(50, browserWidth);
var initialYPos = getPosition(50, browserHeight);
var speed = 5 + Math.random() * 40;
// create our Snowflake object
var snowflakeObject = new Snowflake(snowflakeClone,
speed,
initialXPos,
initialYPos);
snowflakes.push(snowflakeObject);
}
// remove the original snowflake because we no longer need it visible
snowflakeContainer.removeChild(originalSnowflake);
moveSnowflakes();
}
//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {
if (enableAnimations) {
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.update();
}
}
// Reset the position of all the snowflakes to a new value
if (resetPosition) {
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.xPos = getPosition(50, browserWidth);
snowflake.yPos = getPosition(50, browserHeight);
}
resetPosition = false;
}
requestAnimationFrame(moveSnowflakes);
}
//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
}
//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
resetPosition = true;
}
#snowflakeContainer {
position: absolute;
left: 0px;
top: 0px;
display: none;
}
.snowflake {
position: fixed;
background-color: #ffffff;
user-select: none;
z-index: 1000;
pointer-events: none;
border-radius: 50%;
width: 10px;
height: 10px;
}
<div class="mainbanner">
<div id="snowflakeContainer">
<span class="snowflake"></span>
</div>
<br>
<center>
<p class="topText" style="font-size:8vw;"> Welcome to the ultimate <br>sleepover experience</p><br><br><br>
<p class="topText" style="font-size:4vw;"> By Ultimate Teepee Party</p>
<br><br><br>
<a class="btn_1" href="book.html">Book Your Party</a></center>
</div>
There has to be a way to make it show only inside that banner div and not the whole page?
if you take a look at snow demo page with inspect element, you will realise that the author embedded a whole html page into the page instead of using a div, the idea is that javascript browserHeight = document.documentElement.clientHeight refers to browser width, therefore unless modifying JS, the page only works in whole page, I could see no effect in your original code since the relative positioning is not handled well. refers to following working demo, which allows you to display the snow in whole page. if you only want the effect to apply to a certain element, try modifying the script calculation based on element position. or you can do what the author did, embed a doc into whole page
JsFiddle
<style>
#snowflakeContainer {
position: fixed;
left: 0px;
top: 0px;
display: none;
width: 100vw;
height: 100vh;
}
.snowflake {
position: fixed;
background-color: #CCC;
user-select: none;
z-index: 1000;
pointer-events: none;
border-radius: 50%;
width: 10px;
height: 10px;
background: red;
}
.banner {
position: fixed;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.title {
font-size: 8vw;
}
.author {
font-size: 4vw;
}
</style>
<div id="snowflakeContainer">
<span class="snowflake"></span>
<div class="banner">
<div class="title">
Welcome to the ultimate
</div>
<div class="title">
sleepover experience
</div>
<br />
<br />
<br />
<div class="author">
By Ultimate Teepee Party
</div>
<br />
<br />
<br />
<a class="btn_1" href="book.html">Book Your Party</a>
</div>
</div>
<script>
// Array to store our Snowflake objects
var snowflakes = [];
// Global variables to store our browser's window size
var browserWidth;
var browserHeight;
// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 50;
// Flag to reset the position of the snowflakes
var resetPosition = false;
// Handle accessibility
var enableAnimations = false;
var reduceMotionQuery = matchMedia("(prefers-reduced-motion)");
// Handle animation accessibility preferences
function setAccessibilityState() {
if (reduceMotionQuery.matches) {
enableAnimations = false;
} else {
enableAnimations = true;
}
}
setAccessibilityState();
reduceMotionQuery.addListener(setAccessibilityState);
//
// It all starts here...
//
function setup() {
if (enableAnimations) {
window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
window.addEventListener("resize", setResetFlag, false);
}
}
setup();
//
// Constructor for our Snowflake object
//
function Snowflake(element, speed, xPos, yPos) {
// set initial snowflake properties
this.element = element;
this.speed = speed;
this.xPos = xPos;
this.yPos = yPos;
this.scale = 1;
// declare variables used for snowflake's motion
this.counter = 0;
this.sign = Math.random() < 0.5 ? 1 : -1;
// setting an initial opacity and size for our snowflake
this.element.style.opacity = (.1 + Math.random()) / 3;
}
//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function() {
// using some trigonometry to determine our x and y position
this.counter += this.speed / 5000;
this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
this.scale = .5 + Math.abs(10 * Math.cos(this.counter) / 20);
// setting our snowflake's position
setTransform(Math.round(this.xPos), Math.round(this.yPos), this.scale, this.element);
// if snowflake goes below the browser window, move it back to the top
if (this.yPos > browserHeight) {
this.yPos = -50;
}
}
//
// A performant way to set your snowflake's position and size
//
function setTransform(xPos, yPos, scale, el) {
el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`;
}
//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {
// get our snowflake element from the DOM and store it
var originalSnowflake = document.querySelector(".snowflake");
// access our snowflake element's parent container
var snowflakeContainer = originalSnowflake.parentNode;
snowflakeContainer.style.display = "block";
// get our browser's size
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
// create each individual snowflake
for (var i = 0; i < numberOfSnowflakes; i++) {
// clone our original snowflake and add it to snowflakeContainer
var snowflakeClone = originalSnowflake.cloneNode(true);
snowflakeContainer.appendChild(snowflakeClone);
// set our snowflake's initial position and related properties
var initialXPos = getPosition(50, browserWidth);
var initialYPos = getPosition(50, browserHeight);
var speed = 5 + Math.random() * 40;
// create our Snowflake object
var snowflakeObject = new Snowflake(snowflakeClone,
speed,
initialXPos,
initialYPos);
snowflakes.push(snowflakeObject);
}
// remove the original snowflake because we no longer need it visible
snowflakeContainer.removeChild(originalSnowflake);
moveSnowflakes();
}
//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {
if (enableAnimations) {
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.update();
}
}
// Reset the position of all the snowflakes to a new value
if (resetPosition) {
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
for (var i = 0; i < snowflakes.length; i++) {
var snowflake = snowflakes[i];
snowflake.xPos = getPosition(50, browserWidth);
snowflake.yPos = getPosition(50, browserHeight);
}
resetPosition = false;
}
requestAnimationFrame(moveSnowflakes);
}
//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
}
//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
resetPosition = true;
}
</script>
I have 2 sets of code in here. One is the simple bounce off code. The other is a function. I've tried to make it a function but it doesn't seem to be working properly.
The bg framerate doesn't clear in the sense that a string of balls show rather than a ball bouncing and animating.
if(this.y_pos > 400) this condition doesn't seem to be working even tho it works when it is drawn in the draw function.
var sketch = function (p) {
with(p) {
p.setup = function() {
createCanvas(800, 600);
// x_pos = 799;
// y_pos = 100;
// spdx = -random(5,10);
// spdy = random(12,17);
};
p.draw = function() {
background(0);
// fill(255);
// ellipse(x_pos,y_pos,50);
// x_pos += spdx;
// y_pos += spdy;
// if(y_pos > 400)
// {
// spdy *= -1;
// }
// for( var i = 0; i < 10; i++)
avalance(799, 100, random(5,10), random(12,17));
};
function avalance(x, y, spdx, spdy)
{
this.x_pos = x;
this.y_pos = y;
this.spdx = spdx;
this.spdy = spdy;
this.x_pos = 799;
this.y_pos = 100;
this.spdx = 1;
this.spdy = 1;
this.movement = function()
{
this.x_pos += -spdx;
this.y_pos += spdy;
if(this.y_pos > 400)
{
this.spdy *= -1;
}
}
this.draw = function()
{
this.movement();
this.drawnRox();
}
this.drawnRox = function()
{
fill(255);
ellipse(this.x_pos,this.y_pos,50);
}
}
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
Let's address both issues:
The draw() function is called for each new frame and in it you call avalance which creates a new ball. To fix that you need to
Create a global variable let ball; out of setup() and draw() so that you can reuse that later;
In setup create a new ball and assign it to your ball variable: ball = new avalance(799, 100, random(5,10), random(12,17));
In draw() you want to update the ball and that's what its own draw() function does (I would advise renaming it update() for example, to avoid confusion with the p5 specific draw() function). So you just need to call ball.draw() in draw().
This creates a ball which moves but still don't respect your 400px limit.
The issue is that in movement() you add spdx and spdy to the position but when the ball crosses the limit you update this.spdy, so you need to update the function with this code:
this.x_pos += -this.spdx;
this.y_pos += this.spdy;
And you should be good! Here is a code pend with your code working as you intend.
Also as a bonus advise: You probably want to use some p5.Vector objects to store positions, speeds and accelerations it really makes your code easier to read and to use. You could also rename your function Avalance (capital A) to show that you actually use a class and that this function shouldn't be called without new.
As #statox suggested, do new avalance(799, 100, random(5,10), random(12,17)) in the setup() section and call draw of the ball in draw() section.
You can test the code below by clicking "Run code snippet".
var sketch = function (p) {
with(p) {
var ball;
p.setup = function() {
createCanvas(800, 600);
ball = new avalance(799, 100, random(5,10), random(12,17));
};
p.draw = function() {
background(0);
ball.draw();
};
function avalance(x, y, spdx, spdy)
{
function movement ()
{
x += -spdx;
y += spdy;
if (y > height || y < 0)
{
spdy *= -1;
}
if (x > width || x < 0)
{
spdx *= -1;
}
}
this.draw = function()
{
movement();
drawnRox();
}
function drawnRox ()
{
fill(255);
ellipse(x,y,50);
}
}
}
};
let node = document.createElement('div');
window.document.getElementById('p5-container').appendChild(node);
new p5(sketch, node);
body {
background-color:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<div id="p5-container"></div>
I am currently working on a project in Code.org's Game Lab. In this game, if the object(bee) collides with another object, it's velocity should increase permanently. Is there any way to do this? Here is a link:
https://studio.code.org/projects/gamelab/bObYvRkfcSN938ptuiIyH0ZdF1de4jhaiOYZLgfTTwM/edit
Here is a code snippet:
//Making the bee
var bee = createSprite(200, 200);
//Set animation for 'bee' as bee_1
bee.setAnimation("bee_1");
//Scaling the bee tp 0.5x
bee.scale = 0.5;
var velocity = 2;
bee.velocityY = velocity;
//Making the walls
function draw() {
background("white");
createEdgeSprites();
bee.bounceOff(edges);
if (bee.isTouching(edges)) {
velocity = velocity * 1.25;
}
/*
if (keyDown("up")) {
bee.velocityX = 0;
bee.velocityY = velocity * -1;
}
else if (keyDown("down")) {
bee.velocityX = 0;
bee.velocityY = velocity;
}
else if (keyDown("right")) {
bee.velocityX = velocit;
bee.velocityY = 0;
}
else if (keyDown("left")) {
bee.velocityX = -2;
bee.velocityY = 0;
}
if (velocity>15) {
velocity = 10;
}
else if (velocity<-15) {
velocity = -10;
}*/
drawSprites();
}
Unfortunately, the snippet cannot be run as I don't have access to the HTML and CSS code. I have tried using the isTouching() method, but that method only works as long as the bee is touching the walls. I need a way to make it so that when the bee collides with any object (I plan on adding more sprites which will function as walls), the velocity variable is set to 1.25 times itself. i.e.
if (<insert condition here>) {
velocity = velocity * 1.25;
}
I would appreciate any other tips on how to improve my code also.
I did what you wanted me to do for the velocity, and added how I think you could improve your code. You don't have to do the changes if you don't want to. It is just optional. Here is the code of the conditional by itself:
if (bee.bounceOff(s_edges)) {
velocity = velocity * 1.25;
}
if you want the full code then here it is:
showMobileControls(false, true, true, true);
var player = createGroup();
//Making the bee
var bee = createSprite(200,200);
//Set animation for 'bee' as bee_1
bee.setAnimation("bee_1");
//Scaling the bee to 0.5x
//I changed it to 1 for us to see it better. I also made the "exit" bigger
bee.scale = 1;
player.add(bee);
//Game Over animation
var endAnimation = createGroup();
var gameOver = createSprite(200,200);
gameOver.setAnimation("GameOver");
gameOver.scale = 0.5;
endAnimation.add(gameOver);
//I turned it off for it to look "better"
bee.debug = false;
var velocity = 5;
//Making the edges
var s_edges = createGroup();
var edge_left = createSprite(2.5,200,5,400);
var ebound_left = createSprite(2.49,200,5,400);
var edge_right = createSprite(397.5,200,5,400);
var ebound_right = createSprite(397.61,200,5,400);
var edge_top = createSprite(200,2.5,400,5);
var ebound_top = createSprite(200,2.49,400,5);
var edge_bottom = createSprite(132.5,397.7,355,5);
var ebound_bottom = createSprite(170,397.5,340,5);
var bound = createSprite(370,440,100,30);
var left_bound = createSprite(311,408,8,40);
var right_bound = createSprite(397,408,10,40);
s_edges.add(edge_left);
s_edges.add(edge_right);
s_edges.add(edge_top);
s_edges.add(edge_bottom);
var bounds = createGroup();
bounds.add(bound);
bounds.add(left_bound);
bounds.add(right_bound);
var failsafe = createGroup();
failsafe.add(ebound_bottom);
function draw() {
var checker = bee.isTouching(s_edges);
background("white");
if (checker === true) {
velocity = velocity *1.25;
}
if (keyDown("up")) {
bee.velocityX = 0;
bee.velocityY = velocity * -1;
}
else if (keyDown("down")) {
bee.velocityX = 0;
bee.velocityY = velocity;
}
else if (keyDown("right")) {
bee.velocityX = velocity;
bee.velocityY = 0;
}
else if (keyDown("left")) {
bee.velocityX = velocity * -1;
bee.velocityY = 0;
}
if (velocity>25) {
velocity = 10;
}
else if (velocity<-25) {
velocity = -10;
}
//I did what you wanted for the increase velocity over here
if (bee.bounceOff(s_edges)) {
velocity = velocity * 1.25;
}
bee.bounceOff(s_edges);
bee.collide(bounds);
failsafe.collide(bee);
drawSprites(s_edges);
drawSprites(player);
drawSprites(bounds);
//I changed the bee x and y
if (bee.y>390 && 311<bee.x<311) {
bee.destroy();
background("gray");
drawSprites(endAnimation);
}
}
If you want it in code.org then here it is:
https://studio.code.org/projects/gamelab/9Plf9wVdWthBxs8ML0ebRFWoQ73oI_VPiUk_o_tNhtk
I'm using setInterval to call a function that animates a fractal on a HTML5 canvas. There is also a slider to allow the user to change the quality of the fractal. Everything works fine until I start changing the slider. When I change it, the fractal animation becomes choppy, and eventually the "drawFractal" function stops being called.
Here is the slider HTML:
<input type="range" id="qualitySlider" min="1" max="10"></input>
Here is the javascript (it just generates a fractal):
var count = 0.5;
var slider = document.getElementById("qualitySlider");
var g = document.getElementById("drawingCanvas").getContext("2d");
function drawFractal() {
var cellSize = Math.ceil(slider.value);
//canvas is 700 by 400
g.fillStyle = "black";
g.clearRect(0, 0, 700, 400);
//Eveything from here to the end of this function generates the fractal
var imagC = Math.cos(count)*0.8;
var realC = Math.sin(count)*0.5;
for (x = 0; x < 700; x+=cellSize) {
for (y = 0; y < 400; y+=cellSize) {
var yCoord = (x / 700.0 - 0.5)*3;
var xCoord = (y / 400.0 - 0.5)*3;
var real = xCoord;
var imag = yCoord;
var broken = 0;
for (i = 0; i < 8; i++) {
var temp = real*real - imag*imag + realC;
imag = 2*imag*real + imagC;
real = temp;
if (real*real + imag*imag >= 4) {
broken = true;
break;
}
}
if (!broken) {
g.fillRect(x, y, cellSize, cellSize);
}
}
}
count = count + 0.04;
}
setInterval(drawFractal, 60);
I just need the "drawFractal" function to be called reliably every 60 milliseconds.
This is my improved code. I just used requestAnimationFrame to recursively call the "drawFractal" function. I also restricted the animation to 24 frames/sec with the setTimeout function.
var count = 0.5;
var qualitySlider = document.getElementById("qualitySlider");
var g = document.getElementById("drawingCanvas").getContext("2d");
function drawFractal() {
var cellSize = Math.ceil(qualitySlider.value);
//canvas is 700 by 400
g.fillStyle = "black";
g.clearRect(0, 0, 700, 400);
var imagC = Math.cos(count)*0.8;
var realC = Math.sin(count)*0.5;
for (x = 0; x < 700; x+=cellSize) {
for (y = 0; y < 400; y+=cellSize) {
var yCoord = (x / 700.0 - 0.5)*3;
var xCoord = (y / 400.0 - 0.5)*3;
var real = xCoord;
var imag = yCoord;
var broken = 0;
for (i = 0; i < 8; i++) {
var temp = real*real - imag*imag + realC;
imag = 2*imag*real + imagC;
real = temp;
if (real*real + imag*imag >= 4) {
broken = true;
break;
}
}
if (!broken) {
g.fillRect(x, y, cellSize, cellSize);
}
}
}
count = count + 0.04;
setTimeout(function() {
requestAnimationFrame(drawFractal);
}, 41);
}
drawFractal();
You are using setInterval() to call drawFractal every 60 ms, and then every time drawFractal is executed, you're calling setInterval() again, which is unnecessary. You now have two timers attempting to draw fractals every 60 ms... then you'll have 4, then 8, etc.
You need to either (1) call setInterval() once at the start of program execution and not call it again, or (2) switch to using setTimeout(), and call it at the end of each drawFractal().
I'd use the second option, just in case your fractal ever takes more than 60 ms to draw.