In my scroll event listener I loop through all my .project elements then add or remove a class depending on their current position from the top of the viewport. I want to add a class to an element when it is at 80% of viewport height and remove it at 100% and 0%.
The logic I have should work fine, but the class rarely gets added at all.
var projects = document.querySelectorAll(".project");
var counter = document.getElementById("counter");
var viewH = window.innerHeight || document.documentElement.clientHeight;
window.addEventListener(
"scroll",
function() {
for (var i = 0; i < projects.length; i++) {
var project = projects[i];
// get dist from top of viewport
distTop = project.getBoundingClientRect().top;
distPercent = Math.round(distTop / viewH * 100);
// play at 80%
if (distPercent == "80") {
project.classList.add("play");
counter.innerHTML = i + 1;
}
// stop at 0%
if (distPercent == "0") {
project.classList.remove("play");
}
// stop if off screen
if (distPercent =="100") {
project.classList.remove("play");
}
}
},
false
);
window.addEventListener('resize', function () {
viewH = window.innerHeight || document.documentElement.clientHeight;
})
#half {
position:fixed;
top:50%;
height: 1px;
background: red;
width: 100%;
}
#projects {
padding-top:60vh;
width: 50vw;
margin: 0 auto;
}
#counter {
position: fixed;
top:20px;
left: 20px;
font-size:20px
}
.project {
background:pink;
height: 50vh;
width: 50vw;
margin-bottom:100px;
transition: background 0.3s ease-in-out;
}
.play {background:red}
* {
padding:0;
margin:0;
}
<div id="half"></div>
<div id="counter">0</div>
<div id="projects">
<div class="project">1</div>
<div class="project">2</div>
<div class="project">3</div>
<div class="project">4</div>
<div class="project">5</div>
</div>
Related
I am working on small application
i want to display the div if the user scroll up to > 100px from the current position and hide div if the user scroll down to > 50 px from current postion
example code
myID = document.getElementById("myID");
var myScrollFunc = function() {
var y = window.scrollY;
if (y >= 200) {
myID.className = "bottomMenu show"
} else {
myID.className = "bottomMenu hide"
}
};
window.addEventListener("scroll", myScrollFunc);
body {
height: 2000px;
}
.bottomMenu {
position: fixed;
bottom: 0;
width: 100%;
height: 60px;
border-top: 1px solid #000;
background: red;
z-index: 1;
transition: all 1s;
}
.hide {
opacity: 0;
left: -100%;
}
.show {
opacity: 1;
left: 0;
}
<div id="myID" class="bottomMenu hide"></div>
can any one help with code in javascript
Finded the way to solve this
first we want to get the scroll direction
and create two counter 1.upcounter 2. down counter
and if we start scroll up increase the upcounter and set down counter
to 0
and if we start scroll dow increase the downcounter and set up
counter to 0
if the up counter value reaches your value for example if reaches 100
display the div
and if the down counter reaches your value for example if reaches 50
hide the div
code example
myID = document.getElementById("myID");
function showSmartMenu() {
// current scroll position
var st = window.pageYOffset || document.documentElement.scrollTop;
// scrolling up
if (st < lastScrollTop) {
upCounter += 1;
downCounter = 0;
if (upCounter == 100) {
myID.className = "bottomMenu show"
}
} else { // scrolling down
downCounter -= 1;
upCounter = 0;
if (downCounter == -50) {
myID.className = "bottomMenu hide"
}
}
lastScrollTop = st <= 0 ? 0 : st;
}
var lastScrollTop = 0;
var upCounter = 0
var downCounter = 0
window.addEventListener("scroll", showSmartMenu)
body {
height: 2000px;
}
.bottomMenu {
position: fixed;
bottom: 0;
width: 100%;
height: 60px;
border-top: 1px solid #000;
background: red;
z-index: 1;
transition: all 1s;
}
.hide {
opacity: 0;
left: -100%;
}
.show {
opacity: 1;
left: 0;
}
<div id="myID" class="bottomMenu hide"></div>
Trying to create a Scroll Indicator, which would not be horizontal, but vertical. The problem is that when I try to start scrolling the bar that indicated the position isn't scaling...
HTML
<div id="scrollbar">
<div id="bar">
</div>
<div>
CSS
#scrollbar
{
width: 1%;
height: 100%;
padding: 0;
margin: 0 0 0 auto;
right: 0;
top: 0;
position: fixed;
visibility: visible;
background-color: transparent;
}
#scrollbar #bar
{
width: inherit;
height: 0%;
background-color: #ccc;
}
JS
var bar = document.getElementById("bar");
window.onscroll = function () { scrollIndicator() };
window.onload = function () { scrollIndicator() };
function scrollIndicator()
{
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = 100;
if(height > 0)
{
scrolled = (winScroll / height) * 100;
}
bar.style.height = scrolled + "%";
}
I absolutely cannot find the problem...
your web page doesn't have enough content for it to scroll, hence scroll event isn't firing.
You need to fix the html, #scrollbar is missing a closing div tag and add enough content on the webpage so that it scrolls.
You also need to change the width of #bar from inherit to 100%.
var bar = document.getElementById("bar");
window.onscroll = function() {
scrollIndicator()
};
function scrollIndicator() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = 100;
if (height > 0) {
scrolled = (winScroll / height) * 100;
}
bar.style.height = scrolled + "%";
}
#scrollbar {
width: 1%;
height: 100%;
padding: 0;
margin: 0 0 0 auto;
right: 0;
top: 0;
position: fixed;
background-color: transparent;
}
#scrollbar #bar {
width: 100%;
height: 0%;
background-color: blue;
}
.section {
height: 100vh;
}
.section:nth-child(even) {
background: green;
}
.section:nth-child(odd) {
background: red;
}
<div id="scrollbar">
<div id="bar"></div>
</div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
i want to add width to my div by the how much page height is so it can show how much page is left if page scrolled to bottom div width should be 100% and if it at middle it should be half
window.onscroll = function () {
addLoaderWidth();
}
function addLoaderWidth() {
var addWidth = window.pageYOffset;
document.getElementById('load').style.width = addWidth + 'px';
}
Your javascript works just fine. I had to add some style for the #load element, and add a container around the element that was scrollable. But it seems to work as expected:
window.onscroll = function () {
addLoaderWidth();
}
function addLoaderWidth() {
var addWidth = window.pageYOffset;
document.getElementById('load').style.width = addWidth + 'px';
}
#load {
height: 10px;
width: 0px;
background-color: blue;
position: fixed;
top: 0;
left: 0;
transition: all .2s ease;
}
.container {
height: 1000px;
position: relative;
}
<div class="container">
<div id="load"></div>
</div>
You can do this by calculating the percentage that was scrolled down and use that value as the width of the element.
const progress = document.getElementById('progress');
window.addEventListener('scroll', function() {
let d = document.documentElement, b = document.body;
let percentage = (d.scrollTop||b.scrollTop) / ((d.scrollHeight||b.scrollHeight) - d.clientHeight) * 100;
progress.style.width = percentage + '%';
});
#progress {
position: fixed;
top: 0;
left: 0;
height: 8px;
width: 0%;
background-color: #48E;
}
#content {
height: 2000px;
}
<div id="progress"></div>
<div id="content"></div>
I have created a small demo of two boxes animating in and out based on scroll position. But this isn't exactly what I want to achieve. What I want is for the boxes to animate based on scroll position not just transition in and out when a certain point is reached.
For example the scrolling should control the animation so if you scroll down the boxes will animate in, if you scroll up they will animate out. If you stop scrolling mid animation the animation will stop. If you reverse the scroll position the animation will reverse. So the animation only happens as you scroll.
I hope that is clear enough for you to understand. I will try provide a link to what I am trying to achieve. But for now here's my demo just using a transition to animate the boxes.
jQuery(document).ready(function($){
var scroll_pos = $(window).scrollTop();
var box = $('#container').offset().top - 200;
$(window).on('scroll', function(){
scroll_pos = $(window).scrollTop();
$('p').html(scroll_pos);
if(scroll_pos >= box){
$('#left').addClass('animate');
$('#right').addClass('animate');
}else{
$('#left').removeClass('animate');
$('#right').removeClass('animate');
}
});
});
#container{
width: 600px;
height: 300px;
margin: 1000px auto;
overflow: hidden;
font-size: 0;
}
#left{
width: 55%;
height: 300px;
background-color: blue;
display: inline-block;
transform: translateX(-100%);
transition: all 0.5s;
}
#right{
width: 45%;
height: 300px;
background-color: yellow;
display: inline-block;
transform: translateX(100%);
transition: all 0.5s;
}
#left.animate{
transform: translateX(0%);
}
#right.animate{
transform: translateX(0%);
}
p{
position: fixed;
top: 0;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<p></p>
<div id="container">
<div id="left"></div>
<div id="right"></div>
</div>
Here's an example of what I want to achieve. As you can see the scroll controls the animation of the fidget spinner https://ampbyexample.com/visual_effects/basics_of_scrollbound_effects/
Based on this answer you could do someting like:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
// Now our stuff:
var $container = $("#container");
var $left = $("#left");
var $right = $("#right");
$container.inViewport(function( px ) {
var v = 1 - px / $container.height(); // Value from 1.0 to 0.0 and v.versa
$("p").text(v);
$left.css({transform: `translateX(${ -v * 100 }%)`});
$right.css({transform: `translateX(${ v * 100 }%)`});
});
body {
height: 500vh;
}
#container {
position: relative;
margin: 0 auto;
top: 200vh;
overflow: hidden;
width: 60vw;
height: 60vh;
}
#left,
#right {
width: 50%;
height: 100%;
float: left;
}
#left {
background-color: blue;
transform: translateX(-100%);
}
#right {
background-color: yellow;
transform: translateX(100%);
}
p {position: fixed; top:0; left: 0;}
<div id="container">
<div id="left"></div>
<div id="right"></div>
</div>
<p></p>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I try to make this effect using css.
This is the effect:
I try to make div that:
div {
height: 300px;
width: 10px;
position: absolute;
border-radius: 0px 500px 500px 0;
-moz-border-radius: 0px 500px 500px 0;
-webkit-border-radius: 0px 500px 500px 0;
background-color: grey;
opacity:0.1;
}
and then by css change the width of this effect.But it look very ugly it more square then circle and also I the change in the width dont make it become like the effect. it looks like the shape become bigger in width but not become more circle...
How can I make this effect by css/js ? everything that I tried with the div look very bad.
Thanks.
The effect is a little tricky because of its shape. The key is that the circle that you are creating with the div has to be moved mostly off screen to get a curve that aligns more with the example you gave.
.container .effect{
position:absolute;
width:200px;
height:80%;
top:10%;
right:-140px;
background-color:#fff;
border-radius:100% 100% 100% 100%;
transition:width 500ms ease-in-out, right 500ms ease-in-out, opacity 500ms ease-in-out;
opacity:.7;
}
Here is a fiddle with more details. Try turning the overflow:hidden off on the .container element to see more details of whats going on. The JavaScript is just to show the effect happening.
**Side note: the background image is not my own and was used for education purposes. Credit belongs with the original owner.
Just give it a try (Don't forget to emulate touch events in chrome):
var _div = document.getElementById('wrapper');
var _elem = document.getElementById('div');
_div.addEventListener('touchmove', function () {
_elem.style.width = '60px';
});
_div.addEventListener('touchend', function () {
_elem.style.width = '0';
});
*, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#div {
height: 95%;
width: 0;
top: 2.5%;
position: absolute;
border-radius: 0 500px 500px 0;
-moz-border-radius: 0 500px 500px 0;
-webkit-border-radius: 0 500px 500px 0;
background-color: gray;
opacity: 0.1;
-webkit-transition: width .2s; /* Safari */
transition: width .2s;
}
#wrapper {
width: 100%;
height: 100%;
background: darkgreen;
}
<div id="wrapper">
<div id='div'></div>
</div>
Here is another take using pseudo-elements and transforms. When scroll reaches end on both sides, the faux-rubber-banding effect will show up.
Works with mouse scroll to test on non-touch screen desktops. For Chrome, can emulate mouse events to test.
Demo Fiddle: http://jsfiddle.net/abhitalks/v4mLkttL/
Demo Snippet:
var $wrap = $('#wrap'), startX, isDrag = false;
$wrap.on('touchstart', function(e) {
startX = e.originalEvent.touches[0].clientX; isDrag = true;
});
$wrap.on('touchmove', function(e) {
var delta = e.originalEvent.changedTouches[0].clientX - startX,
pos = $(this).scrollLeft(), w = $(this).width(),
iw = $(this).innerWidth(), sh = this.scrollWidth
;
if (isDrag) {
if ((delta > 0) && (pos <= 0)) {
$wrap.addClass('rubberLeft');
isDrag = false; e.preventDefault();
}
if ((delta < 0) && (pos + iw >= sh)) {
$wrap.addClass('rubberRight');
isDrag = false; e.preventDefault();
}
}
});
$wrap.on('touchend', function(e) {
isDrag = false; clearRubber();
});
$wrap.on('mousewheel DOMMouseScroll', function(e) {
var start = e.originalEvent,
delta = start.wheelDelta || -start.detail,
pos = $(this).scrollLeft(), w = $(this).width(),
iw = $(this).innerWidth(), sh = this.scrollWidth
;
this.scrollLeft += delta * -1;
if (pos <= 0) { $wrap.addClass('rubberLeft'); setTimeout(clearRubber, 600); }
else if (pos + iw >= sh) { $wrap.addClass('rubberRight'); setTimeout(clearRubber, 600); }
else { clearRubber(); }
e.preventDefault();
});
function clearRubber() { $wrap.removeClass('rubberLeft').removeClass('rubberRight'); }
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body { height: 100vh; width: 100vw; overflow: hidden; }
#wrap {
min-width: 100vw; height: 100vh;
overflow-y: hidden; overflow-x: scroll;
background-color: #000; white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
#wrap img { display: inline-block; vertical-align: top; }
#wrap::before, #wrap::after {
content: ''; display: block;
position: absolute; top: 4%;
width: 100px; height: 90%;
background-color: rgba(255,255,255,0.6);
box-shadow: 0 0 10px 4px rgba(0,0,0,0.5);
border-radius: 50%; transform: translateX(0px);
transition: transform 0.5s;
}
#wrap::before { left: -105px; }
#wrap::after { right: -105px; }
#wrap.rubberLeft::before { transform: translateX(45px); }
#wrap.rubberRight::after { transform: translateX(-45px); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrap">
<img class="page" src='//lorempixel.com/240/320' />
<img class="page" src='//lorempixel.com/241/320' />
<img class="page" src='//lorempixel.com/239/320' />
<img class="page" src='//lorempixel.com/240/320' />
<img class="page" src='//lorempixel.com/241/320' />
<img class="page" src='//lorempixel.com/239/320' />
</div>