vue-cli thiee中CSS2DRenderer使用 (生成标题卡片)

效果图

效果图

注意:鼠标滚动 标题卡片大小不变

1. 引入 CSS2DRenderer.js

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min";
import {CSS2DObject,CSS2DRenderer} from "three/examples/jsm/renderers/CSS2DRenderer.js";

2. 在 初始渲染 three.js 中添加

let labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
document.body.appendChild(labelRenderer.domElement);
controls = new OrbitControls(camera, labelRenderer.domElement);

2.1 屏幕发生变化可以添加

window.addEventListener('resize', function() {
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
})

3. 在刷新three.js 函数中 (requestAnimationFrame)添加

labelRenderer.render(scene, camera);

4. 创建 标题 卡片 函数

 methods: {
  //初始渲染
   initial() {
      ......
     let data = {
        name: "这是一个标题",
        scale: { x: 0, y: 0, z: 0 },
      };
      let img = require("@/assets/logo.png");
      let title = this.titleCard(data, img);
      scene.add(title);
      this.animate();
  },

    // 生成 标题 卡片
    titleCard(text, imgs) {
      laberDiv = document.createElement("div"); //创建div容器
      laberDiv.className = "laber_name";
      laberDiv.innerHTML = `<div class='title_text'>${text.name}</div>
         <div class= 'laber_imgs'><img src="${imgs}" alt=""></div>`;

      let pointLabel = new CSS2DObject(laberDiv);
      pointLabel.position.set(text.scale.x, text.scale.y, text.scale.z);
      return pointLabel;
    },
}

5. css样式

  .laber_name{
        width: 100px;
        height: 120px;
        color: #05D2FF;
    }
    .laber_name .title_text{
        height: 20px;
        width: 100%;
        line-height: 20px;
        font-size: 12px;
        font-weight: 700;
        text-align: center;
    }
    .laber_name .laber_imgs{
        width: 100px;
        height: 100px;
        
    }
    .laber_name .laber_imgs img{
        width: 100%;
        height: 100%;
    }

6. 完整示例代码

  <!-- 使用 three 中 CSS2DRenderer 生成标题卡片  鼠标滚动 标题卡片不变 -->
<template>
  <div class="title_TEXT">
    <div class="title_state">
      <div
        class="title_state_li"
        @click="clickState(index)"
        :class="stateIndex == index ? 'title_state_li_te' : 'state_li'"
        v-for="(item, index) in stateData"
        :key="index"
      >
        {{ item.name }}
      </div>
    </div>
    <div id="title_CSS2DRenderer"></div>
  </div>
</template>

<script>
//---------------------- 引用 three 的属性 --------------------------------
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min";
import {
  CSS2DObject,
  CSS2DRenderer,
} from "three/examples/jsm/renderers/CSS2DRenderer.js";
//---------------------- 引用 three 的属性 --------------------------------

// ----------------------------------- 自定义属性 -----------------------
// 创建场景对象Scene
let scene = new THREE.Scene();
//点光源
let point = new THREE.PointLight(0xffffff);
//环境光
let ambient = new THREE.AmbientLight(0x444444);
//创建相机对象 属性
let camera = null;
// 创建渲染器对象
let renderer = new THREE.WebGLRenderer({
  //增加下面两个属性,可以抗锯齿
  antialias: true,
  alpha: true,
});
let controls = null;
let labelRenderer = new CSS2DRenderer(); // 使用 CSS2DRenderer
let laberDiv = null; //  DoM属性
// ----------------------------------- 自定义属性 -----------------------
export default {
  name: "titleCSS2DRenderer",
  data() {
    return {
      stateData: [
        {
          name: "开",
        },
        {
          name: "关",
        },
      ],
      stateIndex: 0,
    };
  },
  mounted() {
    this.initial();
  },
  methods: {
    // 初始 加载
    initial() {
      let CSS2D = document.querySelector("#title_CSS2DRenderer");
      let gridHelper = new THREE.GridHelper(400, 10, 0x2c2c2c, 0x666666);
      scene.add(gridHelper); // 网格辅助线
      /**
       * 光源设置
       */
      point.position.set(400, 200, 300); //点光源位置
      scene.add(point); //点光源添加到场景中

      scene.add(ambient); //环境光添加到场景中
      /**
       * 相机设置
       */
      let width = window.innerWidth; //窗口宽度
      let height = window.innerHeight; //窗口高度
      let k = width / height; //窗口宽高比
      let s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
      //创建相机对象
      camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 300, 200); //设置相机位置
      camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
      /**
       * 创建渲染器对象
       */
      renderer.setSize(width, height); //设置渲染区域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
      CSS2D.appendChild(renderer.domElement); //body元素中插入canvas对象

      labelRenderer.setSize(window.innerWidth, window.innerHeight);
      labelRenderer.domElement.style.position = "absolute";
      labelRenderer.domElement.style.top = 0;
      CSS2D.appendChild(labelRenderer.domElement);

      //执行渲染操作   指定场景、相机作为参数
      renderer.render(scene, camera);

      controls = new OrbitControls(camera, labelRenderer.domElement);
      // 如果使用animate方法时,将此函数删除
      //controls.addEventListener( 'change', render );
      // 使动画循环使用时阻尼或自转 意思是否有惯性
      controls.enableDamping = true;
      //动态阻尼系数 就是鼠标拖拽旋转灵敏度
      controls.dampingFactor = 0.25;
      //是否可以缩放
      controls.enableZoom = true;
      //是否自动旋转
      controls.autoRotate = true;
      controls.autoRotateSpeed = 0.3;
      //设置相机距离原点的最近距离
      controls.minDistance = 1;
      //设置相机距离原点的最远距离
      controls.maxDistance = 300;
      //是否开启右键拖拽
      controls.enablePan = true;
      //上下翻转的最大角度
      controls.maxPolarAngle = 1.5;
      //上下翻转的最小角度
      controls.minPolarAngle = 0.3;
      // 使用 CSS2DRenderer.js

      let data = {
        name: "这是一个标题",
        scale: { x: 0, y: 0, z: 0 },
      };
      let img = require("@/assets/logo.png");
      let title = this.titleCard(data, img);
      scene.add(title);
      this.animate();
    },
    // 生成 标题 卡片
    titleCard(text, imgs) {
      laberDiv = document.createElement("div"); //创建div容器
      laberDiv.className = "laber_name";
      laberDiv.innerHTML = `<div class='title_text'>${text.name}</div>
         <div class= 'laber_imgs'><img src="${imgs}" alt=""></div>`;

      let pointLabel = new CSS2DObject(laberDiv);
      pointLabel.position.set(text.scale.x, text.scale.y, text.scale.z);
      return pointLabel;
    },
    // 自动刷新
    animate() {
      TWEEN.update();
      controls.update();
      labelRenderer.render(scene, camera);
      requestAnimationFrame(this.animate);
      renderer.render(scene, camera);
    },
    // 切换状态
    clickState(index) {
      this.stateIndex = index;
      if (index === 0) {
        laberDiv.className = "laber_name";
      } else {
        laberDiv.className = "laber_name_te";
      }
    },
  },
};
</script>
<style lang="scss">
#title_CSS2DRenderer {
  .laber_name {
    width: 100px;
    height: 120px;
    color: #05d2ff;
  }
  .laber_name_te {
    display: none;
  }
  .laber_name .title_text {
    height: 20px;
    width: 100%;
    line-height: 20px;
    font-size: 12px;
    font-weight: 700;
    text-align: center;
  }
  .laber_name .laber_imgs {
    width: 100px;
    height: 100px;
  }
  .laber_name .laber_imgs img {
    width: 100%;
    height: 100%;
  }
}
</style>
<style lang="scss" scoped>
.title_state {
  position: fixed;
  top: 20px;
  left: 20px;
  z-index: 100;
  display: flex;
  border-radius: 4px;
  overflow: hidden;
  .title_state_li {
    width: 50px;
    height: 30px;
    background-color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 14px;
    cursor: pointer;
  }
  .state_li:hover {
    background-color: #f1f1f1;
  }
  .title_state_li_te {
    font-weight: 700;
    color: #fff;
    background-color: #00a6ff;
  }
}
#title_CSS2DRenderer {
  width: 100%;
  height: 100%;
}
</style>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容