Start CSS animation after scrolling to particular section of page - javascript

I am trying to animate images using CSS on a webpage. The animation is working fine but I want to START the animation it only when user reaches at a particular section of the page. Here is my code:
<div class="sec1-right">
<img class="sec1-dmush1" src ="sec1-dmush1.png">
</div>
CSS
.sec1-right{
position: relative;
width: 50%;
float: right;
box-sizing: border-box;
min-height: 600px;
margin-top: 86px;
}
/* first section animation */
.sec1-dmush1 {
animation: fadeAndScale .9s cubic-bezier(.45,-0.22,.34,1.69);
transform-origin:center bottom;
max-width: 150px;
width: 100%;
position: absolute;
left: 180px;
top: 300px;
z-index: 0;
}
Animation
#keyframes fadeAndScale{
from{
opacity:0;
transform: scale3d(0,0,1);
}
to{
opacity: 1;
transform: scale3d(1,1,1);
}
}
How can I achieve

You need to write scroll event in javascript. element offsetTop minus window height. So as soon as element comes in viewport event starts.
Javascript:
var scrollpos = window.scrollY; // window scroll position
var wh = window.innerHeight-50; // as soon as element touches bottom with offset event starts
var element = document.querySelector(".sec1-dmush1"); //element
window.addEventListener('scroll', function(){
if(scrollpos > (element.offsetTop - wh)){
element.classList.add("onScroll");
}
});
JsFiddle
jQuery:
$(window).scroll(function(){
var wh = $(window).height()-50;
if($(window).scrollTop() > $('.sec1-dmush1').offset().top-wh){
$('.sec1-dmush1').addClass('onScroll');
}
});
jsFiddle
If you have multiple elements to animate. You can use waypoint js to reduce some efforts.
var wh = $(window).height();
var waypoints = $('.sec1-dmush1').waypoint(function(direction) {
$(this.element).addClass('onScroll');
console.log(11);
}, {
offset: wh-50
});
jsFiddle

using javascript you can find the scroll event . After the specific px(height). You can add a class to the existing class(jquery) for which you trying to animate.

Related

How to add dynamic div on that position where i clicked

I want to make an image zoom effect on my project. When the user clicks on that image I want image to be zoom. But the problem is that the div which I create dynamically is appended top of the body what I want is append this div above that image.
I try something like this:-
export const imagezoom = () => {
const image = document.querySelectorAll(".zoom");
image.forEach((e) => {
e.addEventListener("click", zoom);
});
};
function zoom(event) {
const div = document.createElement("div");
const container = document.querySelector("body");
div.classList.add("zoomDiv");
const img = document.createElement("img");
img.src = this.src;
img.classList.add("zoomImage");
console.log("added");
div.appendChild(img);
container.appendChild(div);
}
.zoomDiv {
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 100%;
z-index: 11;
background-color: black;
transition: all 250ms ease-in;
display: flex;
justify-content: center;
align-items: center;
animation-name: zoom;
animation-duration: 0.6s;
}
.zoomImage {
width: 80%;
height: 80%;
z-index: 11;
animation-name: zoom;
animation-duration: 0.6s;
object-fit: contain;
}
#keyframes zoom {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
<img class="zoom" src="../../../assets/Subject/physics/8.png" alt="" />
Here's what you do.
Put the image in a div. Make sure the image uses all the space in the containing div.
Set the position of that div to "relative".
Use
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
To get the position of the mouse relative to the div container you put your image in. Make sure the dynamically generated image position to "absolute".
Use x and y to set the left and top CSS properties dynamically.
I don't probably think I understood what you are trying to do but according to this title How to add dynamic div on that position where i clicked try the following.
Add some JavaScript on your clickable image where you want to zoom
Example
var x = document.querySelector('clickable_image');
x.addEventListener('click', e => {
image.style.setProperty('--x',e.clientX + 'px');
image.style.setProperty('--y',e.clientY + 'px');
});
and if you already done to set the above properties ad them in your CSS first of all add position: absolute; and add the following where --y is for top and --x for left
.clickable_image {
position: absolute;
top: var(--y);
left: var(--x);
}
the above will positioning that div to where you clicked

jquery increase/decrease image contrast on scroll

This site I am developing is using HTML5, CSS3, Bootstrap 4, and Jquery. I would like to have a scroll effect on a full-screen background-image that is at the very top of my page (100vh hero banner type thing). I am trying to gradually increase the contrast (css filter: contrast(some%)) of an image as the user scrolls down (its fine if the image is completely unrecognizable by the time it leaves viewport).
I have some Jquery that somewhat does the effect I am looking for, however I would like the effect to be more gradual.
The main issue I am having is that when the user scrolls back to the top of the page the contrast value gets set to 0% leaving a completely grayed out image. What I would like is for the contrast to gradually decrease back to normal (100%) as the user scrolls back up all the way to the top of the page.
I have set up a very simplified codepen. I couldn't get a css background-image url value to reference an external link from codepen, so I am targeting the effect on a full screen image ().
Thanks!
Link to the Pen: [codepen-link][1]
[1]: http://codepen.io/wdzajicek/pen/MVovZE
See code below in snippet
$(document).ready(function (){
$(window).scroll(function(){
var pixelstop = $(window).scrollTop();
$(".myimage ").css("filter", "contrast(" + pixelstop + "%)");
});
});
.header {
height: 100vh;
}
.myimage {
position:absolute;
top: 0;
left: 0;
min-width: 100%;
width; 100%;
z-index: -1;
}
.jumbotron {
position: relative;
background-color: unset;
margin-top: 150px;
z-index: 999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="header text-center">
<img src="https://raw.githubusercontent.com/wdzajicek/portfolio/master/assets/img/header-bg.jpg" class="myimage" alt="">
</header>
There is the main problem in $(window).scrollTop(); it will return 0 value
that's why contrast value gets set to 0% leaving a completely grayed out image
var pixelstop = $(window).scrollTop();
replace the code with
var pixelstop = 100+100*$(window).scrollTop()/$(window).height();
don't just copy this code please understand thanks.
$(document).ready(function (){
$(window).scroll(function(){
var pixelstop = 100+100*$(window).scrollTop()/$(window).height();
console.log(pixelstop);
$(".myimage ").css("filter", "contrast(" + pixelstop + "%)");
});
});
.header {
height: 100vh;
}
.myimage {
position:absolute;
top: 0;
left: 0;
min-width: 100%;
width; 100%;
z-index: -1;
}
.jumbotron {
position: relative;
background-color: unset;
margin-top: 150px;
z-index: 999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<header class="header text-center">
<img src="https://raw.githubusercontent.com/wdzajicek/portfolio/master/assets/img/header-bg.jpg" class="myimage" alt="">
</header>
100 is default value of filter contrast not 0. that's why the background is grey out because it reaches zero.

SlideUp Jquery for modal popup

I have created an email subscription popup modal. Right now I have the modal set to fade in but instead of that I want the modal to slide up from bottom of the page to the top. I tried slideUp() instead of fadeIn() but it does not work. I feel like I am missing something. Do I need to create another function for the slideUp()? It is a popup modal so it is ready when the window scrolls instead of on a click event. Any help is appreciated. Thank you. My code is below.
$(document).scroll(function() {
if (!$("#mc_embed_signup").data("userClosed")) {
$(".popup-close").click(function(e) {
closeSPopup(e);
});
var a = $(this).scrollTop();
if (a > 400) {
$("#mc_embed_signup").slideUp(600);
}
}
});
function closeSPopup(e) {
e.preventDefault();
$("#mc_embed_signup").data("userClosed", true);
$("#mc_embed_signup").hide();
}
jQuery .slideUp() hides the matched elements with a sliding motion. If you want to slide your popup up, you could use .animate()
$("#popup").show().animate({top: (window.innerHeight / 2 - 50) + "px"}, 1000);
#popup {
display: none;
width: 200px;
height: 100px;
position: fixed;
top: 100%;
left: calc(50% - 100px);
background-color:cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="popup"><div>
.slideDown() should be used, but!.. instead of using top: NN in CSS use the bottom: NN. This way the element "anchors" to it's bottom property, and the .slideDown() will perform from bottom to top!
var $popup = $("#popup");
$popup.slideDown();
#popup {
position: absolute;
transform: translate(-50%, 0);
bottom: 24px; /* don't use top. Use bottom */
left:50%;
width: 300px;
height: 160px;
background:red;
display: none;
}
<div id="popup">Popup ou yeah</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How to let a navigation bar fadeout to the top after fading in?

I know how to make the navigation bar fading into the viewport from the top.
$(document).scroll(function () {
var x = $(window).scrollTop();
console.log(x)
if (x > 699) {
$("header").addClass("fix");
} else {
$("header").removeClass("fix");
}
});
.fix {
position: fixed;
background:#fff;
-webkit-animation: test .5s linear;
}
.fix + main {
padding-top: 100px;
}
#-webkit-keyframes test {
from { top:-100px }
to { top:0 }
}
When it removes the class, it just disappears.
How can i make fade out back to the top?
I log it into console only for testing. (Yes, i wrote the code, it's not copy paste.)
There is no need to use keyframes here, a simple transition will do the trick
You need to put the position fixed and the original top value on the header itself and only update the animated value when scrolling.
The issue you had before was you had position fixed on the fix class, as soon as you remove the fix class, your element is no longer fixed so it will disappear without any animations. In other words, it can only animate if you had the fix class on it.
https://jsfiddle.net/19qdtL3L/
I edited the scroll value so it will show up sooner
$(document).scroll(function() {
var x = $(window).scrollTop();
console.log(x)
if (x > 300) {
$("header").addClass("fix");
} else {
$("header").removeClass("fix");
}
});
header {
top: -100px;
position: fixed;
transition: top 0.5s;
}
.fix {
background: green;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>header element</header>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br> <br><br><br><br><br> <br><br><br><br><br>
<br>sdfdsf
Your actual keyframe is only going one way : down (top: -100px to top: 0). What you want to do can't work like this.
You could do this without a keyframe, only with a transition :
$('button').on('click',function(){
$('div').toggleClass('shown');
});
div{
position: static;
top: -50px;
left: 0;
width: 100%;
height: 50px;
background-color: red;
transition: all .5s;
}
div.shown{
top: 0;
}
button{
margin-top:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button>Click me</button>

Trying to make continuous JavaScript slider

The problem with my slider is that when it gets to the last slide and i click next it jumps over the two slides to get to the first one. Similarly when i am on the first slide and click previous, it jumps over slides to get to the last one. I would like to make it that when i get to the last slide and click NEXT the first slide would come from the right to left. (similar concept for the PREVIOUS button on first slide). I tried using insertBefore() and appendChild() for the slides but couldn't figure it out...
Here is my code:
// Slider
const slider_wrapp = document.querySelector('.tract-slider');
const slider = document.querySelector('.tract-slider-wrapp');
var slide = document.getElementsByClassName('tract-slide');
const leftBtn = document.querySelector('.slide-left');
const rightBtn = document.querySelector('.slide-right');
let swWidth = slider_wrapp.clientWidth;
let sliderWidth = swWidth * slide.length;
let slideWidth = 0;
slider.style.width = sliderWidth + "px";
for (var i = 0; i < slide.length; i++) {
slide.item(i).style.width = swWidth + "px";
}
function moveRight() {
slideWidth === sliderWidth - swWidth ? slideWidth = 0 : slideWidth += swWidth;
slider.style.transform = "translateX(" + (-slideWidth) + "px)";
}
function moveLeft() {
slideWidth === 0 ? slideWidth = sliderWidth - swWidth : slideWidth -= swWidth;
slider.style.transform = "translateX(" + (-slideWidth) + "px)";
}
rightBtn.addEventListener("click", function() {
moveRight();
});
leftBtn.addEventListener("click", function() {
moveLeft();
});
.tract-slider {
width: 100%;
height: 75vh;
position: relative;
overflow: hidden;
}
.tract-slider-wrapp {
height: 100%;
position: relative;
-webkit-transition: all 350ms cubic-bezier(.08, .13, 0, .81);
-o-transition: all 350ms cubic-bezier(.08, .13, 0, .81);
transition: all 350ms cubic-bezier(.08, .13, 0, .81);
}
.tract-slide {
height: 100%;
float: left;
position: relative;
display: block;
background-position: center;
-webkit-background-size: cover;
background-size: cover;
}
.tract-slide:nth-child(1) {
background-image: url("https://static.pexels.com/photos/126282/pexels-photo-126282.jpeg");
}
.tract-slide:nth-child(2) {
background-image: url("https://static.pexels.com/photos/29017/pexels-photo-29017.jpg");
}
.tract-slide:nth-child(3) {
background-image: url("https://static.pexels.com/photos/70760/dandelion-dandelion-seeds-taraxacum-fluffy-70760.jpeg");
}
.tract-slider-control {
position: absolute;
left: 0;
bottom: 0;
background: #ffffff;
padding: 1em;
}
.tract-slider-btn {
display: inline-block;
cursor: pointer;
margin-left: 1em;
}
.tract-slider-btn:nth-child(1) {
margin-left: 0;
}
<div class="tract-slider">
<div class="tract-slider-wrapp">
<div class="tract-slide"></div>
<div class="tract-slide"></div>
<div class="tract-slide"></div>
</div>
<div class="tract-slider-control">
<div class="tract-slider-btn slide-left">Prev</div>
<div class="tract-slider-btn slide-right">Next</div>
</div>
</div>
PS. Please use JavaScript for solution
Creating an infinite slider means you need to move your slides around in DOM so they give the impression of a continuous track.
The first thing you need to change is having their backgrounds tied up to their position in DOM. If we want to slide back from first slide to the last one, we need to take the last slide, prepend it before the first one but, considering your current CSS, that will change the backgrounds of all slides, as they are currently bound to their position in DOM (...:nth-child {background-image:...}...).
The second thing that needs changing is positioning the slides into the slider track. If they're floated, whenever we change their order, all the rest of the slides will be affected. By positioning them with position:absolute each slide moves independently, without affecting the others, so it's easier to rearrange them while keeping control.
Long story short, I started from scratch and placed all methods inside a single object: theSlider.
The reset() function does the heavy lifting: it puts before class on first element, current on second and after on all the rest. So you have to put the "last" slide first, because the slider will start with it appended before the "current" one.
The sliding is done by applying go-left and go-right classes to the track. After the transition is done, I just move the first/last slide into the new position, depending on case, and run reset() again (which strips all classes and reapplies them based on new positions).
Animations are handled by CSS. All JavaScript does is apply/remove classes and move the slides in DOM.
var theSlider = {
track : document.querySelector('.tract-slider-wrapp'),
// has to match `transition-duration` in CSS:
duration : 600,
reset : function() {
var slides = document.querySelectorAll('.tract-slider-wrapp > div');
for (var i = 0; i < slides.length; i++) {
slides[i].className = '';
slides[i].classList.add(i > 1? 'after' : (i ? 'current':'before'))
}
},
init : function() {
theSlider.reset();
theSlider.track.classList.remove('not-loaded')
},
next : function() {
theSlider.track.classList.add('go-right');
setTimeout(function(){
var firstSlide = document.querySelector('.tract-slider-wrapp > div:first-child');
theSlider.track.appendChild(firstSlide);
theSlider.reset();
theSlider.track.classList.remove('go-right')
},theSlider.duration)
},
prev : function() {
theSlider.track.classList.add('go-left');
setTimeout(function() {
var lastSlide = document.querySelector('.tract-slider-wrapp > div:last-child');
theSlider.track.insertBefore(lastSlide, theSlider.track.firstChild);
theSlider.reset();
theSlider.track.classList.remove('go-left')
},theSlider.duration)
},
prevButton : document.querySelector('.slide-left'),
nextButton : document.querySelector('.slide-right')
};
window.addEventListener("load", theSlider.init);
theSlider.prevButton.addEventListener('click', theSlider.prev);
theSlider.nextButton.addEventListener('click', theSlider.next);
.tract-slider {
width: 100%;
height: 75vh;
position: relative;
overflow: hidden;
background-color: #f5f5f5;
}
.tract-slider-wrapp {
height: 100%;
transition: all 350ms cubic-bezier(.08, .13, 0, .81);
opacity: 1;
}
.tract-slider-wrapp.not-loaded {
opacity: 0;
}
.tract-slider-wrapp>div {
height: 100%;
position: absolute;
background: transparent no-repeat 50% 50% /cover;
width: 100%;
}
.tract-slider-wrapp > div.before {
margin-left: -100%;
}
.tract-slider-wrapp > div.current + div {
margin-left: 100%;
}
.tract-slider-wrapp > div.after ~ div {
opacity: 0;
}
.tract-slider-control {
position: absolute;
width: 100%;
z-index: 1;
top: 50%;
display: flex;
justify-content: space-between;
transform: translateY(-50%);
}
.tract-slider-control div {
background-color: rgba(0,0,0,.35);
padding: .5rem 1rem;
color: white;
cursor: pointer;
}
.tract-slider-control :first-child {
border-radius: 0 17px 17px 0;
}
.tract-slider-control :last-child {
border-radius: 17px 0 0 17px;
}
body {
margin: 0;
}
.go-right div {
transform: translateX(-100%);
}
.go-left div {
transform: translateX(100%);
}
.go-right div, .go-left div {
transition-property: transform;
transition-timing-function: cubic-bezier(.4,0,.2,1);
/* has to match `duration` in js: */
transition-duration: 600ms;
}
<div class="tract-slider">
<div class="tract-slider-wrapp not-loaded">
<div style="background-image:url('https://static.pexels.com/photos/126282/pexels-photo-126282.jpeg')"></div>
<div style="background-image:url('https://static.pexels.com/photos/29017/pexels-photo-29017.jpg')"></div>
<div style="background-image:url('https://static.pexels.com/photos/70760/dandelion-dandelion-seeds-taraxacum-fluffy-70760.jpeg')"></div>
</div>
<div class="tract-slider-control">
<div class="tract-slider-btn slide-left">Prev</div>
<div class="tract-slider-btn slide-right">Next</div>
</div>
</div>
If you want to change the animation duration you need to change it in both js and css.
The only current limitation is it needs at least 3 slides to work. I guess it could be adjusted to work with only two slides by: cloning the "inactive" slide into third position, removing the clone after transition and cloning the other one.
ToDo's:
prefix CSS so it works in more browsers
replace .classList.add('whatever') with .className += ' whatever' and
.classList.remove('whatever') with .className.replace('whatever', '') if you want to show IE some love.
I told the above just to tell you this: if you want to get going, don't reinvent the wheel.
It's great you use vanilla javascript. But sooner or later you'll end up writing your own wrappers for common things. Depending on how good you are/have become, you'll write your own, limited, custom version of jQuery. Allow me to put things into perspective: Google included a lite version of jQuery into AngularJS. It's that good.
You, as an single developer, do not stand a chance at writing a better, more streamlined and tested version of it. And besides, you don't have to. Use your skill and abilities to go forward, not sideways.

Categories

Resources