vue-cli three中 Sprite使用 (生成标题卡片)

效果图

效果图

注意:鼠标滚动 也跟着变化

1. 引入

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

2. Sprite 生成图标

先创建 canvas图标 => 在使用 Sprite 生成 图标

methods: {
     // Sprite 生成图标 (将canvas生成图标 放入 Sprite里面生成)
    pointImgs(obj) {
      let material = new THREE.SpriteMaterial({
        map: this.canvasIcon({
          text: obj.name,
        }),
      });
      let particle = new THREE.Sprite(material);
      particle.scale.set(70, 70, 2); // 图标大小
      particle.position.set(obj.scale.x, obj.scale.y, obj.scale.z);
      return particle;
    },
    // canvas生成图标
    canvasIcon(obj) {
      let canvas = document.createElement("canvas");
      canvas.width = 1000;
      canvas.height = 1000;
      let ctx = canvas.getContext("2d");
      // ctx.textAlign="center"
      ctx.fillStyle = "rgba(0,0,0,0)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.font = "bold 80px normal";

      // ctx.fillStyle = '#000';
      ctx.fillRect(1, 1, canvas.width, 100);
      // ctx.lineWidth = 1;
      ctx.fillStyle = "#05D2FF";
      ctx.textAlign = "center";
      ctx.fillText(obj.text, 500, 80);
      ctx.drawImage(imgIcon, 100, 100, 799, 799);
      // ctx.draw()
      let texture = new THREE.Texture(canvas);
      // texture.needsUpdate = true
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      texture.needsUpdate = true;
      return texture;
    },
}

3. 完整示例代码

  <!-- 使用 three 中 Sprite 生成标题卡片  鼠标滚动 也跟着变化  -->
<template>
  <div>
    <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_Sprite"></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";

//---------------------- 引用 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 imgIcon = new Image();
imgIcon.src = require("@/assets/logo.png"); // 图片
let spriteTitle = new THREE.Group(); // 生成的标题图标数据  (用来控制开关的)
// ----------------------------------- 自定义属性 -----------------------
export default {
  name: "titleState",
  data() {
    return {
      stateData: [
        {
          name: "开",
        },
        {
          name: "关",
        },
      ],
      stateIndex: 0,
    };
  },
  mounted() {
    this.initial();
  },
  methods: {
    // 初始化加载
    initial() {
      let Sprite = document.querySelector("#title_Sprite");
      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); //设置背景颜色
      Sprite.appendChild(renderer.domElement); //body元素中插入canvas对象
      //执行渲染操作   指定场景、相机作为参数
      renderer.render(scene, camera);

      controls = new OrbitControls(camera, renderer.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;
        let data = {
        name: "这是一个标题",
        scale: { x: 0, y: 0, z: 0 },
      };
      let title = this.pointImgs(data); // 标题图片数据
      spriteTitle.add(title);
      scene.add(spriteTitle)
      this.animate();
    },
    // Sprite 生成图标 (将canvas生成图标 放入 Sprite里面生成)
    pointImgs(obj) {
      let material = new THREE.SpriteMaterial({
        map: this.canvasIcon({
          text: obj.name,
        }),
      });
      let particle = new THREE.Sprite(material);
      particle.scale.set(70, 70, 2); // 图标大小
      particle.position.set(obj.scale.x, obj.scale.y, obj.scale.z);
      return particle;
    },
    // canvas生成图标
    canvasIcon(obj) {
      let canvas = document.createElement("canvas");
      canvas.width = 1000;
      canvas.height = 1000;
      let ctx = canvas.getContext("2d");
      // ctx.textAlign="center"
      ctx.fillStyle = "rgba(0,0,0,0)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.font = "bold 80px normal";

      // ctx.fillStyle = '#000';
      ctx.fillRect(1, 1, canvas.width, 100);
      // ctx.lineWidth = 1;
      ctx.fillStyle = "#05D2FF";
      ctx.textAlign = "center";
      ctx.fillText(obj.text, 500, 80);
      ctx.drawImage(imgIcon, 100, 100, 799, 799);
      // ctx.draw()
      let texture = new THREE.Texture(canvas);
      // texture.needsUpdate = true
      texture.wrapS = THREE.RepeatWrapping;
      texture.wrapT = THREE.RepeatWrapping;
      texture.needsUpdate = true;
      return texture;
    },

    // 自动刷新
    animate() {
      TWEEN.update();
      controls.update();
      requestAnimationFrame(this.animate);
      renderer.render(scene, camera);
    },
    clickState(index){
         this.stateIndex = index;
        if(index === 0) {
            spriteTitle.visible =true;
        }else{
            spriteTitle.visible =false;
        }
    }
  },
};
</script>

<style lang="scss" scoped></style>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容