I'm using the HTML5 attribute draggable = "true" on some of my divs on my webpage. I want it so that when you drag one of these items to the bottom of the page, it scrolls the page down and when you drag it to the top, it scrolls the page up.
I will eventually make a playlist on my sidebar, and since it will not always be on view depending on where you're looking on the page, the page needs to scroll when you're dragging.
My page is here and you can try dragging the pictures of the posts around. On Chrome, it automatically lets me scroll down when I drag to the bottom, but not up. On Firefox, it doesn't automatically let me scroll either direction. Any help?
Here's a simple jsfiddle to get you started. On Chrome you should be able to drag the Google icon down and have it scroll the page down, but not going up.
here is a code that will scroll-up or scroll-down your page while you are dragging something. Just placing your dragging object at top or bottom of the page. :)
var stop = true;
$(".draggable").on("drag", function (e) {
stop = true;
if (e.originalEvent.clientY < 150) {
stop = false;
scroll(-1)
}
if (e.originalEvent.clientY > ($(window).height() - 150)) {
stop = false;
scroll(1)
}
});
$(".draggable").on("dragend", function (e) {
stop = true;
});
var scroll = function (step) {
var scrollY = $(window).scrollTop();
$(window).scrollTop(scrollY + step);
if (!stop) {
setTimeout(function () { scroll(step) }, 20);
}
}
I have made a simple JavaScript drag and drop class. It can automatically scroll up or down the page while dragging.
See this jsfiddle. Also avaliable at my github page.
Dragging at a high speed is not recommended now. I need to work out that.
Code below is a part of the library.
var autoscroll = function (offset, poffset, parentNode) {
var xb = 0;
var yb = 0;
if (poffset.isBody == true) {
var scrollLeft = poffset.scrollLeft;
var scrollTop = poffset.scrollTop;
var scrollbarwidth = (document.documentElement.clientWidth - document.body.offsetWidth); //All
var scrollspeed = (offset.right + xb) - (poffset.right + scrollbarwidth);
if (scrollspeed > 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = offset.left - (xb);
if (scrollspeed < 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = (offset.bottom + yb) - (poffset.bottom);
if (scrollspeed > 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
scrollspeed = offset.top - (yb);
if (scrollspeed < 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
} else {
var scrollLeft = offset.scrollLeft;
var scrollTop = offset.scrollTop;
var scrollbarwidth = parentNode.offsetWidth - parentNode.clientWidth; //17
var scrollbarheight = parentNode.offsetHeight - parentNode.clientHeight; //17
var scrollspeed = (offset.right + xb) - (poffset.right - scrollbarwidth);
if (scrollspeed > 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = offset.left - (xb + poffset.left);
if (scrollspeed < 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = (offset.bottom + scrollbarheight + yb) - (poffset.bottom);
if (scrollspeed > 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
scrollspeed = offset.top - (yb + poffset.top);
if (scrollspeed < 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
}
};
Here is the javascript version of AngularPlayers answer, I added horizontal support. I noticed both the JQuery solution and Javascript solution have a bug on mobile safari that allows the page to infinitely grow when the bounce effect from overscrolling happens.
The purpose of VerticalMaxed and HorizontalMaxed is to check that the scroll bars are not maxed before scrolling again. This prevents the page from growing during overscroll bounce.
var stopX = true;
var stopY = true;
document.addEventListener('drag', function(e) {
if (event.target.classList.contains('draggable')) {
stopY = true;
// Handle Y
if (e.clientY < 150) {
stopY = false;
scroll(0,-1)
}
if ((e.clientY > ( document.documentElement.clientHeight - 150)) && !VerticalMaxed()) {
stopY = false;
scroll(0,1)
}
// Handle X
stopX = true;
if (e.clientX < 150) {
stopX = false;
scroll(-1,0)
}
if ((e.clientX > ( document.documentElement.clientWidth - 150)) && !HorizontalMaxed()) {
stopX = false;
scroll(1,0)
}
}
});
document.addEventListener('dragend', function(e) {
if (event.target.classList.contains('draggable')) {
stopY = true;
//stopY = true;
stopX = true;
}
});
// On drag scroll, prevents page from growing with mobile safari rubber-band effect
var VerticalMaxed = function(){ return (window.innerHeight + window.scrollY) >= document.body.offsetHeight}
var HorizontalMaxed = function(){ return (window.pageXOffset) > (document.body.scrollWidth - document.body.clientWidth);}
var scroll = function (stepX, stepY) {
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
window.scrollTo((scrollX + stepX), (scrollY + stepY));
if (!stopY || !stopX) {
setTimeout(function () { scroll(stepX, stepY) }, 20);
}
}
Related
I'm facing a very strange error, which is animation on body during mouse scroll. I think its happening because of the jQuery event window.scroll. I have tried a lot of things like unbinding of animation on mouse scroll, but nothing works. Below is my code.
$(document).on("scroll", function () {
var lastScrollTop = 0;
var windowHeight = $(window).scrollTop();
var seccion1 = $("#seccion1").height();
var seccion2 = $("#seccion2").offset().top;
var alturaseccion2 = $("#seccion2").height();
//this function returns in which section is the user with the scroll
var localizacion = comprobarSeccion(seccion1, seccion2);
if (windowHeight > lastScrollTop) {
// down scroll
console.log("scrollabajo");
if (localizacion == 1) {
$("html, body").animate({
scrollTop: $("#seccion2").offset().top
}, 2);
$(document).bind("scroll");
} else if (localizacion == 2) {
if (windowHeight >= ((alturaseccion2 * 0.80) + seccion2) && windowHeight <= (alturaseccion2 + seccion2)) {
} else {
}
}
} else {
// up scroll
console.log("scrollarriba");
}
lastScrollTop = windowHeight;
});
ยดยดยด
I'm not sure what you are trying to accomplish, but if your trying to trigger an event with a specific scroll value you can use the code below
$(window).scroll(function () {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
alert("scroll is greater than 500 px)
} else if(scroll==500){
alert("scroll has hit 500px");
}
});
I followed Paul Lewis's guide to debounce and requestAnimationFrame. I'm translating an image across the screen on scroll when it comes into view.
var bicycles = $('.tandem-bike', context),
lastScrollY = 0,
ticking = false;
function update() {
var windowHeight = window.innerHeight,
windowWidth = $(window).width(),
bikeTop = [];
bicycles.each( function (i, el) {
bikeTop[i] = $(this).offset();
});
bicycles.each(function(i, el) {
var position = bikeTop[i];
var fromTop = position.top - windowHeight;
var imgHeight = $(this).height();
// When this image scrolls into view.
if (lastScrollY > fromTop && lastScrollY < position.top + imgHeight && i == 1 ) { // 375 ~= height of image
var translate = Math.floor((lastScrollY - fromTop) / ((windowHeight + imgHeight + 300) / windowWidth));
console.log('add tp tranlate ', translate);
$(this).css('transform', 'translateX(' + (translate - 275) + 'px)');
}
});
ticking = false;
}
function onScroll() {
lastScrollY = window.scrollY;
requestTick();
}
function requestTick() {
if(!ticking) {
requestAnimationFrame(update);
ticking = true;
}
}
window.addEventListener('scroll', onScroll, false);
This works great and the bicycle-built-for-two slides effortlessly across the screen. However, I want the image to "bounce" when the user stops scrolling. I figure an easy way would be to add a class when the animation ends, and pull it off when the animation starts. The obvious place to do that is within the if block in requestTick().
if(!ticking) {
$('.tandem-bike').removeClass('bounce');
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
}
or
if(!ticking) {
requestAnimationFrame(update);
$('.tandem-bike').addClass('bounce');
ticking = true;
} else {
$('.tandem-bike').removeClass('bounce');
}
}
Neither works, and I don't love then because I'm whole-sale adding classes to all the animated images on the page. (I would live with that if it worked)
I built a magnifying glass in JavaScript, which works well when I click on it or click and dragging it, but it should not hide from the screen.
$(".menu-left-preview-box-preview").bind('click', function (e) {
window.location = "page" + ($(this).index() + 1) + ".html";
});
var native_width = 0;
var native_height = 0;
var magnifyIsMouseDown = false;
$(".magnify").parent().mousedown(function (e) {
magnifyIsMouseDown = true;
});
$(".magnify").mousemove(function (e) {
if (magnifyIsMouseDown) {
if (!native_width && !native_height) {
var image_object = new Image();
image_object.src = $(".small").attr("src");
native_width = image_object.width;
native_height = image_object.height;
} else {
var magnify_offset = $(this).offset();
var mx = e.pageX - magnify_offset.left;
var my = e.pageY - magnify_offset.top;
if (mx < $(this).width() && my < $(this).height() && mx > 0 && my > 0) {
$(".large").fadeIn(100);
} else {
$(".large").fadeOut(100);
}
if ($(".large").is(":visible")) {
var rx = Math.round(mx / $(".small").width() * native_width - $(".large").width() / 2) * -1;
var ry = Math.round(my / $(".small").height() * native_height - $(".large").height() / 2) * -1;
var bgp = rx + "px " + ry + "px";
var px = mx - $(".large").width() / 2;
var py = my - $(".large").height() / 2;
$(".large").css({ left: px, top: py, backgroundPosition: bgp });
}
}
}
});
$(".magnify").parent().mouseup(function (e) {
magnifyIsMouseDown = false;
$(".large").fadeOut(100);
});
$(".magnify").parent().mouseleave(function (e) {
$(".large").fadeOut(100);
});
manageSlide();
By default the magnifying glass must be there on the screen. The magnifying glass can be dragged and after it's dropped it must remain there at it's dropped position.
On clicking and dragging the magnify glass is working well, but it should not hide from the screen. It should be there on screen.
Provide handle of magnify glass with that circle (in design).
Working example: http://jsfiddle.net/mohsin80/4ww8efx5/
I replaced the if (magnifyIsMouseDown) { by if (isDragging) { and created the following methods:
var isDragging = false;
$(".magnify").parent().mouseup(function(e) {
isDragging = false;
});
$(".magnify").parent().mousedown(function(e) {
isDragging = true;
});
To make a simulated drag event with jQuery.
Here is the fiddle. Hope it helped :)
I have written a simple custom section snapping script, works great in chrome and safari, but after nothing happens in firefox...
What it is does:
When scrolling stops it checks the direction and location of each secrion... if the top of a section is within a certain range either go to the top of the page or bottom. (scroll directions is also checked). Also, it accounts for the height of a fixed header. Like I said works in Chrome and Safari. Any ideas what's wrong?
$( document ).ready(function() {
var animating = false;
var mainHeader = $('#main-header');
var items = $("section");
var lastOffset = 0;
var scrollDir = 'none';
$(window).scroll(function() {
var windowHeight = $(this).height();
var currOffset = $(this).scrollTop();
var headerHeight = mainHeader.outerHeight();
if (currOffset > lastOffset) {
scrollDir = 'down';
} else {
scrollDir = 'up';
}
lastOffset = currOffset;
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
var currentItem = $(value);
var sectionOffset = currentItem.offset().top;
var sectionDist = sectionOffset - currOffset;
if ( scrollDir === 'up' && sectionDist > windowHeight*0.15 && sectionDist < windowHeight ) {
animating = true;
$('body').animate( { scrollTop: sectionOffset-windowHeight + 'px' }, 250);
setTimeout(function() { animating = false; }, 300);
return false;
}
else if ( scrollDir === 'down' && sectionDist < windowHeight*0.85 && sectionDist > 0 ) {
animating = true;
$('body').animate( { scrollTop: sectionOffset-headerHeight + 'px' }, 250);
setTimeout(function() { animating = false; }, 300);
return false;
}
});
}, 200));
}
});
});
Found the answer here...
Animate scrollTop not working in firefox
Firefox places the overflow at the html level, unless specifically styled to behave differently.
To get it to work in Firefox, use
$('body,html').animate( ... );
on my site I have 6 divs each div the same height and width of the browser window, so 5 are out of view, 3 left aligned then 3 more on top, as so....
When my visitors scroll, id like to scroll along to the 3rd div, then scroll up to the 4th, then continue scrolling horizontally. Is this possible with jQuery, and if so how can it be done?
Check this out. It allows you to scroll in different directions and set up "slides" like above
http://joelb.me/scrollpath/
Simple (maybe helpful) and not perfect:
var win = $(window),
doc = $(document),
bodyH = doc.height() - win.height(),
page4 = $('#page4');
win.scrollTop(bodyH);
$(document).on('DOMMouseScroll mousewheel', function(e, delta) {
delta = delta || -e.originalEvent.detail / 3 || e.originalEvent.wheelDelta / 120;
if(delta < 0) {
if(win.scrollLeft() > page4.offset().left && win.scrollTop() !== 0) {
win.scrollTop(win.scrollTop() + delta * 30);
} else {
win.scrollLeft(win.scrollLeft() - delta * 30);
}
} else {
if(win.scrollLeft() < page4.offset().left && (win.scrollTop() > 0 || win.scrollTop() === 0) && win.scrollTop() !== bodyH) {
win.scrollTop(win.scrollTop() + delta * 30);
} else {
win.scrollLeft(win.scrollLeft() - delta * 30);
}
}
e.preventDefault();
});
demo