js function repeats on window resize - javascript

I have created random stars using a js unction which manipulates CSS based on window height & width. My goal was to fit them at all-time in the viewport as I resize the height and width of the window.
The problem is every time that I resize the window, the js function adds CSS to previous ones without removing them first which causes a horizontal scroll and other unappealing visual issues.
Is there any way to prevent that? perhaps disabling and re-enabling the function or something else that fits the stars exactly in the viewport and make them behave dynamically as the width and height change without keeping the previous applied css properties and values?
<style>
body, html {margin: 0;}
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
</style>
<body>
<div id="header"></div>
<script>
window.onresize = function() {
skyCity();
};
function skyCity() {
for( var i=0; i < 400; i++) {
var header = document.getElementById("header"),
cityLight = document.createElement("i"),
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
</script>
</body>

Simply said, every time you resize, you call skyCity() which runs header.appendChild(cityLight); 400 times. It is just programmed to add new lights...
You can, a) remove every <i> from #header in skyCity() before the loop,
and b), b for better, init the 400 <i> once on load, on then on resize just update their properties.

it seems that the issue is it appends more i tags or stars when resizing, not really css issue.
I suggest to clear the wrapper #header before adding more <i>s.
You can do something like this:
window.onresize = function() {
skyCity();
};
function skyCity() {
var header = document.getElementById("header")
header.innerHTML=''
for( var i=0; i < 400; i++) {
var cityLight = document.createElement("i"),
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
<div id="header"></div>
You can check the full page link so you can try to resize the window

I would suggest you keep the "stars" as an array (cityLights in the code below) and apply the new style every time the browser size changes.
<style>
body, html {margin: 0;}
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
</style>
<body>
<div id="header"></div>
<script>
window.onresize = function() {
skyCity();
};
var header = document.getElementById("header");
var cityLights = []
for( var i=0; i < 400; i++) {
cityLights.push(document.createElement("i"));
}
function skyCity() {
for( var i=0; i < 400; i++) {
var cityLight = cityLights[i],
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
</script>
</body>

Related

I wanna repeat function infinite but i couldn't

I wanna do some effect to my background so i tought i can add some shapes flying around but i do only 1 shape i cant loop or anything
i tried call function more than a one time but it doesnt help
function animasyon(a) {
window.onload=function(){
var id = setInterval(anim,5);
$('body').append('<div class=shape></div>');
$('body').append('<div class=shape></div>');
var kutu = document.getElementsByClassName("shape");
var pos = 0;
var x = window.innerWidth;
var y = window.innerHeight;
var borderSize = Math.floor(Math.random() * 3 ) + 1;
var ySize = Math.floor(Math.random() * y ) + 1;
var Size = Math.floor(Math.random() * 30 ) + 5;
var yon = Math.floor(Math.random() *2)+1;
var dolu = Math.floor(Math.random() *2)+1;
if (ySize > 50) { ySize-=20; }
function anim(){
if (pos == x) {
clearInterval(id);
document.getElementById("shape").remove();
}else{
pos++;
kutu[a].style.position = "absolute";
kutu[a].style.border = "solid rgb(119,38,53) "+borderSize+"px";
kutu[a].style.left = pos+"px";
kutu[a].style.width = Size+"px";
kutu[a].style.height = Size+"px";
if (yon == 1) { ySize-=0.2; } else { ySize+=0.2; }
if (dolu==1) {kutu[a].style.background = "rgb(119,38,53)";}
if (kutu[a].offsetTop < 0 || kutu[a].offsetTop > y-30) {document.getElementById("shape").remove();}
kutu[a].style.top = ySize+"px";
}
}
}
}
animasyon(0);
Try Calling 'anim' function in this way
setInterval(function(){anim()},5);
Your problem is that you are assigning window.onload function a value inside the function animasyon
window.onload holds only 1 function. If you call animation function more than once, then the last one will overwrite the first one.
Edit: You need to separate your animation logic from the page load logic. They are completely separate things.
Here is an example of adding multiple objects and animating each separately.
// HTML
<div id="container">
<div id="ball"></div>
<div id="ball2"></div>
<div id="ball3"></div>
<div id="ball4"></div>
</div>
// CSS
#ball, #ball2, #ball3, #ball4 {
background: red;
border: 1px solid #FAFDFA;
display: inline-block;
width: 1em;
height: 1em;
border-radius: 2em;
position: absolute;
}
#ball2 {
background: blue;
}
#ball3 {
background: green;
}
#ball4 {
background: purple;
}
#container {
width: 512px;
height: 512px;
background: black;
position: relative;
}
// JS
const container = document.getElementById('container');
const stageWidth = 512;
const stageHeight = 512;
const makeFall = (elementId) => {
// this function makes an enlement fall in random direction
const animationSpeed = 4;
// your onload function
const ball = document.getElementById(elementId);
let directionX = (Math.random() * animationSpeed * 2) - animationSpeed;
let directionY = Math.random() * animationSpeed;
const setRandomStart = () => {
ball.style.top = '10px';
ball.style.left = (Math.random() * (stageWidth / 2)) + 'px';
directionX = (Math.random() * animationSpeed * 2) - animationSpeed;
directionY = Math.random() * animationSpeed;
}
setRandomStart();
let animationInterval = setInterval(() => {
let px = parseFloat(ball.style.left);
let py = parseFloat(ball.style.top);
px += directionX;
py += directionY;
if (px > stageWidth - 20 || py > stageHeight - 20 || px < -20) {
setRandomStart();
} else {
ball.style.left = px + 'px';
ball.style.top = py + 'px';
}
}, 48);
}
// In Your onload function you can add the elements and then animate
makeFall('ball');
makeFall('ball2');
makeFall('ball3');
makeFall('ball4');
https://jsfiddle.net/753oL8re/4/

CircleType text remove whitespace after rotateY

I'm having this code:
<div id="curvy">
This is the curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(1100);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
/* var css = $(this).css('transform');
css = css + ' rotateY(-50deg)'; */
if(counter > 5) {
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
$(this).css('vertical-align','top');
console.log(text);
//$(this).html('');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
/* newElem.css('position','relative');
newElem.css('z-index',counter); */
newElem.css('vertical-align','top');
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
//console.log(value);
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
}
</style>
This is working fine but after I start rotating each letter using rotateY in its own span, the parent span seems to add a white space in between that I want to get rid of.
Check jsfiddle
Well I was approaching it totally incorrectly.
The issue wasnt the spans, the padding or any margins but the translateX or rotate value.
Since CircleType was using the initial size of the letter when rendering the effect, the manipulations that I did through jQuery later weren't taken into account by it.
I had to save the matrix and then decide if I would go for an increment on the rotate value or on the translateX value. I chose the latter because it felt less complicated to play with. Since I need that the rotation will begin after a specific amount of character, I use the appropriate checks.
<div id="curvy">
Curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(900);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
var padding = 0;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
var css = $(this).css('transform').replace(/[^0-9\-.,]/g, '').split(',');
var x = css[12] || css[4];
var y = css[13] || css[5];
var a = css[0];
var b = css[1];
var angle = Math.atan2(b, a) * (180/Math.PI);
if(counter > 5) {
if(counter >= 12) {
padding = padding + 6 ;
} else
padding = padding + 4 ;
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
x = parseFloat(x) + padding;
$(this).css('transform', 'translateX('+x+'px) rotate('+angle+'deg)');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
top: 50%;
left: 50%;
position: absolute;
}
</style>
Updated jsFiddle

Not able to get the image elements in correct position

I want to achieve something like image shown below.
More specifically, I need to have smiley faces randomly distributed throughout a 500px area and have a border on the right-hand side of the area.
but with the following code I am not getting the desired result.
<!DOCTYPE html>
<html>
<head>
<style>
img {
position: absolute
}
div {
width: 500px;
height: 500px
}
#rightSide {
position: absolute;
left: 500px;
border-left: 1px solid black
}
</style>
</head>
<body onload="generateFaces()">
<div id="leftSide"></div>
<div id="rightSide"></div>
<script>
var numberOfFaces = 5;
var top_position = 400;
var left_position = 400;
var theLeftSide = document.getElementById("leftSide");
var i = 0;
function generateFaces() {
while (i < numberOfFaces) {
var this_img = document.createElement("img");
this_img.src = "#";
this_img.style.top = top_position + "px";
this_img.style.left = left_position + "px";
theLeftSide.appendChild(this_img);
top_position = top_position - 50;
left_position = left_position - 50;
i++;
}
}
</script>
</body>
</html>
The result I am getting for the above code snippet looks like
How will I make it proper?
In your while loop you subtract 50 from top and left every time, so you get even distances for each image.
Use Math.random() for random values. The function returns values between 0 and 1, so multiply with the container size to get random positions.
You just need to go with random funtion if you require random positions. For fix position you need to implement particular position checks.
top_position = Math.random()*400; left_position = Math.random()*400;
JS Fiddle - https://jsfiddle.net/manishghec/13k8caen/
If you want to use random positions:
top_position = Math.random()*400; left_position = Math.random()*400;
this_img.style.top = top_position + "px";
this_img.style.left = left_position + "px";
theLeftSide.appendChild(this_img);
Here is the fiddle: https://jsfiddle.net/v222wgav/1/
This is how you generate random top_position locations and random left_position locations.
You should be able to modify the code below to suit your needs.
I've included a random function getRandom which is just a standard "get a random number within this range" function.
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
To use it, just provide a minimum number of pixels, and a maximum number of pixels in the range you need.
getRandom(0, 400);
var numberOfFaces=5;
var top_position = getRandom(0, 400);
var left_position = getRandom(0, 400);
var theLeftSide = document.getElementById("leftSide");
var i = 0;
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateFaces()
{
while(i < numberOfFaces)
{
var this_img = document.createElement("img");
this_img.src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/718smiley.svg/60px-718smiley.svg.png";
this_img.style.top = top_position + "px";
this_img.style.left = left_position + "px";
theLeftSide.appendChild(this_img);
top_position = getRandom(0, 400);
left_position = getRandom(0, 400);
i++;
}
}
img {
position:absolute
}
div {
width:500px;height:500px
}
#rightSide {
position:absolute;
left: 0px;
top: 0px;
border-right: 1px solid black
}
<!DOCTYPE html>
<html>
<body onload="generateFaces()">
<div id="leftSide"></div>
<div id="rightSide"></div>
</body>
</html>
I would do away with the #rightSide div all together like so:
var numberOfFaces=5;
var top_position = getRandom(0, 400);
var left_position = getRandom(0, 400);
var theLeftSide = document.getElementById("leftSide");
var i = 0;
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateFaces()
{
while(i < numberOfFaces)
{
var this_img = document.createElement("img");
this_img.src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/718smiley.svg/60px-718smiley.svg.png";
this_img.style.top = top_position + "px";
this_img.style.left = left_position + "px";
theLeftSide.appendChild(this_img);
top_position = getRandom(0, 400);
left_position = getRandom(0, 400);
i++;
}
}
img {
position:absolute
}
div {
width:500px;height:500px
}
#leftSide {
border-right: 1px solid black
}
<!DOCTYPE html>
<html>
<body onload="generateFaces()">
<div id="leftSide"></div>
</body>
</html>
Happy Random Smilies!
Resources:
Image Credit: https://commons.wikimedia.org/wiki/File:718smiley.svg
How to use generate random numbers in a specific range

random position of images

i found a script that would position divs / images randomly. However, it isn't completely working the way i want/need it to.
The images are loaded each within a div (which isn't ideal i guess). I have around 30 images.
But they don't load nicely and var posy = (Math.random() * ($(document).height() - 0)).toFixed(); doesn't work nicely either. The images mostly load on top (i think that the images in the blog don't count so it gets the height without images?)
So what I want: Load the in more nicely Randomize them so they get to the bottom of the page, too
var circlePosition = document.getElementsByClassName('circle');
console.log(circlePosition);
function position() {
for (var i = 0; i < circlePosition.length; i++ ) {
//give circle a random position
var posx = (Math.random() * ($(document).width() - 0)).toFixed();
var posy = (Math.random() * ($(document).height() - 0)).toFixed();
//apply position to circle
$(circlePosition[i]).css({
'position':'absolute',
'left':posx+'px',
'top':posy+'px',
})
}
} //end function position
var circleTotal = circlePosition.length;
$('.circle').click(function() {
$(this).fadeOut();
circleTotal = circleTotal - 1;
console.log(circleTotal);
if(circleTotal == 0) {
position()
$('.circle').fadeIn();
}
});
position();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="//placehold.it/1x5000"> <!-- Placeholder image to show issue -->
<div class="circle">
<img src="http://static.tumblr.com/tensqk8/k8anq0438/01.png">
</div>
<div class="circle">
<img src="http://static.tumblr.com/tensqk8/k8anq0438/01.png">
</div>
A clean and readable and solution without a jQuery dependence might be something like this. It avoids unnecessarily wrapping your images in divs by positioning the images themselves. It includes a hidden element as a sort of "poor man's" shadow DOM.
http://jsfiddle.net/sean9999/yv9otwr7/9/
;(function(window,document,undefined){
"use strict";
var init = function(){
var canvas = document.querySelector('#x');
var icon_template = document.querySelector('#template');
var icon_width = 40;
var icon_height = 30;
var the_images = [
'http://static.tumblr.com/tensqk8/k8anq0438/01.png',
'http://static.tumblr.com/tensqk8/rYanq05el/04.png',
'http://static.tumblr.com/tensqk8/SYknq05py/05.png',
'http://static.tumblr.com/tensqk8/s7inq057d/03.png'
];
var pickRandomImage = function(){
var i = Math.floor( Math.random() * the_images.length );
return the_images[i];
};
var total_number_of_images = 10;
var max_height = canvas.offsetHeight - icon_height;
var max_width = canvas.offsetWidth - icon_width;
var randomCoordinate = function(){
var r = [];
var x = Math.floor( Math.random() * max_width );
var y = Math.floor( Math.random() * max_height );
r = [x,y];
return r;
};
var createImage = function(){
var node = icon_template.cloneNode(true);
var xy = randomCoordinate();
node.removeAttribute('id');
node.removeAttribute('hidden');
node.style.top = xy[1] + 'px';
node.style.left = xy[0] + 'px';
node.setAttribute('src',pickRandomImage());
canvas.appendChild(node);
};
for (var i=0;i<total_number_of_images;i++){
createImage();
};
};
window.addEventListener('load',init);
})(window,document);
body {
background-color: #fed;
}
#x {
border: 3px solid gray;
background-color: white;
height: 400px;
position: relative;
}
#x .icon {
position: absolute;
z-index: 2;
}
<h1>Randomly distributed images</h1>
<div id="x"></div>
<img src="#" class="icon" hidden="hidden" id="template" />
try moving your position(); call inside the $(window).load function.
I think maybe the images are being positioned before all the images have loaded, so the page is shorter then.

Change div width every 1 second by 5px

I tried to change div width every 1 second by 5px using JavaScript. How can I make this work?
Here's my code:
<html>
<head>
<title>JS Functions</title>
</head>
<body>
<div style="width:100px; height:100px; background:gray" id="box" onclick="bigger()"></div>
<script>
function bigger()
{
var w = 100
var h = 100
while(w < 1000, h < 1000)
{
w = w+5;
h = h+5;
document.getElementById('box').style.width = w
document.getElementById('box').style.height = h
setInterval();
}
}
</script>
</body>
</html>
No while loop needed. You can just use setInterval:
var w = 100;
var h = 100;
var foo = setInterval(function () {
if(w>1000) cancelInterval(foo)
w = w + 5;
h = h + 5;
document.getElementById('box').style.width = w + 'px';
document.getElementById('box').style.height = h + 'px';
}, 1000);
<div style="width:100px; height:100px; background:gray" id="box" onclick="bigger()"></div>
You need to use setInterval to call your code every second, so move it outside of the bigger() function. Also you need the full value for style, including the unit you're using.
try this
<html>
<head>
<title>JS Functions</title>
</head>
<body>
<div style="width:100px; height:100px; background:gray" id="box"></div>
<script>
var w = 100;
var h = 100;
function bigger()
{
if (w < 1000 && h < 1000)
{
w = w+5;
h = h+5;
document.getElementById('box').style.width = w + 'px';
document.getElementById('box').style.height = h + 'px';
} else {
clearInterval(int);
}
}
var int = setInterval(bigger, 1000);
</script>
</body>
</html>
Let's say you have a div wth id='boxToEnlarge'
The JSFiddle: http://jsfiddle.net/7qtb1u8e/1/
And this is the actual code:
function enlargeBox(){
//get current size
var currentWidth = document.getElementById('boxToEnlarge').offsetWidth;
var currentHeight = document.getElementById('boxToEnlarge').offsetHeight;
//add 5 more pixels to current size
document.getElementById('boxToEnlarge').style.width = currentWidth + 5 +'px';
document.getElementById('boxToEnlarge').style.height = currentHeight + 5 +'px';
}
//call the enlargeBox func every 1 sec (1000 milliseconds)
setInterval(function(){enlargeBox()},1000);
We are reading the current size of the div we want to enlarge then we add 5px to that amount and apply it on it's width/height CSS properties.
We wrap the above in a function and using setInterval, we call that function once every n milliseconds, in this case 1000ms which equals 1 second

Categories