flickity
flickity copied to clipboard
Enable scrolling via mousewheel
I'm experiencing a little problem with one of my sliders.
// Defined in seperate JS file
function scrollEnd(flickelem) {
// FLICKITY DragEnd
if ( flickelem.options.freeScroll ) {
flickelem.isFreeScrolling = true;
}
// set selectedIndex based on where flick will end up
var index = flickelem.dragEndRestingSelect();
if ( flickelem.options.freeScroll && !flickelem.options.wrapAround ) {
// if free-scroll & not wrap around
// do not free-scroll if going outside of bounding cells
// so bounding cells can attract slider, and keep it in bounds
var restingX = flickelem.getRestingPosition();
flickelem.isFreeScrolling = -restingX > flickelem.cells[0].target &&
-restingX < flickelem.getLastCell().target;
} else if ( !flickelem.options.freeScroll && index == flickelem.selectedIndex ) {
// boost selection if selected index has not changed
index += flickelem.dragEndBoostSelect();
}
// apply selection
// TODO refactor this, selecting here feels weird
flickelem.select( index );
}
// Inside a <script> tag inside the document
$(function(){
$(document).ready(function(e) {
var cellCount = $('.gallery-cell').length;
var canWrapAround = false;
if(cellCount > 1) canWrapAround = true;
$('.text-slider').flickity({
accessibility: true,
autoPlay: false,
cellAlign: 'center',
cellSelector: undefined,
contain: true,
draggable: true,
freeScroll: true,
friction: 0.2,
imagesLoaded: true,
initialIndex: 0,
percentPosition: true,
prevNextButtons: false,
pageDots: false,
resize: true,
rightToLeft: false,
watchCSS: false,
wrapAround: canWrapAround
}).mousewheel(function(e) {
e.preventDefault();
var flickelem = Flickity.data(this);
if (e.deltaX) {
flickelem.x += e.deltaX * e.deltaFactor;
}
else if (e.deltaY) {
flickelem.x += e.deltaY * e.deltaFactor;
}
scrollEnd(flickelem);
});
$(window).load(function(e) {
$('.text-slider').flickity('resize');
});
});
});
I am using the jQuery mousewheel
plugin to support scrolling inside flickity. But somehow on mobile devices occasionally I can't reach the last cell. It always flicks back to the previous one. Could it be a bug or could it be a fault of me?
Add a 👍 reaction to this issue if you would like to see this feature added. Do not add +1 comments — They will be deleted.
Thanks for taking a shot at this. I haven't looked in to supporting mousewheel, or providing an API to manipulate the slider position. I'll categorize this as a feature request for now. I'm focusing on releasing the core feature set for Flickity at the moment. I'll come back to this afterwards.
Reclassifying this issue as a feature request. Flickity does not currently support manipulation of the slider position. If you would like to see this feature, please +1 or subscribe to this issue.
+1
+1
(I have a homegrown carousel in place at http://theartificial.nl/ and want to replace it, but mousey-scroll is important to me.)
+1
Got something here ;)
$('.gallery').mousewheel(function(e) {
e.preventDefault();
var flkty = Flickity.data(this);
if (!window.wheeling) {
// console.log('start wheeling!');
if(e.deltaX > 0 || e.deltaY < 0){
flkty.next();
} else if(e.deltaX < 0 || e.deltaY > 0){
flkty.previous();
}
}
clearTimeout(window.wheeling);
window.wheeling = setTimeout(function() {
// console.log('stop wheeling!');
delete window.wheeling;
// reset wheeldelta
window.wheeldelta.x = 0;
window.wheeldelta.y = 0;
}, 250);
window.wheeldelta.x += e.deltaFactor * e.deltaX;
window.wheeldelta.y += e.deltaFactor * e.deltaY;
if(window.wheeldelta.x > 500 || window.wheeldelta.y > 500 || window.wheeldelta.x < -500 || window.wheeldelta.y < -500){
window.wheeldelta.x = 0;
window.wheeldelta.y = 0;
if(e.deltaX > 0 || e.deltaY < 0){
flkty.next();
} else if(e.deltaX < 0 || e.deltaY > 0){
flkty.previous();
}
}
// console.log(window.wheeldelta);
});
Found this approach over here: http://stackoverflow.com/questions/3515446/jquery-mousewheel-detecting-when-the-wheel-stops
+1
I'm presently hacking my way through this, trying to engage Flickity's lovely touch/click behavior for horizontal scrolling. The best discussion about relevant issues seems to be this issue on the jQuery mousewheel plugin: https://github.com/jquery/jquery-mousewheel/issues/36
+1 This feature would make me a very happy human.
+1
Thanks @pavethiran, the approach you are recommending is really interesting, but it only scrolls to the next cell/element. Do you have an idea how to do an actual free mouse scroll with it. Would be so useful, because flickity would cover then almost every possible interaction with the user.
@gerwitz hello. You can try our wheel-indicator to implement wheel support for gallery.
+1
+1
+1
+1
+1 :)
+1
After much searching I found the functionality I was looking for in iDangerous' Swiper: https://github.com/nolimits4web/Swiper - it's also beautifully written and well documented so I'd recommend checking it out :)
If this is still and issue then this might help someone: https://iamsteve.me/blog/entry/enhancing-horizontal-scrolling-with-flickity-js
I have decided to not add this feature. Mouse wheel are most commonly used for vertical scrolling. Flickity is horizontal. Adding this feature would add additional complexity for a small feature. Sorry to say no here!
For people who want to "hack in" mousewheel support, this was my approach:
- Install the wheel NPM package which uses MDN's cross browser event listener for wheel events.
- Install the normalize-wheel NPM package which uses Facebook's fixed-data-table mousewheel normalizer to normalize mousewheel delta values across browsers and systems.
- Let
slider
be a Flickity instance andwheel
be the wheel NPM package - Use the following piece of code:
import wheel from 'wheel';
import normalizeWheel from 'normalize-wheel';
wheel.addWheelListener(slider.$element[0], event => {
const wheelNormalized = normalizeWheel(event);
slider.applyForce(-wheelNormalized.pixelY / 4);
slider.startAnimation();
slider.dragEnd();
});
This uses Flickity's internal force, animation and drag functions to perform slider movement and therefore correctly handles slide indexes, freescroll, friction etc.
Note that this uses the pixelY
property of the normalized wheel event. So it registers any vertical mouse scrolling as horizontal movement and does nothing with any horizontal mouse scrolling.
Also note that the slider.dragEnd()
call fires the 'dragEnd' event with undefined
parameters.
This code example uses NPM packages and arrow functions. If you don't want to use NPM packages or arrow functions, use the following piece of code after loading MDN's cross browser event listener for wheel events and Facebook's fixed-data-table normalizeWheel function yourself:
addWheelListener(slider.$element[0], function (event) {
var wheelNormalized = normalizeWheel(event);
slider.applyForce(-wheelNormalized.pixelY / 4);
slider.startAnimation();
slider.dragEnd();
});
Where slider
again is the Flickity instance.
UPDATE January 18th 2018: Added velocity normalization across browsers
People keep asking for this feature, so I'm re-opening.
Add a 👍 reaction to this issue if you would like to see this feature added. Do not add +1 comments — They will be deleted.
For people who want to "hack in" mousewheel support, this was my approach:
- Install the wheel NPM package which uses MDN's cross browser event listener for wheel events.
- Install the normalize-wheel NPM package which uses Facebook's fixed-data-table mousewheel normalizer to normalize mousewheel delta values across browsers and systems.
- Let
slider
be a Flickity instance andwheel
be the wheel NPM package- Use the following piece of code:
import wheel from 'wheel'; import normalizeWheel from 'normalize-wheel'; wheel.addWheelListener(slider.$element[0], event => { const wheelNormalized = normalizeWheel(event); slider.applyForce(-wheelNormalized.pixelY / 4); slider.startAnimation(); slider.dragEnd(); });
This uses Flickity's internal force, animation and drag functions to perform slider movement and therefore correctly handles slide indexes, freescroll, friction etc.
Note that this uses the
pixelY
property of the normalized wheel event. So it registers any vertical mouse scrolling as horizontal movement and does nothing with any horizontal mouse scrolling.Also note that the
slider.dragEnd()
call fires the 'dragEnd' event withundefined
parameters.This code example uses NPM packages and arrow functions. If you don't want to use NPM packages or arrow functions, use the following piece of code after loading MDN's cross browser event listener for wheel events and Facebook's fixed-data-table normalizeWheel function yourself:
addWheelListener(slider.$element[0], function (event) { var wheelNormalized = normalizeWheel(event); slider.applyForce(-wheelNormalized.pixelY / 4); slider.startAnimation(); slider.dragEnd(); });
Where
slider
again is the Flickity instance.UPDATE January 18th 2018: Added velocity normalization across browsers
Anyway to do this without Jquery? Trying to codepen this and having no luck...
Anyway to do this without Jquery? Trying to codepen this and having no luck...
@joebentaylor, my hack isn't using jQuery if I'm correct. What issue are you encountering?
@LuudJanssen
i was looking for something like this for a full width/height slider, thank you! i did some user tests and found out people using safari on apple laptops were likely to scroll horizontally using the trackpad, here is the workaround I've came with
const wheelNormalized = normalizeWheel(event);
const highestValue = Math.abs(wheelNormalized.pixelY) >= Math.abs(wheelNormalized.pixelX) ?
wheelNormalized.pixelY : wheelNormalized.pixelX * 0.75
this.flkty.applyForce(-highestValue / 8);
this.flkty.startAnimation();
this.flkty.dragEnd();
in addition to your code, it performs a simple check for highest value on x or y axis scroll and use this value, i did not try it on iOs though
Anyway to do this without Jquery? Trying to codepen this and having no luck...
@joebentaylor, my hack isn't using jQuery if I'm correct. What issue are you encountering?
I guess im confused as to what $element
is
After running the code i get this error TypeError: Cannot read property '0' of undefined
@joebentaylor
adding $
before a variable is a naming convention for DOM selectors
if the method is not defined then probably the library is not exectuded the right way
finally you can replace slider.$element[0]
by a simple DOM element query such as document.querySelector('.carousel')
(adapt the code if you have multiple sliders, the original code assume that slider.$element
is an available array, it wasn't in my case either)
@LeoSeyers Im confused as to what element needs to be though, we are replacing slider with our slider name / reference, so whats $element supposed to reference? the slides?