Horizontal scroll on mouseMove - wide div in smaller div with overflow:hidden (Can't get the math to work)

17,072

You script is not smooth, so I modified it completely (sorry :)
with a really simple approach:

$(function() {

  const $bl = $(".thumbs-block"),
    $th = $(".thumbs"),
    blW = $bl.outerWidth(),
    blSW = $bl.prop("scrollWidth"),
    wDiff = (blSW / blW) - 1, // widths difference ratio
    mPadd = 60, // Mousemove Padding
    damp = 20; // Mousemove response softness

  let posX = 0,
    mX2 = 0, // Modified mouse position
    mmAA = blW - (mPadd * 2), // The mousemove available area
    mmAAr = (blW / mmAA), // get available mousemove fidderence ratio
    itv = null;

  const anim = () => {
    posX += (mX2 - posX) / damp; // zeno's paradox equation "catching delay"    
    $th.css({
      transform: `translateX(${-posX * wDiff}px)`
    });
  };

  $bl.on("mousemove", function(e) {
    const mouseX = e.pageX - $(this).prop("offsetLeft");
    mX2 = Math.min(Math.max(0, mouseX - mPadd), mmAA) * mmAAr;
  }).on("mouseenter", function(e) {
    itv = setInterval(anim, 10);
  }).on("mouseleave", function() {
    clearInterval(itv);
  });

});
.thumbs-block {
  position: relative;
  overflow: hidden;
  max-width: 100%;
}

.thumbs-block .thumbs {
  display: flex;
  flex-flow: row nowrap;
}
<div class="thumbs-block">
  <div class="thumbs">
    <a class="thumb"><img src="http://placehold.it/120x120/0bf&text=01" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/f0b&text=02" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/bf0&text=03" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/b0f&text=04" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/fb0&text=05" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/0fb&text=06" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/0bf&text=07" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/f0b&text=08" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/bf0&text=09" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/b0f&text=10" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/fb0&text=11" /></a>
    <a class="thumb"><img src="http://placehold.it/120x120/0fb&text=12" /></a>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Share:
17,072
martindilling
Author by

martindilling

Updated on July 24, 2022

Comments

  • martindilling
    martindilling almost 2 years

    I'm trying to make a "line" of image thumbs, where it scrolls on mousemove. And I got it to work, but my problem now is that i wanted to make a "padding" on the sides so I doesn't have to have the mouse all the way out to the sides to see the first/last thumb. But I really really can't get it to work :/

    This is the script I have now:

    // MouseMove scrolling on thumbs
    var box = $('.thumbs-block'),
        innerBox = $('.thumbs'),
        lastElement = innerBox.find('a:last-child');
    
    var offsetPx = 100;
    var boxOffset = box.offset().left;
    
    var boxWidth = box.width() /* - (offsetPx*2)*/;
    var innerBoxWidth = (lastElement[0].offsetLeft + lastElement.outerWidth(true)) - boxOffset /* + (offsetPx*2)*/;
    
    scrollDelayTimer = null;
    box.mousemove(function (e) {
        console.log('boxWidth: ' + boxWidth + '   innerBoxWidth: ' + innerBoxWidth + '   box.scrollLeft(): ' + box.scrollLeft());
    
        var mouseX = e.pageX;
        var boxMouseX = mouseX - boxOffset;
    
        if ((boxMouseX > offsetPx) && (boxMouseX < (boxWidth - offsetPx))) {
            var left = (boxMouseX * (innerBoxWidth - boxWidth) / boxWidth) /* - offsetPx*/;
    
            clearTimeout(scrollDelayTimer);
            scrollDelayTimer = setTimeout(function () {
                scrollDelayTimer = null;
                box.stop().animate({
                    "scrollLeft": left
                }, {
                    queue: false,
                    duration: 500,
                    easing: 'linear'
                });
            }, 10);
        }
    });
    

    There are some of the places I've tried adding the offset (commented out inline), some of it gets it working in one end but not the other :/

    I'm pretty sure it's a problem in the math, but I can't figure out what I should do :/

    Here's a jsFiddle: http://jsfiddle.net/6CJfs/1/

    I hope I made my problem clear enough, not sure how to explain it otherwise, and hope someone can help :)

  • martindilling
    martindilling about 11 years
    Sorry for the late answer, have been a busy ;) But it looks really awesome :P thanks so much for the help, hope I can implement it in my project later today ;)
  • martindilling
    martindilling about 11 years
    I've just testet it in my project, works like a charm :P Thanks for your help, voted up and accepted ;)
  • Anupal
    Anupal almost 9 years
    Help needed. Its not getting proper width on resizing the window thus some the first and end div get hide. Any fix to it?
  • leemon
    leemon over 7 years
    Can this script be changed to work with various carousels in the same page? If so, how?
  • Roko C. Buljan
    Roko C. Buljan over 7 years
    @user1991185 you can wrap it inside an .each() but I'd suggest to create a flexible and reusable a jQuery plugin: learn.jquery.com/plugins/basic-plugin-creation ... if that's over the top, sorry for not being of much help, I have no time currently to create a snippet.