首页 > 解决方案 > 在 VueJS 中调整画布大小

问题描述

又是我,和blob。我正在努力让我的画布元素像 VueJS 中的其他布局一样调整大小并具有移动响应能力。我正在使用 NuxtJS。

下面是我的 VueJS 文件(我在触发窗口大小调整的方法中调用了 resize() 方法):

<template id="breath">
  <div id="page__home">
    <v-row dense>
      <v-col cols="12" align="center" justify="center">
        <h1 class="card__header">
          <v-icon large color="black">
            mdi-comment-question-outline
          </v-icon>
          Mindful Breathing
        </h1>
        <canvas id="canvas" width="450" height="450"></canvas>
        <h1 class="instructions">{{ breathText[0] }}</h1>
        <v-container fluid class="container">
          <v-row align="center" justify="center">
            <v-spacer></v-spacer>
            <v-btn fab medium color="secondary">
              <v-icon color="black">
                mdi-volume-high
              </v-icon>
            </v-btn>
            <v-spacer></v-spacer>
            <v-btn fab x-large color="primary" @click="start">
              <v-icon large color="white">
                mdi-play
              </v-icon>
            </v-btn>
            <v-spacer></v-spacer>
            <v-btn fab medium color="secondary">
              <v-icon color="black">
                mdi-tune-vertical
              </v-icon>
            </v-btn>
            <v-spacer></v-spacer>
          </v-row>
        </v-container>
      </v-col>
    </v-row>
  </div>
</template>

<script>
import Blob from "../assets/content/Blob_Point"
import { Point } from "../assets/content/Blob_Point"
let oldMousePoint = { x: 0, y: 0 }
let blob = new Blob()
let hover = false
export default {
  data() {
    return {
      canvas: null,
      x: 0,
      y: 0,
      isDrawing: false,
      rectWidth: 200,
      dir: 0.25,
      radius: 200,
      ticker: undefined,
      timer: undefined,
      timerState: "stopped",
      displaySec: 10,
      breathText: ["Inhale", "Hold", "Exhale", "Hold"],
    }
  },
  mounted() {
    let canvas = document.getElementById("canvas")
    this.canvas = canvas.getContext("2d")
    canvas.setAttribute("touch-action", "none")
    blob = new Blob(this.color, this.canvas)
    blob.color = "#8CE5EA"
    blob.canvas = canvas
    blob.init()
    blob.render()
    blob.f_varySize()
  },
  created() {
    window.addEventListener("pointermove", this.mouseMove)
    window.addEventListener("mousemove", this.mouseMove)
  },
  methods: {
    start() {
      if (this.timerState !== "running") {
        this.tick()
        this.timerState = "running"
      } else {
        window.clearInterval(this.timer)
        this.timerState = "stopped"
      }
    },
    // ------ Text Change methods + Timer ---------//
    tick() {
      this.timer = window.setInterval(() => {
        this.textChange()
      }, 500)
    },
    textChange() {
      const first = this.breathText.shift()
      this.breathText = this.breathText.concat(first)
    },
    // ------------------------------------------//
    // ------ Window Resize (Not functioning)---//
    resize() {
      document.getElementById("canvas").width = window.innerWidth
      document.getElementById("canvas").height = window.innerHeight
    },
    //-------//
    // -------- spring/wave animation on mouseOver of blob ----//
    mouseMove(e) {
      let pos = blob.center
      let diff = { x: e.clientX - pos.x, y: e.clientY - pos.y }
      let dist = Math.sqrt(diff.x * diff.x + diff.y * diff.y)
      let angle = null
      blob.mousePos = {
        x: pos.x - e.clientX,
        y: pos.y - e.clientY,
      }
      if (dist < blob.radius && hover === false) {
        let vector = {
          x: e.clientX - pos.x,
          y: e.clientY - pos.y,
        }
        angle = Math.atan2(vector.y, vector.x)
        hover = true
        // blob.color = '#77FF00';
      } else if (dist > blob.radius && hover === true) {
        let vector = {
          x: e.clientX - pos.x,
          y: e.clientY - pos.y,
        }

        angle = Math.atan2(vector.y, vector.x)
        hover = false
        blob.color = null
      }
      if (typeof angle == "number") {
        let nearestPoint = null
        let distanceFromPoint = 100
        blob.points.forEach((point) => {
          if (Math.abs(angle - point.azimuth) < distanceFromPoint) {
            // console.log(point.azimuth, angle, distanceFromPoint);
            nearestPoint = point
            distanceFromPoint = Math.abs(angle - point.azimuth)
          }
        })
        if (nearestPoint) {
          let strength = {
            x: oldMousePoint.x - e.clientX,
            y: oldMousePoint.y - e.clientY,
          }
          strength =
            Math.sqrt(strength.x * strength.x + strength.y * strength.y) * 1
          if (strength > 100) strength = 100
          nearestPoint.acceleration = (strength / 100) * (hover ? -1 : 1)
        }
      }
      oldMousePoint.x = e.clientX
      oldMousePoint.y = e.clientY
    },
    // ----- //
    // ------ Blob initialisation ------//
    init() {
      for (let i = 0; i < this.numPoints; i++) {
        let point = new Point(this.divisional * (i + 1), this)
        point.acceleration = -1 + Math.random() * 2
        this.push(point)
      }
    },
    //---------//
    // ------ changing blob radius (Not working) ----//
    f_varySize() {
      console.log("testing")
      this.ticker = setInterval(() => {
        /*if (this.radius > 200) {
          this.dir = -0.25
          //console.log(g_radius);
        }
        if (this.radius < 200) {
          this.dir = 0.25
          //console.log(g_radius);
        } */
        this.radius += this.dir
      }, 20)
    },
  },
}
</script>

<style scoped>
#canvas {
  border: 1px solid grey;
  z-index: -1;
}
.instructions {
  color: #fff;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 100;
}
</style>

我应该在脚本标签之外执行此操作吗?VueJS 中是否有另一种我没有用来实现这一目标的方法?我试过设置

      document.getElementById("canvas").width = window.innerWidth
      document.getElementById("canvas").height = window.innerHeight

      document.getElementById("canvas").width = this.window.innerWidth
      document.getElementById("canvas").height = this.window.innerHeight

但它似乎没有任何效果。

这是桌面视图和移动视图的屏幕截图

桌面视图

移动视图

感谢到目前为止一直在回答我的问题的每个人,您给了我很大的帮助!我是开发新手,所以这是一条崎岖的道路:D

标签: vue.jshtml5-canvasnuxt.jsresponsive

解决方案


如果您使用的是 vuetify,那么断点可以帮助您根据屏幕设置动态高度宽度

  new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      computed :{
        getWidth() {
          if(this.$vuetify.breakpoint.mobile){
              return 200
          } else {
              return 300
          }
          
        },
        getHeight() {
          if(this.$vuetify.breakpoint.mobile){
              return 200
          } else {
              return 300
          }
        }
      }
    })
canvas{
  border : 1px solid
}
<!DOCTYPE html>
<html>
<head>
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
  <div id="app">
    <v-app>
      <v-main>
        <v-container>
          <canvas id="canvas" :width="getWidth" :height="getHeight"></canvas>
        </v-container>
      </v-main>
    </v-app>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
</body>
</html>


推荐阅读