【问题标题】:TypeError: Cannot read property 'width' of undefined - Nuxt JS and canvasTypeError:无法读取未定义的属性“宽度” - Nuxt JS 和画布
【发布时间】:2020-08-09 22:02:04
【问题描述】:

我正在尝试在 Nuxt JS 中的 canvas 元素上运行草图,但我遇到了一些问题(我对 Vue JS 完全陌生)。

虽然我在 VS Code 中没有错误,但在浏览器控制台中有错误:

client.js?06a0:84 TypeError: Cannot read property 'width' of undefined
at Blob.get (Blob_Point.js?a5e5:126)
at Blob.render (Blob_Point.js?a5e5:29)

下面是我的 Vue 文件的代码:

<template>
  <div>
    <h1 class="pa-5 text-center">Blob</h1>
    <canvas id="myCanvas" width="600" height="400"></canvas>
    <!--<v-btn @click="drawRect">Clear</v-btn> -->
  </div>
</template>

<script>
import Blob from "../assets/content/Blob_Point"
//import { Point } from "../assets/content/Blob_Point"
//import Point from "../assets/content/Blob_Point"
let oldMousePoint = { x: 0, y: 0 }
let blob = new Blob()
//let point = new Point()
let hover = false
let canvas
export default {
  data() {
    return {
      canvas: null,
      x: 0,
      y: 0,
      isDrawing: false,
      rectWidth: 200,
      //hover: false,
      //oldMousePoint: { x: 0, y: 0 },
    }
  },
  mounted() {
    let canvas = document.getElementById("myCanvas")
    this.canvas = canvas.getContext("2d")
  },
  created() {
    new Blob("#C09EFF")
    blob.canvas = canvas
    blob.init()
    blob.render()
  },
  methods: {
    /* showCoordinates(e) {
      this.x = e.offsetX
      this.y = e.offsetY
    },
    drawLine(x1, y1, x2, y2) {
      let ctx = this.vueCanvas
      ctx.beginPath()
      ctx.strokeStyle = "black"
      ctx.lineWidth = 1
      ctx.moveTo(x1, y1)
      ctx.lineTo(x2, y2)
      ctx.stroke()
      ctx.closePath()
    },
    draw(e) {
      if (this.isDrawing) {
        this.drawLine(this.x, this.y, e.offsetX, e.offsetY)
        this.x = e.offsetX
        this.y = e.offsetY
      }
    },
    beginDrawing(e) {
      this.x = e.offsetX
      this.y = e.offsetY
      this.isDrawing = true
    },
    stopDrawing(e) {
      if (this.isDrawing) {
        this.drawLine(this.x, this.y, e.offsetX, e.offsetY)
        this.x = 0
        this.y = 0
        this.isDrawing = false
        //windowWidth = 0,
      }
    }, */
    resize() {
      document.getElementById("myCanvas").width = window.innerWidth
      document.getElementById("myCanvas").height = window.innerHeight
    },
    /*drawRect() {
      this.vueCanvas.clearRect(0, 0, 600, 800)

      //this.vueCanvas.beginPath()
      //this.vueCanvas.rect(20, 20, this.rectWidth, 100)
      //this.vueCanvas.stroke()
    },*/
    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
    },
  },
 }
 </script>

 <style scoped>
 #myCanvas {
  border: 1px solid grey;
 }
 </style>

以下是我正在导入的 Blob_Point JS 文件:

/* eslint-disable */

// Blob Class
export default class Blob {
  // setup function
  constructor(color) {
    //the objects setup
    // 'this' is a reference to the current class
    this.points = []
    this._color = color
  }
  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)
    }
  }
  render() {
    let canvas = this.canvas
    let ctx = this.ctx
    let position = this.position
    let pointsArray = this.points
    let radius = this.radius
    let points = this.numPoints
    let divisional = this.divisional
    let center = this.center
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    pointsArray[0].solveWith(pointsArray[points - 1], pointsArray[1])
    let p0 = pointsArray[points - 1].position
    let p1 = pointsArray[0].position
    let _p2 = p1
    // this is the draw
    ctx.beginPath()
    ctx.moveTo(center.x, center.y)
    ctx.moveTo((p0.x + p1.x) / 2, (p0.y + p1.y) / 2)
    for (let i = 1; i < points; i++) {
      pointsArray[i].solveWith(
        pointsArray[i - 1],
        pointsArray[i + 1] || pointsArray[0]
      )
      let p2 = pointsArray[i].position
      var xc = (p1.x + p2.x) / 2
      var yc = (p1.y + p2.y) / 2
      ctx.quadraticCurveTo(p1.x, p1.y, xc, yc)
      // ctx.lineTo(p2.x, p2.y);
      //ctx.fillStyle = this.color;
      // ctx.fillRect(p1.x-2.5, p1.y-2.5, 5, 5);
      p1 = p2
    }

    var xc = (p1.x + _p2.x) / 2
    var yc = (p1.y + _p2.y) / 2
    ctx.quadraticCurveTo(p1.x, p1.y, xc, yc)
    ctx.lineTo(_p2.x, _p2.y)

    ctx.closePath()
    ctx.fillStyle = this.color
    ctx.fill()
    ctx.strokeStyle = this.color
    // ctx.stroke();

    /*
    ctx.fillStyle = '#000000';
    if(this.mousePos) {
    let angle = Math.atan2(this.mousePos.y, this.mousePos.x) + Math.PI;
    }*/
    //requestAnimationFrame(this.render.bind(this))
  }

  push(item) {
    if (item instanceof Point) {
      this.points.push(item)
    }
  }
  set color(value) {
    this._color = value
  }
  get color() {
    return this._color
  }
  set canvas(value) {
    if (
      value instanceof HTMLElement &&
      value.tagName.toLowerCase() === "canvas"
    ) {
      this._canvas = canvas
      this.ctx = this._canvas.getContext("2d")
    }
  }
  get canvas() {
    return this._canvas
  }
  set numPoints(value) {
    if (value > 10) {
      this._points = value
    }
  }
  get numPoints() {
    return this._points || 32
  }
  set radius(value) {
    if (value > 0) {
      this._radius = value
    }
  }
  get radius() {
    return this._radius || 300
  }
  set position(value) {
    if (typeof value == "object" && value.x && value.y) {
      this._position = value
    }
  }
  get position() {
    return this._position || { x: 0.5, y: 0.5 }
  }
  get divisional() {
    return (Math.PI * 2) / this.numPoints
  }
  get center() {
    return {
      x: this.canvas.width * this.position.x,
      y: this.canvas.height * this.position.y,
    }
  }
  set running(value) {
    this._running = value === true
  }
  get running() {
    return this.running !== false
  }
}
// Point Class
export class Point {
  constructor(azimuth, parent) {
    this.parent = parent
    this.azimuth = Math.PI - azimuth
    this._components = {
      x: Math.cos(this.azimuth),
      y: Math.sin(this.azimuth),
    }
    this.acceleration = -0.3 + Math.random() * 0.6
  }
  solveWith(leftPoint, rightPoint) {
    this.acceleration =
      (-0.3 * this.radialEffect +
        (leftPoint.radialEffect - this.radialEffect) +
        (rightPoint.radialEffect - this.radialEffect)) *
        this.elasticity -
      this.speed * this.friction
  }
  set acceleration(value) {
    if (typeof value == "number") {
      this._acceleration = value
      this.speed += this._acceleration * 2
    }
  }
  get acceleration() {
    return this._acceleration || 0
  }
  set speed(value) {
    if (typeof value == "number") {
      this._speed = value
      this.radialEffect += this._speed * 3
    }
  }
  get speed() {
    return this._speed || 0
  }
  set radialEffect(value) {
    if (typeof value == "number") {
      this._radialEffect = value
    }
  }
  get radialEffect() {
    return this._radialEffect || 0
  }
  get position() {
    return {
      x:
        this.parent.center.x +
        this.components.x * (this.parent.radius + this.radialEffect),
      y:
        this.parent.center.y +
        this.components.y * (this.parent.radius + this.radialEffect),
    }
  }
  get components() {
    return this._components
  }
  set elasticity(value) {
    if (typeof value === "number") {
      this._elasticity = value
    }
  }
  get elasticity() {
    return this._elasticity || 0.001
  }
  set friction(value) {
    if (typeof value === "number") {
      this._friction = value
    }
  }
  get friction() {
    return this._friction || 0.0085
  }
}

关于为什么 Blob_Point.js 文件的第 29 和 127 行抛出错误的任何想法?

我在 chrome 中附加了 2 个开发人员工具屏幕,以显示错误及其指向的 JS。

感谢您的帮助!

【问题讨论】:

    标签: vue.js canvas nuxt.js


    【解决方案1】:

    我可以确定的主要问题在这里。我在代码中添加了 cmets。

    Blob_Point.js

    render() {
      let canvas = this.canvas // this references the Blob Class (not the Vue instance) and there is no initialised property such as canvas in the class
    }

    要解决这个主要问题,您可以执行以下操作

    Blob_Point.js

    export default class Blob {
      constructor(color, canvas) {
        //the objects setup
        // 'this' is a reference to the current class
        this.points = []
        this._color = color;
        this.canvas = canvas
      }
    }

    然后在.vue文件中

    .Vue

    mounted() {
      let canvas = document.getElementById("myCanvas");
      this.canvas = canvas.getContext("2d");
      blob = new Blob("#C09EFF", this.canvas); // now canvas in the Blob Class constructor will refer to the vue instance canvas
      blob.canvas = canvas;
      blob.init();
      blob.render();
    },

    我在这里发现了另一个问题。

    set canvas(value) {
      if (
        value instanceof HTMLElement &&
        value.tagName.toLowerCase() === "canvas"
      ) {
        this._canvas = canvas // there is no initialised constructor property as _canvas
        this.ctx = this._canvas.getContext("2d") // there is no initialised constructor property such as _canvas
      }
    }
    get canvas() {
      return this._canvas // there is no initialised constructor property as _canvas
    }

    【讨论】:

    • 非常感谢!这为我指明了正确的方向,blob 现在正在显示:) 你是对的,我必须将“this.canvas”作为参数传递给 Vue 文件中的“new Blob()”。另外,是的,我什至没有注意到我正在为画布引用一个旧的 html id,这导致它也不显示(facepalm)。
    猜你喜欢
    • 2021-07-08
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 2019-02-16
    • 2014-10-13
    • 2021-11-02
    相关资源
    最近更新 更多