Zayn
Zayn

Reputation: 741

How to restrict image dragging inside div?

I have attached snippet where I have an image which is draggable and zoomable inside a div. But there is one issue, when moving image from left to right, it should not be able to move if the corner of image meets the corner of parent for both X and Y. I actually want to know when the corners of image meets with parent div corners because I dont want to allow dragging when this condition meets. Background red color should not be visible when dragging image.

window.repositionImage = function(event){
var element = document.getElementById('img');
  
  element.addEventListener('mousedown', function(e){
    
    e.stopPropagation();
    element.style.cursor = "grabbing";
    if (e.target != element) return;
    
    var offsetX = e.pageX - element.offsetLeft;
    var offsetY = e.pageY - element.offsetTop;
  
    var move = function(e){
     element.style.left = e.pageX - offsetX + "px";
     element.style.top = e.pageY - offsetY + "px";
    }
    
    var stop = function(){
      element.style.cursor = "default";
      document.removeEventListener("mousemove", move);
      document.removeEventListener("mouseup", stop);
    }
    
    
    document.addEventListener("mousemove", move);
    document.addEventListener("mouseup", stop);
   }) 
}

window.panChangeHandler = function(e){
  var element = document.getElementById('img');
   if (e.target.value == 0) {
      element.style.left = "0px";
      element.style.top = "0px";
   }

  img.style.transform = `scale(1.${e.target.value})`;
}
.item {
  border: 1px solid;
  background: red;
  width: 300px;
  height: 300px;
  overflow: hidden;
  position:relative;
}

.item img {
  position:absolute;
  width: 100%;
  height: 100%;
  -webkit-user-drag: none;
  left:0;
  top:0;
}

.slider {

  z-index: 9;
  position: absolute;
  left: 0;
  top: 0;
  margin-left: -20px;
  margin-top: 70px;
  writing-mode: bt-lr; /* IE */
  -webkit-appearance: slider-vertical; /* WebKit */
  transform: rotateZ(270deg);
}

.slider input {
  width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class='item'>
  <span class='slider'>
    <input type='range' aria-orientation="vertical"
      value="0"  min="0" max="9"  step="1"                       oninput="panChangeHandler(event)"
    />
  </span>
  <img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image' onmouseover="repositionImage(event)" />
</div>

Upvotes: 2

Views: 533

Answers (3)

Zayn
Zayn

Reputation: 741

I managed to solve this issue:

function parseComplexStyleProperty(str) {
        var regex = /(\w+)\((.+?)\)/g,
            transform = {},
            match;

        while ((match = regex.exec(str))) transform[match[1]] = match[2];

        return transform;
    };

window.repositionImage = function(event){
var element = document.getElementById('img');
  
  element.addEventListener('mousedown', function(e){
    
    e.stopPropagation();
    element.style.cursor = "grabbing";
    if (e.target != element) return;
    
    var offsetX = e.pageX - element.offsetLeft;
    var offsetY = e.pageY - element.offsetTop;
      var x = 0;
    var y = 0;
    
    var move = function(e){
         x = e.pageX - offsetX;
      y = e.pageY - offsetY;
     element.style.left = e.pageX - offsetX + "px";
     element.style.top = e.pageY - offsetY + "px";
    }
    
    var stop = function(){
      element.style.cursor = "default";
          var t = parseComplexStyleProperty(element.style.transform);
      
       if (!Object.keys(t).length) {
          element.style.left = "0px";
          element.style.top = "0px";
        }
  else {
          var imageWidth = element.clientWidth * parseFloat(t.scale);
          var imageHeight =
              element.clientHeight * parseFloat(t.scale);
          var pointToSubX = Math.trunc(
            (imageWidth - parent.clientWidth) / 2
          );
          var pointToSubY = Math.trunc(
            (imageHeight - parent.clientHeight) / 2
          );
          
          if (x > pointToSubX || x < -pointToSubX) {
            if (x > pointToSubX)
              element.style.left = pointToSubX + "px";
            else element.style.left = -pointToSubX + "px";
          }
          
          if (y > pointToSubY || y < -pointToSubY) {
            if (y > pointToSubY)
              element.style.top = pointToSubY + "px";
            else element.style.top = -pointToSubY + "px";
          }
      
      document.removeEventListener("mousemove", move);
      document.removeEventListener("mouseup", stop);
    }
    }
    
    
    document.addEventListener("mousemove", move);
    document.addEventListener("mouseup", stop);
   }) 
}

window.panChangeHandler = function(e){
  var element = document.getElementById('img');
  img.style.transform = `scale(1.${e.target.value})`;
}
document.getElementById("img").disabled = true;
.item {
     margin-right: 1px;
    height: 200px;
    background: white;
    overflow: hidden;
  position: relative;
}

.item img {
transform: scale(1);
position: relative;
    background-color: #eee;
  width: 100%;
  height: 100%;
  -webkit-user-drag: none;
  left:0;
  top:0;
}

.slider {

  z-index: 9;
  position: absolute;
  left: 0;
  top: 0;
  margin-left: -20px;
  margin-top: 70px;
  writing-mode: bt-lr; /* IE */
  -webkit-appearance: slider-vertical; /* WebKit */
  transform: rotateZ(270deg);
}

.slider input {
  width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class='item'>
  <span class='slider'>
    <input type='range' aria-orientation="vertical"
      value="0"  min="0" max="9"  step="1"                       oninput="panChangeHandler(event)"
    />
  </span>
  <img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image' 
       onmouseover="repositionImage(event)" />
</div>

Upvotes: 0

kaize
kaize

Reputation: 811

There is a simple css fix you can try but I'm not sure about it's crossbrowser compatibility. Change the .item img position to sticky.

window.repositionImage = function(event){
var element = document.getElementById('img');
  
  element.addEventListener('mousedown', function(e){
    
    e.stopPropagation();
    element.style.cursor = "grabbing";
    if (e.target != element) return;
    
    var offsetX = e.pageX - element.offsetLeft;
    var offsetY = e.pageY - element.offsetTop;
  
    var move = function(e){
     element.style.left = e.pageX - offsetX + "px";
     element.style.top = e.pageY - offsetY + "px";
    }
    
    var stop = function(){
      element.style.cursor = "default";
      document.removeEventListener("mousemove", move);
      document.removeEventListener("mouseup", stop);
    }
    
    
    document.addEventListener("mousemove", move);
    document.addEventListener("mouseup", stop);
   }) 
}

window.panChangeHandler = function(e){
  var element = document.getElementById('img');
  img.style.transform = `scale(1.${e.target.value})`;
}
document.getElementById("img").disabled = true;
.item {
  border: 1px solid;
  background: red;
  width: 300px;
  height: 300px;
  overflow: hidden;
  position:relative;
}

.item img {
  position: sticky;
  width: 100%;
  height: 100%;
  -webkit-user-drag: none;
  left:0;
  top:0;
}

.slider {

  z-index: 9;
  position: absolute;
  left: 0;
  top: 0;
  margin-left: -20px;
  margin-top: 70px;
  writing-mode: bt-lr; /* IE */
  -webkit-appearance: slider-vertical; /* WebKit */
  transform: rotateZ(270deg);
}

.slider input {
  width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class='item'>
  <span class='slider'>
    <input type='range' aria-orientation="vertical"
      value="0"  min="0" max="9"  step="1"                       oninput="panChangeHandler(event)"
    />
  </span>
  <img id='img' src="https://images.unsplash.com/photo-1494548162494-384bba4ab999?ixlib=rb-1.2.1&w=1000&q=80" alt='image' onmouseover="repositionImage(event)" />
</div>

Upvotes: 1

rajratna maitry
rajratna maitry

Reputation: 508

Check

if (e.target.tagName == "DIV" ) return;

On drop event

Upvotes: 0

Related Questions