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


その2はこちら

モードを切り替える

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

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

...
..
.

ペンで適当に描いて・・・

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

ペンの色を切り替える

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

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>

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

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

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

子の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>
...
..
.

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

リセットボタン押下!

元通りになりました。

オマケ

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

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

まず親
「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)の実装