2016-10-14 55 views
4

我可以找到類似的問題,涉及jQuery UI lib,或者只有css沒有拖動的句柄,但沒有純數學的東西。旋轉時使用拖動手柄調整div的大小

我試圖執行的是有一個可調整大小和可旋轉的div。到目前爲止這麼簡單,我可以做到。

但是,旋轉時,它會變得更加複雜,調整大小的手柄會以相反的方式進行計算:當從形狀拖離時,它會減小大小而不是增加。

除了計算,我希望能夠根據旋轉來改變調整大小手柄的光標,以便始終有意義。 爲此,我正在考慮檢測哪個象限是調整大小的句柄,並通過css應用類來更改光標。

  1. 我不想重新發明輪子,但我想要一個輕量級的代碼和簡單的用戶界面。所以我的要求是jQuery,但沒有別的。沒有jQuery UI。
  2. 我可以開發,直到實現這一點,但它現在對我來說太數學了。我很堅持,這就是爲什麼我需要你的幫助來檢測何時輪換足以使計算逆轉。

最終我在尋找UX改進,如果有人有一個想法或更好的例子來告訴我!

這裏是我的代碼和Codepen嘗試:http://codepen.io/anon/pen/rrAWJA

<html> 
<head> 
    <style> 
    html, body {height: 100%;} 

    #square { 
     width: 100px; 
     height: 100px; 
     margin: 20% auto; 
     background: orange; 
     position: relative; 
    } 
    .handle * { 
     position: absolute; 
     width: 20px; 
     height: 20px; 
     background: turquoise; 
     border-radius: 20px; 
    } 
    .resize { 
     bottom: -10px; 
     right: -10px; 
     cursor: nwse-resize; 
    } 
    .rotate { 
     top: -10px; 
     right: -10px; 
     cursor: alias; 
    } 
    </style> 
    <script type="text/javascript" src="js/jquery.js"></script> 
    <script> 
     $(document).ready(function() 
     { 
      new resizeRotate('#square'); 
     }); 

     var resizeRotate = function(targetElement) 
     { 
      var self = this; 
      self.target = $(targetElement); 
      self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>'); 
      self.currentRotation = 0; 
      self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right']; 

      self.bindEvents = function() 
      { 
       self.handles 
        //=============================== Resize ==============================// 
        .on('mousedown', '.resize', function(e) 
        { 
         // Attach mouse move event only when first clicked. 
         $(document).on('mousemove', function(e) 
         { 
          var topLeft = self.target.offset(), 
           bottomRight = {x: topLeft.left + self.target.width(), y: topLeft.top + self.target.height()}, 
           delta = {x: e.pageX - bottomRight.x, y: e.pageY - bottomRight.y}; 

          self.target.css({width: '+=' + delta.x, height: '+=' + delta.y}); 
         }) 
         .one('mouseup', function(e) 
         { 
          // When releasing handle, round up width and height values :) 
          self.target.css({width: parseInt(self.target.width()), height: parseInt(self.target.height())}); 
          $(document).off('mousemove'); 
         }); 
        }) 
        //============================== Rotate ===============================// 
        .on('mousedown', '.rotate', function(e) 
        { 
         // Attach mouse move event only when first clicked. 
         $(document).on('mousemove', function(e) 
         { 
          var topLeft = self.target.offset(), 
           center = {x: topLeft.left + self.target.width()/2, y: topLeft.top + self.target.height()/2}, 
           rad = Math.atan2(e.pageX - center.x, e.pageY - center.y), 
           deg = (rad * (180/Math.PI) * -1) + 135; 

          self.currentRotation = deg; 
          // console.log(rad, deg); 
          self.target.css({transform: 'rotate(' + (deg)+ 'deg)'}); 
         }) 
         .one('mouseup', function(e) 
         { 
          $(document).off('mousemove'); 
          // console.log(self.positions[parseInt(self.currentRotation/90-45)]); 
          $('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation/90-45)]); 
         }); 
        }); 
      }; 
      self.init = function() 
      { 
       self.bindEvents(); 
       self.target.append(self.handles.clone(true)); 
      }(); 
     } 
    </script> 
</head> 
<body> 
    <div id="all"> 
     <div id="square"></div> 
    </div> 
</body> 
</html> 

感謝您的幫助!

+0

將鼠標位置轉換爲矩形的本地座標系(使用其逆向變換),最後得到基本情況,這似乎已經處理得很好。 –

+0

謝謝你的幫助。但是,你如何檢測它何時必須反轉,你必須檢測我們是否處於某個象限內? – antoni

+0

爲什麼你必須檢測?它將永遠是相反的。如果它沒有變換(即變換是單位矩陣),那麼逆將是單位矩陣。 –

回答

2

這裏是你的代碼的修正版,實現你想要什麼:

$(document).ready(function() { 
    new resizeRotate('#square'); 
}); 

var resizeRotate = function(targetElement) { 
    var self = this; 
    self.target = $(targetElement); 
    self.handles = $('<div class="handle"><div class="resize" data-position="bottom-right"></div><div class="rotate"></div></div>'); 
    self.currentRotation = 0; 
    self.w = parseInt(self.target.width()); 
    self.h = parseInt(self.target.height()); 
    self.positions = ['bottom-right', 'bottom-left', 'top-left', 'top-right']; 

    self.bindEvents = function() { 
    self.handles 
     //=============================== Resize ==============================// 
     .on('mousedown', '.resize', function(e) { 
     // Attach mouse move event only when first clicked. 
     $(document).on('mousemove', function(e) { 
      var topLeft = self.target.offset();   

      var centerX = topLeft.left + self.target.width()/2; 
      var centerY = topLeft.top + self.target.height()/2; 

      var mouseRelativeX = e.pageX - centerX; 
      var mouseRelativeY = e.pageY - centerY; 

      //reverse rotation 
      var rad = self.currentRotation * Math.PI/180; 
      var s = Math.sin(rad); 
      var c = Math.cos(rad); 
      var mouseLocalX = c * mouseRelativeX + s * mouseRelativeY; 
      var mouseLocalY = -s * mouseRelativeX + c * mouseRelativeY; 

      self.w = 2 * mouseLocalX; 
      self.h = 2 * mouseLocalY; 
      self.target.css({ 
       width: self.w, 
       height: self.h 
      }); 
      }) 
      .one('mouseup', function(e) { 
       $(document).off('mousemove'); 
      }); 
     }) 
     //============================== Rotate ===============================// 
     .on('mousedown', '.rotate', function(e) { 
     // Attach mouse move event only when first clicked. 
     $(document).on('mousemove', function(e) { 
      var topLeft = self.target.offset(), 
       center = { 
       x: topLeft.left + self.target.width()/2, 
       y: topLeft.top + self.target.height()/2 
       }, 
       rad = Math.atan2(e.pageX - center.x, center.y - e.pageY) - Math.atan(self.w/self.h), 
       deg = rad * 180/Math.PI; 

      self.currentRotation = deg; 
      self.target.css({ 
       transform: 'rotate(' + (deg) + 'deg)' 
      }); 
      }) 
      .one('mouseup', function(e) { 
      $(document).off('mousemove'); 
      $('.handle.resize').attr('data-position', self.positions[parseInt(self.currentRotation/90 - 45)]); 
      }); 
     }); 
    }; 
    self.init = function() { 
    self.bindEvents(); 
    self.target.append(self.handles.clone(true)); 
    }(); 
} 

的主要變化如下:

在調整大小事件,鼠標位置被轉換到局部座標系基於當前的旋轉。大小由鼠標在本地系統中的位置確定。

rotate事件計算框的縱橫比(- Math.atan(self.w/self.h)部分)。

如果您想根據當前旋轉更改光標,請檢查手柄的角度(即self.currentRotation + Math.atan(self.w/self.h) * 180/Math.PI)。例如。如果每象限有一個遊標,只需檢查該值是否在0..90,90..180等之間。您可能需要檢查文檔是否以及何時由atan2返回負數。

注意:偶爾閃爍是由於盒子不是垂直居中引起的。

+0

謝謝你的回覆。這正是我所期待的。除了現在我看到閃爍的結果,如果你玩的太多,並且不是非常友好的用戶友好,我會因爲我的想法而感到有點失望。任何人都可以向我推薦一些UX改進嗎? :) – antoni

+0

閃爍可能可以避免,如果一些照顧。上面的代碼只是爲了說明向本地座標的轉換。你失去了句柄意味着什麼? –

+0

當你旋轉,然後拖走有時手柄丟失,那麼當你試圖將元素拖出瀏覽器。因此,我使用代碼更新了我的codepen,並添加了最小寬度和最小高度,以防止正方形無法使用,如果拖到0爲止。http://codepen.io/anon/pen/BLgVOZ。閃爍仍然存在,我明白你的意思是不是垂直對齊,但我怎麼能這樣做,如果這個工具應該適用於wysiwyg圖像。我無法垂直對齊它們。爲什麼閃爍發生在底部而不是我第一次嘗試? – antoni

相關問題