はじめに
この記事はもう一つの記事、
Vue + Canvas で作るグラフィックアプリの骨格
の SVG 版です。
Canvas や SVG のおかげでブラウザ上でもインタラクティブにグラフィックを簡単に扱えるようになりました。
おまけに Vue を使うとまるでパソコン上のアプリを作るかのように Web 上にグラフィックアプリを作ることができます。
この記事では Vue + SVG でマウスで四角を書いていくような 80 行程度の簡単なサンプルを作ることで、Web 上のグラフィックアプリの骨格を示したいと思います。
準備
- node, npm をダウンロードします
https://nodejs.org
この記事では node v12.4.0 で検証しています
- vue-cli をダウンロードして、とりあえず qvs という名前でアプリを作ります。
$ npm i @vue/cli -g
$ vue create qvs
$ cd qvs
$ yarn serve
この記事では vue 3.12.0 で検証しています。yarn を使ってない人は最後の行は
$ npm run serve
になると思います。
なお、以下のコードは ESLint の掟に従ってないので、vue create qvs
の時に ESLint をはずさないと多分エラーになると思われます。
また、セパレータを前に書いたり、引数とか変数の名前が _ だったりするのは単なる趣味ですので、気に入らなくても怒らないでください。
コード
src/App.vue を以下のようにしてみます。
<template>
<div id=app style="overflow: scroll">
<div id=menu style="position: fixed; top: 0; left: 0">
<button @click="mode='select'" >select </button>
<button @click="mode='rect'" >rect </button>
</div>
<svg
style = "margin: 24px 4px 4px 4px; background: aliceblue"
:class = "{ drawRect: mode == 'rect' }"
:width = "extent[ 0 ]"
:height = "extent[ 1 ]"
@mousedown = "mouseDown"
@mousemove = "mouseMove"
@mouseup = "mouseUp"
@keyup.esc = "keyUpESC"
>
<template v-for="_ in elements">
<rect v-bind="_" stroke=black fill=none />
</template>
<rect v-bind=dragRect stroke=blue fill=none />
</svg>
</div>
</template>
<script>
export default {
data : () => (
{ b : null
, c : null
, mode : 'select'
, elements : []
}
)
, computed: {
extent () {
return [ 700, 500 ]
}
, svg () {
return this.$el.getElementsByTagName( 'svg' )[ 0 ]
}
, dragRect() {
return ( ! this.b || ! this.c )
? null
: { x : this.b.offsetX
, y : this.b.offsetY
, width : this.c.offsetX - this.b.offsetX
, height : this.c.offsetY - this.b.offsetY
}
}
}
, methods : {
mouseDown( _ ) {
this.b = _
}
, mouseMove( _ ) {
this.c = _
}
, mouseUp( _ ) {
this.c = _
switch ( this.mode ) {
case 'rect':
this.elements.push( this.dragRect )
break
}
this.b = null
}
, keyUpESC( _ ) {
this.mode = 'select'
}
}
, mounted() {
this.svg.setAttribute( 'tabindex', 0 )
}
}
</script>
<style>
.drawRect {
cursor: crosshair
}
</style>
勘所
キーイベントの取得
svg に tabindex 属性をつけると、キーイベントを取得できるようになります。
this.svg.setAttribute( 'tabindex', 0 )
カーソルの切り替え
mode が 'select' と 'rect' の2つの状態が存在します。
'rect' の状態の時にクロスヘアカーソルを表示するために
クラスとスタイルのバインディングを動的に使っています。
:class = "{ drawRect: mode == 'rect' }"
<style>
.drawRect {
cursor: crosshair
}
</style>
v-bind でプロパティを一括設定
プロパティ名と同じキーを持つ辞書を用意して
dragRect = {
x : 100
, y : 200
, width : 300
, height : 400
}
<rect v-bind=dragRect />
とやると、
<rect x=100 y=200 width=300 height=400 />
と展開されます。
最後に
この記事が何かの役にたてたら幸いです。わからないことがあればコメントください!