I'm trying to scroll by every section, it's working but it won't scroll to the last section just stops at the 3rd one and won't move down after that.
What am I doing wrong?
<div class="body" data-spy="scroll" data-target=".navbar-fixed-top">
<section id="red" class="bc1">
</section>
<section id="blue" class="bc2">
</section>
<section id="green" class="bc3">
</section>
<section id="blue" class="bc4">
</section>
</div>
<script>
var $pages = $('section'), tot = $pages.length, c = 0, pagePos = 0, down = 0, listen = true;
$('.body').on('DOMMouseScroll mousewheel', function(e) {
e.preventDefault();
if (!listen)
return;
listen = false;
down = e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0;
c = Math.min(Math.max(0, down ? ++c : --c), tot - 1);
pagePos = $pages.eq(c).offset().top;
$(this).stop().animate({
scrollTop : pagePos
}, 850, function() {
listen = true;
});
});
</script>
The problem is that offset measures the distance of the element from the top of the body. But once you have scrolled the offset is different since the elements have moved closer/further from the last scroll.
So in order to account for this you need to add the scrollTop() of the .body element.
Updated code
var $pages = $('section'),
tot = $pages.length,
c = 0,
pagePos = 0,
down = 0,
listen = true,
body = $('.body');
body.on('DOMMouseScroll mousewheel', function(e) {
e.preventDefault();
if (!listen)
return;
listen = false;
down = e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0;
c = Math.min(Math.max(0, down ? ++c : --c), tot - 1);
pagePos = $pages.eq(c).offset().top + body.scrollTop();
$(this).stop().animate({
scrollTop: pagePos
}, 850, function() {
listen = true;
});
});
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.bc1,
.bc2,
.bc3,
.bc4 {
height: 100vh;
}
#red {
background: red;
}
#blue {
background: blue;
}
#green {
background: green;
}
.body {
height: 100vh;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="body" data-spy="scroll" data-target=".navbar-fixed-top">
<section id="red" class="bc1"></section>
<section id="blue" class="bc2"></section>
<section id="green" class="bc3"></section>
<section id="blue" class="bc4"></section>
</div>
Related
I want to set top:0(offset:0) when image come in viewport on single scroll (like on every single scroll next image set to top 0 of image position or offset 0 of image) after completing scrolling all image, continue scrolling the page. Any one have any idea, JavaScript code for this?
Here is link for try out JsFiddle
<div class="main-div">
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-
1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-
1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-
1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
</div>
.main-div {
box-sizing: border-box;
}
.sticky-div {
position: sticky;
top:0;
height:100vh;
}
if($(window).width() >= 1024){
(function($) {
var selector = ".home-product-slider .product-item";
var $slides = $(selector);
var currentSlide = 0;
var isAnimating = false;
var stopAnimation = function() {
setTimeout(function() {
isAnimating = false;
}, );
};
var bottomIsReached = function($elem) {
var rect = $elem[0].getBoundingClientRect();
return rect.bottom <= $(window).height();
};
var topIsReached = function($elem) {
var rect = $elem[0].getBoundingClientRect();
return rect.top >= 0;
};
document.addEventListener(
"wheel",
function(event) {
var $currentSlide = $($slides[currentSlide]);
if (isAnimating) {
event.preventDefault();
return;
}
var direction = -event.deltaY;
if (direction < 0) {
// next
if (currentSlide + 1 >= $slides.length) return;
if (!bottomIsReached($currentSlide)) return;
event.preventDefault();
currentSlide++;
var $slide = $($slides[currentSlide]);
var offsetTop = $slide.offset().top;
isAnimating = false;
$("html, body").animate(
{
scrollTop: offsetTop,
behavior: 'smooth'
},
stopAnimation
);
} else {
// back
if (currentSlide - 1 < 0) return;
if (!topIsReached($currentSlide)) return;
event.preventDefault();
currentSlide--;
var $slide = $($slides[currentSlide]);
var offsetTop = $slide.offset().top;
isAnimating = false;
$("html, body").animate(
{
// scrollTop: offsetTop
},
stopAnimation
);
}
{ passive: false }
},
);
})(jQuery);
//home page slider script end here
}
You're looking for scroll snapping. On the container that controls the scrolling set the scroll-snap-type: y mandatory rule. Here you say that there should be snapped in the y axis and that the snap should be honored without exceptions.
On the elements that you want snapped, use the scroll-snap-align property. Set this to start indicating that the start of the element that scrolls into view should fall on the snap grid.
Do beware, the combination of position: sticky and scroll snapping could lead to buggy behavior on Safari iOS. source
html,
body {
margin: 0;
overflow: hidden;
}
.main-div {
box-sizing: border-box;
width: 1000px;
height: 100vh;
max-width: 100%;
overflow-y: auto;
scroll-snap-type: y mandatory;
}
.sticky-div {
position: sticky;
top: 0px;
width: 100%;
max-height: 100%;
height: 750px;
scroll-snap-align: start;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="main-div">
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
</div>
I am scrolling section to section, but if I scroll harshly with the mouse (not just one easy scroll) or I scroll harshly on the laptop touchpad, it shakes up and down before the scrolling animation starts or even jumps 2 sections!
Is it possible to make it scroll smoothly and always one section only (not jump 2 sections) regardless of how hard someone scrolls and basically disable scrolling while the animation is taking place?
My code (JSFiddle):
var isAnimated = false;
var nbhdLength = $('.nbhd').length;
var lastSectionId = nbhdLength - 1;
var allHeight = (nbhdLength - 1) * window.innerHeight;
var up = true;
function setHeights() {
$('.nbhd').css('height', window.innerHeight);
}
setHeights();
$('html').mousewheel(function(e) {
var up = e.deltaY > 0;
if (up) {
console.log('up');
up = true;
} else {
console.log('down');
up = false;
// console.log(up);
}
if (!up && $('#id' + lastSectionId).hasClass('scrolledto') || (!up && !$('.scrolledto').length)) {
$('.scrolledto').removeClass('scrolledto');
return;
}
if (isAnimated) return;
isAnimated = true;
var currentSectionId = $('.nbhd.scrolledto').data('id');
up ? currentSectionId-- : currentSectionId++;
if (currentSectionId < 0) currentSectionId = 0;
if (!$('.scrolledto').length) currentSectionId = lastSectionId;
$('.scrolledto').removeClass('scrolledto');
var section = $('#id' + currentSectionId);
section.addClass('scrolledto');
var pos = section.offset().top;
$('body, html').animate({
scrollTop: pos
}, 1000, function() {
setTimeout(function() {
isAnimated = false;
}, 100)
console.log($(window).scrollTop());
});
});
.div {
width: 100%;
}
.red {
background: red;
}
.yellow {
background: yellow;
}
.green {
background: green;
}
.blue {
background: blue;
}
.abovefooter {
background: gray;
height: 200px;
}
.footer {
background: black;
height: 350px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
<div id="id0" data-id="0" class="nbhd red scrolledto"></div>
<div id="id1" data-id="1" class="nbhd yellow"></div>
<div id="id2" data-id="2" class="nbhd green"></div>
<div id="id3" data-id="3" class="nbhd blue"></div>
<div class="abovefooter"></div>
<div class="footer"></div>
You need to prevent the default mouseWheel event from happening, using javascript to perform the desired effect instead.
$('html').mousewheel(function(e) {
e.preventDefault();
//...
}
Demo: https://jsfiddle.net/b67uw0cx/1/
I am creating a maze game, and I want to detect when the image following the cursor reaches a certain div, the finishing point. I have the image following the mouse, and I have the container that the image will be in. When the image reaches the div, I want something to trigger, lets say an alert. How can I achieve this?
var startMove;
$(document).mousemove(function(e) {
var DIFF_SNAP = 10;
var DIFF_UNSNAP = 100;
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if (!startMove && Math.abs(difLeft) < DIFF_SNAP && Math.abs(difTop) < DIFF_SNAP) {
startMove = true;
$('html').removeClass('showCursor');
} else if (startMove && !(Math.abs(difLeft) < DIFF_UNSNAP && Math.abs(difTop) < DIFF_UNSNAP)) {
startMove = false;
}
if (startMove) {
$("#image").css({
left: e.pageX,
top: e.pageY
});
} else {
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function() {
startMove = false;
})
html {cursor: none;}
html.showCursor{cursor: default;}
#image{
position:absolute;
width:25px;
height:auto;
}
div{
margin-left: 500px;
width: 200px;
height: 50px;
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png"/>
<div></div>
Jsfiddle: https://jsfiddle.net/3x7cgLdr/25/
if ($('#TargetDiv').is(':hover')) {
// alert('hello');
$("#image").addClass("red");
}else{
$("#image").removeClass("red");
}
Using this .is() function with :hover selector inside the
if(startMove){
}
Section simply does that without any hassle the is() function Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
.is() function documentation
var startMove;
$(document).mousemove(function(e) {
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if (difLeft < 10 && difLeft > -10 && difTop < 10 && difTop > -10) {
startMove = true;
$('html').removeClass('showCursor');
}
if (startMove) {
$("#image").css({
left: e.pageX,
top: e.pageY
});
if ($('#TargetDiv').is(':hover')) {
// alert('hello');
$("#image").addClass("red");
} else {
$("#image").removeClass("red");
}
} else {
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function() {
startMove = false;
})
html {
cursor: none;
}
html.showCursor {
cursor: default;
}
#image {
position: absolute;
width: 25px;
height: auto;
}
#TargetDiv {
height: 100px;
width: 100px;
background: green;
margin: 100px auto;
}
.red {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png" />
<div id="TargetDiv">
</div>
I have added a class to set border red to the div when it hovers on the div with mouse and cursor image superimposed that is startMove="true".And removes when it is not hovered .I have commented the alert box;You can turn it on if you want
You already have a flag called startMove that is active whenever the cursor is dragged, use the mouseenter event on the target div as follows:
var startMove;
$(document).mousemove(function(e){
var difLeft = $('#image').offset().left - e.pageX;
var difTop = $('#image').offset().top - e.pageY;
if(difLeft < 10 && difLeft > -10 && difTop < 10 && difTop > -10 ){
startMove = true;
$('html').removeClass('showCursor');
}
if(startMove){
$("#image").css({left:e.pageX, top:e.pageY});
}
else{
$('html').addClass('showCursor');
}
});
$(document).mouseleave(function(){
startMove = false;
})
$("#drop").mouseenter(function(){
if(startMove)
alert("Success");
});
.
<img id="image" src="http://static.micheljansen.org/uploads/mac-osx-arrow-cursor.png"/>
<div id="drop">
</div>
.
html {cursor: none;}
html.showCursor{cursor: default;}
#image{
position:absolute;
width:25px;
z-index: 100;
height:auto;
}
#drop{
width:100px;
height:100px;
background:green;
position: absolute;
left:200px;
top: 300px;
z-index:99
}
see a demo: https://jsfiddle.net/hycd913y/
Basically I have a structure like this, my goal is to animate 4 divs so that when you click on one the other slide out and when you click on the container they return to their initial positions.
var TL = new TimelineMax;
$('.quater').on('click', function () {
$faders = $('.container').find('.quater').not(this),
$faders.each(function () {
TL.to($(this), 1, {autoAlpha:0, x:50}, 0);
});
});
$('.container').on('click', function () {
TL.reverse();
TL.clear();
});
The problem is that if I omit the "TL.clear();" it will work just for the first ".quater" div clicked, if i put in the "TL.clear();" the animation will not reverse anymore.
jsFiddle.
Snippet:
var container = document.querySelector('.container');
var items = document.querySelectorAll('.item');
var duration = 0.6;
var ease = Expo.easeOut;
var numItems = items.length;
var i;
container.addEventListener('click', onContainerClicked, false);
for (i = 0; i < numItems; i += 1) {
(function(index){
items[index].timeline = new TimelineMax({ paused: true });
items[index].timeline.fromTo(items[index], duration, { y: 0, autoAlpha: 0.4 }, { y: -104, autoAlpha: 1, ease: ease });
items[index].addEventListener('click', onItemClicked, false);
}(i));
}
function onContainerClicked() { reverseAll(); }
function onItemClicked(e) {
reverseAll();
e.target.timeline.play();
}
function reverseAll() {
for (i = 0; i < numItems; i += 1) { items[i].timeline.reverse(); }
}
html, body {
margin: 0;
padding: 0;
}
.container {
background: #444;
width: 512px;
height: 104px;
}
.item {
float: left;
margin: 2px 0 0 2px;
width: 100px;
height: 100px;
}
.item:nth-child(odd) { background: #0cc; }
.item:nth-child(even) { background: #cc0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<div class="container"></div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
Scenario
I am having a functionality in my project in which we have to add a note in a section and then it can be moved to the other sections. It is a sort of task tracking.
I am able to add a note dynamically created into one section and have made that note dragable. The note, sections are divs.
Problem
I am not able to drag the note to the other section or div. the note is draggable in its own section (div). Please help me with the solution so that it can be moved to other section.
Here is my HTML code:
<div id="addTaskDiv" style="height: 150px">
<a id="addTask" onclick="AddNote();">ADD Task</a> <a id="a1" onclick="AddText();">Submit</a>
</div>
<div id="MySplitter">
<div id="leftDiv" style="height: 150px; border-style: groove; width: 100%;">
left here
</div>
<div id="splitterUpperDiv">
<div id="midDiv" style="height: 150px; border-style: groove; width: 100%;">
middle here
</div>
<div id="rightDiv" style="height: 150px; width: 100%; border-style: groove;">
right here
</div>
</div>
</div>
Here is my .js
$().ready(function () {
$("#MySplitter").splitter();
$("#splitterUpperDiv").splitter();
$("#rightDiv").droppable();
$("#midDiv").droppable();
$("#leftDiv").droppable();
});
function AddNote(args, seder) {
var i = (typeof this.rel != 'undefined') && (this.rel - 0) == this.rel ? this.rel : 0;
var br = document.createElement("br");
$("#addTaskDiv")[0].appendChild(br);
addArea();
return false;
}
function addArea() {
var i = (typeof this.rel != 'undefined') && (this.rel - 0) == this.rel ? this.rel : 0;
var button = $(this);
var commentField = $('<textarea/>'); // create a textarea element
commentField[0].id = 'added' + i;
commentField
.css({
position: 'absolute',
width: 200, // textbox 200px by 100px
height: 100
})
// set the textarea's value to be the saved content, or a default if there is no saved content
.val(button.data('textContent') || 'This is my comment field\'s text')
// set up a keypress handler on the textarea
.keypress(function (e) {
if (e.which === 13) { // if it's the enter button
e.preventDefault(); // ignore the line break
button.data('textContent', this.value); // save the content to the button
$(this).remove(); // remove the textarea
}
})
.appendTo($("#addTaskDiv")[0]); // add the textarea to the document
}
function AddText() {
var i = (typeof this.rel != 'undefined') && (this.rel - 0) == this.rel ? this.rel : 0;
var a = $("#added0")[0].value;
var x = document.createElement("div");
x.width = '200px';
x.height = 'auto';
x.id = 'lable' + i;
this.rel = i + 1;
x.innerText = a;
var br = document.createElement("br");
$("#leftDiv")[0].appendChild(br);
$("#leftDiv")[0].appendChild(x);
$("#lable" + i + "").draggable();
}
You can try this :-
$("#rightDiv").droppable({
accept: '.draggableObject',
});
Please study this example code,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
section{
background: rgba(0, 0, 0, .1);
padding: 20px;
height: 350px;
margin: 20px 0 0 0;
border-radius: 20px;
}
#myDiv{
cursor: move;
background: red;
height: 150px;
width: 150px;
float: left;
}
#targetDiv{
background: red;
height: 300px;
width: 300px;
float: right;
}
</style>
</head>
<body>
<script>
window.onload = function(){
var count=0;
var myDiv=document.getElementById('myDiv');
var targetDiv=document.getElementById('targetDiv');
myDiv.addEventListener('dragstart', function(e)
{
/* change ui to see clearly */
this.style.opacity= 0.2;
this.style.borderStyle= 'dashed';
targetDiv.style.backgroundColor= 'yellow';
/* set text from this as an argument to transfer */
e.dataTransfer.setData("Text", this.innerHTML);
}, false);
myDiv.addEventListener('dragend', function(e)
{
/* change ui to see clearly */
this.style.opacity=1;
this.style.borderStyle= 'solid';>
targetDiv.style.backgroundColor='red';
/* change text of dragend div */
this.innerHTML="Total Count : "+ (++count) ;
}, false);
targetDiv.addEventListener('dragover', function(e)
{
/* change ui to see clearly */
this.style.backgroundColor='green';
if(e.preventDefault){ e.preventDefault(); };
},false);
targetDiv.addEventListener('dragleave', function(e)
{
/* change ui to see clearly */
this.style.backgroundColor='yellow';
}, false);
targetDiv.addEventListener('drop', function(e)
{
/* get text from dropped div */
this.innerHTML= e.dataTransfer.getData("Text");
if( e.preventDefault ){ e.preventDefault(); };
},false);
}
</script>
<div draggable="true" id="myDiv">
Drag able Area.
</div>
<div id="targetDiv">
Target Area.
</div>
</body>
</html>