svg旋转矩阵逆矩阵 [英] svg rotation matrix inverse matrix
问题描述
我是日本的初学者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屋!