jQuery计算旋转矩形的bouding箱



我已经看过有关此的其他一些帖子,但仍然无法弄清楚该公式为什么不起作用。

计算旋转矩形的边界框:

w' = sin(a)*h + cos(a)*w;
h' = sin(a)*w + cos(a)*h;

问题在于,我得到了w'h'根本不精确的怪异行为。

// calculate rotation angle of shape
function getRotationDegrees(obj) {
  var matrix = obj.css("-webkit-transform") ||
    obj.css("-moz-transform") ||
    obj.css("-ms-transform") ||
    obj.css("-o-transform") ||
    obj.css("transform");
  if (matrix !== 'none') {
    var values = matrix.split('(')[1].split(')')[0].split(',');
    var a = values[0];
    var b = values[1];
    var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
  } else {
    var angle = 0;
  }
  if (angle < 0) angle += 360;
  return angle;
}
var shape = $('.shape'),
  shapeLeft = shape.position().left,
  shapeTop = shape.position().top,
  shapeWidth = shape.width(),
  shapeHeight = shape.height(),
  angle = getRotationDegrees(shape),
  // formula below
  height = Math.abs(shapeWidth * Math.sin(angle)) + Math.abs(shapeHeight * Math.cos(angle)),
  width = Math.abs(shapeHeight * Math.sin(angle)) + Math.abs(shapeWidth * Math.cos(angle));
$('#g1').css('width', width);
$('#g2').css('height', height);
.elements,
.element {
  position: absolute
}
#s2 {
  background: #333333;
  top: 60px;
  left: -25px;
  width: 300px;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="layout" style="position:relative; margin-top:50px; margin-left:70px;">
  <div class="elements">
    <div id="g1" class="element" style="background:red;left:-35px;top:-10px;height:2px;"></div>
    <div id="g2" class="element" style="background:red;left:-35px;top:-10px;width:2px;"></div>
    
    <div id="s2" class="element shape" style="transform: rotate(8deg);"></div>
  </div>
</div>

我在做什么错?

两个错误来源:

  1. (次要)角度的圆形。(不知道您的意思是"已经是一个综合号码")

  2. (主要)您直接在Math.cos / sin中使用getRotationDegrees的结果。这些函数需要 readians ,即Math.atan2直接返回的结果。


下面的片段添加了边界框的其他两个边缘,以及正确的位置偏移。我添加了一个滑块以更改旋转角度,以说明此代码坚固。

function getMatrix(obj) {
   var matrix = obj.css("-webkit-transform") ||
                obj.css("-moz-transform") ||
                obj.css("-ms-transform") ||
                obj.css("-o-transform") ||
                obj.css("transform");
   return (matrix == 'none') ? null : matrix.split('(')[1].split(')')[0].split(',');
}
// calculate rotation angle of shape
function getRotationRadians(matrix) {
   var angle = matrix ? Math.atan2(matrix[1], matrix[0]) : 0;
   if (angle < 0) angle += 2.0 * Math.PI;
   return angle;
}
// calculate translation
function getTranslation(matrix) {
   return matrix ? [matrix[4], matrix[5]] : [0, 0];
}
// calculate bounding box
function getBoundingBox(shape) {
   var shapeLeft = shape.position().left,
       shapeTop = shape.position().top,
       shapeWidth = shape.width(),
       shapeHeight = shape.height();
       
   var matrix = getMatrix(shape);
   
   var angle = getRotationRadians(matrix);
   var height = Math.abs(shapeWidth * Math.sin(angle)) + Math.abs(shapeHeight * Math.cos(angle));
   var width = Math.abs(shapeHeight * Math.sin(angle)) + Math.abs(shapeWidth * Math.cos(angle));
   var trans = getTranslation(matrix);
   var left = trans[0] - (width * 0.5);
   var top = trans[1] - (height * 0.5);
   
   return {'x': left, 'y': top, 'w': width, 'h': height};
}
formatBox($('.shape'));
function formatBox(shape) {
   var box = getBoundingBox(shape);
     
   var offx = 124, offy = 109;
   var g1 = $('#g1'), g2 = $('#g2'), g3 = $('#g3'), g4 = $('#g4');
   g1.css('width', box.w);
   g2.css('height', box.h);
   g3.css('width', box.w);
   g4.css('height', box.h);
   g1.css('left', offx + box.x);
   g2.css('left', offx + box.x);
   g3.css('left', offx + box.x);
   g4.css('left', offx + box.x + box.w);
   g1.css('top', offy + box.y);
   g2.css('top', offy + box.y);
   g3.css('top', offy + box.y + box.h);
   g4.css('top', offy + box.y);
}
    
var angleInp = document.getElementById("angleInp");
angleInp.addEventListener("change", function() {
   var shape = $('.shape');
   shape.css('transform', 'rotate(' + angleInp.value + 'deg)');
   formatBox(shape);
}, false);
.elements,
.element {
  position: absolute
}
#s2 {
  background: #333333;
  top: 60px;
  left: -25px;
  width: 300px;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="slider">
   <input class="bar" type="range" id="angleInp" min="0" max="360" value="15" onchange="angleInp.value=value"/>
</div>
<div class="layout" style="position:relative; margin-top:50px; margin-left:70px;">
  <div class="elements">
    <div id="g1" class="element" style="background:red;left:0px;top:0px;height:2px;"></div>
    <div id="g2" class="element" style="background:red;left:0px;top:0px;width:2px;"></div>
    <div id="g3" class="element" style="background:red;left:0px;top:0px;height:2px;"></div>
    <div id="g4" class="element" style="background:red;left:0px;top:0px;width:2px;"></div>
    
    <div id="s2" class="element shape" style="transform: rotate(15deg);"></div>
  </div>
</div>

最新更新