1. 3D 标注

除了 CSS2DRender 和 CSS3DRender,最常用的标注方式还有 CanvasTexture 。

1.1. CSS2DRender、 CSS3DRender 和 CanvasTexture 区别

  • CSS2DRender:尺寸固定,正面永远朝向用户,适合复杂的场景,需写 html,代码分散。

  • CSS3DRender: 真正的 3D 标注,将 html 内容转换为 3D 对象并插入到场景中,需写 html,代码分散。

  • CanvasTexture: 也可以实现 CSS2DRender 和 CSS3DRender 的效果,SS2DRender 使用 CanvasTexture + Sprite;CSS3DRender 使用 CanvasTexture + Mesh。由于使用了 canvas 作为纹理贴图,只能绘制简单的样式,好处是逻辑代码集中,好维护。

1.2. CanvasTexture + Sprite

import * as THREE from "three";

export default class TextVideo {
  constructor(
    scene,
    text = "helloworld",
    position = new THREE.Vector3(0, 0, 0),
    euler = new THREE.Euler(0, 0, 0)
  ) {
    this.text = text;
    // 创建canvas对象
    const canvas = document.createElement("canvas");
    this.canvas = canvas;
    canvas.width = 1024;
    canvas.height = 1024;

    const video = document.createElement("video");
    this.video = video;
    video.src = "./video/chatFrame.mp4";
    // 如果想要视频能够自动播放,那么就设置为静音
    video.muted = true;
    video.loop = true;
    video.play();

    const context = canvas.getContext("2d");
    this.context = context;
    this.texture = new THREE.CanvasTexture(canvas);
    const planeGeometry = new THREE.PlaneGeometry(2, 2, 1, 1);
    // this.planeMaterial = new THREE.MeshBasicMaterial({
    //   map: this.texture,
    //   alphaMap: this.texture,
    //   color: 0xffffff,
    //   side: THREE.DoubleSide,
    //   transparent: true,
    //   blending: THREE.AdditiveBlending,
    //   depthWrite: false,
    // });
    this.planeMaterial = new THREE.SpriteMaterial({
      map: this.texture,
      alphaMap: this.texture,
      color: 0xffffff,
      side: THREE.DoubleSide,
      transparent: true,
      blending: THREE.AdditiveBlending,
      depthTest: true,
      depthWrite: true,
    });
    this.mesh = new THREE.Sprite(this.planeMaterial);
    this.mesh.scale.set(5, 5, 1);
    // this.mesh = new THREE.Mesh(planeGeometry, this.planeMaterial);
    this.mesh.position.copy(position);
    this.mesh.rotation.copy(euler);
    scene.add(this.mesh);
  }

  drawVideoText(text) {
    let context = this.context;
    context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    context.drawImage(this.video, 0, 0, 1024, 1024);
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.font = "bold 100px Arial";
    context.fillStyle = "rgba(0,255,255,1)";
    context.fillText(text, this.canvas.width / 2, this.canvas.height / 2);
    this.texture.needsUpdate = true;
    this.planeMaterial.needsUpdate = true;
  }

  update(deltaTime) {
    this.drawVideoText(this.text);
  }
}

1.3. CanvasTexture + Mesh

import * as THREE from "three";

export default class TextVideo {
  constructor(
    scene,
    text = "helloworld",
    position = new THREE.Vector3(0, 0, 0),
    euler = new THREE.Euler(0, 0, 0)
  ) {
    this.text = text;
    // 创建canvas对象
    const canvas = document.createElement("canvas");
    this.canvas = canvas;
    canvas.width = 1024;
    canvas.height = 1024;

    const video = document.createElement("video");
    this.video = video;
    video.src = "./video/chatFrame.mp4";
    // 如果想要视频能够自动播放,那么就设置为静音
    video.muted = true;
    video.loop = true;
    video.play();

    const context = canvas.getContext("2d");
    this.context = context;
    this.texture = new THREE.CanvasTexture(canvas);
    const planeGeometry = new THREE.PlaneGeometry(2, 2, 1, 1);
    this.planeMaterial = new THREE.MeshBasicMaterial({
      map: this.texture,
      alphaMap: this.texture,
      color: 0xffffff,
      side: THREE.DoubleSide,
      transparent: true,
      blending: THREE.AdditiveBlending,
      depthWrite: false,
    });
    this.mesh = new THREE.Mesh(planeGeometry, this.planeMaterial);
    this.mesh.position.copy(position);
    this.mesh.rotation.copy(euler);
    scene.add(this.mesh);
  }

  drawVideoText(text) {
    let context = this.context;
    context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    context.drawImage(this.video, 0, 0, 1024, 1024);
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.font = "bold 100px Arial";
    context.fillStyle = "rgba(0,255,255,1)";
    context.fillText(text, this.canvas.width / 2, this.canvas.height / 2);
    this.texture.needsUpdate = true;
    this.planeMaterial.needsUpdate = true;
  }

  update(deltaTime) {
    this.drawVideoText(this.text);
  }
}
Copyright © tomgou 2022 all right reserved,powered by Gitbook该文章修订时间: 2023-09-23 14:53:16

results matching ""

    No results matching ""