LoginSignup
6
2

More than 5 years have passed since last update.

VueでKonva.jsとcanvasを使ってお絵描き(その3)

Last updated at Posted at 2019-05-01

その2はこちら

モードを切り替える

その2で感のいい人は気づいていると思います、
親(CallCanvas.vue)のmodeプロパティを子(FreeDrawing.vue)に渡してあげればいいだけですね。
今回、親と子のプロパティ名を一緒にしてしまって紛らわしいので、以下構文。
【:<子のプロパティ名="<親のプロパティ名>">】
(※子のpropsプロパティにmodeを宣言しておいてください)

CallCanvas.vue
<template>
    <div>
        ...
        ..
        .
        <FreeDrawing
          :backgroundImage="imageFile"
          :mode="mode" <!-- この行を追加-->
        />
    </div>
</template>

...
..
.

ペンで適当に描いて・・・
image.png

モードを消しゴムに切り替えて消します。
(キャンバスに表示している画像は消えません、また消しゴムで消えるように切り替える処理はすでに入れてあります。)
image.png

ペンの色を切り替える

これも同様に、親のプロパティを子に渡して、子側でペンの色をキャンバスに設定してあげればよいです。

CallCanvas.vue
<template>
    <div>
        ...
        ..
        .
        <FreeDrawing
          :backgroundImage="imageFile"
          :mode="mode"
          :brushColor="brushColor" <!-- この行を追加-->
        />
    </div>
</template>

...
..
.

子のFreeDrawing.vueにはすでにペンの色が変更された場合のウォッチャー(watch)があるので、何もしなくてよいです。

FreeDrawing.vue
...
..
.

<script>
import Konva from 'konva'

export default {
  name: 'FreeDrawing',
  // propsは親のCallCanvasから値を受け取るためのプロパティ
  props: {
    ...
    ..
    .
  },
  data: () => ({
    ...
    ..
    .
  }),
  mounted: function () {
    ...
    ..
    .
  },
  methods: {
    ...
    ..
    .
  },
  watch: {
    // ペンの色変更
    brushColor: function () {
      this.context.strokeStyle = this.brushColor
    }
  }
}
</script>

ペンの色を変えることができました。
image.png

image.png

リセットボタンでキャンバスをクリアする

毎回ページをリロードさせるのはめんどくさいので、キャンバスのリセットを実装します。

子のFreeDrawing.vueにはすでに「onClearCanvas」メソッドがあるので、
親からそのメソッドを呼ぶだけです。

CallCanvas.vue
<template>
    <div>
        <div class="md-layout md-gutter" style="margin-left: 340px">
          <div class="md-layout-item">
            ...
            ..
            .
            <md-field style="float: left; margin-top: -8px">
              <md-button
                @click="clearCanvas" <!-- この行を追加 -->
                class="md-dense md-raised md-primary"
              >
                  リセット
              </md-button>
            </md-field>

            ...
            ..
            .
          </div>
        </div>
        <FreeDrawing
          ref="freeDrawing" <!-- この行を追加 -->
          :backgroundImage="imageFile"
          :mode="mode"
          :brushColor="brushColor"
        />
    </div>
</template>

<script>
import FreeDrawing from './FreeDrawing.vue'

export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    // キャンバスをクリアする
    clearCanvas: function () {
      this.$refs.freeDrawing.onClearCanvas()
      this.init()
    }
  },
  ...
  ..
  .
}
</script>
...
..
.

落書きして、モードを意味もなく消しゴムにします。
image.png

リセットボタン押下!
image.png
元通りになりました。

オマケ

親から子のキャンバスクリアメソッドを呼ぶだけでしたが、
子から親のメソッドを呼ぶこともできます。

以下の構文で親のイベントを渡して、子側で任意のイベント名称を使用して渡されたイベントを実行できます。
【@<任意のイベント名称>="<イベント>"】

まず親
「init()メソッド」を"on-init"という名称で子に渡します。
小側で受け取るためのプロパティ等は不要です。

CallCanvas.vue
<template>
    <div>
        ...
        ..
        .
        <FreeDrawing
          ref="freeDrawing"
          :backgroundImage="imageFile"
          :mode="mode"
          :brushColor="brushColor"
          @on-init="init" <!-- この行追加 -->
        />
    </div>
</template>

<script>
import FreeDrawing from './FreeDrawing.vue'

export default {
  ...
  ..
  .
  methods: {
    // モードとペンの色を初期状態にする
    init: function () {
      this.mode = this.defaultMode
      this.brushColor = this.defaultBrushColor
    },
    // キャンバスをクリアする
    clearCanvas: function () {
      this.$refs.freeDrawing.onClearCanvas()
      // this.init()
    }
  },
  ...
  ..
  .
}
...
..
.

では子側です。
$emitを使用すれば、親からもらったイベントを実行することができます。
【this.$emit('<親からもらったイベント名称>')】

今回"on-init"というイベントをもらっているので、this.$emit('on-init')とします。

FreeDrawing.vue
...
..
.

<script>
import Konva from 'konva'

export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    onClearCanvas: function () {
      this.context.globalCompositeOperation = 'destination-out'
      this.context.fillRect(0, 0, this.width, this.height)
      this.drawingLayer.draw()

      this.$emit('on-init') // この行を追加
    },
    ...
    ..
    .
  },
  ...
  ..
  .
}
</script>

結果的に挙動は変わりませんが、こういうこともできるよという小技的なオマケでした。

次は「戻る」「進む」ボタンを実装しようと思います。
その4:戻る(undo) と やり直し(redo)の実装

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2