Add Scrollbar to a page that doesnt need it? - javascript

I have made this scrolling effect that comes into action when page is scrolled. Now, i want to show a scrollbar on the page which when present at the starting position, all the divs are at 100% width and when at bottom, all divs are at 0% width.
EDIT - Basically I want to control whatever animation I have made, not with wheel event but by using a scrollbar, controlling the div widths using scrollTop etc.
var leftDiv = document.querySelectorAll(".lcurtain");
var rightDiv = document.querySelectorAll(".rcurtain");
var locker = document.getElementById("locker");
document.addEventListener("wheel", change);
var per = 100;
var angle = 0;
function change(e) {
if (e.deltaY > 0 && per > 0) {
for (var i = 0; i < 4; i++) {
leftDiv[i].style.width = per - 1 + "%";
rightDiv[i].style.width = per - 1 + "%";
}
per -= 1;
} else if (e.deltaY < 0 && per < 100) {
for (var i = 0; i < 4; i++) {
leftDiv[i].style.width = per + 1 + "%";
rightDiv[i].style.width = per + 1 + "%";
}
per += 1;
}
}
html {
width: 100%;
height: 100%;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
position: relative;
}
.lcurtain,
.rcurtain {
width: 100%;
height: 12.5%;
position: absolute;
}
#div1 {
top: 0;
left: 0;
background-color: blue;
}
#div2 {
top: 12.5%;
right: 0;
background-color: red;
}
#div3 {
top: 25%;
left: 0;
background-color: green;
}
#div4 {
top: 37.5%;
right: 0;
background-color: purple;
}
#div5 {
top: 50%;
left: 0;
background-color: orange;
}
#div6 {
top: 62.5%;
right: 0;
background-color: cyan;
}
#div7 {
top: 75%;
left: 0;
background-color: brown;
}
#div8 {
top: 87.5%;
right: 0;
background-color: pink;
}
<div id="div1" class="lcurtain"></div>
<div id="div2" class="rcurtain"></div>
<div id="div3" class="lcurtain"></div>
<div id="div4" class="rcurtain"></div>
<div id="div5" class="lcurtain"></div>
<div id="div6" class="rcurtain"></div>
<div id="div7" class="lcurtain"></div>
<div id="div8" class="rcurtain"></div>
<script src="script.js"></script>

Here's the solution using CSS vh units and scroll event handler.
When a scroll events is handled it calculates the relative current scroll position in percents:
100 - (scrollTop / (scrollHeight - clientHeight) * 100)
thus 100% means the very top scroll position, otherwise 0% means we're at the very bottom.
Reference: Cross-Browser Method to Determine Vertical Scroll Percentage in Javascript.
Then we just apply this calculated value to the divs style.width parameters.
var leftDiv = document.querySelectorAll(".lcurtain");
var rightDiv = document.querySelectorAll(".rcurtain");
document.addEventListener("scroll", change);
function change(e) {
var h = document.documentElement;
var b = document.body;
var st = 'scrollTop';
var sh = 'scrollHeight';
var percent = 100 - (h[st] || b[st] / ((h[sh] || b[sh]) - h.clientHeight) * 100) + "%";
for (var i = 0; i < 4; i++) {
leftDiv[i].style.width = percent;
rightDiv[i].style.width = percent;
}
}
html {
width: 100%;
height: 1000vh;
}
body {
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
position: fixed;
}
.lcurtain,
.rcurtain {
width: 100%;
height: 12.5%;
position: absolute;
}
#div1 {
top: 0;
left: 0;
background-color: blue;
}
#div2 {
top: 12.5%;
right: 0;
background-color: red;
}
#div3 {
top: 25%;
left: 0;
background-color: green;
}
#div4 {
top: 37.5%;
right: 0;
background-color: purple;
}
#div5 {
top: 50%;
left: 0;
background-color: orange;
}
#div6 {
top: 62.5%;
right: 0;
background-color: cyan;
}
#div7 {
top: 75%;
left: 0;
background-color: brown;
}
#div8 {
top: 87.5%;
right: 0;
background-color: pink;
}
<div id="div1" class="lcurtain"></div>
<div id="div2" class="rcurtain"></div>
<div id="div3" class="lcurtain"></div>
<div id="div4" class="rcurtain"></div>
<div id="div5" class="lcurtain"></div>
<div id="div6" class="rcurtain"></div>
<div id="div7" class="lcurtain"></div>
<div id="div8" class="rcurtain"></div>

Related

is there a way to make a background scroll down while some content stay in the middle at all time?

I'm trying to do something like (in js, html, sass) :
when I scroll the page down my layers (ground, sky, space, ...) go down
my content (that will be a rocket going in the sky) stay in the middle of the screen and will move to the sides like if it were to be flying (that will be for later)
some elements will move on the layers (like asteroids going from right to left or something) (for later)
So here are some ideas of code I tried but this seem odd and do not work as intended; as you can see, the layers are scrolling as intended, but they are not all showing for whatever reason, they seem to fill all the page size but they shouldn't and i'm going round and round about this on the internet and no one seem to have done something like this.
// Functions
detectPageVerticalPosition = () => {
pageVerticalPosition = pageYOffset;
};
getDivs = () => {
for (
let div = document.getElementsByTagName("div"), i = 0; i < div.length; i++
) {
div[i].getAttribute("class") == "layer-vertical" &&
layerVerticalArray.push(div[i]);
}
console.log("layerVerticalArray: ", layerVerticalArray);
};
moveLayers = () => {
for (let i = 0; i < layerVerticalArray.length; i++) {
layerVerticalArray[i].style.bottom = -1 * pageVerticalPosition + "px";
}
};
// End Functions
// Variables
var pageVerticalPosition = 0,
layerVerticalArray = new Array();
// End Variables
// Events
window.onload = e => {
getDivs();
// console.log(layerVerticalArray);
};
window.onscroll = e => {
detectPageVerticalPosition();
moveLayers();
};
// End Events
body {
margin: 0;
}
#page {
position: relative;
height: 20000px;
width: 100%;
}
#rocket-container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
#rocket-container #rocket {
position: absolute;
width: 100px;
height: 100px;
left: calc(50% - 50px);
top: calc(50% - 50px);
}
#background-container {
position: fixed;
height: 100%;
width: 100%;
background-color: red;
overflow: hidden;
}
#background-container .layer-vertical {
width: 100%;
height: 3500px;
}
#background-container #layer-vertical-1 {
position: absolute;
background-color: blue;
}
#background-container #layer-vertical-1 #cloud-1 {
outline-style: dashed;
right: 0px;
}
#background-container #layer-vertical-1 #cloud-2 {
outline-style: dotted;
bottom: 0px;
}
#background-container #layer-vertical-2 {
background-color: green;
}
#background-container #layer-vertical-3 {
background-color: purple;
}
.cloud {
position: absolute;
width: 180px;
height: 120px;
background-image: url(../images/cloud.png);
}
<div class="page">
<div class="background-container">
<div class="layer-vertical" id="layer-vertical-1">
Layer 1
<div class="cloud" id="cloud-1"></div>
<div class="cloud" id="cloud-2"></div>
</div>
<div class="layer-vertical" id="layer-vertical-2">
Layer 2
</div>
<div class="layer-vertical" id="layer-vertical-3">
Layer 3
</div>
</div>
<div id="rocket-container">
<div id="rocket">STAY MIDDLE</div>
</div>
</div>
[1]: https://via.placeholder.com/180/120
So, here's what i found in order to fix this (jsfiddle: http://jsfiddle.net/kjrte2sd/2/)
i used some jquery to make the background-container scroll down as intended instead of each elements scrolling down by himself.
now the page div is gone and the body handle the sizing of the whole thing.
i guess the answer was simpler than i expected it to be.
var winHeight = $(window).innerHeight();
$(document).ready(() => {
$(".layer-vertical").height(winHeight);
$("body").height(winHeight * $(".layer-vertical").length);
});
window.addEventListener("resize", e => {
$(".layer-vertical").height($(window).innerHeight());
});
$(window).on("scroll", () => {
$("#background-container").css("bottom", $(window).scrollTop() * -1);
});
body {
margin: 0;
padding: 0;
}
#rocket-container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
#rocket-container #rocket {
position: absolute;
width: 100px;
height: 100px;
left: calc(50% - 50px);
top: calc(50% - 50px);
}
#background-container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
#background-container .layer-vertical {
width: 100%;
}
#background-container .layer-vertical h1 {
width: 100px;
position: relative;
display: block;
margin: 0 auto;
text-align: center;
top: 50%;
}
#background-container #layer-vertical-1 {
background-color: green;
}
#background-container #layer-vertical-2 {
background-color: red;
}
#background-container #layer-vertical-3 {
background-color: white;
}
#background-container #layer-vertical-4 {
background-color: pink;
}
#background-container #layer-vertical-5 {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="background-container">
<div class="layer-vertical" id="layer-vertical-5">
<h1>5</h1>
</div>
<div class="layer-vertical" id="layer-vertical-4">
<h1>4</h1>
</div>
<div class="layer-vertical" id="layer-vertical-3">
<h1>3</h1>
</div>
<div class="layer-vertical" id="layer-vertical-2">
<h1>2</h1>
</div>
<div class="layer-vertical" id="layer-vertical-1">
<h1>1</h1>
</div>
</div>
<div id="rocket-container">
<div id="rocket">STAY MIDDLE</div>
</div>

Adapt image movement to window size in javascript

I made an animation on my website which moves if clicked on. The problem is that on the javascript function that manage it, I gave a series of coordinates which fits only if the browser is in full screen. Here are some example:
https://imgur.com/a/Ug6eQlp and https://imgur.com/a/bPrVg5y
This is my javascript function:
function init(){
imgObj = document.getElementById('minion');
immagine = document.getElementById('immagine_minion');
imgObj.style.position= 'absolute';
imgObj.style.top = '240px';
imgObj.style.left = '-300px';
imgObj.style.visibility='hidden';
appaer();
}
And this, for example, the method which moves it as soon as I open the page:
function appaer(){
immagine.src="../img/minion_dx.png";
if (parseInt(imgObj.style.left)<200) {
imgObj.style.left = parseInt(imgObj.style.left) + 5 + 'px';
imgObj.style.visibility='visible';
animate = setTimeout(appaer,20);
} else
stop();
}
How can I make it fit for every screen resolution?
this should get you started
var stage_number = 0
function go_to_next_stage() {
stage_number++
var stage = document.getElementById("stage" + stage_number)
me.style.left = getComputedStyle(stage).getPropertyValue("left")
me.style.top = getComputedStyle(stage).getPropertyValue("top")
if (stage_number > 3) stage_number = 0
}
img {
position: absolute;
left: -100px;
top: 0;
transition: left 2s, top 2s
}
.stage {
width: 100px;
height: 100px;
border: 1px solid black;
position: absolute;
}
#stage1 {
left: 0;
top: 0;
}
#stage2 {
right: 0;
top: 0;
}
#stage3 {
right: 0;
bottom: 0;
}
#stage4 {
left: 0;
bottom: 0;
}
div {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
<img id="me" src="https://de.gravatar.com/userimage/95932142/195b7f5651ad2d4662c3c0e0dccd003b.png?size=100" />
<div onclick="go_to_next_stage()">click anywhere to continue</div>
<div class="stage" id="stage1">
</div>
<div class="stage" id="stage2">
</div>
<div class="stage" id="stage3">
</div>
<div class="stage" id="stage4">
</div>

mousedown and touchstart not registering on mobile devices

I have created the following simple image comparison slider - modified from the version on w3schools (I know my mistake to use their code).
This all works fine on a desktop but when I try to use it on a mobile, nothing happens - it doesn't even register the console.log on the mousedown/touchstart (when I press on the slider button with my finger).
I was wondering if anyone could spot anything obvious with why it isn't working on mobile devices
(() => {
$.fn.imageComparisonSlider = function() {
var returnValue = this.each((index, item) => {
var $container = $(this);
var $overlay = $container.find('.image-comparison-slider__bottom-image');
var $slider = $('<span class="image-comparison-slider__slider"></span>');
var $window = $(window);
var touchStarted = false;
var width = $container.outerWidth();
$container.prepend($slider);
$container.on('mousedown touchstart', '.image-comparison-slider__slider', event => {
event.preventDefault();
console.log('touchstart');
touchStarted = true;
});
$window.on("mousemove touchmove", windowEvent => {
if (touchStarted) {
// get the cursor's x position:
let pos = getCursorPos(windowEvent);
// prevent the slider from being positioned outside the image:
if (pos < 0) pos = 0;
if (pos > width) pos = width;
// execute a function that will resize the overlay image according to the cursor:
slide(pos);
}
});
$window.on('mouseup touchend', event => {
event.preventDefault();
touchStarted = false;
});
function getCursorPos(e) {
var thisEvent = e || window.event;
// calculate the cursor's x coordinate, relative to the image
return thisEvent.pageX - $container.offset().left;
}
function slide(x) {
// set the width of the overlay
$overlay.width(width - x);
// position the slider
$slider[0].style.left = x + 'px';
}
function resetSlider() {
$overlay.width('50%');
$slider[0].style.left = $overlay.width() + 'px'
width = $container.outerWidth();
}
});
return returnValue;
};
})($);
$('.image-comparison-slider__container').imageComparisonSlider();
.image {
display: block;
width: 100%;
}
.image-comparison-slider__title {
text-align: center;
}
.image-comparison-slider__container,
.image-comparison-slider__image-holder {
position: relative;
}
.image-comparison-slider__bottom-image {
position: absolute;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
z-index: 1;
width: 50%;
}
.image-comparison-slider__caption {
position: absolute;
padding: 1rem;
color: white;
background: rgba(0, 0, 0, 0.6);
z-index: 2;
white-space: nowrap;
}
.image-comparison-slider__top-image .image-comparison-slider__caption {
top: 0;
left: 0;
}
.image-comparison-slider__bottom-image .image-comparison-slider__caption {
bottom: 0;
right: 0;
}
.image-comparison-slider__image {
display: block;
z-index: 1;
}
.image-comparison-slider__bottom-image .image {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: auto;
}
.image-comparison-slider__slider {
position: absolute;
z-index: 3;
cursor: ew-resize;
/*set the appearance of the slider:*/
width: 50px;
height: 50px;
background-color: rgba(255, 96, 38, 0.8);
border-radius: 50%;
top: 50%;
left: 50%;
display: flex;
justify-content: center;
align-items: center;
transform: translate(-50%, -50%);
}
.image-comparison-slider__slider:after {
content: "< >";
color: white;
font-weight: bold;
font-size: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="image-comparison-slider__container">
<div class="image-comparison-slider__image-holder image-comparison-slider__top-image">
<img src="https://www.fillmurray.com/g/400/300" alt="A test image 1" class="image">
<div class="image-comparison-slider__caption">Left Image</div>
</div>
<div class="image-comparison-slider__image-holder image-comparison-slider__bottom-image">
<img src="https://www.fillmurray.com/400/300" alt="A test image 2" class="image">
<div class="image-comparison-slider__caption">Right Image</div>
</div>
</div>
Fiddle link for code
Ok have managed to fix this - the touch wasn't registering because of the transform so I changed that and just used negative margin as the button was a fixed size.
I then had to fix the thisEvent.pageX for android - so did a check with isNaN and then set it to e.originalEvent.touches[0].pageX if it was true.
Working version:
(() => {
$.fn.imageComparisonSlider = function() {
var returnValue = this.each((index, item) => {
var $container = $(this);
var $overlay = $container.find('.image-comparison-slider__bottom-image');
var $slider = $('<span class="image-comparison-slider__slider"></span>');
var $window = $(window);
var touchStarted = false;
var width = $container.outerWidth();
$container.prepend($slider);
$container.on('mousedown touchstart', '.image-comparison-slider__slider', event => {
event.preventDefault();
console.log('touchstart');
touchStarted = true;
});
$window.on("mousemove touchmove", windowEvent => {
if (touchStarted) {
// get the cursor's x position:
let pos = getCursorPos(windowEvent);
// prevent the slider from being positioned outside the image:
if (pos < 0) pos = 0;
if (pos > width) pos = width;
// execute a function that will resize the overlay image according to the cursor:
slide(pos);
}
});
$window.on('mouseup touchend', event => {
event.preventDefault();
touchStarted = false;
});
function getCursorPos(e) {
var thisEvent = e || window.event;
let xVal = thisEvent.pageX;
if (isNaN(xVal)) {
xVal = e.originalEvent.touches[0].pageX;
}
// calculate the cursor's x coordinate, relative to the image
return xVal - $container.offset().left;
}
function slide(x) {
// set the width of the overlay
$overlay.width(width - x);
// position the slider
$slider[0].style.left = x + 'px';
}
function resetSlider() {
$overlay.width('50%');
$slider[0].style.left = $overlay.width() + 'px'
width = $container.outerWidth();
}
});
return returnValue;
};
})($);
$('.image-comparison-slider__container').imageComparisonSlider();
.image {
display: block;
width: 100%;
}
.image-comparison-slider__title {
text-align: center;
}
.image-comparison-slider__container,
.image-comparison-slider__image-holder {
position: relative;
}
.image-comparison-slider__bottom-image {
position: absolute;
overflow: hidden;
top: 0;
right: 0;
bottom: 0;
z-index: 1;
width: 50%;
}
.image-comparison-slider__caption {
position: absolute;
padding: 1rem;
color: white;
background: rgba(0, 0, 0, 0.6);
z-index: 2;
white-space: nowrap;
}
.image-comparison-slider__top-image .image-comparison-slider__caption {
top: 0;
left: 0;
}
.image-comparison-slider__bottom-image .image-comparison-slider__caption {
bottom: 0;
right: 0;
}
.image-comparison-slider__image {
display: block;
z-index: 1;
}
.image-comparison-slider__bottom-image .image {
position: absolute;
right: 0;
top: 0;
height: 100%;
width: auto;
}
.image-comparison-slider__slider {
position: absolute;
z-index: 3;
cursor: ew-resize;
width: 50px;
height: 50px;
background-color: rgba(255, 96, 38, 0.8);
border-radius: 50%;
top: 50%;
left: 50%;
display: flex;
justify-content: center;
align-items: center;
margin: -25px 0 0 -25px;
}
.image-comparison-slider__slider:after {
content: "< >";
color: white;
font-weight: bold;
font-size: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="image-comparison-slider__container">
<div class="image-comparison-slider__image-holder image-comparison-slider__top-image">
<img src="https://www.fillmurray.com/g/400/300" alt="A test image 1" class="image">
<div class="image-comparison-slider__caption">Left Image</div>
</div>
<div class="image-comparison-slider__image-holder image-comparison-slider__bottom-image">
<img src="https://www.fillmurray.com/400/300" alt="A test image 2" class="image">
<div class="image-comparison-slider__caption">Right Image</div>
</div>
</div>

Fit colliding elements in the container dynamically

I have absolutely positioned elements with different position.top and height generated from database.
All I'm trying to do is to un-collide these elements by shifting them to the right while adjusting width to fit inside the <body> container.
I'm having an issue applying 'left' position to the collided elements.
I use https://sourceforge.net/projects/jquerycollision/ to detect collision.
Here is how the final picture should look:
$('div').each(function() {
var name = $(this).text();
var hits = $(this).collision('div').not(this); // Find colliding elements
console.log(name + ' collides with: ' + hits.length + ' others');
if (hits.length > 0) {
var widthAll = 100 / (hits.length + 1);
// Shift colliding elements to the right with equal width
$(hits).add(this).each(function(i) {
var name = $(this).text();
$(this).css({ 'left': widthAll * i + '%', 'width': widthAll + '%' });
});
}
});
div {
position: absolute;
width: 10em;
font-size: 0.75em;
color: white;
}
.blue {
top: 0;
height: 80%;
background-color: blue;
}
.red {
top: 15%;
height: 5%;
background-color: red;
}
.yellow {
top: 17%;
height: 10%;
background-color: yellow;
color: black;
}
.green {
top: 30%;
height: 5%;
background-color: green;
}
.magenta {
top: 36%;
height: 3%;
background-color: magenta;
}
.cyan {
top: 50%;
height: 5%;
background-color: cyan;
color: black;
}
.brown {
top: 81%;
height: 5%;
background-color: brown;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://rawgit.com/dsbaars/jquery-collision/master/js/jquery-collision.min.js"></script>
<div class='blue'>blue</div>
<div class='red'>red</div>
<div class='yellow'>yellow</div>
<div class='green'>green</div>
<div class='magenta'>magenta</div>
<div class='cyan'>cyan</div>
<div class='brown'>brown</div>
I think I have completed your code as you have requested. The idea is,
First block of code shifts the divs to the right so that they don't overlap.
Second block makes the width of the divs evenly distributed according to size of the body.
Last block increases the width of rest of the divs to take remaining space.
"use strict";
var divs = $('div'),
mx = 0,
mxs = [0],
bw = $("body").outerWidth(),
steps = 1;
divs.each(function(i) {
for (var j = i + 1; j < divs.length; j++) {
if (!$(this).data("x")) $(this).data("x", 0);
if (j < divs.length) {
var hit = $(this).collision(divs[j]);
if (hit.length) {
hit = $(divs[j]);
hit.css("left", "+=" + Math.ceil($(this).outerWidth()));
hit.data("x", hit.position().left);
if (mx < hit.data("x")) {
mxs.push(mx = hit.data("x"));
steps++;
}
}
}
}
});
divs.each(function(i) {
let iw = $(this).outerWidth(),
fw = bw / steps;
$(this).outerWidth(fw);
for (var j = i + 1; j < divs.length; j++) {
$(this).collision(divs[j]).css("left", "+=" + Math.ceil((fw - iw) * mxs.indexOf($(divs[j]).data("x"))));
}
});
divs.each(function() {
var os = $(this).outerWidth(),
ts = bw - $(this).position().left;
$(this).outerWidth(ts);
if ($(this).collision(divs).not(this).length) {
$(this).outerWidth(os);
}
});
body {
margin: 0;
}
div {
position: absolute;
width: 10em;
font-size: 0.75em;
color: white;
left: 0;
}
.blue {
top: 0;
height: 80%;
background-color: blue;
}
.red {
top: 15%;
height: 5%;
background-color: red;
}
.yellow {
top: 17%;
height: 10%;
background-color: yellow;
color: black;
}
.green {
top: 20%;
height: 50%;
background-color: green;
}
.magenta {
top: 36%;
height: 3%;
background-color: magenta;
}
.cyan {
top: 50%;
height: 5%;
background-color: cyan;
color: black;
}
.brown {
top: 81%;
height: 5%;
background-color: brown;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/dsbaars/jquery-collision/master/js/jquery-collision.min.js"></script>
<div class='blue'>blue</div>
<div class='red'>red</div>
<div class='yellow'>yellow</div>
<div class='green'>green</div>
<div class='magenta'>magenta</div>
<div class='cyan'>cyan</div>
<div class='brown'>brown</div>
Above snippet is non-responsive. If you wish it to be responsive, then simply listen to resize event, change the value of bw and repeat code blocks 2 and 3.
As mentioned in the comments: jquery-collision.min.js had some unressolved bugs so, as suggested by Alex G, https://www.48design.de/de/news/2009/11/20/kollisionsabfrage-per-jquery-plugin-update-v11/ may be an alternative.

How to move two different images across the screen using JavaScript

I have been challenged with a website that requires me to make two images race at random across the screen to a finish line. I am required to make this happen using JavaScript. Unfortunately I have ran into some trouble here making this happen.
I have the script that allows a div container and an object "animate" (which is a small square) to move across the screen to the right as I am supposed to do. My question comes into play when trying to do this to two different images.
The goal is to have the animation I have created to apply to the images, I cannot figure out how to apply the functions to the images already placed on the page to make it seem as if they are racing on random intervals across the page to the finish line.
I understand the concept of the animation and the JavaScript behind it, I just dont understand how to make it apply to an image, and more than 1 image at that.
Please advise.
Here is my code that I am using: you can see that I left my demo animation on the page, and the two images I am looking to apply it to.
function myMove()
{
var elem = document.getElementById("animate");
var pos = 0;
var id = setInterval(frame, 5);
function frame()
{
if (pos == 350)
{
clearInterval(id);
}
else
{
pos++;
elem.style.left = pos + 'px';
}
}
}
<div id="traffic-light">
<div id="stopLight" class="bulb"></div>
<div id="yeildLight" class="bulb"></div>
<div id="goLight" class="bulb"></div>
</div>
<style>
body {
overflow: hidden;
}
#bluefish {
position: absolute;
top: 31pc;
width: 17pc;
left: -.5pc;
}
#turtle {
position: absolute;
width: 15pc;
top: 20pc;
}
body {
background-image: url("http://www.hpud.org/wp-content/uploads/2015/08/WaterBackground2.jpg")
}
.finishline {
position: absolute;
right: -12pc;
top: 18pc;
}
#traffic-light {
height: 10pc;
width: 4pc;
background-color: #333;
border-radius: 20pc;
position: absolute;
}
.bulb {
height: 2pc;
width: 2pc;
background-color: #111;
border-radius: 50%;
margin: 15px auto;
transition: background 500ms;
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background: red;
}
</style>
<img id="bluefish" src="http://clipartist.net/openclipart.org/2013/July/Blue_Fish_Goldfish.png">
<img id="turtle" src="http://www.clipartkid.com/images/386/turtle-free-stock-photo-illustration-of-a-green-sea-turtle-uPgZrm-clipart.png">
<img src="https://t1.rbxcdn.com/877010da8ce131dfcb3fa6a9b07fea89" class="finishline">
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
Try this one:
function myMove()
{
var elemBluefish = document.getElementById("bluefish");
var elemBluefishWin = document.getElementById("bluefishwin");
var elemTurtle = document.getElementById("turtle");
var elemTurtleWin = document.getElementById("turtlewin");
var posBluefish = 0;
var posTurtle = 0;
var hasWinner = false;
elemBluefishWin.style.display = 'none';
elemTurtleWin.style.display = 'none';
var id = setInterval(frame, 5);
function frame()
{
if(posBluefish >= 350 && posTurtle >= 350)
{
clearInterval(id);
return;
}
if(posBluefish < 350)
{
posBluefish += Math.round(Math.random()*10);
if(posBluefish >= 350)
{
posBluefish = 350;
if(!hasWinner){
hasWinner = true;
elemBluefishWin.style.display = 'unset';
}
}
elemBluefish.style.left = posBluefish + 'px';
}
if(posTurtle < 350)
{
posTurtle += Math.round(Math.random()*10);
if(posTurtle >= 350)
{
posTurtle = 350;
if(!hasWinner){
hasWinner = true;
elemTurtleWin.style.display = 'unset';
}
}
elemTurtle.style.left = posTurtle + 'px';
}
}
}
<div id="traffic-light">
<div id="stopLight" class="bulb"></div>
<div id="yeildLight" class="bulb"></div>
<div id="goLight" class="bulb"></div>
</div>
<style>
body {
overflow: hidden;
}
#bluefish {
position: absolute;
top: 31pc;
width: 17pc;
left: -.5pc;
}
#turtle {
position: absolute;
width: 15pc;
top: 20pc;
}
#bluefishwin {
position: absolute;
right: 1pc;
top: 31pc;
display: none;
}
#turtlewin {
position: absolute;
right: 1pc;
top: 20pc;
display: none;
}
body {
background-image: url("http://www.hpud.org/wp-content/uploads/2015/08/WaterBackground2.jpg")
}
.finishline {
position: absolute;
right: -12pc;
top: 18pc;
}
#traffic-light {
height: 10pc;
width: 4pc;
background-color: #333;
border-radius: 20pc;
position: absolute;
}
.bulb {
height: 2pc;
width: 2pc;
background-color: #111;
border-radius: 50%;
margin: 15px auto;
transition: background 500ms;
}
/*#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background: red;
}*/
</style>
<img id="bluefish" src="http://clipartist.net/openclipart.org/2013/July/Blue_Fish_Goldfish.png">
<img id="turtle" src="http://www.clipartkid.com/images/386/turtle-free-stock-photo-illustration-of-a-green-sea-turtle-uPgZrm-clipart.png">
<img src="https://t1.rbxcdn.com/877010da8ce131dfcb3fa6a9b07fea89" class="finishline">
<img id="bluefishwin" src="http://a.dryicons.com/images/icon_sets/coquette_part_3_icons_set/png/128x128/prize_winner.png">
<img id="turtlewin" src="http://a.dryicons.com/images/icon_sets/coquette_part_3_icons_set/png/128x128/prize_winner.png">
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
</div>
It gets an element for each image and adds every 5ms a random amount of pixels (between 0 and 9) to each pos of image.
If both "racers" reached the target (350px) the interval is cleared and the race is over.
The winner gets an image displayed at the finish line.
an example:
function startRace() {
animateRacer("player1", true);
animateRacer("player2", true);
}
function animateRacer(playerId, reset) {
var elem = document.getElementById(playerId);
var pos = parseInt(elem.style.left, 10);
if (isNaN(pos) || reset) {
pos = 0;
}
//console.log(playerId + ': ' + pos);
if (pos < 450) {
pos += randStep(3);
elem.style.left = pos + 'px';
setTimeout('animateRacer("' + playerId + '")', randStep(5));
}
}
function randStep(max) {
var min = 1;
return Math.floor(Math.random() * (max - min)) + min;
}
body {
overflow: hidden;
}
#container {
width: 500px;
height: 160px;
position: relative;
background-color: yellow;
}
.player {
width: 50px;
height: 50px;
background-color: gray;
position: relative;
}
#player1 {
background-color: red;
top: 20px;
}
#player2 {
background-color: blue;
top: 40px;
}
<p>
<button onclick="startRace()">Start Race</button>
</p>
<div id="container">
<div id="player1" class="player"></div>
<div id="player2" class="player"></div>
</div>
function mover(obj) {
this.obj=obj;
this.pos = 0;
this.id = setInterval(this.frame, 5);
}
mover.prototype.frame=function() {
if (this.pos == 350) {
clearInterval(this.id);
} else {
this.pos++;
this.obj.style.left = this.pos + 'px';
}
}
}
Simply do:
img1=new mover(document.getElementById("pic1"));
You can repeat this with every image and you could store them into an array:
images=[];
function letsmove(){
images.push(new mover(someid));
...
}
And you can do this with all images on the site:
images=[];
function letsmove(){
domimages=document.getElementsByTagName("img");
domimages.forEach(function(img){
images.push(new mover(img));
});
}
}
See JS OOP and JS Prototyping for more explanation

Categories

Resources