【JavaScript】canvasで画像上に座標を指定してブロック枠を描画する方法

  • Vue.jsを使用
  • 画像を描画
  • 画像上に座標を指定してブロック枠を描画

コード

<template>
  <div>
    <!-- canvas要素を配置、サイズ、refを指定 -->
    <canvas ref="canvas" :width="canvasWidth" :height="canvasHeight" />
  </div>
</template>
<script>
export default {
  data() {
    return {
      canvasWidth: 400,
      canvasHeight: 800
    }
  },
  computed: {
    // 画像のURLを取得しています
    imageUrl() {
      return this.$store.getters["images/getImageUrl"]
    },
    // ブロックの各頂点の座標を取得しています
    coordinate() {
      retun this.$store.getters["coordinates"/getCoordinate"]
    }
  },
  async mounted() {
    // DOMが生成されている必要があるのでmounted内で呼び出し
    await this.getImageUrl()
    this.draw()
  },
  methods: {
    async getImageUrl() {
      await this.$store.dispatch(
        "images/getImageUrl",
      )
    },
    draw() {
      // * $refsでcanvas要素を取得
      const canvas = this.$refs.canvas
      // 平面に描画するので2d
      const ctx = canvas.getContext("2d")
      // img要素を作成
      const img = document.createElement("img")
      // src属性にURLを指定
      img.src = this.imageUrl

      // 画像の読み込みが終わったあとに描画したいのでloadイベントのあとで処理
      img.addEventListener("load", () => {
        // 元の画像の横幅を取得
        const originalWidth = img.naturalWidth
        // 縮尺を計算
        const reducedScale = this.canvasWidth / originalWidth
        // 座標空間の変形
        // 変形を適用する場合には、先に変形を指定してから図形を描画するという順序になります。
        // 変形を後から指定しても、先に描画した図形には変形が適用されないので注意してください。
        ctx.scale(reducedScale, reducedScale)

        // 画像の描画、img要素と描画したい位置を指定
        ctx.drawImage(img, 0, 0)

        // 線の太さを指定
        ctx.lineWidth = 5
        // 線の色を指定
        ctx.strokeStyle = "#0f0"

        // 各頂点を取得
        cost xMax = this.Coordinate.x_max
        cost xMin = this.Coordinate.x_min
        cost yMax = this.Coordinate.y_max
        cost yMin = this.Coordinate.y_min
        // 新しいパスを開始
        ctx.beginPath()
        // パスの始点を移動
        ctx.moveTo(xMin, yMin)
        // どこまで線を引くか指定、右に移動
        ctx.lineTo(xMax, yMin)
        // 下に移動
        ctx.lineTo(xMax, yMax)
        // 左に移動
        ctx.lineTo(xMin, yMax)
        // パスを閉じる
        ctx.closePath()
        // 線を描画
        ctx.stroke()
      })
    }
  }
}
</script>