Search code examples
javascriptbackend

The problem of not being able to create a rectangular colored area when the drawable semicircle is drawn to the far right


I want the rectangular shaped blue colored area to remain in view when the draw-able semicircle (with vault size background) is pulled to the far right.

   var handle = document.getElementById("handle");
  // Check if the handle reached the maximum position
  if (newWidth >= maxBarWidth) {
    handle.style.backgroundImage = "url('https://virtualisedreality.files.wordpress.com/2012/07/the-best-top-desktop-blue-wallpapers-blue-wallpaper-blue-background-hd-33.jpg')"; // Set to your new blue image
} else {
    handle.style.backgroundImage = "url('https://i.gifer.com/2P5x.gif')"; // Set back to the original image
} 

With this code, it turns a vague blue color at a sensitive point. Can we solve it easily using an approach like this or in a different way? Currently, part of the Background is visible on the right.

// Make the handle draggable
dragElement(document.getElementById("handle"));

function dragElement(elmnt) {
  var startPosX = 0,
    currentPosX = 0;
  var maxBarWidth = window.innerWidth - (elmnt.offsetWidth / 16); // Tarayıcı penceresinin genişliğini kullanma , Set the maximum width for the bar.

  elmnt.onmousedown = dragMouseDown;

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    startPosX = e.clientX;
    document.onmouseup = closeDragElement;
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    currentPosX = e.clientX - startPosX;
    startPosX = e.clientX;
    var bar = document.getElementById("bar");
    var newWidth = bar.offsetWidth + currentPosX;

    // Define the minimum width to keep the handle from entering the bar area
    var minBarWidth = 3; // This is the initial width of the bar

    // Restrict the width within the minimum and maximum bounds
    newWidth = Math.max(minBarWidth, Math.min(newWidth, maxBarWidth));

    // Set the new width
    bar.style.width = newWidth + "px";

  }

  function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
  }
}
#bar {
  position: fixed;
  /* Fixed position to stay in place on scroll */
  top: 0;
  bottom: 0;
  left: 0;
  width: 3px;
  /* Initial width of the bar */
  background-color: #f1f1f1;
  /* Background of the bar */
  border-right: 1px solid #d3d3d3;
  /* Border of the bar */
  z-index: 9;
}

#handle {
  width: 100px;
  /* Diameter of the handle circle */
  height: 100px;
  /* Height of the handle circle */
  background-color: #2196F3;
  border-radius: 50%;
  /* Make it round */
  position: absolute;
  /* Absolute position within the bar div */
  top: 50%;
  /* Center it vertically */
  right: -3.125em;
  /* Align to the right of the bar */
  transform: translateY(-50%);
  /* Adjust vertical position */
  cursor: pointer;
  /* Change cursor to indicate it's draggable */
  z-index: 10;
  clip-path: inset(0 0 0 50%);
  /* Clip left half of the circle */
  background-image: url('https://i.gifer.com/2P5x.gif');
  background-repeat: no-repeat;
  background-size: 90% 100%;
  /* Width and height values */
  background-position: calc(100% + 0.625em) center;
  /* Move the image to the right by 10 pixels from the edge */
}
<html>

<body>
  <div id="bar">
    <!-- This is the draggable handle -->
    <div id="handle"></div>
  </div>
</body>

</html>

Desired situation:

enter image description here


Solution

    1. The bar.offsetWidth returns the element width with its border. Since you set the border-right to 1px in css, this value will be always 1 more than the width you set. It was causing issues with scrolling (bar was not following the mouse movements exactly). I changed it to bar.clientWidth, which returns width without border. More on: Understanding offsetWidth, clientWidth, scrollWidth and -Height, respectively
    2. In the maxBarWidth variable you divided elmnt.offsetWidth by 16. You have a circle and visible is only half of it, so you should not divide it by 16, but by 2 (or multiply by 0.5, same thing). Also, you set in css right: -3.125em, but you really wanna move it half the width again, so either change the width to 6.250em (double the width without sign) or simply change the right property to -50px (half the width). See the snippet

    Edited the snippet per comments

    // Make the handle draggable
    dragElement(document.getElementById("handle"));
    
    function dragElement(elmnt) {
      var startPosX = 0,
        currentPosX = 0;
      var maxBarWidth = window.innerWidth - (elmnt.offsetWidth / 16); // Set the maximum width for the bar.
      console.log(`maxBarWidth = ${window.innerWidth} - (${elmnt.offsetWidth} / 16) = ${maxBarWidth}`);
      elmnt.onmousedown = dragMouseDown;
    
      function dragMouseDown(e) {
        e = e || window.event;
        e.preventDefault();
        startPosX = e.clientX;
        document.onmouseup = closeDragElement;
        document.onmousemove = elementDrag;
      }
    
      function elementDrag(e) {
        e = e || window.event;
        e.preventDefault();
        currentPosX = e.clientX - startPosX;
        startPosX = e.clientX;
        var bar = document.getElementById("bar");
        var newWidth = bar.clientWidth + currentPosX;
        //console.log(`newWidth = ${bar.clientWidth} + ${currentPosX} = ${newWidth}`)
        // previous: console.log(`newWidth = ${bar.offsetWidth} + ${currentPosX} = ${newWidth}`)
    
        // Define the minimum width to keep the handle from entering the bar area
        var minBarWidth = 3; // This is the initial width of the bar
    
        // Restrict the width within the minimum and maximum bounds
        newWidth = Math.max(minBarWidth, Math.min(newWidth, maxBarWidth));
    
        var handle = document.getElementById("handle");
       
       // Adding or removing the 'blue-bg' class based on the handle's position
    if (newWidth >= maxBarWidth) {
        handle.classList.add('blue-bg');
    } else {
        handle.classList.remove('blue-bg');
    }
        // Set the new width
        bar.style.width = newWidth + "px";
      }
    
      function closeDragElement() {
        // stop moving when mouse button is released:
        document.onmouseup = null;
        document.onmousemove = null;
      }
    }
    #bar {
      position: fixed;
      /* Fixed position to stay in place on scroll */
      top: 0;
      bottom: 0;
      left: 0;
      width: 3px;
      /* Initial width of the bar */
      background-color: #f1f1f1;
      /* Background of the bar */
      border-right: 1px solid #d3d3d3;
      /* Border of the bar */
      z-index: 9;
    }
    
    #handle {
      width: 100px;
      /* Diameter of the handle circle */
      height: 100px;
      /* Height of the handle circle */
      background-color: #2196F3;
      border-radius: 50%;
      /* Make it round */
      position: absolute;
      /* Absolute position within the bar div */
      top: 50%;
      /* Center it vertically */
      right: -3.125em;
      /* Align to the right of the bar */
      transform: translateY(-50%);
      /* Adjust vertical position */
      cursor: pointer;
      /* Change cursor to indicate it's draggable */
      z-index: 10;
      clip-path: inset(0 0 0 50%);
      /* Clip left half of the circle */
      background-image: url('https://i.gifer.com/2P5x.gif');
      background-repeat: no-repeat;
      background-size: 90% 100%;
      /* Width and height values */
      background-position: calc(100% + 0.625em) center;
      /* Move the image to the right by 10 pixels from the edge */
    }
    
    #handle.blue-bg {
        background-image: url('https://virtualisedreality.files.wordpress.com/2012/07/the-best-top-desktop-blue-wallpapers-blue-wallpaper-blue-background-hd-33.jpg');
        background-position-x: right;
    }
    <html>
    
    <body>
      <div id="bar">
        <!-- This is the draggable handle -->
        <div id="handle"></div>
      </div>
    </body>
    
    </html>