效果图
注意:
鼠标滚动 也跟着变化
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>