I have been trying to use an Animated Background, using Javascript I found on this link : https://codepen.io/nashvail/pen/wpGgXO
It's working fine. But the problem is that once implemented, it's all over the screen.
I want the animations to be in some particular DIV element of my web page.
Help me Out.
// Some random colors
const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
const numBalls = 50;
const balls = [];
for (let i = 0; i < numBalls; i++) {
let ball = document.createElement("div");
ball.classList.add("ball");
ball.style.background = colors[Math.floor(Math.random() * colors.length)];
ball.style.left = `${Math.floor(Math.random() * 100)}vw`;
ball.style.top = `${Math.floor(Math.random() * 100)}vh`;
ball.style.transform = `scale(${Math.random()})`;
ball.style.width = `${Math.random()}em`;
ball.style.height = ball.style.width;
balls.push(ball);
document.body.append(ball);
}
// Keyframes
balls.forEach((el, i, ra) => {
let to = {
x: Math.random() * (i % 2 === 0 ? -11 : 11),
y: Math.random() * 12
};
let anim = el.animate(
[
{ transform: "translate(0, 0)" },
{ transform: `translate(${to.x}rem, ${to.y}rem)` }
],
{
duration: (Math.random() + 1) * 2000, // random duration
direction: "alternate",
fill: "both",
iterations: Infinity,
easing: "ease-in-out"
}
);
});
.ball {
position: absolute;
border-radius: 100%;
opacity: 0.7;
}
<div class="ball">
</div>
Like this?
// Some random colors
const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
const numBalls = 50;
const balls = [];
for (let i = 0; i < numBalls; i++) {
let ball = document.createElement("div");
ball.classList.add("ball");
ball.style.background = colors[Math.floor(Math.random() * colors.length)];
ball.style.left = `${Math.floor(Math.random() * 100)}%`;
ball.style.top = `${Math.floor(Math.random() * 100)}%`;
ball.style.transform = `scale(${Math.random()})`;
ball.style.width = `${Math.random()}em`;
ball.style.height = ball.style.width;
balls.push(ball);
document.getElementById("box").append(ball);
}
// Keyframes
balls.forEach((el, i, ra) => {
let to = {
x: Math.random() * (i % 2 === 0 ? -11 : 11),
y: Math.random() * 12
};
let anim = el.animate(
[
{ transform: "translate(0, 0)" },
{ transform: `translate(${to.x}rem, ${to.y}rem)` }
],
{
duration: (Math.random() + 1) * 2000, // random duration
direction: "alternate",
fill: "both",
iterations: Infinity,
easing: "ease-in-out"
}
);
});
.ball {
position: absolute;
border-radius: 100%;
opacity: 0.7;
}
#box{
width: 300px;
height: 300px;
border: 1px solid red;
position: relative;
overflow: hidden;
}
<div id="box"></div>
The issue is, you are appending balls to the body. That's why they are appearing all over the screen. You have to make a container with some width and height and append the created balls to that container only:
// Some random colors
const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
const numBalls = 50;
const balls = [];
for (let i = 0; i < numBalls; i++) {
let ball = document.createElement("div");
ball.classList.add("ball");
ball.style.background = colors[Math.floor(Math.random() * colors.length)];
ball.style.left = `${Math.floor(Math.random() * 100)}vw`;
ball.style.top = `${Math.floor(Math.random() * 100)}vh`;
ball.style.transform = `scale(${Math.random()})`;
ball.style.width = `${Math.random()}em`;
ball.style.height = ball.style.width;
balls.push(ball);
document.querySelector('.ballContainer').append(ball);
}
// Keyframes
balls.forEach((el, i, ra) => {
let to = {
x: Math.random() * (i % 2 === 0 ? -11 : 11),
y: Math.random() * 12
};
let anim = el.animate(
[
{ transform: "translate(0, 0)" },
{ transform: `translate(${to.x}rem, ${to.y}rem)` }
],
{
duration: (Math.random() + 1) * 2000, // random duration
direction: "alternate",
fill: "both",
iterations: Infinity,
easing: "ease-in-out"
}
);
});
.ball {
position: absolute;
border-radius: 100%;
opacity: 0.7;
}
.ballContainer{
width: 350px;
height: 175px;
border: 1px solid gray;
position: relative;
overflow: hidden;
background-color: lightgray;
}
<div class="ballContainer">
</div>
The balls run a random path. That means some of balls will go out of bounds (your div).
You can add CSS to hide the scroll bars.
html * {
overflow: hidden;
}
Related
There is an animation of the flight of leaves in pure js. The problem is that it needs to be optimized for maximum performance, because there will be more animations of this kind on the page. Besides optimizing the original SVG image and reducing the number of leaflets, what tips can you give to improve the performance of your code?
var LeafScene = function(el) {
this.viewport = el;
this.world = document.createElement('div');
this.leaves = [];
this.options = {
numLeaves: 6,
wind: {
magnitude: 0,
maxSpeed: 12,
duration: 300,
start: 0,
speed: 10
},
};
this.width = this.viewport.offsetWidth;
this.height = this.viewport.offsetHeight;
this.timer = 0;
this._resetLeaf = function(leaf) {
leaf.x = this.width * 2 - Math.random()*this.width*1.75;
leaf.y = -10;
leaf.z = Math.random()*200;
if (leaf.x > this.width) {
leaf.x = this.width + 10;
leaf.y = Math.random()*this.height/2;
}
if (this.timer == 0) {
leaf.y = Math.random()*this.height;
}
leaf.rotation.speed = Math.random()*10;
var randomAxis = Math.random();
if (randomAxis > 0.5) {
leaf.rotation.axis = 'X';
} else if (randomAxis > 0.25) {
leaf.rotation.axis = 'Y';
leaf.rotation.x = Math.random()*180 + 90;
} else {
leaf.rotation.axis = 'Z';
leaf.rotation.x = Math.random()*360 - 180;
leaf.rotation.speed = Math.random()*3;
}
leaf.xSpeedVariation = Math.random() * 0.8 - 0.4;
leaf.ySpeed = Math.random() + 1.5;
return leaf;
}
this._updateLeaf = function(leaf) {
var leafWindSpeed = this.options.wind.speed(this.timer - this.options.wind.start, leaf.y);
var xSpeed = leafWindSpeed + leaf.xSpeedVariation;
leaf.x -= xSpeed;
leaf.y += leaf.ySpeed;
leaf.rotation.value += leaf.rotation.speed;
var t = 'translateX( ' + leaf.x + 'px ) translateY( ' + leaf.y + 'px ) translateZ( ' + leaf.z + 'px ) rotate' + leaf.rotation.axis + '( ' + leaf.rotation.value + 'deg )';
if (leaf.rotation.axis !== 'X') {
t += ' rotateX(' + leaf.rotation.x + 'deg)';
}
leaf.el.style.webkitTransform = t;
leaf.el.style.MozTransform = t;
leaf.el.style.oTransform = t;
leaf.el.style.transform = t;
if (leaf.x < -10 || leaf.y > this.height + 10) {
this._resetLeaf(leaf);
}
}
this._updateWind = function() {
if (this.timer === 0 || this.timer > (this.options.wind.start + this.options.wind.duration)) {
this.options.wind.magnitude = Math.random() * this.options.wind.maxSpeed;
this.options.wind.duration = this.options.wind.magnitude * 50 + (Math.random() * 20 - 10);
this.options.wind.start = this.timer;
var screenHeight = this.height;
this.options.wind.speed = function(t, y) {
var a = this.magnitude/2 * (screenHeight - 2*y/3)/screenHeight;
return a * Math.sin(2*Math.PI/this.duration * t + (3 * Math.PI/2)) + a;
}
}
}
}
LeafScene.prototype.init = function() {
for (var i = 0; i < this.options.numLeaves; i++) {
var leaf = {
el: document.createElement('div'),
x: 0,
y: 0,
z: 0,
rotation: {
axis: 'X',
value: 0,
speed: 0,
x: 0
},
xSpeedVariation: 0,
ySpeed: 0,
path: {
type: 1,
start: 0,
},
image: 1
};
this._resetLeaf(leaf);
this.leaves.push(leaf);
this.world.appendChild(leaf.el);
}
this.world.className = 'leaf-scene';
this.viewport.appendChild(this.world);
this.world.style.webkitPerspective = "400px";
this.world.style.MozPerspective = "400px";
this.world.style.oPerspective = "400px";
this.world.style.perspective = "400px";
var self = this;
window.onresize = function(event) {
self.width = self.viewport.offsetWidth;
self.height = self.viewport.offsetHeight;
};
}
LeafScene.prototype.render = function() {
this._updateWind();
for (var i = 0; i < this.leaves.length; i++) {
this._updateLeaf(this.leaves[i]);
}
this.timer++;
requestAnimationFrame(this.render.bind(this));
}
var leafContainer = document.querySelector('.falling-leaves'),
leaves = new LeafScene(leafContainer);
leaves.init();
leaves.render();
body, html {
height: 100%;
}
.falling-leaves {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 100%;
max-width: 880px;
max-height: 880px;
transform: translate(-50%, 0);
border: 20px solid #fff;
border-radius: 50px;
background-size: cover;
overflow: hidden;
}
.leaf-scene {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
transform-style: preserve-3d;
}
.leaf-scene div {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background: url(https://www.flaticon.com/svg/static/icons/svg/892/892881.svg) no-repeat;
background-size: 100%;
transform-style: preserve-3d;
-webkit-backface-visibility: visible;
backface-visibility: visible;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<div class="falling-leaves"></div>
Unless you're using HTML Canvas, vanilla JS solutions are pretty heavy compared to CSS/JS hybrid because of the browser call stack.
It looks like this:
JS > Style > Layout > Paint > Composite
By minimizing the amount of calculations the browser has to do in JS and grouping reads/writes to the DOM you'll see a significant performance increase. The workload can be recorded with Chrome Dev tools under 'Performance' tab. And you'll be able to see every step the browser is taking to display the content. The less steps, the better performance .. simple as that.
You're writing to the DOM every single transform which is heavy even with 3d acceleration.
I usually make use of CSS variables and transitions for dynamic animation that I update in steps.
What you did is great otherwise. Try rendering on a HTML Canvas and your performance problems will vanish. Here's a start:
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
But if you want or cant do canvas adapt to utilize CSS to not drop further than the Paint browser call for majority of frames.
https://codepen.io/jesserosenfield/pen/LYNGRXV
var path = anime.path('#prog-svg path'),
pathEl = document.querySelectorAll('#prog-svg path')[0],
mylength = pathEl.getTotalLength(),
mypt1 = pathEl.getPointAtLength(mylength * .10),
mypt2 = pathEl.getPointAtLength(mylength * .25);
var motionPath = anime({
targets: '.prog-circ',
translateX: path('x'),
translateY: path('y'),
rotate: path('angle'),
easing: 'easeInOutCirc',
duration: 5000,
direction: 'alternate',
autoplay: false,
elasticity: 200,
loop: false,
update: function(anim){
console.log(path('x'));
}
});
motionPath.seek(1210);
motionPath.play();
This code does what I want it to do in the broad scheme of things, but I have a more specific use case.
I'm using this SVG as a progress bar on a form:
When the user completes step #1 of the form, I want the circle to animate from point A to point B. When the user completes step #2 of the form, I want the circle to animate from point B to point C... and so on.
While motionpath.seek() gets me to the correct point along the path, it sets the circle there with no animation– is there an equivalent function to seek() that will get ANIMATE the circle rather than just set it?
Furthermore I attempted to use getTotalLength() and getPointAtLength() to try and animate like so:
var motionPath = anime({
targets: '.prog-circ',
translateX: [mypt1.x, mypt2.x],
translateY: [mypt1.y, mypt2.y],
but that did not animate the circle along the path.
Any help much appreciated. Thanks!
With one long path I think it's hard to support moving between points since you need to track current progress and convert it to actual length depending on easing function.
I'd split your <path/> into 3 pieces, generate timeline for animation between those 3 pieces and then easily manipulate moving circle back and forth.
Here's an example of how it can be done:
const svg = document.getElementById('prog-svg');
const pathEl = document.querySelector('#prog-svg path');
const totalLength = pathEl.getTotalLength();
const points = [['A', 10], ['B', 25], ['C', 75], ['D', 90]];
function splitPath() {
const interval = 3;
const toLen = percentage => percentage * totalLength / 100;
const paths = [];
for (let i = 0; i < points.length; i++) {
const from = toLen(points[i][1]);
for (let j = i + 1; j < points.length; j++) {
const to = toLen(points[j][1]);
const segments = [];
for (let k = from; k <= to; k += interval) {
const { x, y } = pathEl.getPointAtLength(k);
segments.push([x, y]);
}
paths.push({
segments, path: `${i}-${j}`
});
}
}
paths.forEach(subPath => {
const subPathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
subPathEl.setAttribute('class', `st0 st0--hidden`);
subPathEl.setAttribute('d', `M ${subPath.segments.map(([x, y]) => `${x},${y}`).join(' ')}`);
svg.appendChild(subPathEl);
subPath.el = subPathEl;
});
return paths;
}
const subPaths = splitPath();
function addPoint(name, progress) {
const point = pathEl.getPointAtLength(totalLength * progress / 100);
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('fill', '#fff');
text.setAttribute('font-size', '1.6em');
text.textContent = name;
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('r', '30');
circle.setAttribute('fill', '#000');
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
g.setAttribute('transform', `translate(${point.x},${point.y})`);
g.appendChild(circle);
g.appendChild(text);
svg.appendChild(g);
// center text
const textBB = text.getBBox();
const centerX = textBB.width / 2;
const centerY = textBB.height / 4;
text.setAttribute('transform', `translate(${-centerX},${centerY})`);
return circle;
}
points.forEach(([name, progress]) => addPoint(name, progress));
const progressCircle = document.querySelector('.prog-circ');
progressCircle.style.display = 'block';
const animations = subPaths.map(subPath => {
const animePath = anime.path(subPath.el);
return anime({
targets: progressCircle,
easing: 'easeInOutCirc',
autoplay: false,
duration: 1000,
translateX: animePath('x'),
translateY: animePath('y'),
rotate: animePath('angle'),
});
});
// move circle to the first point
animations[0].reset();
let currentStep = 0;
function moveTo(step) {
if (step < 0 || step > animations.length) return;
const delta = step - currentStep;
const path = delta > 0 ? `${currentStep}-${step}` : `${step}-${currentStep}`;
const animationIndex = subPaths.findIndex(subPath => subPath.path === path);
const animationToPlay = animations[animationIndex];
if (delta < 0 && !animationToPlay.reversed) {
animationToPlay.reverse();
}
if (delta > 0 && animationToPlay.reversed) {
animationToPlay.reverse();
}
animationToPlay.reset();
animationToPlay.play();
currentStep = step;
pagination.selectedIndex = step;
}
const btnPrev = document.getElementById('btn-prev');
const btnNext = document.getElementById('btn-next');
const pagination = document.getElementById('pagination');
btnPrev.addEventListener('click', () => moveTo(currentStep - 1));
btnNext.addEventListener('click', () => moveTo(currentStep + 1));
pagination.addEventListener('change', (e) => moveTo(+e.target.value));
body {
margin: 0;
}
.st0 {
fill: none;
stroke: #000000;
stroke-width: 5;
stroke-linecap: round;
stroke-miterlimit: 160;
stroke-dasharray: 28;
}
.st0--hidden {
stroke: none;
}
.prog-circ {
display: none;
position: absolute;
border-radius: 100%;
height: 30px;
width: 30px;
top: -15px;
left: -15px;
background: #ccc;
opacity: .7;
}
.form-actions {
margin-top: 2em;
display: flex;
justify-content: center;
}
#pagination,
.form-actions button + button {
margin-left: 2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js"></script>
<svg id="prog-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1919.1 155.4">
<g>
<path class="st0" d="M4,84.1c0,0,58.8-57.1,235.1,17.9s348.1,18.9,470.2-44.6C800.6,9.7,869.6-2,953.5,6.6c0,0,19,4.1,38.6,14.4
c20.7,10.9,40.7,40.6,40.7,65.6c0,40.2-29.5,64.8-69.7,64.8s-70.1-29.2-70.1-69.4c0-32.3,31.2-59.6,61.8-61.8
c67.2-4.7,103.5-46.8,375.6,70.1c164.9,70.8,220.1-1.1,371.1-11.7c120.5-8.4,213.7,28.6,213.7,28.6"/>
</g>
</svg>
<div class="prog-circ"></div>
<div class="form-actions">
<button id="btn-prev">Prev</button>
<button id="btn-next">Next</button>
<select id="pagination">
<option value="0">A</option>
<option value="1">B</option>
<option value="2">C</option>
<option value="3">D</option>
</select>
</div>
Good day Guys,
I am trying to use a spinner that shows on the entire page when i click on Submit button. The below are the codes snippets.
This is the JS code
<script type="text/javascript"
src="#Url.Content("~/Scripts/spin.js")"></script>
<script type="text/javascript">
$(function () {
$("#searchbtn").click(function () {
$("#loading").fadeIn();
var opts = {
lines: 12, // The number of lines to draw
length: 7, // The length of each line
width: 4, // The line thickness
radius: 10, // The radius of the inner circle
color: '#000', // #rgb or #rrggbb
speed: 1, // Rounds per second
trail: 60, // Afterglow percentage
shadow: false, // Whether to render a shadow
hwaccel: false // Whether to use hardware acceleration
};
var target = document.getElementById('loading');
//var spinner = new Spinner(opts).spin(target);
var spinner = new Spin.Spinner(opts).spin(target);
});
});
This is the CSS below
#loading {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(255,255,255,0.8);
z-index: 1000;
}
#loadingcontent {
display: table;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
#loadingspinner {
display: table-cell;
vertical-align: middle;
width: 100%;
text-align: center;
font-size: larger;
padding-top: 80px;
}
Below is the DIV that holds the searching.
<div id="loading">
<div id="loadingcontent">
<p id="loadingspinner">
Searching things...
</p>
</div>
</div>
<div class="col-md-12">
<p>
#using (Html.BeginForm("AllLoanProcessed", "Transactions", new { area = "Transactions" }, FormMethod.Get))
{
<b>Search By:</b>
#Html.RadioButton("searchBy", "Account_Number", true) <text>Account Number</text>
#Html.RadioButton("searchBy", "Surname") <text> Surname </text> <br />
#Html.TextBox("search", null, new { placeholder = "Search Value", #class = "form-control" })
<br />
<input type="submit" value="Search" id="searchbtn" class="btn btn-primary btn-block" />
}
</p>
</div>
The issue is that, when i click on the search button, The spin does not load.
Am I missing something? OR any one has any other spinner method that works that will cover the whole page when running.
EDIT:
The below is the spin.js file content.
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var defaults = {
lines: 12,
length: 7,
width: 5,
radius: 10,
scale: 1.0,
corners: 1,
color: '#000',
fadeColor: 'transparent',
animation: 'spinner-line-fade-default',
rotate: 0,
direction: 1,
speed: 1,
zIndex: 2e9,
className: 'spinner',
top: '50%',
left: '50%',
shadow: '0 0 1px transparent',
position: 'absolute',
};
var Spinner = /** #class */ (function () {
function Spinner(opts) {
if (opts === void 0) { opts = {}; }
this.opts = __assign(__assign({}, defaults), opts);
}
/**
* Adds the spinner to the given target element. If this instance is already
* spinning, it is automatically removed from its previous target by calling
* stop() internally.
*/
Spinner.prototype.spin = function (target) {
this.stop();
this.el = document.createElement('div');
this.el.className = this.opts.className;
this.el.setAttribute('role', 'progressbar');
css(this.el, {
position: this.opts.position,
width: 0,
zIndex: this.opts.zIndex,
left: this.opts.left,
top: this.opts.top,
transform: "scale(" + this.opts.scale + ")",
});
if (target) {
target.insertBefore(this.el, target.firstChild || null);
}
drawLines(this.el, this.opts);
return this;
};
/**
* Stops and removes the Spinner.
* Stopped spinners may be reused by calling spin() again.
*/
Spinner.prototype.stop = function () {
if (this.el) {
if (typeof requestAnimationFrame !== 'undefined') {
cancelAnimationFrame(this.animateId);
}
else {
clearTimeout(this.animateId);
}
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
this.el = undefined;
}
return this;
};
return Spinner;
}());
export { Spinner };
/**
* Sets multiple style properties at once.
*/
function css(el, props) {
for (var prop in props) {
el.style[prop] = props[prop];
}
return el;
}
/**
* Returns the line color from the given string or array.
*/
function getColor(color, idx) {
return typeof color == 'string' ? color : color[idx % color.length];
}
/**
* Internal method that draws the individual lines.
*/
function drawLines(el, opts) {
var borderRadius = (Math.round(opts.corners * opts.width * 500) / 1000) +
'px';
var shadow = 'none';
if (opts.shadow === true) {
shadow = '0 2px 4px #000'; // default shadow
}
else if (typeof opts.shadow === 'string') {
shadow = opts.shadow;
}
var shadows = parseBoxShadow(shadow);
for (var i = 0; i < opts.lines; i++) {
var degrees = ~~(360 / opts.lines * i + opts.rotate);
var backgroundLine = css(document.createElement('div'), {
position: 'absolute',
top: -opts.width / 2 + "px",
width: (opts.length + opts.width) + 'px',
height: opts.width + 'px',
background: getColor(opts.fadeColor, i),
borderRadius: borderRadius,
transformOrigin: 'left',
transform: "rotate(" + degrees + "deg) translateX(" + opts.radius +
"px)",
});
var delay = i * opts.direction / opts.lines / opts.speed;
delay -= 1 / opts.speed; // so initial animation state will include trail
var line = css(document.createElement('div'), {
width: '100%',
height: '100%',
background: getColor(opts.color, i),
borderRadius: borderRadius,
boxShadow: normalizeShadow(shadows, degrees),
animation: 1 / opts.speed + "s linear " + delay + "s infinite " +
opts.animation,
});
backgroundLine.appendChild(line);
el.appendChild(backgroundLine);
}
}
function parseBoxShadow(boxShadow) {
var regex = /^\s*([a-zA-Z]+\s+)?(-?\d+(\.\d+)?)([a-zA-Z]*)\s+(-?\d+(\.\d+)?)
([a-zA-Z]*)(.*)$/;
var shadows = [];
for (var _i = 0, _a = boxShadow.split(','); _i < _a.length; _i++) {
var shadow = _a[_i];
var matches = shadow.match(regex);
if (matches === null) {
continue; // invalid syntax
}
var x = +matches[2];
var y = +matches[5];
var xUnits = matches[4];
var yUnits = matches[7];
if (x === 0 && !xUnits) {
xUnits = yUnits;
}
if (y === 0 && !yUnits) {
yUnits = xUnits;
}
if (xUnits !== yUnits) {
continue; // units must match to use as coordinates
}
shadows.push({
prefix: matches[1] || '',
x: x,
y: y,
xUnits: xUnits,
yUnits: yUnits,
end: matches[8],
});
}
return shadows;
}
/**
* Modify box-shadow x/y offsets to counteract rotation
*/
function normalizeShadow(shadows, degrees) {
var normalized = [];
for (var _i = 0, shadows_1 = shadows; _i < shadows_1.length; _i++) {
var shadow = shadows_1[_i];
var xy = convertOffset(shadow.x, shadow.y, degrees);
normalized.push(shadow.prefix + xy[0] + shadow.xUnits + ' ' + xy[1] +
shadow.yUnits + shadow.end);
}
return normalized.join(', ');
}
function convertOffset(x, y, degrees) {
var radians = degrees * Math.PI / 180;
var sin = Math.sin(radians);
var cos = Math.cos(radians);
return [
Math.round((x * cos + y * sin) * 1000) / 1000,
Math.round((-x * sin + y * cos) * 1000) / 1000,
];
}
why my checkCollision function is not working in foreach loop ? I want to check whether obs (obstacle) is hits/overlaps on collector (gray object). I am checking every 1 millisecond using setInterval checkCollision function. Basically I am trying to build a simple car game. please help me and thank you in advance
let body = document.body[0];
let container = document.querySelector(".container");
let allObstacles = [];
let colors = ["green", "green", "red"];
let collector = document.getElementById("collector");
class Obstacle {
constructor(yPos) {
this.yPos = -50;
}
randomnum() {
let randX = Math.floor(Math.random() * (container.clientWidth - 50));
return randX;
}
createObstacle() {
let obstacle = document.createElement("div");
obstacle.classList.add("obstacle");
let bgColor = colors[Math.floor(Math.random() * colors.length)];
obstacle.style.width = "50px";
obstacle.style.height = "50px";
obstacle.style.position = "absolute";
obstacle.style.left = this.randomnum() + "px";
obstacle.style.top = this.yPos + "px";
obstacle.style.backgroundColor = bgColor;
obstacle.dataset.behave = bgColor;
container.appendChild(obstacle);
return obstacle;
}
element = this.createObstacle();
updatePosition() {
this.yPos += 2;
this.element.style.top = this.yPos + "px";
}
kill() {
this.element.remove();
}
}
let dropObs = setInterval(function() {
allObstacles.forEach(function(obs) {
obs.updatePosition();
});
allObstacles.forEach(function(obs) {
// why checkCollision function is not working?
if (checkCollision(obs, collector)) {
console.log("hit");
}
if (obs.yPos > container.clientHeight) {
obs.kill();
}
});
}, 10);
let generateObs = setInterval(function() {
let obs = new Obstacle();
allObstacles.push(obs);
}, 2000);
function checkCollision(obj1, obj2) {
var obj1Y = obj1.offsetTop;
var obj2Y = obj2.offsetTop;
var obj1X = obj1.offsetLeft;
var obj2X = obj2.offsetLeft;
if (
obj2Y + 100 >= obj1Y &&
obj2Y <= obj1Y + 100 &&
obj2X + 100 >= obj1X &&
obj2X <= obj1X + 100
) {
return 1;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: 0;
}
html,
body {
width: 100%;
height: 100%;
}
.container {
position: relative;
width: 100%;
height: 100%;
}
#collector {
width: 50px;
height: 100px;
background: gray;
position: absolute;
top: calc(100vh - 100px);
left: 50%;
margin-left: -25px;
}
<div class="container">
<div id="collector"></div>
</div>
The first thing you should not use setInterval for this type of animation. Use requestAnimationFrame
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
obj1X,obj1Y comming undefined.
I have the following site on which I tried implementing a very nice looking animation. I don't know why but it keeps creating white space around my page and if I also add a button (as I did in the fiddle) it just goes crazy. What is the solution to this?
FIDDLE: https://jsfiddle.net/7suL84my/
CODE OF ANIMATION:
// Some random colors
const colors = ["#3CC157", "#2AA7FF", "#1B1B1B", "#FCBC0F", "#F85F36"];
const numBalls = 50;
const balls = [];
for (let i = 0; i < numBalls; i++) {
let ball = document.createElement("div");
ball.classList.add("ball");
ball.style.background = colors[Math.floor(Math.random() * colors.length)];
ball.style.left = `${Math.floor(Math.random() * 100)}vw`;
ball.style.top = `${Math.floor(Math.random() * 100)}vh`;
ball.style.transform = `scale(${Math.random()})`;
ball.style.width = `${Math.random()}em`;
ball.style.height = ball.style.width;
balls.push(ball);
document.body.append(ball);
}
// Keyframes
balls.forEach((el, i, ra) => {
let to = {
x: Math.random() * (i % 2 === 0 ? -11 : 11),
y: Math.random() * 12
};
let anim = el.animate(
[
{ transform: "translate(0, 0)" },
{ transform: `translate(${to.x}rem, ${to.y}rem)` }
],
{
duration: (Math.random() + 1) * 2000, // random duration
direction: "alternate",
fill: "both",
iterations: Infinity,
easing: "ease-in-out"
}
);
});
From your link on the css file change this :
#main{
background-color:black;
color:white;
width:98%;
height:98%;
align-content: center;
}
to this:
#main{
background-color:black;
color:white;
width:100%;
height:100%;
align-content: center;
}