I have some text elements that should move in their x-axis based on the scroll position.
Please see this pen for reference:
https://codepen.io/magglomag/pen/GRZwRNB
HTML
<h1 class="moving-text-wrapper">
<div class="moving-text moving-text-1" data-scroll-speed="-4">Lorem</div>
<div class="moving-text moving-text-2" data-scroll-speed="2">ipsum</div>
<div class="moving-text moving-text-3" data-scroll-speed="9">sonsetetur</div>
<div class="moving-text moving-text-4" data-scroll-speed="-6">sit</div>
<div class="moving-text moving-text-5" data-scroll-speed="3">amet</div>
</h1>
CSS
html {
height: 300vh;
}
.moving-text-wrapper {
margin-top: 100vh;
text-align: center;
}
jQuery
$.fn.moveIt = function(){
var $window = $(window);
var instances = [];
$(this).each(function(){
instances.push(new moveItItem($(this)));
});
window.addEventListener('scroll', function(){
var scrollTop = $window.scrollTop();
var elemOffsetTop = $( '.moving-text-wrapper' ).offset().top;
var translateX = elemOffsetTop - scrollTop - $( window ).height()/2;
instances.forEach(function(inst){
inst.update(translateX);
});
}, {passive: true});
}
var moveItItem = function(el){
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
};
moveItItem.prototype.update = function(translateX){
this.el.css('transform', 'translateX(' + -(translateX / this.speed) + 'px)');
};
$(function(){
$('[data-scroll-speed]').moveIt();
});
What I’d like to add is a little easing to the variable translateX, so when the scrolling stops the text will move a little bit longer and does not stop directly like in the current pen.
Any hints how to solve that?
Many thanks!
Actually this was quite easy to solve with CSS transitions:
I just added a transition to the elements like this:
.moving-text {
transition-property: transform;
transition-duration: 1s;
transition-timing-function: ease-out;
}
See updated Codepen for reference:
https://codepen.io/magglomag/pen/YzqRPoX
Related
I have a ReactJS project and I've been advised not to use jQuery for various reasons, so I'm attempting to convert the following jQuery to JavaScript -- it smoothly changes background color while scrolling the page:
$( window ).ready(function() {
var wHeight = $(window).height();
$('.slide')
.height(wHeight)
.scrollie({
scrollOffset : -50,
scrollingInView : function(elem) {
var bgColor = elem.data('background');
$('body').css('background-color', bgColor);
}
});
});
CSS:
* { box-sizing: border-box }
body {
font-family: 'Coming Soon', cursive;
transition: background 1s ease;
background: #3498db;
}
p {
color: #ecf0f1;
font-size: 2em;
text-align: center;
}
a {
text-decoration: none;
}
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2542/jquery.scrollie.min_1.js"></script>
<div class="main-wrapper">
<div class="slide slide-one" data-background="#3498db">
<p>Title</p>
<center>Go To Green.</center>
</div>
<div class="slide slide-two" data-background="#27ae60">
<a name="green">
<p>Green area</p>
<center>Go To Red.</center>
</a>
</div>
<div class="slide slide-three" data-background="#e74c3c">
<a name="red">
<p>Red area</p>
<center>Page over. Hope that was helpful :)</center>
</a>
</div>
But how can I do the conversion to JavaScript to fit the ReactJS project?
Thank you in advance and will be sure to accept/upvote answer
Changing from JQuery to JavaScript is always possible. Because JQuery builds on JavaScript. Most of the time ( like in your case ) it's not even that much work.
I've not changed your CSS or HTML. So this is just some new JavaScript. However you should put this script at the end of your website.
(function() { // create an own scope and run when everything is loaded
// collect all the slides in this array and apply the correct height
var slides = document.getElementsByClassName('slide')
for (slide of slides) slide.style.height = window.innerHeight + 'px'
// use the native scroll event
document.addEventListener("scroll", function() {
// how much have we scrolled already
var currentOffset = document.documentElement.scrollTop || document.body.scrollTop
// now check for all slides if they are in view (only one will be)
for (slide of slides) {
// 200 is how much before the top the color should change
var top = slide.getBoundingClientRect().top + currentOffset - 200
var bottom = top + slide.offsetHeight
// check if the current slide is in view
if (currentOffset >= top && currentOffset <= bottom) {
// set the new color, the smooth transition comes from the CSS tag
// CSS: transition: background 1s ease;
document.body.style.background = slide.dataset.background
break
}
}
})
}())
Additionally you might want to listen on resize event, because as of now when you resize the window will look a bit off ( this replaces the 5 line of the code above)
function setSize() {
for (slide of slides) slide.style.height = window.innerHeight + 'px'
}
window.addEventListener("resize", setSize)
setSize()
Solution
(function() {
var slides = document.getElementsByClassName('slide')
function setSize() {
for (slide of slides) slide.style.height = window.innerHeight + 'px'
}
window.addEventListener("resize", setSize)
setSize()
document.addEventListener("scroll", function() {
var currentOffset = document.documentElement.scrollTop || document.body.scrollTop
for (slide of slides) {
// 100 is how much before the top the color should change
var top = slide.getBoundingClientRect().top + currentOffset - 100
var bottom = top + slide.offsetHeight
if (currentOffset >= top && currentOffset <= bottom) {
document.body.style.background = slide.dataset.background
break
}
}
})
}())
body {
font-family: 'Coming Soon', cursive;
transition: background 1s ease;
background: #3498db;
}
p {
color: #ecf0f1;
font-size: 2em;
text-align: center;
}
a { text-decoration: none;
}
<div class="main-wrapper">
<div class="slide slide-one" data-background="#3498db">
<p>Title</p>
<center>Go To Green.</center>
</div>
<div class="slide slide-two" data-background="#27ae60">
<a name="green">
<p>Green area</p>
<center>Go To Red.</center>
</a>
</div>
<div class="slide slide-three" data-background="#e74c3c">
<a name="red">
<p>Red area</p>
<center>Page over. Hope that was helpful :)</center>
</a>
</div>
The plugin you are referring to links an example from their README that includes a link to a newer version that makes use of this other plugin that does not use jQuery and in fact does what you want it to do, I think. It is called in-view and it looks very good to me (both the functionality and the code).
Its usage is very similar to what you are doing currently. From the newer example linked above:
var $target = $('.wrapper');
inView('.section').on('enter', function(el){
var color = $(el).attr('data-background-color');
$target.css('background-color', color );
});
I do realize that I am in a way not answering the question, because this is not a jQuery-to-vanilla-JS guide, but I do think that it helps to know that somebody already did it for you.
Should give you some idea.
var wHeight = window.innerHeight;
To select elements in javascript:
on browser open inspect element, console tab and type:
document.get
and it gives you hint what to get
To get style of element:
var elem1 = document.getElementById("elemId");
var style = window.getComputedStyle(elem1, null);
To set Property:
document.body.style.setProperty(height`, wHeight +"px");
Below is some modifications that you can make, As people commented I am not trying to teach you how to's but want to give you some start:
// $( window ).ready(function() { //remove this
var wHeight = $(window).height(); // USe this instead: var wHeight = window.innerHeight;
$('.slide') //instead of selecting with jquery "$('.slide')" select with: Javascript var x = document.getElementsByClassName("example") ;
.height(wHeight) // Here you are chaining methods, read this article https://schier.co/blog/2013/11/14/method-chaining-in-javascript.html
.scrollie({
scrollOffset : -50,
scrollingInView : function(elem) {
var bgColor = elem.data('background'); //var bgColor = window.getComputedStyle(elem, null);
$('body').css('background-color', bgColor); //document.body.style.background = bgColor;
}
});
// }); //remove this
For .... in
var t = document.getElementsByClassName('slide')
console.log(typeof t) //object
for (var prop in t) {
console.log('t.' + prop, '=', t[prop]);
// output is index.html:33 t.0 = <div class="slide slide-one" data- background="#3498db">…</div>
// output is index.html:33 t.1 = <div class="slide slide-two" data- background="#27ae60">…</div>
// output is index.html:33 t.2 = <div class="slide slide-three" data-background="#e74c3c">…</div><a name="red">…</a></div>
// output is index.html:33 t.length = 3
// output is index.html:33 t.item = function item() { [native code] }
// output is index.html:33 t.namedItem = function namedItem() { [native code] }
}
I know how to fix the animation that goes down only when the image is showing up in the window with jQuery, but now I want to do that with JavaScript. Struggling with that. The image must be fluently go down (+50px for 1.6 seconds). Have googling around, but most of them are done with jQuery I suggest and that is not what I want. Furtermore the animation should start when the scrollTop is between 600px and 800px.
function scrollFunction() {
var animate = document.getElementById("picture");
var position = 0;
var top = 0;
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if(scrollTop > 600 && scrollTop < 800){
position++;
animate.style.top = position + "50px";
} else {
stop();
}
}
function stop() {
clearTimeout(animate);
}
#picture {
width: 100%;
height: auto;
top: -5px;
position: relative;
display: block;
margin-left: auto;
margin-right: auto;
margin-bottom: 20px;
}
<div class="col-sm-12 col-xs-12">
<h1 class="responsive-h1">Mi<span class="logo-orange"> Pad2</span></h1>
<p class="edition-title above-text-black">Black Edition</p>
<img src="Img/picture.jpg" id="picture"/>
</div>
jsFiddle : https://jsfiddle.net/n1q3fy8w/
Javascript
var imgSlide = document.getElementById('slidedown-image');
var slideDown = setInterval(function() {
var topVal = parseInt(window.getComputedStyle(imgSlide).top, 10);
imgSlide.style.top = (topVal + 1) + "px";
}, 15);
setTimeout(function( ) { clearInterval( slideDown ); }, 1600);
You get the element first, after that you setup a setInterval which will basically move our img downwards, we then also set a setTimeout which after 1600ms remvoes the slideDown interval and the image stops. Your image however may need position: absolute.
The above answer will only work in Chrome, this however should work in all browswers
jsFiddle : https://jsfiddle.net/n1q3fy8w/1/
javascript
var imgSlide = document.getElementById('slidedown-image');
var slideDown = setInterval(function() {
var topVal = parseInt(imgSlide.style.top, 10);
imgSlide.style.top = (topVal + 1) + "px";
}, 15);
setTimeout(function( ) { clearInterval( slideDown ); }, 1600);
Ok so getComputedStyle only works in chrome, so to get this to work on all other browsers, you have to specifically set the css property on the element and not via CSS.
When you use javascript to access an element and change its style like so element.style.bottom = '150px' the .style gets you all of the css values for your inline styles on that element, so any css changes on an element that is done via a .css/.less file you can't access via javascript.
So all the above code does is we set a top: 0 on the element itself and in our code we use imageSlide.style.top instead of chrome's window.getComputedStyle
Have you considered using a CSS transition? if you are changing the value of top you should be able to add transition: top 1.6s in your css (to picture). (Then the vendor prefixed versions when you get it working)
I want to detect clicks and move elements from off-screen right to off-screen left with jquery.
I achieved the general idea already (fiddle) but only for one div, once.
HTML:
<div class = "outer">
<div id = "box">
</div>
</div>
CSS:
body {
overflow-x: hidden;
height: 500px;
}
#box{
height: 100px;
width: 100px;
background: #FF00FF;
position: absolute;
right: -100px;
}
JS:
$(document).ready(function(){
$(document).click(function(){
var bodyHeight = document.body.clientHeight;
var randPosY = Math.floor((Math.random()*bodyHeight));
$('#box').css('top', randPosY);
$("#box").animate({left: '-100px'}, 5000);
});
});
How can make a new instance div appear (at random y-position) per click on the document?
My random y-position is calculated in jQuery the following way, but gets its value from my css height: 500px; - how can I make this value responsive?
Use a function constructor to add object instances of a div, where each one uses .box class instead of #box:
fiddle
function SlidingDiv(bodyHeight){
this.randPosY = Math.floor((Math.random()*bodyHeight));
this.$div = $("<div>").addClass('box').appendTo('.outer');
};
SlidingDiv.prototype.slide = function(){
this.$div.css('top', this.randPosY);
this.$div.animate({left: '-100px'}, 5000);
};
$(document).ready(function(){
$(document).click(function(){
var bodyHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
var div = new SlidingDiv(bodyHeight);
div.slide();
});
});
Edit: To remove divs, you could try the complete function:
SlidingDiv.prototype.slide = function() {
this.$div.css('top', this.randPosY);
this.$div.animate({
left: '-100px',
duration: 5000,
complete: function() { this.$div.remove(); }.bind(this)
});
};
Hello, I want a certain text to appear when I scroll past it or when I scroll until the point where the text is. The effect when appearing should be somewhat like the first effect on the top of the website http://namanyayg.com/.
I want the effect in minimal code with pure CSS and JS i.e no jQuery.
I was thinking that maybe I would use something like a display:none property for a span and then when you scroll past it the display becomes block but I dont know how to trigger the effect using javascript.
Any help would be appreciated.
First wrap whatever your text or content that you want to show on scroll, in one div so that you can show hide the div depending upon the scroll. Write two classes for your target div.
Your CSS:
/*Use this class when you want your content to be hidden*/
.BeforeScroll
{
height: 100px; /*Whatever you want*/
width: 100%; /*Whatever you want*/
.
.
display: none;
}
/*Use this class when you want your content to be shown after some scroll*/
.AfterScroll
{
height: 100px; /*Whatever you want*/
width: 100%; /*Whatever you want*/
.
.
display: block;
}
Your HTML:
<!--Set class BeforeScoll to your target div-->
<div id = "divToShowHide" class = "BeforeScroll">Content you want to show hide on scroll</div>
Your Script:
<!--include these script in head section or wherever you want-->
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js" type="text/javascript"></script>
<script type = "text/javascript">
$(document).ready(function(){
//Take your div into one js variable
var div = $("#divToShowHide");
//Take the current position (vertical position from top) of your div in the variable
var pos = div.position();
//Now when scroll event trigger do following
$(window).scroll(function () {
var windowpos = $(window).scrollTop();
//Now if you scroll more than 100 pixels vertically change the class to AfterScroll
// I am taking 100px scroll, you can take whatever you need
if (windowpos >= (pos.top - 100)) {
div.addClass("AfterScroll");
}
//If scroll is less than 100px, remove the class AfterScroll so that your content will be hidden again
else {
s.removeClass("AfterScroll");
}
//Note: If you want the content should be shown always once you scroll and do not want to hide it again when go to top agian, no need to write the else part
});
});
</script>
Hope it will solve your problem.
I would recommend this plugin
http://johnpolacek.github.io/superscrollorama/
Edit:
I don't know how no one noticed that the solution had to be made without using external libraries like jQuery. However, the solution is extremely easy with basic functionality. Find it here
HTML:
<div id="parent-div">
<div id="child-div">
Psst .. I am here!!
</div>
</div>
CSS:
#parent-div
{
position:relative;
height:3000px;
width:300px;
background-color:red;
}
#child-div
{
color:white;
position:relative;
top:1000px;
width:300px;
display:none;
text-align:center;
}
JS:
var body=document.getElementsByTagName("body")[0];
var parent=document.getElementById("parent-div");
var child=document.getElementById("child-div");
body.onscroll = function(){
//console.log(documenhttps://fiddle.jshell.net/3urv0tp0/#tidyt.getElementById("child-div").style.top)
if(document.documentElement.scrollTop>=child.offsetTop)//Adjust Tolerance as you want
{
child.style.display="block"
}
};
I was looking for this either. Here i was trying to make "show text after scrolling to (number)px with fade effect". I wish it will work as it works for me :) The animation will be playing again if u scroll back to it, idk how to make it just one like in web u showed xd (i will edit if I find out)
window.addEventListener("scroll", function() {showFunction()});
function showFunction() {
if (document.body.scrollTop > 900 || document.documentElement.scrollTop > 900) {
document.getElementById("toptexts2").style.display = "block";
} else {
document.getElementById("toptexts2").style.display = "none";
}
}
.toptexts2 {
animation: fadeEffect 3s; /* fading effect takes 3s */
}
#keyframes fadeEffect { /* from 0 to full opacity */
from {opacity: 0;}
to {opacity: 1;}
}
<div class="toptexts2" id="toptexts2">
<div>Hi!</div>
<div>↓ go down ↓</div>
</div>
I like this:
var doc = document, dE = doc.documentElement, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function xy(e, d){
if(!d)d = 'Top';
d = 'offset'+d;
var r = e[d];
while(e.offsetParent){
e = e.offsetParent; r += e[d];
}
return r;
}
function x(e){
return xy(e, 'Left');
}
function y(e){
return xy(e);
}
var txt = E('theId'), txtS = txt.style;
onscroll = function(){
var left = dE.scrollLeft || bod.scrollLeft || 0;
var top = dE.scrollTop || bod.scrollTop || 0;
var w = innerWidth || dE.clientWidth || bod.clientWidth;
var h = innerHeight || dE.clientHeight || bod.clientHeight;
if(top > y(txt)-h){
txtS.display = 'none';
}
else{
txtS.display = 'block';
}
}
I left the left stuff in there, just in case, but you can probably remove it.
var div=$("#divtochange");
$(window).scroll(function () {
var windowpos = $(window).scrollTop();
//---check the console to acurately see what the positions you need---
console.log(windowpos);
//---------------------
//Enter the band you want the div to be displayed
if ((windowpos >= 0) && (windowpos <= 114)){
div.addClass("AfterScroll");
}
else{
div.removeClass("AfterScroll");
}
I have <div id="test"></div>and <a id="trigger"></a>. Div has width 300px. I want the div to re size it's width to 100px when user click trigger and want to re size to previous size when user again click the trigger. How can i make this using jquery??
Thanks in advance...:)
blasteralfred
Assign a variable of 1 for click and 0 for unclick and then use the .click function as follows:
$(document).ready(function(){
TriggerClick = 0;
$("a#trigger").click(function(){
if(TriggerClick==0){
TriggerClick=1;
$("div#test").animate({width:'100px'}, 500);
}else{
TriggerClick=0;
$("div#test").animate({width:'300px'}, 500);
};
});
});
UPDATE - BETTER ANSWER
I made this suggestion awhile back; but believe there is a more elegant and pragmatic approach to solving this. You could use CSS transitions and have jquery simply add/remove a class that initiates the transition:
Working Fiddle:
https://jsfiddle.net/2q0odoLk/
CSS:
#test {
height: 300px;
width: 300px;
background-color: red;
/* setup the css transitions */
-webkit-transition: width 1s;
-moz-transition: width 1s;
transition: width 1s;
}
#test.small {
width: 100px;
}
jQuery:
$("a#trigger").on('click', function(){
$("div#test").toggleClass('small');
});
This is Html Part of this toggle:
<div id="start">
<div class="slide"></div>
</div>
This is CSS part for that:
<style>
#start{ margin-bottom:60px; display:block; font-size:16px; width:14px; height:79px; position:relative; top:25px; line-height:21px; color:#F0F; background:url(./start1.JPG) left top no-repeat;}
.slide{ background:#98bf21; max-width:500px; width:100; height:100px;position:absolute; left:14px;}
</style>
<script>
$(document).ready(function()
{
function tog()
{
var w = $(".slide").css('width');
if(w=='0px')
{
$(".slide").animate({
width:500
});
}
else
{
$(".slide").animate({
width:0
});
}
}
$("#start").click(function()
{
tog();
});
});
</script>
You need to bind an .click()-Event to #trigger and toggle the animation.
http://api.jquery.com/toggle/
http://api.jquery.com/animate/
Something like this should to the trick.
$('#trigger').bind('click', function() { $('#test').animate({"width": "100px"}, "slow"); })
For those looking for a shorter but yet working version you could do this:
$('a#trigger').on('click', function(e) {
e.preventDefault();
var w = ($('div#test').width() == 300 ? 100 : 300);
$('div#test').animate({width:w},150);
});
The shortest version:
$('a#trigger').on('click', function(e) {
e.preventDefault();
$('div#test').animate({width:($('div#test').width() == 300 ? 100 : 300)},150);
});
On a function:
function toggleWidth(target, start, end, duration) {
var w = ($(target).width() == start ? end : start);
$(target).animate({width:w},duration);
return w;
}
Usage:
$('a#trigger').on('click', function(e) {
e.preventDefault();
toggleWidth($("div#test"), 300, 100, 150);
});
Finally on a JQuery.fn.extend function:
jQuery.fn.extend({
toggleWidth: function(start, end, duration) {
var w = ($(this).width() == start ? end : start);
$(this).animate({width:w},duration);
return w;
}
});
Usage:
$('a#trigger').on('click', function(e) {
e.preventDefault();
$("div#test").toggleWidth(300, 100, 150);
});