3

Ok so with this slider I would like to use the "free mode" as this gives the effect I would like when sliding. Everything is how I want it (size & number of slides) but the one thing I would like it to do is after the slider has stopped (after a user slides it to a side) the slider would align with 3 slides to fit the container (much like the "carousel mode").

To explain a little better I have this image:

So at the top we have the after math of a slide. And at the bottom is what it should look like. So the slider lands on 4 slides, the slider should now move slightly to the side so slide 2 is touching the left side and slide 4 is complete showing. image

I have tried a fair few things but cannot get this working. Most of what I have tried is within the site (linked at the top) using the API settings etc. Not much point of me posting all the ones I tried as I may have missed things etc.

Current settings:

slidesPerView: 3,
momentumRatio: 1,
freeMode: true,
freeModeFluid: true,

Here is a demo of what I have so far. Any help on this would be great and I would even be willing to give a little extra rep to anyone that can solve this (I have been trying for a while), so +50 rep to anyone that solves this.

DEMO HERE

Just to make sure we are all on the same page, it should only "lock on" to a slide once the movement has finished. It must be stopped and then move to fit 3 slides in the container.

Note: I will be using this on an iPad, just a little note encase someone comes up with something not compatible.

Ruddy
  • 9,795
  • 5
  • 45
  • 66

3 Answers3

3

Solution 0

This solution adds a callback to when the CSS transitions finishes. This also handles the situation where no swipe occurs. For instance, the user clicks, drags, and releases but no transition occurs.

CSS

.swiper-wrapper {
    transition:all 1s ease;
    -webkit-transition:all 1s ease;
}
.transition {
    background:white;
}

JavaScript

var mouseClick = false;
var mySwiper = new Swiper('.swiper-container', {
    slidesPerView: 3,
    momentumRatio: 1,
    freeMode: true,
    freeModeFluid: true,
    onTouchEnd: function () {
        mouseClick = true;
        $('.swiper-wrapper').toggleClass('transition');
    },
})

$(".swiper-wrapper").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function () {
    if (mouseClick) {
        if (Math.abs(mySwiper.positions.current) % 320.0 < 160) {
            mySwiper.swipePrev();
        } else {
            mySwiper.swipeNext();
        }
        mouseClick = false;
    }
});

To Edit: http://jsfiddle.net/Xuz4z/15/
Working Example: http://jsfiddle.net/Xuz4z/15/embedded/result/

Solution 1

Somewhere to start. This solution uses the current position to determine whether to slide forward or back. It doesn't work perfectly because the value is sometimes obtained before the sliding is complete.

var mySwiper = new Swiper('.swiper-container', {
    slidesPerView: 3,
    momentumRatio: 1,
    queueEndCallbacks: true,
    freeMode: true,
    freeModeFluid: true,
    onTouchEnd: function () {
        setTimeout(function () {
            if (Math.abs(mySwiper.positions.current) % 320 < 160) {
                mySwiper.swipePrev();
            } else {
                mySwiper.swipeNext();
            }
            console.log(Math.abs(mySwiper.positions.current) % 320);
        }, 500);
    },
})

Working Example: http://jsfiddle.net/Xuz4z/12/embedded/result/

Community
  • 1
  • 1
JSuar
  • 21,056
  • 4
  • 39
  • 83
  • This is great, just the closest edge fails, If am pulling it say 90% of the element, it still slides out – Mr. Alien Jan 29 '14 at 17:11
  • @Mr.Alien I'm hoping to find a simple solution for the closest edge issue. – JSuar Jan 29 '14 at 17:14
  • I guess this can be solved by the total element `width` scroll position, and window width, these factors can play for the push – Mr. Alien Jan 29 '14 at 17:16
  • Upvoted for your efforts though, this somehow does the trick, but the real fun is when we makeout the edges swipe to the nearest corner – Mr. Alien Jan 29 '14 at 17:24
  • Thanks, @Mr.Alien. Check out the latest solution. Not perfect but close to it. – JSuar Jan 29 '14 at 17:32
  • Getting closer :) haha bounties gonna go to you then once ruddy accepts, I don't need this anyways, he will be deciding ;) but good going – Mr. Alien Jan 29 '14 at 17:40
  • Its looking pretty dam good. Its seems a bit "glitchly". It doesn't seem to respond to well to swiping left and right. It seems to jam up at times and then glitch around. I will take a good took at it tomorrow when I have the correct tools to play around with it in my real project. But it definitely looks promising. Good job! – Ruddy Jan 29 '14 at 17:46
  • @Ruddy, Yea, I wasn't happy with the glitchy feel either. Made another update that just utilizes the current position of the window. This is much cleaner. – JSuar Jan 29 '14 at 20:56
  • @Ruddy the last update is pretty much what you wanted... -JSugar, great effort.. Cheers~ – Mr. Alien Jan 30 '14 at 04:35
  • i like these kind of efforts where OP is different, bounty guy is different and then someone else gives a gud short answer....+1 to both this answer and the question too!! :) – NoobEditor Jan 30 '14 at 06:16
  • Like I said this is really good. By far better then anything I can do, but due to the timer it doesn't have the feel I need. I need it to stop and when it stops then move into place. Having a timer makes is "buggy" and a bit unpredictable. I will start having a mess around with it to see what I can do and how well it works in my project. Still this is a very good effort and i'm quite impressed! – Ruddy Jan 30 '14 at 08:03
  • @Ruddy, I definitely agree. A delay timer is certainly not a clean solution. Just added another which utilizes a CSS transition callback. Appears to be the cleanest solution I've found so far. – JSuar Jan 30 '14 at 16:18
  • @Ruddy, I noticed that my solution didn't handle a regular click and drag event (with no swipe action). My recent updates takes this use case into account. – JSuar Jan 31 '14 at 17:48
  • @JSuar, you are amazing.... I think that is what need. I will have to test it like before. But that looks pretty dam spot on. Thank you for all your time and effort! I will get back to you when I get a chance to use this in my project! – Ruddy Jan 31 '14 at 21:10
  • @Mr.Alien Agreed, this is very good stuff! Thank you for bounty. – Ruddy Feb 02 '14 at 20:25
  • @Ruddy mark the answer as correct and I will award him the bounty, I upvoted sathya raj as well for his efforts – Mr. Alien Feb 02 '14 at 20:26
  • 2
    @Ruddy Glad I could help out. Mr.Alien, thanks for the bounty. – JSuar Feb 03 '14 at 00:12
  • @JSuar Sorry to bother you again but as you had a good look at this. Any idea how I would go about setting a focus slide when it loads. So I can use `onFirstInit` to use a function when it loads. Any idea how to start on a certain div what we choose. e.g: `on load start on slide id="green"`. Any help on this would be great. – Ruddy Feb 04 '14 at 09:22
  • @JSuar Just a little update. The only way I can think to do it is `onFirstInit: function () { $(".swiper-wrapper").css('-webkit-transform', "translate3d(-640px,0px, 0px)"); },` – Ruddy Feb 04 '14 at 09:39
  • @Ruddy, that's a good bet. The `initialSlide` parameter doesn't animate to the slide. `mySwiper.swipeTo` would work but it's by index rather than the element id. That might be cleaner than the explicit translate CSS. – JSuar Feb 04 '14 at 13:04
2

You can also do simple thing like this just move next slide or prevslide using condition itself like this

 var forward = true;
var pos = 0;
var mySwiper = new Swiper('.swiper-container', {
    slidesPerView: 3,
    momentumRatio: 1,
    freeMode: true,
    freeModeFluid: true,
    onSlideChangeEnd: function (dir) {
        console.log(dir.activeIndex);
        if(dir.activeIndex > pos){
            forward = true;        
        }else{
            forward = false;
        }
        pos = dir.activeIndex;
    }
})
var perm = true;
mySwiper.wrapperTransitionEnd(fun1, true);

function fun1() {
    if (perm) {
        if (forward) {
            mySwiper.swipeNext();
        } else {
            mySwiper.swipePrev();
        }

        perm = false;
    } else {
        perm = true;
    }
}

Here is your updated jsfiddle

Sathya Raj
  • 1,079
  • 2
  • 12
  • 30
  • 1
    Nice job. However, this solution doesn't handle the use case where the user clicks and drags the columns rather than swiping them. Since there's no transition, the final adjustment to the nearest edge is never made. Also, [based on the documentation](http://www.idangero.us/sliders/swiper/api.php), `onSlideChangeEnd` does not work with `freemode`. – JSuar Feb 01 '14 at 13:47
0

Hate to say but it seems free mode is what's stopping you. Can't even call an onSlideChangeEnd callback function while using it. If you were savvy enough I suppose you could utilize the onTouchMove callback function to activate a custom listener of some kind that can tell when the wrapper comes to rest at which point it could determine a snap-position based on 320 * the index of the slider with left edge closest to screen's left edge.

That said, best of luck!

Frankenscarf
  • 1,189
  • 7
  • 10
  • Hmm, the thing is I need free mode because the slider does exactly what I want it to do (movement wise). I'm not great with jQuery so any chance you could give it ago? I guess it may not be possible as we cant use that call. And I need it so the slider stops and then moves to position the 3 sides correctly. – Ruddy Jan 27 '14 at 12:42
  • 2
    Sorry I'm not savvy enough to whip anything like that up. It would be like watching a caveman trying to use a vending machine; he'll eventually get a snack but it won't be pretty. Maybe a listener that checks every second after the onTouchMove callback to see if the wrapper's x is still changing until it stops? Code gurus? Anyone think that would work? – Frankenscarf Jan 27 '14 at 13:10