旋转时使用拖动手柄调整div的大小

我可以找到类似的问题涉及jQuery UI lib,或者只有css没有拖动句柄,但没有纯数学。

我尝试执行的是拥有可resize且可旋转的div。 到目前为止这么容易,我可以做到。

但是旋转时会变得更加复杂,resize手柄会以相反的方式进行计算:当拖离形状时,它会减小尺寸而不是增加。

除了计算,我希望能够根据旋转更改resize手柄的光标,以便始终有意义。 为此,我正在考虑检测哪个象限是resize句柄并应用类来通过css更改游标。

  1. 我不想重新发明轮子,但我想拥有一个轻量级代码和简单的UI。 所以我的要求是jQuery,但没有别的。 没有jQuery UI。
  2. 我可以发展直到达到这个目标,但现在它对我来说太过数学了……我很困惑这就是为什么我需要你的帮助来检测旋转何时足以使计算反转。

最终我正在寻找用户体验改进,如果有人有想法或更好的例子给我看!

这是我的代码和Codepen尝试: http ://codepen.io/anon/pen/rrAWJA

   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; }    $(document).ready(function() { new resizeRotate('#square'); }); var resizeRotate = function(targetElement) { var self = this; self.target = $(targetElement); self.handles = $('
'); 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)); }(); }

谢谢您的帮助!

以下是对代码的修改,可以实现您的目标:

 $(document).ready(function() { new resizeRotate('#square'); }); var resizeRotate = function(targetElement) { var self = this; self.target = $(targetElement); self.handles = $('
'); 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)); }(); }

主要变化如下:

在resize事件中,基于当前旋转将鼠标位置变换为局部坐标系。 然后通过鼠标在本地系统中的位置确定大小。

rotate事件考虑了框的宽高比( - Math.atan(self.w / self.h)部分)。

如果要根据当前旋转更改光标,请检查手柄的角度(即self.currentRotation + Math.atan(self.w / self.h) * 180 / Math.PI )。 例如,如果每个象限有一个光标,只需检查该值是否介于0..90,90..180之间,依此类推。 如果atan2返回负数,您可能需要检查文档。

注意:偶尔的闪烁是由于盒子没有垂直居中造成的。

Nico的答案大多是正确的,但最终结果计算不正确 – >这导致了闪烁的BTW。 发生的事情是2x乘法增加或减少了尺寸。 应将原始半宽添加到新的半宽以计算正确的新宽度和高度。

而不是这个:

 self.w = 2 * mouseLocalX; self.h = 2 * mouseLocalY; 

它应该是这样的:

 self.w = (self.target.width() / 2) + mouseLocalX; self.h = (self.target.height() / 2) + mouseLocalY;