I'm practicing js and for long time i cant solve problem bellow.
I have function for changing the blurry background "changeBg", but it does not work when called.
Also key event function are not working dont know why.
I will appreciate any hints where to search for problems.
I know the code is wet but it's far from end "product".
//counting img tags
var n = $("img").length;
var m = n - 2;
//alert("jest " + m + "tagow img");
//adding onclick to source of file
var source = $(".slider-inner > img").attr("src");
$(".slider-inner > img").attr("onclick", "location.href=\'" + source + "\'");
for (i = 1; i <= m; i++) {
$(".dotcontainer").append($("<div class=\"dot\">x</div>"));
$('.slider-inner img').attr('id', function (i) {
return 'x' + (i + 1);
});
$('.dotcontainer div').attr('id', function (i) {
return 'x' + (i + 1);
});
var url = $('.slider-inner img:nth-child(' + i + ')').attr("src");
console.log(i);
}
///temporary solution for initial background
$(".bg").css('background', "url('"+ source +"')");
$(".bg").css('background-repeat', "no-repeat");
$(".bg").css('background-size', "cover");
$(".bg").css('background-position', "center");
//making first dot active
$('.dotcontainer div:nth-child(' + 1 + ')').addClass('activee');
//function changing backgorund
function changeBg() {
$(".bg").css('background', "url('"+ source +"')");
$(".bg").css('background-repeat', "no-repeat");
$(".bg").css('background-size', "cover");
$(".bg").css('background-position', "center");
};
// next buttton
$('.next').on('click', function nextImage() {
var currentImg = $('.active');
var nextImg = currentImg.next();
var currentdot = $('.activee');
var nextdot = currentdot.next();
if (nextImg.length) {
currentImg.removeClass('active').css('z-index', -10);
nextImg.addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
nextdot.addClass('activee');
var source = nextImg.attr("src");
nextImg.attr("onclick", "location.href=\'" + source + "\'");
changeBg();
} else {
currentImg.removeClass('active').css('z-index', -10);
$('#x1').addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
$('.dotcontainer div:nth-child(' + 1 + ')').addClass('activee');
}
});
//prev button
$('.prev').on('click', function prevImage() {
var currentImg = $('.active');
var prevImg = currentImg.prev();
var currentdot = $('.activee');
var prevdot = currentdot.prev();
var n = $("img").length;
var m = n - 2;
if (prevImg.length) {
currentImg.removeClass('active').css('z-index', -10);
prevImg.addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
prevdot.addClass('activee');
changeBg();
} else {
currentImg.removeClass('active').css('z-index', -10);
$('.slider-inner img:nth-child(' + m + ')').addClass('active').css('z-index', 10);
currentdot.removeClass('activee');
$('.dotcontainer div:nth-child(' + m + ')').addClass('activee');
}
});
//switch active dots
$(".dot").click(function (event) {
$('.activee').attr('class', 'dot');
$(this).attr('class', 'dot activee');
var aktkrop = $(".activee").attr("id");
var fotoa = $('.slider-inner .active').attr("id");
$(".active").removeClass("active");
$("#" + aktkrop).attr("class", "active")
});
//temp shadowbox temporary solution
$('.btn').on('click', function () {
$(".boxx").css("display", "block");
});
$('.close').on('click', function () {
$(".boxx").css("display", "none");
});
document.addEventListener('keydown',function(e){
if (e.keyCode === 37) {
prevImage();
} else if(e.keyCode === 39) {
nextImage();
}
});
body {
font-family: "Arial", sans-serif;
font-size: 14px;
color: #fff;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
margin: 0;
padding: 0;
}
.bg{
z-index: -2;
position: absolute;
width: 100%;
height: 100%;
filter: blur(30px);
-webkit-filter: blur(30px);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
margin: 0;
padding: 0;
}
.blackshadow{
z-index: -1;
position: absolute;
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
}
a {
color: #fff;
text-decoration: none;
}
h1 {
text-align: center;
}
.container {
width: 540px;
margin: 40px auto;
overflow: auto;
}
.slider-inner {
width: 500px;
height: 300px;
position: relative;
overflow: hidden;
float: left;
padding: 3px;
border: #666 solid 1px;
}
.slider-inner img {
display: none;
width: 500px;
height: 300px;
}
.slider-inner img.active {
display: inline-block;
}
.prev,
.next {
float: left;
margin-top: 130px;
cursor: pointer;
}
.prev {
position: relative;
margin-right: -45px;
z-index: 100;
}
.next {
position: relative;
margin-left: -45px;
z-index: 100;
}
.buba {
display: flex;
align-items: center;
justify-content: center;
}
.dotcontainer {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
align-items: center;
justify-content: center;
}
.dot {
cursor: pointer;
margin: 5px;
width: 20px;
height: 20px;
background-color: gray;
border-radius: 50%;
text-align: center;
justify-content: center;
color: black;
font-weight: 800;
}
.activee {
background-color: white;
}
.boxx {
width: 100%;
height: 100%;
background-color: black;
opacity: 0.6;
position: fixed;
z-index: 11;
margin: 0;
padding: 0;
display: none;
}
.close {
margin-left: 300px;
margin-top: 300px;
z-index: 11;
}
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="https://code.jquery.com/jquery-3.1.1.js" integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
crossorigin="anonymous"></script>
</head>
<body>
<div class="bg"></div>
<div class="blackshadow"></div>
<div class="boxx">
<div class="closee">
<button class="close">Close</button>
</div>
</div>
<button class="btn">Kliknij</button>
<div class="container">
<h1>JQSlider</h1>
<div class="slider-outer">
<img src="http://www.fotem.pl/data/7d87e07a3066629171add66003d.png" id="prev" class="prev" alt="Prev">
<div class="slider-inner">
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832_1280.jpg" class="active">
<img src="https://cdn.pixabay.com/photo/2015/12/01/20/28/green-1072828_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/06/19/21/24/the-road-815297_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2015/01/28/23/35/landscape-615429_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2019/09/30/14/51/squirrel-4515962_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2016/07/22/16/29/fog-1535201_1280.jpg">
<img src="https://cdn.pixabay.com/photo/2016/11/23/13/48/beach-1852945_1280.jpg">
</div>
<img src="http://www.fotem.pl/data/6f1498615d84ca14dbf0de784bd.png" id="next" class="next" alt="Next">
</div>
</div>
<div class="dotcontainer">
</div>
</body>
<script type="text/javascript" src="script.js">
</script>
</html>
Thank you in advance.
Code:
https://codepen.io/odzeradodeveloperajava/pen/EMLbzz
The background did not change as the source variable was not up-to date with the image src. You will need to ensure, that the source is not only declared once, but the value in it will always be updated on every event.
The keyup event handler is throwing exceptions as it cannot access the nextImage() and prevImage() methods. You will need to separate the methods and re-use them when needed as callBackFunction or just call it directly:
function prevImage() {
// code inside
}
function nextImage() {
// code inside
}
$('.next').on('click', nextImage);
$('.prev').on('click', prevImage);
document.addEventListener('keyup', function (e) {
if (e.keyCode === 37) {
prevImage();
} else if (e.keyCode === 39) {
nextImage();
}
});
I've made several changes to the example you've shared. Here is a working Pen: https://codepen.io/attila-antal/pen/KKKVGEd
first of all you have to declare your function nextImage and prevImage outside of the event listener. for example:
function nextImage() {
// your code
}
$('.next').on('click', nextImage);
The background does not change because you have to pass new source to your function. for example:
function changeBg(source) {
// your code
}
When you want to invoke changeBg function you should pass new source: for example: changeBg(newImageUrl);
Related
I have a transform and a check-in javascript. Currently, the alert displays before the actual transform. Is there a way to only display the alert after the transform is complete?
The Object is to do the transform and then do the check so that I can have some sort of event happen to display the winners banner in the middle of the screen. Right now the only objective is to get the check to happen after the transformation.
This is what I have now:
<html>
<head>
<script>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'style.css';
document.getElementsByTagName('HEAD')[0].appendChild(link);
</script>
</head>
<html lang="en">
<body>
<div id="field" class="soccer-field">
<div id="b" class="btnBlue"></div>
<div id="ball" class="btnSoccerBall"></div>
<div id="r" class="btnRed"></div>
</div>
</body>
</html>
<script>
//Add onclick
document.getElementById("b").addEventListener("click", myMoveLeft);
document.getElementById("r").addEventListener("click", myMoveRight);
//Add animation
var item = document.getElementById('ball');
var anim;
var x = 0, y = 0;
function myMoveLeft() {
anim = item.animate([
// keyframes
{ transform: `translate(${x}px, ${y}px)` },
{ transform: `translate(${x + 100}px, ${y}px)` }
], {
duration: 500,
iterations: 1,
fill: 'forwards'
});
x += 100;
if (x == 700) {
alert("ok")
}
}
function myMoveRight() {
anim = item.animate([
// keyframes
{ transform: `translate(${x}px, ${y}px)` },
{ transform: `translate(${x - 100}px, ${y}px)` }
], {
duration: 500,
iterations: 1,
fill: 'forwards'
});
x -= 100;
if (x == -700) {
alert("ok")
}
}
item.addEventListener('animationend', () => {
console.log('Animation ended');
});
</script>
Css
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 20rem;
overflow: hidden;
}
.btnBlue {
background-image:url(b.png);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
margin-left: 20px;
margin-bottom: 20px;
height: 150px;
width: 150px;
}
.btnRed {
background-image:url(r.png);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
margin-right: 20px;
margin-bottom: 20px;
height: 150px;
width: 150px;
}
.btnSoccerBall {
background-image:url(s.png);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
position: relative;
margin: auto;
height: 100px;
width: 100px;
}
.soccer-field {
background-image:url(back.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
height: 100vh;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-end;
/* padding: 0 20px; optional */
}
You can use Animation.onfinish function and move your alert code inside it. Try like below.
document.getElementById("b").addEventListener("click", myMoveLeft);
//Add animation
var item = document.getElementById('ball');
var anim;
var x = 0,
y = 0;
function myMoveLeft() {
anim = item.animate([
// keyframes
{
transform: `translate(${x}px, ${y}px)`
},
{
transform: `translate(${x + 100}px, ${y}px)`
}
], {
duration: 500,
iterations: 1,
fill: 'forwards'
}).onfinish = function() {
x += 100;
if (x == 700) {
alert("ok")
}
};
}
item.addEventListener('animationend', () => {
console.log('Animation ended');
});
<div>
<input type='button' id='ball' value='ball' />
</div>
<input type='button' id='b' value='l' />
I am using Skrollr librabry. In the start it works fine,but as I'm scrolling down,I am experiencing flickering and images do not load. The content of my website are just images. Works fine on firefox, but not on Chrome. Could you please help me. I am using approximately 190 images. Is that an issue?
I am using async calls to fetch the data,and every image is being loaded before the skrollr is rendered.
Here's my working example : https://jsfiddle.net/if_true/v1mLhutc/7/
html
<body>
<div id="fakeloader"></div>
<div style="transform: translate3d(0,0,0);"></div>
<div class="DESKScreen">
<div id="info" hidden="hidden">0</div>
<section id="slide">
<div class="bcg"></div>
</section>
</div>
</body>
CSS
*,:before,:after {
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box;
box-sizing:border-box;
-webkit-backface-visibility:hidden;
backface-visibility: hidden;
}
#info{
position: fixed;
top: 20px;
left: 20px;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
padding: 20px;
z-index: 9999;
}
body {
margin: 0;
width: 100%;
height: 100%;
}
html{
width: 100%;
height: 100%;
}
section {
width: 100%;
max-width: 100%;
height: 100%;
position: fixed;
left: 0;
right: 0;
margin: auto;
}
#slide .bcg {
height: 100%;
width: 100%;
background-size: 100%;
background-position: center top;
background-attachment: fixed;
position: absolute;
transform:translateZ(0)
}
.img{
background-size: cover;
background-repeat: no-repeat;
background-position: center;
display: table;
margin: auto;
max-height: 100vh !important;
height: 100% !important;
}
.item {
width: 100%;
position: absolute;
opacity: 1;
}
`Js`
$(document).ready(function() {
DivImage("sup");
var s = skrollr.init({
render: function(data) {
console.log(data.curTop);
}
});
//Check the screen size.
(function() {
if (screen.width < 768) {
$("#fullpage").fullpage({
//scrollingSpeed: 0,
});
$(".DESKScreen").css("display", "none");
} else if (screen.width > 768) {
$(".MObileScreen").css("display", "none");
}
})();
//Fakeloader for the loadtime
function loader() {
$("#fakeloader").fakeLoader({
timeToHide: 4000,
bgColor: "#e74c3c",
spinner: "spinner2"
});
}
loader();
});
function DivImage(name) {
//console.log(name);
//a counter to set for div id
let counter = 0;
//create the urls based on a nr
var Images = makeUrls();
//first create the div and pass the counter to it
CreateDiv(Images);
}
function makeUrls() {
let base = "images/";
let rest = ".jpg";
let result = [];
for (let i = 0; i < 191; i++) {
let baseNr = 1 + i;
if (baseNr === 2000) {
console.log("base");
} else {
result.push(base + baseNr + rest);
}
}
return result;
}
function CreateDiv(images) {
// debugger;
var from = 0,
to = 0;
let result = [];
for (let i of images) {
var newDiv = $('<div class="img-div"></div>');
newDiv.css({
backgroundImage: `url(${i})`
});
newDiv.attr("data--" + from + "-top", "opacity: 0;");
from += 125;
newDiv.attr("data--" + from + "-top", "opacity: 0;");
from += 125;
newDiv.attr("data--" + from + "-top", "opacity: 1;");
newDiv.attr("data-anchor-target", "#slide");
newDiv.attr("data-skrollr-decks-speed", "300");
$("#slide").append($(newDiv));
}
}
I would please like an explanation to why the slideshow is not working. Below I have used an interval to perpetually change the slideshow, if userClick is false. The white and squared buttons (made of divs) are set to call upon two functions; slideRight() or slideLeft() and clicked(). When the buttons are clicked however, the clicked() function does not seem to change the variable, based on the data on top of the page.
<body>
<div class="page-wrapper">
<header>
<div class="headContent">
<h1 class="titleText">Slideshow</h1>
<h2 class="subTitleText">A slideshow made with JavaScript.</h2>
<p>userClick <span id="uc"></span></p>
</div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Gallery</li>
</ul>
</nav>
</header>
<div class="body-wrapper">
<h1 class="titleText">Slideshow</h1>
<div id="slideshow">
<div id="leftSlide" onclick="leftSlide(); clicked()"></div>
<div id="rightSlide" onclick="rightSlide(); clicked()"></div>
</div>
<p>The image is not invoked by a tag, but invoked by the background property using Javascript.</p>
</div>
<footer>
<p id="footerText">© 2017 <br>Designed by JastineRay</p>
</footer>
</div>
<script language="javascript">
// Slide function
var slide = ["minivan", "lifeinthecity", "sunsetbodyoflove"];
var slideTo = 1;
window.onload = getSlide();
// Previous Image
function leftSlide() {
if (slideTo != 0) {
slideTo = slideTo - 1;
} else if (slideTo == 0) {
slideTo = slide.length - 1;
} else {
alert('SLIDE ERROR');
}
getSlide();
}
// Next Image
function rightSlide() {
if (slideTo != (slide.length - 1)) {
slideTo = slideTo + 1;
} else if (slideTo == (slide.length - 1)) {
slideTo = 0;
} else {
alert('SLIDE ERROR');
}
getSlide();
}
function getSlide() {
imageURL = 'url(images/' + slide[slideTo] + '.jpg)';
document.getElementById("slideshow").style.backgroundImage = imageURL;
}
// Interval Slideshow & Check if user clicked (timeout)
var userClick = false;
window.onload = slideInterval(5000);
// Start Slideshow
function slideInterval(interval) {
while (userClick = false) {
setInterval(function() {
rightSlide();
}, interval)
}
}
// Stop Slideshow and start timeout
function clicked() {
userClick = true;
setTimeout(function() {
userClick = false;
slideInterval();
}, 2000)
}
window.onload = function() {
setInterval(document.getElementById("uc").innerHTML = userClick), 100
}
</script>
</body>
CSS coding below.
* {
margin: 0;
padding: 0;
}
.page-wrapper {
width: 100%;
}
// Class Styling
.titleText {
font-family: monospace;
font-size: 40px;
}
.subTitleText {
font-family: monospace;
font-size: 20px;
font-weight: normal;
}
// Header Styling
header {
height: 500px;
}
.headContent {
margin: 30px 7%;
}
// Navigation Styling
nav {
overflow: hidden;
}
nav ul {
background: black;
background: linear-gradient(#595959, black);
list-style-type: none;
font-size: 0;
padding-left: 13.33%;
margin: 40px 0;
}
nav ul li {
padding: 15px 20px;
border-right: 1px solid #595959;
border-left: 1px solid #595959;
color: white;
display: inline-block;
font-size: 20px;
font-family: sans-serif;
}
// Body Styling
.body-wrapper {
}
.body-wrapper > .titleText {
text-align: center;
font-size: 50px;
}
#slideshow {
overflow: hidden;
margin: 20px auto;
border: 2px solid blue;
height: 350px;
max-width: 800px;
background-size: cover;
background-position: center;
position: relative;
}
#leftSlide {
position: absolute;
left: 40px;
top: 175px;
background-color: white;
height: 40px;
width: 40px;
}
#rightSlide {
position: absolute;
left: 100px;
top: 175px;
background-color: white;
height: 40px;
width: 40px;
}
// Footer Styling
Try changing the checking part to:
window.onload = function() {
setInterval(function () {
document.getElementById("uc").innerHTML = userClick;
}, 100);
}
The first argument of setInterval has to be a function (something that can be called), not a generic piece of code.
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
Setting scrollLeft does reset the scroll bar position and updating the content works as expected but when doing both at the same time the scroll bar gets confused and doesn't reset.
To see the expected behavior vs unexpected behavior view each demo on a device with a touchpad and use the touchpad to scroll left or right inside the wrapper, then try to do the same thing on an android device.
Notice that on a laptop the element will scroll endlessly, on an android device the element will scroll only until it has reached the initially set "max scroll"
What should happen:
When the user scrolls left or right, move the first child element to the end of the nodeList or move the last child to the beginning and reset the scroll position to that of half the with of the first child.
The following are my attempts at fixing the issue
Set transform: translateX(0px) on .inner see here which had worse behavior than before.
the fix listed here which was for a previous bug in android where setting scrollLeft did not work at all. This did not help the issue at all.
wrap.appendChild(inner) on each scroll event, which slowed the scrolling down but didnt fix the issue because chrome remembers scroll positions. This would be a hack even if I could get chrome to forget the scroll position (which looks like it could be plausible but would be yet another hack)
I realize that I could sniff the browser and just revert to jquery ui mobile swipe setup, but I think that if I could get this to work I wouldn't have to use an external library to emulate a native behavior (and native is always better).
var log = function(event) {
var log = document.querySelector('.log');
log.innerHTML = event + "<br>" + log.innerHTML;
};
var wrap = document.querySelector('.wrap');
var inner = document.querySelector('.inner');
var items = document.querySelectorAll('.item');
var controlLeft = document.createElement('a');
controlLeft.className = 'control control-left';
controlLeft.href = 'javascript:void(0)';
controlLeft.innerHTML = '<';
controlLeft.onclick = function() {
log('click left');
inner.scrollLeft++;
};
wrap.appendChild(controlLeft);
var controlRight = document.createElement('a');
controlRight.className = 'control control-right';
controlRight.href = 'javascript:void(0)';
controlRight.innerHTML = '>';
controlRight.onclick = function() {
log('click right');
inner.scrollLeft--;
};
wrap.appendChild(controlRight);
var darken1 = document.createElement('div');
var darken2 = document.createElement('div');
darken1.className = 'darken';
darken2.className = 'darken';
items[0].appendChild(darken1);
items[2].appendChild(darken2);
var getWidth = function(element) {
return Number(window.getComputedStyle(element, null).getPropertyValue('width').replace('px', '')) + 1;
};
wrap.style.overflow = 'hidden';
inner.style.overflowY = 'hidden';
inner.style.overflowX = 'auto';
wrap.style.height = inner.scrollHeight + 'px';
window.onresize = function() {
wrap.style.height = inner.scrollHeight + 'px';
inner.scrollLeft = 0;
inner.scrollLeft = getWidth(items[0]) / 2;
};
inner.scrollLeft = getWidth(items[0]) / 2;
oldScroll = inner.scrollLeft;
inner.onscroll = function() {
if (inner.scrollLeft < oldScroll) {
log('scroll right');
inner.appendChild(inner.querySelector('.item:first-child'));
inner.querySelector('.item:first-child').appendChild(darken1);
inner.querySelector('.item:nth-child(3)').appendChild(darken2);
} else if (inner.scrollLeft > oldScroll) {
log('scroll left');
var first = inner.querySelector('.item:first-child');
var last = inner.querySelector('.item:last-child');
inner.insertBefore(last, first);
inner.querySelector('.item:first-child').appendChild(darken1);
inner.querySelector('.item:nth-child(3)').appendChild(darken2);
}
inner.scrollLeft = 0;
inner.scrollLeft = getWidth(items[0]) / 2;
oldScroll = inner.scrollLeft;
};
*, *::before, *::after {
box-sizing: border-box;
}
html,
body {
padding: 0;
margin: 0;
max-height: 100%;
overflow: hidden;
}
.wrap {
position: relative;
}
.control {
font-weight: bold;
text-decoration: none;
display: inline-block;
position: absolute;
padding: 10px;
background: rgba(255, 255, 255, 0.5);
top: 50%;
transform: translateY(-50%);
color: #FFF;
font-size: 20pt;
}
.control-left {
padding-right: 20px;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
left: 0;
}
.control-right {
padding-left: 20px;
border-top-left-radius: 50%;
border-bottom-left-radius: 50%;
right: 0;
}
.inner {
font-size: 0;
white-space: nowrap;
overflow: auto;
}
.item {
position: relative;
display: inline-block;
font-size: 1rem;
white-space: initial;
padding-bottom: 33.3333%;
width: 50%;
}
.item .darken {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
}
.item[data-n="2"] {
background-image: url(http://www.lorempixel.com/400/300/animals);
background-size: cover;
}
.item[data-n="3"] {
background-image: url(http://www.lorempixel.com/400/300/business);
background-size: cover;
}
.item[data-n="4"] {
background-image: url(http://www.lorempixel.com/400/300/cats);
background-size: cover;
}
.item[data-n="5"] {
background-image: url(http://www.lorempixel.com/400/300/city);
background-size: cover;
}
.item[data-n="6"] {
background-image: url(http://www.lorempixel.com/400/300/food);
background-size: cover;
}
.item[data-n="7"] {
background-image: url(http://www.lorempixel.com/400/300/nightlife);
background-size: cover;
}
.item[data-n="8"] {
background-image: url(http://www.lorempixel.com/400/300/fashion);
background-size: cover;
}
.item[data-n="9"] {
background-image: url(http://www.lorempixel.com/400/300/people);
background-size: cover;
}
.item[data-n="10"] {
background-image: url(http://www.lorempixel.com/400/300/nature);
background-size: cover;
}
.item[data-n="11"] {
background-image: url(http://www.lorempixel.com/400/300/sports);
background-size: cover;
}
.item[data-n="12"] {
background-image: url(http://www.lorempixel.com/400/300/technics);
background-size: cover;
}
.item[data-n="13"] {
background-image: url(http://www.lorempixel.com/400/300/transport);
background-size: cover;
}
<div class="wrap">
<div class="inner">
<div class="item" data-n="2"></div>
<div class="item" data-n="3"></div>
<div class="item" data-n="4"></div>
<div class="item" data-n="5"></div>
<div class="item" data-n="6"></div>
<div class="item" data-n="7"></div>
<div class="item" data-n="8"></div>
<div class="item" data-n="9"></div>
<div class="item" data-n="10"></div>
<div class="item" data-n="11"></div>
<div class="item" data-n="12"></div>
<div class="item" data-n="13"></div>
</div>
</div>
<div class="log">
</div>
To fix this issue temporarily, I wrapped the function in a timeout. The timeout can be as little as 1 millisecond. I don't know why but changing the content and setting scrollLeft at the exact event of the scroll causes the browser to not reset the scroll bar.
(Demo)
inner.onscroll = function() {
window.clearTimeout(window.updateTimeout);
window.updateTimeout = window.setTimeout(function() {
if (inner.scrollLeft < oldScroll) {
log('scroll right');
inner.appendChild(inner.querySelector('.item:first-child'));
} else if (inner.scrollLeft > oldScroll) {
log('scroll left')
var first = inner.querySelector('.item:first-child');
var last = inner.querySelector('.item:last-child');
inner.insertBefore(last, first);
}
inner.querySelector('.item:first-child').appendChild(darken1);
inner.querySelector('.item:nth-child(3)').appendChild(darken2);
inner.scrollLeft = 0;
inner.scrollLeft = getWidth(items[0]) / 2;
oldScroll = inner.scrollLeft;
}, 1);
};
While this does "fix" the issue, I think it is a hack. I'm leaving this question open to see if I can get a real answer.
Every time you want to modify the property that you are using to check if the first or the last element need to be moved, you are also modifying the same info again, so you will get an unexpected behaviour.
Your trick to add a timeout gave the impression of be the solution because it give some time to the program, so it can serialize the information changes.
I've made some changes in your code and it doesn't uses timeout. But, because of the nature of the scroll event, depending on which configuration the user has in its scroll behaviour, one different amount of slides will be scrolled.
So I recommend that you add some verification, which can be a timer (hahahahaha...), but only to toggle a boolean to let the scroll handler go. Like the snnipet below:
inner.onscroll = function(e) {
if (!canScroll) {
return;
}
canScroll = false;
setTimeout(function () {
canScroll = true;
}, 300);
if (inner.scrollLeft < oldScrollLeft) {
// ...
Before you ask, the sense of delay that inner.scrollLeft = 0 then inner.scrollLeft = getWidth(items[0]) / 2; provides is because of this overprocessing that the original program force the browser to do.
var log = function(event) {
var log = document.querySelector('.log');
log.innerHTML = event + "<br>" + log.innerHTML;
};
var wrap = document.querySelector('.wrap');
var inner = document.querySelector('.inner');
var items = document.querySelectorAll('.item');
var controlLeft = document.createElement('a');
controlLeft.className = 'control control-left';
controlLeft.href = 'javascript:void(0)';
controlLeft.innerHTML = '<';
controlLeft.onclick = function() {
log('click left');
inner.scrollLeft++;
};
wrap.appendChild(controlLeft);
var controlRight = document.createElement('a');
controlRight.className = 'control control-right';
controlRight.href = 'javascript:void(0)';
controlRight.innerHTML = '>';
controlRight.onclick = function() {
log('click right');
inner.scrollLeft--;
};
wrap.appendChild(controlRight);
var darken1 = document.createElement('div');
var darken2 = document.createElement('div');
darken1.className = 'darken';
darken2.className = 'darken';
items[0].appendChild(darken1);
items[2].appendChild(darken2);
var getWidth = function(element) {
return Math.floor(Number(window.getComputedStyle(element, null).getPropertyValue('width').replace('px', '')));
};
wrap.style.overflow = 'hidden';
inner.style.overflowY = 'hidden';
inner.style.overflowX = 'auto';
wrap.style.height = inner.scrollHeight + 'px';
var oldScrollLeft = getWidth(items[0]) / 2;
var oldScrollWidth = inner.scrollWidth;
window.onresize = function() {
wrap.style.height = inner.scrollHeight + 'px';
oldScrollWidth = inner.scrollWidth;
oldScrollLeft = getWidth(items[0]) / 2;
inner.scrollLeft = oldScrollLeft;
};
inner.scrollLeft = getWidth(items[0]) / 2;
inner.onscroll = function(e) {
if (inner.scrollLeft < oldScrollLeft) {
log('scroll right');
inner.appendChild(inner.querySelector('.item:first-child'));
inner.querySelector('.item:first-child').appendChild(darken1);
inner.querySelector('.item:nth-child(3)').appendChild(darken2);
} else if (inner.scrollLeft > oldScrollLeft) {
log('scroll left');
var first = inner.querySelector('.item:first-child');
var last = inner.querySelector('.item:last-child');
inner.insertBefore(last, first);
inner.querySelector('.item:first-child').appendChild(darken1);
inner.querySelector('.item:nth-child(3)').appendChild(darken2);
inner.scrollLeft = 0;
}
inner.scrollLeft = oldScrollLeft;
};
*, *::before, *::after {
box-sizing: border-box;
}
html,
body {
padding: 0;
margin: 0;
max-height: 100%;
overflow: hidden;
}
.wrap {
position: relative;
}
.control {
font-weight: bold;
text-decoration: none;
display: inline-block;
position: absolute;
padding: 10px;
background: rgba(255, 255, 255, 0.5);
top: 50%;
transform: translateY(-50%);
color: #FFF;
font-size: 20pt;
}
.control-left {
padding-right: 20px;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
left: 0;
}
.control-right {
padding-left: 20px;
border-top-left-radius: 50%;
border-bottom-left-radius: 50%;
right: 0;
}
.inner {
font-size: 0;
white-space: nowrap;
overflow: auto;
}
.item {
position: relative;
display: inline-block;
font-size: 1rem;
white-space: initial;
padding-bottom: 33.3333%;
width: 50%;
}
.item .darken {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
}
.item[data-n="2"] {
background-image: url(http://www.lorempixel.com/400/300/animals);
background-size: cover;
}
.item[data-n="3"] {
background-image: url(http://www.lorempixel.com/400/300/business);
background-size: cover;
}
.item[data-n="4"] {
background-image: url(http://www.lorempixel.com/400/300/cats);
background-size: cover;
}
.item[data-n="5"] {
background-image: url(http://www.lorempixel.com/400/300/city);
background-size: cover;
}
.item[data-n="6"] {
background-image: url(http://www.lorempixel.com/400/300/food);
background-size: cover;
}
.item[data-n="7"] {
background-image: url(http://www.lorempixel.com/400/300/nightlife);
background-size: cover;
}
.item[data-n="8"] {
background-image: url(http://www.lorempixel.com/400/300/fashion);
background-size: cover;
}
.item[data-n="9"] {
background-image: url(http://www.lorempixel.com/400/300/people);
background-size: cover;
}
.item[data-n="10"] {
background-image: url(http://www.lorempixel.com/400/300/nature);
background-size: cover;
}
.item[data-n="11"] {
background-image: url(http://www.lorempixel.com/400/300/sports);
background-size: cover;
}
.item[data-n="12"] {
background-image: url(http://www.lorempixel.com/400/300/technics);
background-size: cover;
}
.item[data-n="13"] {
background-image: url(http://www.lorempixel.com/400/300/transport);
background-size: cover;
}
<div class="wrap">
<div class="inner">
<div class="item" data-n="2"></div>
<div class="item" data-n="3"></div>
<div class="item" data-n="4"></div>
<div class="item" data-n="5"></div>
<div class="item" data-n="6"></div>
<div class="item" data-n="7"></div>
<div class="item" data-n="8"></div>
<div class="item" data-n="9"></div>
<div class="item" data-n="10"></div>
<div class="item" data-n="11"></div>
<div class="item" data-n="12"></div>
<div class="item" data-n="13"></div>
</div>
</div>
<div class="log">
</div>