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

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

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

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

SVG

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

TypeScript

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

Q&A

解決済

1回答

7751閲覧

vue.js svgデータバインディング

退会済みユーザー

退会済みユーザー

総合スコア0

Vue.js

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

SVG

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

TypeScript

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

0グッド

2クリップ

投稿2018/07/27 11:05

編集2018/07/27 11:11

typescript

1<template> 2 <div id="lineSvgPractice" class="lineSvgPractice" @mousemove="resize" @mouseup="mouseup" > 3 4 5 6 <div class="area"> 7 <svg class="svg" width="100" height="100" viewBox="0 0 100 100" > 8 <circle :cx="point1XNow" :cy="point1YNow" r="1.4" fill="#ffffff" stroke="#000" @mousedown="point1Active"></circle> 9 <line :x1="line1XNow" :y1="line1YNow" :x2="line2XNow" :y2="line2YNow" stroke="#000"></line> 10 <circle :cx="point2XNow" :cy="point2YNow" r="1.4" fill="#ffffff" stroke="#000" @mousedown="point2Active"></circle> 11 </svg> 12 </div> 13 14 15 16 </div> 17</template> 18 19<script lang="ts"> 20import { Component, Prop, Vue } from "vue-property-decorator"; 21 22@Component({ 23 components: { 24 } 25}) 26export default class LineSvgPractice extends Vue { 27 28 29 30/*--------------------------------------------------*/ 31 32 point1ActiveFlag = false 33 point1XBefore = 29 34 point1YBefore = 29 35 point1XNow = 29 36 point1YNow = 29 37 38 line1XBefore = 30 39 line1YBefore = 30 40 line1XNow = 30 41 line1YNow = 30 42 43/*--------------------------------------------------*/ 44 45 point2ActiveFlag = false 46 point2XBefore = 59 47 point2YBefore = 59 48 point2XNow = 59 49 point2YNow = 59 50 51 line2XBefore = 60 52 line2YBefore = 60 53 line2XNow = 60 54 line2YNow = 60 55 56/*--------------------------------------------------*/ 57 58 pointStartX = 0 59 pointStartY = 0 60 61 public point1Active(event){ 62 console.log(event) 63 this.point1ActiveFlag = true 64 this.pointStartX = event.clientX 65 this.pointStartY = event.clientY 66 } 67 68 public point2Active(event){ 69 this.point2ActiveFlag = true 70 this.pointStartX = event.clientX 71 this.pointStartY = event.clientY 72 } 73 74 public mouseup(){ 75 this.point1ActiveFlag = false 76 this.point2ActiveFlag = false 77 this.point1XBefore = this.point1XNow 78 this.point1YBefore = this.point1YNow 79 this.line1XBefore = this.line1XNow 80 this.line1YBefore = this.line1YNow 81 this.point2XBefore = this.point2XNow 82 this.point2YBefore = this.point2YNow 83 this.line2XBefore = this.line2XNow 84 this.line2YBefore = this.line2YNow 85 } 86 87 public resize(event){ 88 if(this.point1ActiveFlag){ 89 this.point1XNow = this.point1XBefore + (event.clientX - this.pointStartX) 90 this.point1YNow = this.point1YBefore + (event.clientY - this.pointStartY) 91 this.line1XNow = this.line1XBefore + (event.clientX - this.pointStartX) 92 this.line1YNow = this.line1YBefore + (event.clientY - this.pointStartY) 93 } 94 95 if(this.point2ActiveFlag){ 96 this.point2XNow = this.point2XBefore + (event.clientX - this.pointStartX) 97 this.point2YNow = this.point2YBefore + (event.clientY - this.pointStartY) 98 this.line2XNow = this.line2XBefore + (event.clientX - this.pointStartX) 99 this.line2YNow = this.line2YBefore + (event.clientY - this.pointStartY) 100 } 101 } 102 103 104} 105</script> 106 107<style lang="scss"> 108.lineSvgPractice { 109 110 .area{ 111 position: relative; 112 width: 100vw; 113 height: 80vh; 114 .svg{ 115 position: absolute; 116 top: 0px; 117 width: 100%; 118 height: 100%; 119 circle{ 120 cursor : pointer 121 } 122 } 123 } 124 125} 126</style>

線の両端をドラッグして移動できる、コードを書いたのですが、マウスの移動距離とsvg要素の移動距離が合いません...
少しドラッグしただけで、すごい動いてしまいます...
解決策をお伺いしたいです...
そもそもこのやり方は正しいのでしょうか
なんか下手な気がして

開発環境は、vue-cli3.0です↓
https://alligator.io/vuejs/using-new-vue-cli-3/


yhg様、恐縮ですが回答依頼させていただきました...
良かったら教えてください!(>_<)

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

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

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

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

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

guest

回答1

0

ベストアンサー

SVG の図形の移動は SVG の表示倍率によって HTML DOM の座標系とズレが生じるので注意が必要です。

ViewBox 100x100 に対して、ブラウザでは 1000x800 とかに拡大されて表示されますので、移動距離にもその分の倍率がかかります。

今回の場合は移動距離に (100 / 表示サイズ) をかけると意図した移動距離になると思います。

ただ、SVG の場合はもっと簡単に座標計算する方法があるので、解説記事貼っておきますね。

今回の方法でやるならこんな感じになると思います。

typescript

1 2<svg ref="svg" ... 3 4// 中略 5 6interface Point { 7 x: number; 8 y: number; 9} 10 11const isElement = (x: any): x is Element => 12 x instanceof Element; 13 14@Component 15export default class LineSvgPractice extends Vue { 16 // 中略 17 18 ratio: Point = { x: 1, y: 1 }; 19 20 mounted() { 21 // マウント完了したら this.updateRatio を呼ぶ 22 // window のリサイズイベントなどが行われた場合にも呼ぶ必要有り 23 this.updateRatio(); 24 } 25 26 // SVG の表示サイズを取得して倍率を保存 27 protected updateRatio() { 28 const { svg } = this.$refs; 29 30 if (!isElement(svg)) return; 31 32 this.ratio = { 33 x: 100 / svg.clientWidth, 34 y: 100 / svg.clientHeight, 35 }; 36 } 37 38 // 中略 39 40 public resize(event: MouseEvent) { 41 if (this.point1ActiveFlag) { 42 // 移動距離に保存してある倍率をかける 43 this.point1XNow = this.point1XBefore + (event.clientX - this.pointStartX) * this.ratio.x; 44 this.point1YNow = this.point1YBefore + (event.clientY - this.pointStartY) * this.ratio.y; 45 this.line1XNow = this.line1XBefore + (event.clientX - this.pointStartX)* this.ratio.x; 46 this.line1YNow = this.line1YBefore + (event.clientY - this.pointStartY) * this.ratio.y; 47 }

投稿2018/07/27 17:45

yhg

総合スコア2161

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

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

退会済みユーザー

退会済みユーザー

2018/07/30 02:08

迅速な回答をくださり本当にありがとうございます。 返信が遅くなり申し訳ないです、今から見てみます(>_<)
退会済みユーザー

退会済みユーザー

2018/07/30 04:58 編集

すみません、まず const isElement = (x: any): x is Element => x instanceof Element; ですが、これはisElementという名前のメソッドとして解釈してよろしいでしょうか。 これは返り値の型が x is Element なのでしょうか。 メソッドの中身では、何もreturnしてませんが...。 そして protected updateRatio() { const { svg } = this.$refs; if (!isElement(svg)) return; this.ratio = { x: 100 / svg.clientWidth, y: 100 / svg.clientHeight, }; } についてですが、 const { svg } = this.$refs; これはまず、this.$refsで得られるオブジェクトのうち、svgというキー値?のものを、const svgに格納できるのでしょうか。 if (!isElement(svg)) return; あとこれについてですが、なぜこの一文を入れると、この後、svgは型をもつことができるのでしょうか。 (x: 100 / svg.clientWidth, y: 100 / svg.clientHeight, の型エラーが消える) たくさん質問してすみません(T_T) 調べていたのですがなかなかに難しくて...(T_T)
yhg

2018/07/30 06:42

isElement はタイプガードを使った関数です。タイプガードの詳細についてはこちらを見ると良いでしょう。 http://js.studio-kingdom.com/typescript/handbook/advanced_types#type_guards_and_differentiating_types 簡単に説明するとタイプガードを使うと、キャストと違い安全に型を確定させることができます。今回の場合は Vue | Element | Vue[] | Element[] という元の型のうち、 Element のときだけ続きを実行したかったのでこのようになりました。 $refs の部分はその認識で大丈夫です。 ちなみに右辺が配列のときは、左辺で [] を使うと同じようなことができます。
退会済みユーザー

退会済みユーザー

2018/07/31 08:18

ありがとうございます、少し分かってきました... コードもすごい満足に動きました(T___T) 本当にありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問