如何正确显示n调整大小? [英] How can I make my n-resize display correctly?

查看:88
本文介绍了如何正确显示n调整大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是最初从调整右中间,右下中间和右下控制点上的矩形的大小很好,因为我无需更改平移坐标即可调整大小.现在,您所看到的问题是,当旋转角度不同于0时,我在矩形的顶部中间(与左中间,左下...相同)的大小调整不起作用,因为当我旋转时会在视觉上改变位置调整大小.

Resizing the rectangle on the Right middle, bottom middle and right bottom control point is fine as I don't need to change the translate coordinates in order to make the resize work. Now my problem as you can see is that my resizing on the top middle (same for the left middle, left bottom...) of my rectangle when the rotate angle is different from 0 doesn't work as it visually changes position when I resize it.

我真的不知道该如何更改,因此非常感谢您的帮助.

I really don't know how to change that so any help is highly appreciated.

注意:在输入字段中将angle更改为0,您将看到代码正常工作,这是 JSFiddle链接.

note: change angle to 0 in the input field and you'll see the code working properly here's the JSFiddle link.

var input = document.getElementById("rotate_input");
var rotate = document.getElementById("rotate");
var rightMiddle = document.getElementById("rm");
var topMiddle = document.getElementById("tm");
var translate = document.getElementById("trslt");
var scale = document.getElementById("scale");
var svg = document.getElementById("main");

var rotateString = rotate.getAttribute('transform');

var controlrm = false;
var controltm = false;

var origRectWidth = 100;
var origRectHeight = 100;
var updatedRectWidth = origRectWidth;
var updatedRectHeight = origRectHeight;

var xScale = 1;
var yScale = 1;

var translateX = 100;
var translateY = 100;

var relevantMouseMoveDist = 0;

var rotateAnleDeg = 30;
var rectangleAngle = parseInt(rotateString.slice(rotateString.indexOf("(") + 1)) * Math.PI / 180; // retrieve the angle from the DOM

var newMousePosn;
var oldMousePosn;

function resizeRightMiddle()
{
  updatedRectWidth += relevantMouseMoveDistCos;
  xScale = updatedRectWidth/origRectWidth;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
}

function resizeTopMiddle()
{
  updatedRectHeight -= relevantMouseMoveDistSin;
  yScale = updatedRectHeight/origRectHeight;
  //get the new Y position
  translateY = translateY + relevantMouseMoveDistSin;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

svg.addEventListener("mousemove", function(e){

  if (newMousePosn) {
  
    // the former mouse pos'n
    oldMousePosn = {x: newMousePosn.x, y: newMousePosn.y};
    
    // the new mouse pos'n
    newMousePosn = {x: e.clientX, y: e.clientY};
    
    // the change in the mouse pos'n coordinates since the last move event
    var deltaMouseMove = {
      x: newMousePosn.x - oldMousePosn.x,
      y: newMousePosn.y - oldMousePosn.y
    };
    
    // the dir'n of this movement
    var angleOfMouseMovement = Math.atan2(deltaMouseMove.y, deltaMouseMove.x);
    
    // the absolute distance the mouse has moved
    var mouseMoveDist = Math.sqrt(
      deltaMouseMove.x * deltaMouseMove.x +
      deltaMouseMove.y * deltaMouseMove.y
    );
     
    // the difference in direction between the mouse movement and orientation of the rectangle
    var angleDifference = angleOfMouseMovement - rectangleAngle;
    
    // the portion of the mouse movement that is in the direction of the rectangle's orientation
    relevantMouseMoveDistCos = mouseMoveDist * Math.cos(angleDifference);
    relevantMouseMoveDistSin = mouseMoveDist * Math.sin(angleDifference);
    
    // resize the rectangle if necessary
    if (controlrm)
      resizeRightMiddle();
    else if (controltm)
      resizeTopMiddle();
  } else {
  
    // establish the mouse pos'n during the first mousemove event
    newMousePosn = {x: e.clientX, y: e.clientY};
  }
  
});

svg.addEventListener("mouseup"  , function(e){
  controlrm = false;
  controltm = false;});

rightMiddle.addEventListener("mousedown", function(e){controlrm = true ;});

topMiddle.addEventListener("mousedown", function(e){controltm = true ;});

// Code for changing the rectangle in the input
input.addEventListener("change", function (){
  rotateAngleDeg = input.value;
  rotate.setAttribute("transform", "rotate(" + rotateAngleDeg + ")");
  rectangleAngle = rotateAngleDeg * Math.PI / 180;
})

svg {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

<svg id="main" width="1000" height="250">
 <g id= "trslt" transform="translate(100, 100)">
  <g id="rotate" transform-origin="center" transform="rotate(30)">
   <g id="scale">
    <path fill="red" stroke="red" d="M 0 0 L 0 100 L 100 100 L 100 0Z" />
    <rect id="rm" fill="black" stroke="black" x=95 y=45 width=10 height=10 />
    <rect id="tm" fill="white" stroke="black" x=45 y=-5 width=10 height=10 />
   </g>
  </g>
 </g>
</svg>
<input id="rotate_input" type="text" placeholder="Change Angle"/>

推荐答案

有很多内容,而且很难解释这些步骤,但实际上是:

There's quite a bit to it and rather difficult to explain the steps, but essentially:

  • svg中将Translate移动到Rotate之后.这样一来,无需考虑旋转会影响方向的情况,即可更轻松地调整对象的大小.
  • 我使用了3个值来应用旋转transform="rotate(0 0 0)".后两个给出旋转的中心.
  • 将框的尺寸更改为以0为中心.并非绝对必要,但我更喜欢以这种方式考虑数学.
  • Moved Translate to after Rotate within the svg. That made it easier to resize the object without needing to take into account the direction that would be affected by the rotation.
  • I used 3 values to apply the rotation transform="rotate(0 0 0)". The second two give the rotation's centre.
  • Changed the box dimensions to be centred at 0. Not strictly necessary but I preferred thinking about the maths that way.

我已经实现了侧面和一个角,我将按照模式进行操作-对于左上角,它只是从 Top 中抓取代码以及 Left 中的代码,并将它们组合起来,就像我已经在 Top Right

I've implemented the sides and one corner, I'll leave it with you to follow the pattern - for the Top Left it's just grabbing code from the Top and the code from the Left and combining them like I've done already within Top Right

我看到旋转并不总是围绕盒子的当前中心点发生的,所以我认为您希望进行校正.

I see the rotation doesn't always happen around the box's current centre point, so that's something that I presume you'll want to look at correcting.

外部演示(与下面的堆栈摘录相同): https://jsfiddle.net/bcjopdqn/2/

External demo (same as Stack Snippet below): https://jsfiddle.net/bcjopdqn/2/

var input = document.getElementById("rotate_input");
var rotate = document.getElementById("rotate");
var rightMiddle = document.getElementById("rm");
var leftMiddle = document.getElementById("lm");
var topMiddle = document.getElementById("tm");
var bottomMiddle = document.getElementById("bm");
var topRight = document.getElementById("tr");

var translate = document.getElementById("trslt");
var scale = document.getElementById("scale");

var rotateString = rotate.getAttribute('transform');

var controlrm = false;
var controllm = false;
var controltm = false;
var controlbm = false;
var controltr = false;

var origRectWidth = 100;
var origRectHeight = 100;
var updatedRectWidth = origRectWidth;
var updatedRectHeight = origRectHeight;

var xScale = 1;
var yScale = 1;

var translateX = 100;
var translateY = 100;

var relevantMouseMoveDist = 0;
var relevantMouseMoveDistXCos, relevantMouseMoveDistXSin;
var relevantMouseMoveDistYCos, relevantMouseMoveDistYSin;

var rotateAngleDeg = 0;
var rectangleAngle = parseInt(rotateString.slice(rotateString.indexOf("(") + 1)) * Math.PI / 180; // retrieve the angle from the DOM

var newMousePosn;
var oldMousePosn;

function resizeLeftMiddle() {
  updatedRectWidth -= relevantMouseMoveDistXCos + relevantMouseMoveDistXSin;
  translateX += relevantMouseMoveDistXCos / 2 + relevantMouseMoveDistXSin / 2;
  xScale = updatedRectWidth / origRectWidth;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

function resizeRightMiddle() {
  updatedRectWidth += relevantMouseMoveDistXCos + relevantMouseMoveDistXSin;
  translateX += relevantMouseMoveDistXCos / 2 + relevantMouseMoveDistXSin / 2;
  xScale = updatedRectWidth / origRectWidth;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

function resizeTopMiddle() {
  updatedRectHeight -= relevantMouseMoveDistYCos + relevantMouseMoveDistYSin;
  translateY += relevantMouseMoveDistYCos / 2 + relevantMouseMoveDistYSin / 2;
  yScale = updatedRectHeight / origRectHeight;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

function resizeBottomMiddle() {
  updatedRectHeight += relevantMouseMoveDistYCos + relevantMouseMoveDistYSin;
  translateY += relevantMouseMoveDistYCos / 2 + relevantMouseMoveDistYSin / 2;
  yScale = updatedRectHeight / origRectHeight;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

function resizeTopRight() {
  updatedRectWidth += relevantMouseMoveDistXCos + relevantMouseMoveDistXSin;
  updatedRectHeight -= relevantMouseMoveDistYCos + relevantMouseMoveDistYSin;
  translateX += relevantMouseMoveDistXCos / 2 + relevantMouseMoveDistXSin / 2;
  translateY += relevantMouseMoveDistYCos / 2 + relevantMouseMoveDistYSin / 2;
  xScale = updatedRectWidth / origRectWidth;
  yScale = updatedRectHeight / origRectHeight;
  scale.setAttribute('transform', 'scale(' + xScale + ',' + yScale + ')');
  translate.setAttribute('transform', 'translate(' + translateX + ',' + translateY + ')');
}

var svg = document.getElementById("main");

svg.addEventListener("mousemove", function(e) {

  if (newMousePosn) {

    // the former mouse pos'n
    oldMousePosn = {
      x: newMousePosn.x,
      y: newMousePosn.y
    };

    // the new mouse pos'n
    newMousePosn = {
      x: e.clientX,
      y: e.clientY
    };

    // the change in the mouse pos'n coordinates since the last move event
    var deltaMouseMove = {
      x: newMousePosn.x - oldMousePosn.x,
      y: newMousePosn.y - oldMousePosn.y
    };

    // the dir'n of this movement
    //var angleOfMouseMovement = Math.atan2(deltaMouseMove.y, deltaMouseMove.x);

    // the absolute distance the mouse has moved
    var mouseMoveDist = Math.sqrt(
      deltaMouseMove.x * deltaMouseMove.x +
      deltaMouseMove.y * deltaMouseMove.y
    );

    // the difference in direction between the mouse movement and orientation of the rectangle
    //var angleDifference = angleOfMouseMovement - rectangleAngle;

    // the portion of the mouse movement that is in the direction of the rectangle's +X and +Y orientation
    relevantMouseMoveDistXCos = deltaMouseMove.x * Math.cos(rectangleAngle);
    relevantMouseMoveDistXSin = deltaMouseMove.y * Math.sin(rectangleAngle);

    relevantMouseMoveDistYCos = deltaMouseMove.x * Math.cos(rectangleAngle + Math.PI / 2);
    relevantMouseMoveDistYSin = deltaMouseMove.y * Math.sin(rectangleAngle + Math.PI / 2);

    // resize the rectangle if necessary
    if (controlrm)
      resizeRightMiddle();
    else if (controllm)
      resizeLeftMiddle();
    else if (controltm)
      resizeTopMiddle();
    else if (controlbm)
      resizeBottomMiddle();
    else if (controltr)
      resizeTopRight();
  } else {

    // establish the mouse pos'n during the first mousemove event
    newMousePosn = {
      x: e.clientX,
      y: e.clientY
    };
  }

});

svg.addEventListener("mouseup", function(e) {
  controlrm = false;
  controllm = false;
  controltm = false;
  controlbm = false;
  controltr = false;
});

rightMiddle.addEventListener("mousedown", function(e) {
  controlrm = true;
});
leftMiddle.addEventListener("mousedown", function(e) {
  controllm = true;
});
topMiddle.addEventListener("mousedown", function(e) {
  controltm = true;
});
bottomMiddle.addEventListener("mousedown", function(e) {
  controlbm = true;
});
topRight.addEventListener("mousedown", function(e) {
  controltr = true;
});

// Code for changing the rectangle in the input
input.addEventListener("change", function() {

  rotateAngleDeg = input.value;

  var translation = (translateX + " " + translateY);
  var rotation = "rotate(" + rotateAngleDeg + " " + translation + ")";

  rotate.setAttribute("transform", rotation);
  //console.log(rotation);

  rectangleAngle = rotateAngleDeg * Math.PI / 180;
})

svg {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

<div>
  <svg id="main" width="1000" height="250">
    <g id="rotate" transform-origin="0 0" transform="rotate(0 0 0)">
      <g id="trslt" transform="translate(100, 100)">
        <g id="scale">
          <path fill="red" stroke="red" d="M -50 -50 L -50 50 L 50 50 L 50 -50Z" />
          <rect id="rm" fill="black" stroke="black" x=45 y=-5 width=10 height=10 />
          <rect id="lm" fill="yellow" stroke="black" x=-55 y=-5 width=10 height=10 />
          <rect id="tm" fill="white" stroke="black" x=-5 y=-55 width=10 height=10 />
          <rect id="bm" fill="orange" stroke="black" x=-5 y=45 width=10 height=10 />
          <rect id="tr" fill="blue" stroke="black" x=45 y=-55 width=10 height=10 />
        </g>
      </g>
    </g>
  </svg>
</div>
<input id="rotate_input" type="text" placeholder="Change Angle" />

这篇关于如何正确显示n调整大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆