Overlapping img using jQuery

I’m trying to implement an effect on overlapping images so when I click and drag a bar the other image underneath should reveal modifying the width. My code works, but it’s kind of buggy. When I click on the bar I have to then release it to make it work, so it’s not really a drag, and it supposed to stop moving when I release the click.
And second, the bar goes right even outside my container. How could I fix my code?

var up = $("#up");
var bar = $("#bar");
var container = $("#container");

bar.on("mousedown", function () {
    container.on("mousemove", function (e) {
        bar.css("left", e.clientX);
        up.width(e.clientX);
    });
});

$("body").on("mouseup", function () {
    container.off("mousemove");
});

container.on("mouseleave", function () {
    container.off("mousemove");
});
* {
    margin: 0;
    box-sizing: border-box;
}

img {
    height: 400px;
    width: 600px;
    object-fit: cover;
}

#up {
    width: 50%;
}

#bottom,
#up {
    position: absolute;
    overflow: hidden;
}

#container {
    position: relative;
    border: 5px solid cornflowerblue;
    height: 410px;
    width: 610px;
}

#bar {
    position: absolute;
    height: 400px;
    width: 10px;
    background-color: hotpink;
    left: 300px;
    cursor: e-resize;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="style.css" />
        <title>Document</title>
    </head>
    <body>
        <div id="container">
            <div id="bottom">
                <img src="https://via.placeholder.com/600x400?text=Image1" alt="image" />
            </div>
            <div id="up">
                <img src="https://via.placeholder.com/600x400?text=Image2" alt="image" />
            </div>
            <div id="bar"></div>
        </div>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <script src="script.js"></script>
    </body>
</html>

2 thoughts on “Overlapping img using jQuery”

  1. Explanation : When the bar was being slid, the images were acting as draggable elements. To stop that, I set draggable attribute to false in both image elements. Besides that, the blue color appearing was highlight because of selection of element. To prevent that, I set CSS property user-select to none for the container divs of images.

    For browser compatibility, use different versions for user-select.

    var up = $("#up");
    var bar = $("#bar");
    var container = $("#container");
    
    bar.on("mousedown", function() {
      container.on("mousemove", function(e) {
        let left = e.clientX;
        let containerWidth = container.width();
        let barWidth = bar.width();
        
        if((left + barWidth) > containerWidth)
          left = containerWidth - barWidth;
        
        bar.css("left", left);
        up.width(left);
      });
    });
    
    
    $("body").on("mouseup", function() {
      container.off("mousemove");
    });
    
    container.on("mouseleave", function() {
      container.off("mousemove");
    });
    * {
      margin: 0;
      box-sizing: border-box;
    }
    
    img {
      height: 400px;
      width: 600px;
      object-fit: cover;
    }
    
    #up {
      width: 50%;
    }
    
    #bottom, #up {
      position: absolute;
      overflow: hidden;
      user-select: none;
    }
    
    #container {
      position: relative;
      border: 5px solid cornflowerblue;
      height: 410px;
      width: 610px;
    }
    
    #bar {
      position: absolute;
      height: 400px;
      width: 10px;
      background-color: hotpink;
      left: 300px;
      cursor: e-resize;
    }
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <div id="container">
      <div id="bottom">
        <img src="https://via.placeholder.com/600x400?text=Image1" alt="image" draggable="false"/>
      </div>
      <div id="up">
        <img src="https://via.placeholder.com/600x400?text=Image2" alt="image" draggable="false"/>
      </div>
      <div id="bar"></div>
    </div>
    Reply
  2. My advise is to NOT unregister (remove) the mousemove event listener.

    Below, I used a barActive as a "flag" to know if the mouse button is down. The flag is resetted on mouseup and mouseleave of the container.

    The mousemove event is a machinegun… But is still not fast enough to "really" follow the mouse. So if a user moves the bar fast, the cursor often is off the bar (I’m sure you noticed it). So a mouseup has good chances to not fire if the mouseup event listener is on the bar. So the event listener has to be on the container.

    Now… While mousemove is not fast enought to follow the mouse perfectly… It often is too fast and may interfeer with the actions you wish to do with the other events, like mousedown were you set the "flag". At the same millisecond, you can have the mousedown event and multiple mousemove events. So to "isolate" it form the mousemove events, I used a real tiny setTimeout. That is giving enought time for the flag to be set bafore any next mousemove to enact.

    About making sure the bar does not go outside the container, I used a condition on e.clientX.

    I also took the container’s padding in account.

    console.clear();
    
    var up = $("#up");
    var bar = $("#bar");
    var container = $("#container");
    var barActive = false;
    
    bar.on("mousedown", function (e) {
      barActive = true;
    });
    
    container.on("mousemove mouseup mouseleave", function (e) {
      if (barActive && e.type === "mousemove") {
        setTimeout(function () {
          if (e.clientX < container.width() && e.clientX>5) {
            bar.css("left", e.clientX - 8);
            up.width(e.clientX - 8);
          }
        }, 1);
        return;
      }
      barActive = false;  // Applies only for mouseup and mouseleave
    });
    * {
      margin: 0;
      box-sizing: border-box;
    }
    
    img {
      height: 400px;
      width: 600px;
      object-fit: cover;
      user-select: none;  /* Prevents the image itself to be selected */
    }
    
    #up {
      width: 50%;
    }
    
    #bottom,
    #up {
      position: absolute;
      overflow: hidden;
    }
    
    #container {
      position: relative;
      border: 5px solid cornflowerblue;
      height: 410px;
      width: 610px;
      overflow: hidden;  /* Will make sure the bar does not go over the border */
    }
    
    #bar {
      position: absolute;
      height: 400px;
      width: 10px;
      background-color: hotpink;
      left: 300px;
      cursor: e-resize;
    }
    <html lang="en">
    
    <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <link rel="stylesheet" href="style.css" />
      <title>Document</title>
    </head>
    
    <body>
      <div id="container">
        <div id="bottom">
          <img src="https://via.placeholder.com/600x400?text=Image1" alt="image" />
        </div>
        <div id="up">
          <img src="https://via.placeholder.com/600x400?text=Image2" alt="image" />
        </div>
        <div id="bar"></div>
      </div>
      <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
      <script src="script.js"></script>
    </body>
    
    </html>

    CodePen

    Reply

Leave a Comment