html – Selection area with the mouse?

Question:

I'm developing the following code, to create an element selection area using the mouse.

var draggingMouse = false;
var leftMouseDrag, topMouseDrag;
$(document).on("mousedown mouseup", "#cloud_main_page", function(e){	
	if (e.type == "mousedown") {
		draggingMouse = true;
		var offset = $(this).offset();
		
		leftMouseDrag = e.pageX - offset.left;
		topMouseDrag = e.pageY - offset.top
		
		$("#cloud_main_page .cloud_mouse_selection").css({"top": topMouseDrag, "left" : leftMouseDrag});
			
	} else{
		draggingMouse = false;	
		$("#cloud_main_page .cloud_mouse_selection").removeAttr("style");
	}
		
}).on("mousemove", "#cloud_main_page", function(e){
	if(draggingMouse){
		var offsetDrag = $("#cloud_main_page .cloud_mouse_selection").offset();
			
		var top = e.pageY - offsetDrag.top;
		var left = e.pageX - offsetDrag.left;
      
		var width = Math.abs(left);
		var height = Math.abs(top);
			
		$("#cloud_main_page .cloud_mouse_selection").css({"width": width, "height": height});
	}
});
#cloud_main_page{
  width:400px;
  height:400px;
  
  position:relative;
}
#cloud_main_page .cloud_mouse_selection{	
	position:absolute;
	
	background-color:rgba(6, 217, 160, 0.05);
	border: 1px solid rgba(6, 217, 160, 0.3);	
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cloud_main_page">
  <div class="cloud_mouse_selection"></div>
</div>

It works fine, as long as the user drags the mouse only from Left to Right and from top to bottom, and this obviously won't always be the same scenario… So how could I do it if the user decides to drag the mouse in different directions?

Answer:

Your mistake here is to always set the top and left properties on the mousedown and not change them afterwards, as there is no negative size, you wouldn't be able to make the box go up or left from its initial position.

The solution to your problem is simple, just set the left and top dynamically considering whether the X and Y coordinates of the mouse are currently larger or smaller than in the mousedown event, in this event we only save the initial coordinates. We treat X and Y separately , as the starting x can be greater than the current one while the current y is greater than the initial one.

Having this information, width and height will always be the distance from the start point to the current mouse position, however left and top must be whoever has the SMALLEST coordinates, in this case being set by a ternary operation.

let draggingMouse = false;
let leftMouseDrag, topMouseDrag;
let startPosition;

$(document).on("mousedown mouseup", "#cloud_main_page", function(e) {
  if (e.type == "mousedown") {
    draggingMouse = true;
    var offset = $(this).offset();

    startPosition = {
      x: e.pageX - offset.left,
      y: e.pageY - offset.top
    }


  } else {
    draggingMouse = false;
    $("#cloud_main_page .cloud_mouse_selection").removeAttr("style");
  }

}).on("mousemove", "#cloud_main_page", function(e) {
  if (draggingMouse) {
    var offset = $(this).offset();

    const actualPosition = {
      x: e.pageX - offset.left,
      y: e.pageY - offset.top
    }

    const width = Math.abs(actualPosition.x - startPosition.x);
    const height = Math.abs(actualPosition.y - startPosition.y);

    $("#cloud_main_page .cloud_mouse_selection").css({
      "width": width,
      "left": actualPosition.x > startPosition.x ? startPosition.x : actualPosition.x
    })

    $("#cloud_main_page .cloud_mouse_selection").css({
      "height": height,
      "top": actualPosition.y > startPosition.y ? startPosition.y : actualPosition.y
    })

  }
});
#cloud_main_page {
  width: 400px;
  height: 400px;
  position: relative;
  background: #eee;
}

#cloud_main_page .cloud_mouse_selection {
  position: absolute;
  background-color: rgba(6, 217, 160, 0.05);
  border: 1px solid rgba(6, 217, 160, 0.3);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cloud_main_page">
  <div class="cloud_mouse_selection"></div>
</div>
Scroll to Top