【问题标题】:Accessing Canvas refs from another component in VueJS从 VueJS 中的另一个组件访问 Canvas 引用
【发布时间】:2021-05-30 17:18:07
【问题描述】:

我有一个使用@vue3/cli 项目创建的非常简单的项目。我的问题很直接,但我找不到简单的或任何解决方案。

我有两个组件。一个组件在视频标签中具有网络摄像头视频渲染,另一个组件具有 html5 画布。我想在另一个组件的画布上渲染一部分视频。我不知道如何将视频图像从一个组件发送到另一个组件。

两个组件都注册在同一层次的一个视图下。

Home -->
    WebCam.vue  
    Canvas.vue

现在我尝试使用 -

将视频作为数据从 WebCam 组件发送到 Canvas 组件
this.emitter.emit('cam-image', {
                       id:'video'
                    image: this.video 
                })

我正在使用 mitt 来发出事件,但这根本不起作用。我看到收到的数据作为整个视频标签记录在我的控制台中。

this.emitter.on("cam-image", data => { 
                 console.log(data.image)
                    this.canvasContext.drawImage(
                      data.image,
                     0, 0,
                     300, 150,
                    0, 0, this.canvasWidth, this.canvasHeight
                );
            })

因此,如果我可以将 Canvas 组件中的 refs 访问到 WebCam 组件并直接从那里渲染图像。

【问题讨论】:

  • 你可以尝试使用 vuex 进行存储和状态管理
  • @tuhin47 如何使用 veux 来做到这一点?
  • @tuhin47 我得到了一个答案,但我觉得使用提供和注入对于这个简单的用例来说太过分了。你能告诉我你的解决方案吗?我基本上做了什么,我将 this.$refs.webcam 存储到存储中的网络摄像头值,并尝试在另一个组件中访问该值。它没有任何失败。

标签: javascript vue.js canvas vuejs3


【解决方案1】:

您有多种选择。如果您只有一个实例,那么全局变量可能是最简单的方法。你可以用 Vuex 做一个全局变量,或者只使用一个全局反应实例(后面的例子)

# global.js
import { ref } from "vue";
export const canvasRef = ref(null);

然后您可以在组件中导入变量

<template>
  ...
  <canvas ref="canvasRef">
  ...
</template>

<script>
  import { canvasRef } = "global.js";

  export default {
    setup() {
      // expose to template
      return {
        canvasRef 
      }
    }
  }
</script>

您可以在另一个组件中以相同的方式导入它,两个组件将共享实例。

您还可以将应用程序上下文中的全局属性与getCurrentInstance().appContext.config.globalProperties.$canvasRef 一起使用,方法是将应用程序中的某处设置为ref(null)(或在定义vue 应用程序时app.config.globalProperties

我想说的更“正确”的方式是使用提供/注入。正确,因为它不需要全局实例,所以它只对需要它的组件可用,因此允许多个实例。

在 Home.vue 中,您将添加 provide,而在子项中,您将使用 inject 以使其可用。这类似于 react 中的 context api。

这里是一个例子,注意由于stackoverflow的限制,camera API是被禁用的,但是在jsfiddle还是可以看到的。

const app = Vue.createApp({
  setup() {
    Vue.provide('canvasRef', Vue.ref(null))
    return {}
  }
});

app.component("WebcamComponent", {
  template: `<div>Webcam<div id="webcam"></div><button @click="onClick">?<button></div>`,
  setup() {
    Webcam.set({
      width: 320,
      height: 240,
      image_format: 'jpeg',
      jpeg_quality: 90
    });

    Vue.onMounted(() => {
      Webcam.attach('#webcam');
    })
    const canvasRef = Vue.inject('canvasRef');

    const onClick = () => {
      Webcam.snap(function(data_uri, canvas) {
        const ctx = canvasRef.value.getContext('2d')
        ctx.drawImage( canvas, 0, 0 );
      })
    };

    return {
      onClick
    };
  }
});

app.component("CanvasComponent", {
  template: `<div>Canvas<div><canvas ref="canvasRef"/></div></div>`,
  setup() {
    const canvasRef = Vue.inject('canvasRef');
    return {
      canvasRef
    };
  }
});

app.mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcamjs/1.0.26/webcam.min.js"></script>
<script src="https://unpkg.com/vue@3.0.3/dist/vue.global.prod.js"></script>

<div id="app">
  <webcam-component></webcam-component>
  <canvas-component></canvas-component>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    • 2018-07-01
    • 2016-09-28
    相关资源
    最近更新 更多