svg旋转矩阵逆矩阵 [英] svg rotation matrix inverse matrix

查看:96
本文介绍了svg旋转矩阵逆矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是日本的初学者Web开发人员.

I am a Japanese beginner web developer.

对不起,我英文不好.

我制作了一个示例代码,您可以移动或调整矩形大小.

I made a sample code that you can move or resize rect.

我正在使用vue.js和svg.

I am using vue.js and svg.

<template>

  <div class="rotate-area">

    <div class="rotate">

      <svg width="608" height="408" viewBox="0 0 608 408" xmlns="http://www.w3.org/2000/svg" class="svg" ref="svg" @mousemove="mouseMove" @mouseup="mouseUp">

        <g stroke-width="1" fill="#ffffff" fill-rule="evenodd" fill-opacity="0" stroke="#000000" class="layer" :transform="rotate">

          <g fill-opacity="1">

            <rect stroke-width="2" fill-opacity="0" :x="masterX" :y="masterY" :width="width" :height="height" @mousedown.self="select($event , 'master')"></rect>

            <rect fill="#ffffff" :x="leftTopX" :y="leftTopY" width="7" height="7" @mousedown.self="select($event , 'leftTop')"></rect>
            <rect fill="#ffffff" :x="rightTopX" :y="rightTopY" width="7" height="7" @mousedown.self="select($event , 'rightTop')"></rect>
            <rect fill="#ffffff" :x="rightBottomX" :y="rightBottomY" width="7" height="7" @mousedown.self="select($event , 'rightBottom')"></rect>
            <rect fill="#ffffff" :x="leftBottomX" :y="leftBottomY" width="7" height="7" @mousedown.self="select($event , 'leftBottom')"></rect>

          </g>

        </g>

      </svg>

    </div>

    <input type="number" v-model="angle">

  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";

@Component({
  components: {}
})
export default class Rotate extends Vue {

  width = 150
  widthBefore = 150
  height = 150
  heightBefore = 150

  masterX = 24
  masterXBefore = 24
  masterY = 25
  masterYBefore = 25

  leftTopX = 20.5
  leftTopXBefore = 20.5
  leftTopY = 20.5
  leftTopYBefore = 20.5

  rightTopX = 170.5
  rightTopXBefore = 170.5
  rightTopY = 20.5
  rightTopYBefore = 20.5

  rightBottomX = 170.5
  rightBottomXBefore = 170.5
  rightBottomY = 172.5
  rightBottomYBefore = 172.5

  leftBottomX = 20.5
  leftBottomXBefore = 20.5
  leftBottomY = 172.5
  leftBottomYBefore = 172.5

  angle = 0

  mouseDownState = false
  mouseDownType = ""
  pointStart = {
    x: 0,
    y : 0
  }

  get middleVector() {
    return { 
      x : (this.leftTopX + this.rightTopX) / 2 ,
      y : (this.leftTopY + this.leftBottomY) / 2
    }
  }

  get rotate() {
    return "rotate(" + this.angle + "," + this.middleVector.x + "," + this.middleVector.y + ")";
  }

  public select(event : MouseEvent , mouseDownType){
    this.mouseDownState = true
    this.mouseDownType = mouseDownType
    this.pointStart.x = event.clientX
    this.pointStart.y = event.clientY
  }

  public mouseMove(event : MouseEvent){
    if(this.mouseDownState){

      let moveDistance = {
        x : event.clientX - this.pointStart.x,
        y : event.clientY - this.pointStart.y
      }

      if(this.mouseDownType=="master"){

        this.masterX = this.masterXBefore + moveDistance.x
        this.masterY = this.masterYBefore +  moveDistance.y
        this.leftTopX = this.leftTopXBefore + moveDistance.x
        this.leftTopY = this.leftTopYBefore + moveDistance.y
        this.rightTopX = this.rightTopXBefore + moveDistance.x
        this.rightTopY = this.rightTopYBefore + moveDistance.y
        this.rightBottomX = this.rightBottomXBefore + moveDistance.x
        this.rightBottomY = this.rightBottomYBefore + moveDistance.y
        this.leftBottomX = this.leftBottomXBefore + moveDistance.x
        this.leftBottomY = this.leftBottomYBefore + moveDistance.y

      }else if (this.mouseDownType == "leftTop") {

        this.masterX = this.masterXBefore + moveDistance.x
        this.masterY = this.masterYBefore +  moveDistance.y
        this.leftTopX = this.leftTopXBefore + moveDistance.x
        this.leftTopY = this.leftTopYBefore + moveDistance.y
        this.rightTopY = this.rightTopYBefore + moveDistance.y
        this.leftBottomX = this.leftBottomXBefore + moveDistance.x

        this.width = this.widthBefore - moveDistance.x
        this.height = this.heightBefore - moveDistance.y

      } else if (this.mouseDownType == "rightTop") {

        this.masterY = this.masterYBefore +  moveDistance.y
        this.leftTopY = this.leftTopYBefore + moveDistance.y
        this.rightTopX = this.rightTopXBefore + moveDistance.x
        this.rightTopY = this.rightTopYBefore + moveDistance.y
        this.rightBottomX = this.rightBottomXBefore + moveDistance.x

        this.width = this.widthBefore + moveDistance.x
        this.height = this.heightBefore - moveDistance.y

      } else if (this.mouseDownType == "rightBottom") {

        this.rightTopX = this.rightTopXBefore + moveDistance.x
        this.rightBottomX = this.rightBottomXBefore + moveDistance.x
        this.rightBottomY = this.rightBottomYBefore + moveDistance.y
        this.leftBottomY = this.leftBottomYBefore + moveDistance.y
        this.width = this.widthBefore + moveDistance.x
        this.height = this.heightBefore + moveDistance.y

      } else if (this.mouseDownType == "leftBottom") {

        this.masterX = this.masterXBefore + moveDistance.x
        this.leftTopX = this.leftTopXBefore + moveDistance.x
        this.rightBottomY = this.rightBottomYBefore + moveDistance.y
        this.leftBottomX = this.leftBottomXBefore + moveDistance.x
        this.leftBottomY = this.leftBottomYBefore + moveDistance.y
        this.width = this.widthBefore - moveDistance.x
        this.height = this.heightBefore + moveDistance.y

      }
    }
  }

  mouseUp(){

    this.mouseDownState = false

    if(this.mouseDownType=="master"){
        this.masterXBefore = this.masterX
        this.masterYBefore = this.masterY
        this.leftTopXBefore = this.leftTopX
        this.leftTopYBefore = this.leftTopY
        this.rightTopXBefore = this.rightTopX
        this.rightTopYBefore = this.rightTopY
        this.rightBottomXBefore = this.rightBottomX
        this.rightBottomYBefore = this.rightBottomY
        this.leftBottomXBefore = this.leftBottomX
        this.leftBottomYBefore = this.leftBottomY
    }else if (this.mouseDownType == "leftTop") {

        this.masterXBefore = this.masterX
        this.masterYBefore = this.masterY
        this.leftTopXBefore = this.leftTopX
        this.leftTopYBefore = this.leftTopY
        this.rightTopYBefore = this.rightTopY
        this.leftBottomXBefore = this.leftBottomX

        this.widthBefore = this.width
        this.heightBefore = this.height

      }else if (this.mouseDownType == "rightTop") {

            this.masterYBefore = this.masterY
            this.leftTopYBefore = this.leftTopY
            this.rightTopXBefore = this.rightTopX
            this.rightTopYBefore = this.rightTopY
            this.rightBottomXBefore = this.rightBottomX

            this.widthBefore = this.width
            this.heightBefore = this.height

      }else if (this.mouseDownType == "rightBottom") {

        this.rightTopXBefore = this.rightTopX
        this.rightBottomXBefore = this.rightBottomX
        this.rightBottomYBefore = this.rightBottomY
        this.leftBottomYBefore = this.leftBottomY
        this.widthBefore = this.width
        this.heightBefore = this.height

      }else if(this.mouseDownType == "leftBottom"){
        this.masterXBefore = this.masterX
        this.leftTopXBefore = this.leftTopX
        this.rightBottomYBefore = this.rightBottomY
        this.leftBottomXBefore = this.leftBottomX
        this.leftBottomYBefore = this.leftBottomY
        this.widthBefore = this.width
        this.heightBefore = this.height
      }
  }

}
</script>

<style lang="scss">
</style>

很抱歉,此代码不时尚,很难阅读.

Sorry that this code is not stylish and it's hard to read.

我在这里有问题.

旋转后调整大小时,抓取的边缘和光标移动不匹配.

When you resize after you rotate it, the edge you grab and the cursor move doesn't match.

当角度为0时,它可以正常工作.

When the angle is 0 , it works properly.

我想使边缘始终跟随光标.

I want to make the edge always follows the cursor.

我以为我必须对旋转矩阵求逆.

I thought I have to inverse rotation matrix.

public mouseMove(event : MouseEvent){
    if(this.mouseDownState){

      let moveDistance = {
        x : event.clientX - this.pointStart.x,
        y : event.clientY - this.pointStart.y
      }

      moveDistance.x = Math.cos(this.angle) * (moveDistance.x - this.middleVector.x) + Math.sin(this.angle) * (moveDistance.y - this.middleVector.y) + this.middleVector.x 

      moveDistance.y = ***

我应该做这样的事情吗?

Should I do something like this?

尽管我不擅长数学.

请有人帮我!!!(> ___<)

Someone help me please!!!(>___<)

推荐答案

当用户单击一个角并移动鼠标时,程序会旋转/调整矩形大小是否正确? 逻辑应该类似于以下内容:

Is it correct that your program rotates/resizes a rectangle when the user clicks on one of the corners and moves their mouse? The logic should be something like the following:

var centerX = ______; //whatever the center of the rect is
var centerY = ______; //whatever the center of the rect is

var rectangleWidth = ________; //initial width of rectangle;
var rectangleHeight = ________; //initial height of rectangle;

var scale = 1; //scale of shown image to original

var rectangleRotation = 0; //initally no rotation

var clickX;
var clickY;
var rotationOfRectangleWhenClicked //rotation of the rectangle at the time it is clicked
var clickScale; //scale of rectangle when clicked
var clickRotation; //angle of mouse to the rectangle's center
var clickDistance; //distance of mouse to center of rectangle

function mouseDown(mouseEvent) {
  //sets variables when a corner gets clicked
  clickX = mouseEvent.clientX;
  clickY = mouseEvent.clientY;
  rotationOfRectangleWhenClicked = rectangleRotzation;
  clickRotation = Math.atan(clickY / clickX);
  clickDistance = Math.sqrt((clickX - centerX) ** 2 + (clickY - centerY) ** 2)
  clickScale = scale;
}

function moveMouse(mouseEvent) {
  //run when you move the mouse after clicking on a corner
  //does the logic of resizing and rotation
  //resize
  var ratioToResize = Math.sqrt(((mouseEvent.clientX - centerX) ** 2 + (mouseEvent.clientY - centerY) ** 2)) / clickDistance
  scale = ratioToResize * clickScale;

  //rotation
  var angle = Math.atan((mouseEvent.clientY - centerY) / (mouseEvent.clientX - centerX))
  rectangleRotation = rotationOfRectangleWhenClicked + angle - clickRotation;
}

function mouseUp(mouseEvent) {
  
}

以下是制作移动矩形的程序:

Here is a program to make a moving rectangle:

<!DOCTYPE html>
    <html>
    <head>
    <script src="math.js" type="text/javascript"></script>
    </head>
    <body>
    It's a moving rectangle!
    <div id = "rectangle" style = "background-color:#ff0000; position:absolute; width: 100px; height: 100px; top:100px; left: 100px">
    </div>
    <script type="text/javascript">
        mousePressed=false;
        centerX = 400;  //whatever the center of the rect is
        centerY = 300;  //whatever the center of the rect is


    rectangleWidth = 400;  //initial width of rectangle;
    rectangleHeight = 300;  //initial height of rectangle;

    rectangleRotation = 0;  //initally no rotation
    rectangle = document.getElementById("rectangle");
    rectangle.style.top = (centerY-rectangleHeight/2)+'px';
    rectangle.style.left = (centerX-rectangleWidth/2)+'px';
    rectangle.style.width = rectangleWidth+'px';
    rectangle.style.height = rectangleHeight+'px';
    rectangle.style.transform = 'rotate('+rectangleRotation*180/Math.PI+'deg)';
    rectangle.onmousedown = mouseDown;
    document.onmouseup = mouseUp;
    document.onmousemove = moveMouse;

    clickX;
    clickY;
    rotationOfRectangleWhenClicked; //rotation of the rectangle at the time it is clicked
    clickWidth;  //width of rectangle when clicked
    clickHeight;  //height of rectangle when clicked
    clickRotation;  //angle of mouse to the rectangle's center
    clickDistance;  //distance of mouse to center of rectangle

    function mouseDown(mouseEvent) {
        //sets variables when a corner gets clicked
        mousePressed=true;
        rectangle.style.backgroundColor = '#0000ff';
        clickX=mouseEvent.clientX;
        clickY=mouseEvent.clientY;
        rotationOfRectangleWhenClicked = rectangleRotation;
        clickRotation = Math.atan2((mouseEvent.clientY-centerY),(mouseEvent.clientX-centerX))
        clickDistance = Math.sqrt((clickX-centerX)**2 + (clickY-centerY)**2);
        clickWidth = rectangleWidth;
        clickHeight = rectangleHeight;
    }
    function moveMouse(mouseEvent) {
        if(!mousePressed) {
        return 0;}
        //run when you move the mouse after clicking on a corner
        //does the logic of resizing and rotation
        rectangle.style.backgroundColor="#00ff00";
        //resize
        var ratioToResize = Math.sqrt(((mouseEvent.clientX-centerX)**2 + (mouseEvent.clientY-centerY)**2))/clickDistance
        rectangleWidth = ratioToResize*clickWidth;
        rectangleHeight = ratioToResize*clickHeight;

        //rotation
        var angle = Math.atan2((mouseEvent.clientY-centerY),(mouseEvent.clientX-centerX))
        rectangleRotation = rotationOfRectangleWhenClicked + angle - clickRotation;

        rectangle.style.top = (centerY-rectangleHeight/2)+'px';
        rectangle.style.left = (centerX-rectangleWidth/2)+'px';
        rectangle.style.width = rectangleWidth+'px';
        rectangle.style.height = rectangleHeight+'px';
        rectangle.style.transform = 'rotate('+rectangleRotation*180/Math.PI+'deg)';
    }

    function mouseUp(mouseEvent) {
        mousePressed=false;
        rectangle.style.backgroundColor = '#ff0000';
    }
</script>
</body>
</html>

这篇关于svg旋转矩阵逆矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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