SVG матрица вращения обратная матрица

Я начинающий веб-разработчик из Японии.

Я плохо говорю по-английски, извините.

Я сделал образец кода, который вы можете перемещать или изменять размер прямоугольника.

Я использую vue.js и 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>

Извините, что этот код не стильный и его трудно читать.

У меня здесь проблема.

Когда вы изменяете размер после поворота, захватываемая кромка и перемещение курсора не совпадают.

Когда угол равен 0, он работает правильно.

Я хочу, чтобы кромка всегда следовала за курсором.

Я думал, что мне нужно инвертировать матрицу вращения.

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 = ***

Должен ли я сделать что-то подобное?

Хотя я плохо разбираюсь в математике.

Кто-нибудь, помогите мне, пожалуйста !!! (> ___ <)

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
159
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Верно ли, что ваша программа вращает / изменяет размер прямоугольника, когда пользователь нажимает на один из углов и перемещает мышь? Логика должна быть примерно такой:

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) {
  
}

Вот программа для создания движущегося прямоугольника:

<!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>

Доброе утро!!! Мне очень жаль, что мой ответ запоздал. Я спал. Я проверю ответ после того, как приеду свою работу. Спасибо, гадость!

Kuru 04.09.2018 03:00

Спасибо. В моем коде ротация происходит только тогда, когда вы вводите число в тег ввода внизу.

Kuru 04.09.2018 03:07

Это отличный код, спасибо вам большое. Но я хочу переместить весь прямоугольник, который является «основным» шаблоном в моем коде. И я хочу, чтобы диагональ края не двигалась при изменении размера. Например, когда вы изменили его размер, потянув leftTop, положение rightBottom не должно измениться.

Kuru 04.09.2018 04:25

Но очень хорошая идея. Большое спасибо. Я могу перевести свой код.

Kuru 04.09.2018 04:54

Спасибо за отличный ответ, но у меня другая проблема, если можете, проверьте мой новый вопрос. stackoverflow.com/questions/52176195/…

Kuru 05.09.2018 04:20

Другие вопросы по теме