質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

1回答

614閲覧

svg 回転を座標の変化で表したい

退会済みユーザー

退会済みユーザー

総合スコア0

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

1クリップ

投稿2018/08/05 09:15

編集2022/01/12 10:55

四角の各頂点に小さい四角があるsvgの回転を、各頂点の座標を動かすことで実現したいです...。
まず以下が、普通にrotateで処理している場合です。

typescript

1//拡張子は.vueです 2 3<template> 4 5 <div class="rotate-area"> 6 <div class="rotate"> 7 8 <svg width="608" height="408" viewBox="0 0 608 408" xmlns="http://www.w3.org/2000/svg" class="svg" ref="svg"> 9 10 <g :transform="getAngle" stroke-width="1" fill="#ffffff" fill-rule="evenodd" fill-opacity="0" stroke="#000000" class="shape"> 11 12 <g fill-opacity="1"> 13 <rect stroke-width="2" fill-opacity="0" :x="64" :y="65" :width="189" :height="46"></rect> 14 15 <rect fill="#FAFAFA" :x="leftTopX" :y="leftTopY" width="7" height="7"></rect> 16 <rect fill="#FAFAFA" :x="rightTopX" :y="rightTopY" width="7" height="7"></rect> 17 <rect fill="#FAFAFA" :x="rightBottomX" :y="rightBottomY" width="7" height="7"></rect> 18 <rect fill="#FAFAFA" :x="leftBottomX" :y="leftBottomY" width="7" height="7"></rect> 19 20 <rect :x="getMiddleX" :y="getMiddleY" width="7" height="7" rx="3.5"></rect> 21 </g> 22 </g> 23 24 </svg> 25 26 </div> 27 28 <button @click="rotate">30°回転</button> 29 30 </div> 31</template> 32 33<script lang="ts"> 34import { Component, Prop, Vue } from 'vue-property-decorator'; 35 36 37@Component({ 38 components: { 39 }, 40}) 41 42export default class Rotate extends Vue { 43 44 leftTopX = 60.5 45 leftTopY = 60.5 46 rightTopX = 249.5 47 rightTopY = 60.5 48 rightBottomX = 249.5 49 rightBottomY = 108.5 50 leftBottomX = 60.5 51 leftBottomY = 108.5 52 53 get getMiddleX(){ 54 return ( this.leftTopX + this.rightTopX ) / 2 55 } 56 57 get getMiddleY(){ 58 return ( this.leftTopY + this.leftBottomY ) / 2 59 } 60 61 angle = 0 62 63 get getAngle(){ 64 return "rotate(" + this.angle + "," + this.getMiddleX + "," + this.getMiddleY + ")" 65 } 66 67 rotate(){ 68 this.angle = 30 69 } 70 71 72} 73 74 75 76</script> 77 78<style lang="scss"> 79 80</style> 81 82

これを座標の変化で表現したいのですがうまくいきません...。
まず一番大きい四角は回転させるしかないとして、その一番大きい四角の頂点となる四つの四角の変化を座標の変化で処理したいです...。
試してみたのが、以下の方法です。
こちらの方法ではrotateはgタグじゃなくて一番大きい四角にのみバインドしてます。

typescript

1//拡張子は.vueです 2 3<template> 4 5 <div class="rotate-area"> 6 <div class="rotate"> 7 8 <svg width="608" height="408" viewBox="0 0 608 408" xmlns="http://www.w3.org/2000/svg" class="svg" ref="svg"> 9 10 <g stroke-width="1" fill="#ffffff" fill-rule="evenodd" fill-opacity="0" stroke="#000000" class="shape"> 11 12 <g fill-opacity="1"> 13 <rect :transform="getAngle" stroke-width="2" fill-opacity="0" :x="64" :y="65" :width="189" :height="46"></rect> 14 15 <rect fill="#FAFAFA" :x="leftTopX" :y="leftTopY" width="7" height="7"></rect> 16 <rect fill="#FAFAFA" :x="rightTopX" :y="rightTopY" width="7" height="7"></rect> 17 <rect fill="#FAFAFA" :x="rightBottomX" :y="rightBottomY" width="7" height="7"></rect> 18 <rect fill="#FAFAFA" :x="leftBottomX" :y="leftBottomY" width="7" height="7"></rect> 19 20 <rect :x="getMiddleX" :y="getMiddleY" width="7" height="7" rx="3.5"></rect> 21 </g> 22 </g> 23 24 </svg> 25 26 </div> 27 28 <button @click="rotate">30°回転</button> 29 30 </div> 31</template> 32 33<script lang="ts"> 34import { Component, Prop, Vue } from 'vue-property-decorator'; 35 36 37@Component({ 38 components: { 39 }, 40}) 41 42export default class Rotate extends Vue { 43 44 leftTopX = 60.5 45 leftTopY = 60.5 46 rightTopX = 249.5 47 rightTopY = 60.5 48 rightBottomX = 249.5 49 rightBottomY = 108.5 50 leftBottomX = 60.5 51 leftBottomY = 108.5 52 53 get getMiddleX(){ 54 return ( this.leftTopX + this.rightTopX ) / 2 55 } 56 57 get getMiddleY(){ 58 return ( this.leftTopY + this.leftBottomY ) / 2 59 } 60 61 angle = 0 62 63 get getAngle(){ 64 return "rotate(" + this.angle + "," + this.getMiddleX + "," + this.getMiddleY + ")" 65 } 66 67 rotate(){ 68 this.angle = 30 69 70 let middleX = this.getMiddleX 71 let middleY = this.getMiddleY 72 73 let radians = this.angle * (Math.PI/180) 74 75 //↓例えばこれは左上の四角のx座標に対する処理なんですけどうまくいかないです 76 this.leftTopX = (this.leftTopX + middleX) * Math.cos(radians) - (this.leftTopY+middleY) * Math.sin(radians) 77 78 } 79 80 81} 82 83 84 85</script> 86 87<style lang="scss"> 88 89</style>

-追記-

よくよく考えたら上記方法だと、大きい四角の位置もずれてしまう

get getAngle(){
return "rotate(" + this.angle + "," + this.getMiddleX + "," + this.getMiddleY + ")"
}

で、this.getMiddleXとかの値も変わってしまうから

なのでここは数字を直接書きました。

あとrotateの関数内で座標を変更してからその変更した座標を使って計算すると計算がくるうので、一度let leftTopXBefore = this.leftTopXのような形で格納するようにしました。

さらに、式も間違えていたように思えたので他記事からの引用で以下のようにしました...
うまくいきませんが、どうでしょうか...(T___T)

rotate(){
this.angle = 30

let leftTopXBefore = this.leftTopX let leftTopYBefore = this.leftTopY let middleX = this.getMiddleX let middleY = this.getMiddleY //let radians = this.angle * (Math.PI/180) this.leftTopX = (leftTopXBefore + middleX) * Math.cos(this.angle) - (leftTopYBefore + middleY) * Math.sin(this.angle) - middleX this.leftTopY = (leftTopXBefore + middleX) * Math.sin(this.angle) + (leftTopYBefore + middleY) * Math.cos(this.angle) - middleY

}

-追記-

y座標が上から下に向かって加算されるので、このような計算をする上での実際の座標はマイナスだと思い

this.leftTopX =
(leftTopXBefore + middleX) * Math.cos(radians) -
(-leftTopYBefore + -middleY) * Math.sin(radians) -
middleX;

このようにもしてみたのですが、うまくいきませんでした...

-追記-

現在のコードと、現在回転させるとどうなるかの画像を追記します。

typescript

1//拡張子は.vueです 2 3<template> 4 5 <div class="rotate-area"> 6 <div class="rotate"> 7 8 <svg width="608" height="408" viewBox="0 0 608 408" xmlns="http://www.w3.org/2000/svg" class="svg" ref="svg"> 9 10 <g stroke-width="1" fill="#ffffff" fill-rule="evenodd" fill-opacity="0" stroke="#000000" class="shape"> 11 12 <g fill-opacity="1"> 13 <rect :transform="getAngle" stroke-width="2" fill-opacity="0" :x="64" :y="65" :width="189" :height="46"></rect> 14 15 <rect fill="#FAFAFA" :x="leftTopX" :y="leftTopY" width="7" height="7"></rect> 16 <rect fill="#FAFAFA" :x="rightTopX" :y="rightTopY" width="7" height="7"></rect> 17 <rect fill="#FAFAFA" :x="rightBottomX" :y="rightBottomY" width="7" height="7"></rect> 18 <rect fill="#FAFAFA" :x="leftBottomX" :y="leftBottomY" width="7" height="7"></rect> 19 20 <!--<rect :x="getMiddleX" :y="getMiddleY" width="7" height="7" rx="3.5"></rect>--> 21 </g> 22 </g> 23 24 </svg> 25 26 </div> 27 28 <button @click="rotate">30°回転</button> 29 30 </div> 31</template> 32 33<script lang="ts"> 34import { Component, Prop, Vue } from "vue-property-decorator"; 35import { RSA_NO_PADDING } from "constants"; 36 37@Component({ 38 components: {} 39}) 40export default class Rotate extends Vue { 41 leftTopX = 60.5; 42 leftTopY = 60.5; 43 rightTopX = 249.5; 44 rightTopY = 60.5; 45 rightBottomX = 249.5; 46 rightBottomY = 108.5; 47 leftBottomX = 60.5; 48 leftBottomY = 108.5; 49 50 get getMiddleX() { 51 return (this.leftTopX + this.rightTopX) / 2; 52 } 53 54 get getMiddleY() { 55 return (this.leftTopY + this.leftBottomY) / 2; 56 } 57 58 angle = 0; 59 60 get getAngle() { 61 return "rotate(" + this.angle + "," + 155 + "," + 84.5 + ")"; 62 } 63 64 rotate() { 65 this.angle = 30; 66 67 let leftTopXBefore = this.leftTopX; 68 let leftTopYBefore = this.leftTopY; 69 70 let middleX = this.getMiddleX; 71 let middleY = this.getMiddleY; 72 73 let radians = this.angle * (Math.PI / 180); 74 75 this.leftTopX = 76 (leftTopXBefore + middleX) * Math.cos(radians) - 77 (-leftTopYBefore + -middleY) * Math.sin(radians) - 78 middleX; 79 80 } 81 82} 83</script> 84 85<style lang="scss"> 86</style>

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/10 04:30

頂点を動かすとどうなるか図で示してください。
退会済みユーザー

退会済みユーザー

2018/08/13 02:44

コメントありがとうございます。追記いたしました...。良かったらみてみてください...。
guest

回答1

0

例えば、こんな感じに小さい矩形を大きい矩形の回転に合わせて移動させたいということでしょうか?

https://codepen.io/anon/pen/bjZvWp

大きな矩形の各頂点の座標を取得したいのであれば、以下のコードを参考してみてください。

js

1const bbox = rect.getBBox() 2const viewportElement = rect.viewportElement 3const screenCTM1 = rect.getScreenCTM() 4const screenCTM2 = viewportElement.getScreenCTM() 5 .inverse() 6const svgPoint = viewportElement.createSVGPoint() 7svgPoint.x = bbox.x 8svgPoint.y = bbox.y 9const topLeft = svgPoint.matrixTransform(screenCTM1) 10 .matrixTransform(screenCTM2) 11svgPoint.x += bbox.width 12const topRight = svgPoint.matrixTransform(screenCTM1) 13 .matrixTransform(screenCTM2) 14svgPoint.y += bbox.height 15const bottomRight = svgPoint.matrixTransform(screenCTM1) 16 .matrixTransform(screenCTM2) 17svgPoint.x = bbox.x 18const bottomLeft = svgPoint.matrixTransform(screenCTM1) 19 .matrixTransform(screenCTM2)

https://codepen.io/anon/pen/jpJJzm

投稿2018/08/13 11:32

編集2018/08/13 21:00
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問