threejs、TWEEN、光晕效果的简单使用

依赖

npm i three

引包

import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
import {OBJLoader} from 'three/examples/jsm/loaders/OBJLoader.js'
import {FBXLoader} from 'three/examples/jsm/loaders/FBXLoader.js'
import {MTLLoader} from 'three/examples/jsm/loaders/MTLLoader.js'

使用

this.krq = new THREE.Object3D();
this.textureLoader = new THREE.TextureLoader();
// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。
this.scene = new THREE.Scene();
var urls = [
  require('@/assets/images/3d/negz.jpg'),
  require('@/assets/images/3d/negz.jpg'),
  require('@/assets/images/3d/negz.jpg'),
  require('@/assets/images/3d/negz.jpg'),
  require('@/assets/images/3d/negz.jpg'),
  require('@/assets/images/3d/negz.jpg'),
];

var cubeLoader = new THREE.CubeTextureLoader();
this.scene.background = cubeLoader.load(urls);

// 创建一个摄像机,它定义了我们正在看的地方
this.camera = new THREE.PerspectiveCamera(40,
  document.documentElement.clientWidth / document.documentElement.clientHeight, 0.5, 10000);
this.camera.position.set(180, 80, 90);//设置相机位置
this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景
this.renderer = new THREE.WebGLRenderer({
  antialias: true,
  logarithmicDepthBuffer: true,
});
this.renderer.setClearColor(new THREE.Color(0x121A39));
this.renderer.setSize(this.canvasWidth, this.canvasHeight);
var alight = new THREE.AmbientLight("#ffffff", 1);
alight.name = "aLight";
this.scene.add(alight);
// TODO 开始添加模型到场景中 后续有方法
// 使用函数进行渲染
var _this = this;
_this.camera.updateProjectionMatrix();
if (_this.renderClock != null) clearInterval(_this.renderClock)
_this.renderClock = setInterval(() => {
  _this.renderer.render(_this.scene, _this.camera);
}, 100)
//控制器
orbit = new OrbitControls(_this.camera, _this.renderer.domElement);
orbit.addEventListener("change", (e) => {
  _this.renderer.render(_this.scene, _this.camera);
});
// 点击事件
this.renderer.domElement.addEventListener('click', function (event) {
  // console.log(event)
  const mouse = new THREE.Vector2();
  var container = document.querySelector('#dom')
  let getBoundingClientRect = container.getBoundingClientRect()
  mouse.x = ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;
  mouse.y = -((event.clientY - getBoundingClientRect.top) / container.offsetHeight) * 2 + 1;

  var raycaster = new THREE.Raycaster()
  //提高点击精度???
  raycaster.params.Line.threshold = 0.01
  raycaster.setFromCamera(mouse, _this.camera);

  const intersects = raycaster.intersectObjects(_this.scene.children);
  // console.log(intersects)
  if (intersects && intersects.length > 0 && intersects[0].object.userData.form) {
    //距离最近的模型
    _this.clickModel = intersects[0].object
    // console.log(_this.clickModel, "clickModel")
    var firstForm = intersects[0].object.userData.form
  }
});

提高点击精度

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// 计算鼠标或触摸点的位置
var container = document.querySelector('#mapContainer')
let getBoundingClientRect = container.getBoundingClientRect()
mouse.x = ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) * 2 - 1;
mouse.y = -((event.clientY - getBoundingClientRect.top) / container.offsetHeight) * 2 + 1;

raycaster.params.Line.threshold = 0.01
raycaster.setFromCamera(mouse, _this.camera);
// 计算与所有对象的交点
const intersects = raycaster.intersectObjects(_this.scene.children, true);
console.log(intersects, "intersects")

加载图片

let _this = this;
var url = require('@/assets/images/other/xxx.png')
new THREE.TextureLoader().load(url,
  (texture) => {
    let height = 10;
    let width = 10;
    const mat = new THREE.MeshBasicMaterial({map: texture, side: THREE.DoubleSide, transparent: true});
    const geom = new THREE.PlaneGeometry(width, height);
    const mesh = new THREE.Mesh(geom, mat);
    var tX = -140
    mesh.position.set(-97, 20, tX);
    mesh.rotation.y = Math.PI / 2
    _this.scene.add(mesh);
  }
);

加载obj模型 OBJLoader

var objLoader = new OBJLoader();
let _this = this;
//这个url似乎只能放在assets文件下 后续再试验放其他地方
objLoader.load('/static/assets/models/floor/floor_obj.obj', obj => {
  // console.log(obj)
  // obj.updateMatrixWorld()
  var mesh = obj.children[0];
  mesh.material = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load('/static/assets/models/floor/2.png'),
  });
  //mesh.scale.set(200, 0.1, 200);
  // mesh.scale.set(0.7, 0.3, 1);
  mesh.position.set(0, -1, 0);
  _this.scene.add(mesh);
});

加载fbx文件 FBXLoader

var _this = this;
var fbxLoader = new FBXLoader()
fbxLoader.load('/static/assets/models/electricbox.fbx', res => {
  var mesh = res.children[0]
  mesh.material = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load('/static/assets/models/electricbox_pic.png'),
  });
  mesh.position.set(0, 0, 0);
  //mesh.scale.set(1, 1, 1)
  //mesh.rotation.y = -Math.PI / 2
  _this.scene.add(mesh);
})

同时加载mtl跟obj

var _this = this;
var objLoader2 = new OBJLoader();
var mtlLoader = new MTLLoader();
mtlLoader.load('/static/assets/models/car/rio.mtl',mtl=>{
  objLoader2.setMaterials(mtl)
  objLoader2.load('/static/assets/models/car/rio.obj', obj => {
    var mesh = obj;
    mesh.scale.set(1, 1, 1);
    mesh.position.set(0, 50, 0);
    _this.scene.add(mesh);
  })
})

改变模型颜色

模型本型.material.color.set('#DAA569');

TWEEN动画

//依赖
npm install @tweenjs/tween.js -S
import TWEEN from "@tweenjs/tween.js";

//获取到具体模型
let mesh = this.tempList[0]
// 获取世界坐标
var worldPosition = new THREE.Vector3();
var position = mesh.getWorldPosition(worldPosition)


var positionTarget = new THREE.Vector3(position.x + 1000, position.y + 1000, position.z + 1000);
var pos2 = new THREE.Vector3(orbit.target.x + 500, orbit.target.y + 500, orbit.target.z + 500);
console.log(orbit.target, "SSS")

//动画开始
this.animateCamera(camera2.position, positionTarget, orbit.target, pos2)

// current1 相机当前的位置
// target1 相机的目标位置
// current2 当前的controls的target
// target2 新的controls的target
animateCamera(current1, target1, current2, target2) {

  var tween = new TWEEN.Tween({
    x1: current1.x, // 相机当前位置x
    y1: current1.y, // 相机当前位置y
    z1: current1.z, // 相机当前位置z
    x2: current2.x, // 控制当前的中心点x
    y2: current2.y, // 控制当前的中心点y
    z2: current2.z // 控制当前的中心点z
  });

  tween.to({
    x1: target1.x, // 新的相机位置x
    y1: target1.y, // 新的相机位置y
    z1: target1.z, // 新的相机位置z
    x2: target2.x, // 新的控制中心点位置x
    y2: target2.y, // 新的控制中心点位置x
    z2: target2.z // 新的控制中心点位置x
  }, 1000);
  tween.onUpdate(function (e) {
    // console.log('onUpdate', e)
    camera2.position.x = e.x1;
    camera2.position.y = e.y1;
    camera2.position.z = e.z1;
    orbit.target.x = e.x2;
    orbit.target.y = e.y2;
    orbit.target.z = e.z2;
    // orbit.update();
  })
  tween.easing(TWEEN.Easing.Cubic.InOut);
  console.log(tween)
  tween.start();
},
startScale(mesh) {
    const r = {scale: mesh.scale.x}
    var s1 = new TWEEN.Tween(r);
    s1.to({scale: 30,}, 1000)
    s1.easing(TWEEN.Easing.Sinusoidal.InOut).repeat(Infinity)
    s1.onUpdate(function (e) {
      mesh.scale.set(e.scale, e.scale, e.scale)
    });
    s1.onStop(function (e) {
      mesh.scale.set(10, 10, 10)
    })
    s1.start();
    // setTimeout(() => {
    //   s1.stop()
    // }, 5000)
  }

跳跃动画

// 创建一个跳跃的Tween动画
jump(mesh) {
  const duration = 2000; // 动画持续时间
  const target = Math.random() * 100 + 200; //

  let _this = this
  new TWEEN.Tween(mesh.position)
    .to({y: target}, duration)
    .easing(TWEEN.Easing.Quadratic.InOut)
    .onComplete(() => _this.jump(mesh)) // 动画完成后继续跳跃
    .start();
},
//在渲染方法里面需要加
function render2() {
  if (!_this.isRenderThreeView) return
  renderer2.render(scene2, camera2);
  orbit.update()
  TWEEN.update()//动画渲染更新
  if (_this.composer) _this.composer.render()
  requestAnimationFrame(render2)
}

模型光晕效果

模型光晕效果

import {FXAAShader} from "three/examples/jsm/shaders/FXAAShader";
import {EffectComposer} from "three/examples/jsm/postprocessing/EffectComposer";
import {RenderPass} from "three/examples/jsm/postprocessing/RenderPass";
import {OutlinePass} from "three/examples/jsm/postprocessing/OutlinePass";
import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass";

//高亮显示模型(呼吸灯)
//注意这里要传入数组
modelLight(selectedObjects) {
  // 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
  this.composer = new EffectComposer(renderer2)
  // 新建一个场景通道  为了覆盖到原理来的场景上
  var renderPass = new RenderPass(scene2, camera2)
  this.composer.addPass(renderPass);

  var w = this.$refs['threeContainerRef'].offsetWidth
  var h = this.$refs['threeContainerRef'].offsetHeight
  // 物体边缘发光通道
  var outlinePass = new OutlinePass(new THREE.Vector2(w, h), scene2, camera2,
    selectedObjects)
  outlinePass.selectedObjects = selectedObjects
  outlinePass.edgeStrength = 15.0 // 边框的亮度
  outlinePass.edgeGlow = 1// 光晕[0,1]
  outlinePass.usePatternTexture = false // 是否使用父级的材质
  outlinePass.edgeThickness = 1.0 // 边框宽度
  outlinePass.downSampleRatio = 1 // 边框弯曲度
  outlinePass.pulsePeriod = 1 // 呼吸闪烁的速度
  outlinePass.visibleEdgeColor = new THREE.Color(0, 0, 255) // 呼吸显示的颜色
  outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色
  outlinePass.clear = true
  this.composer.addPass(outlinePass)
  // 自定义的着色器通道 作为参数
  var effectFXAA = new ShaderPass(FXAAShader)
  effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)
  effectFXAA.renderToScreen = true
  this.composer.addPass(effectFXAA)
},
// 在render函数中记得
if (_this.composer) _this.composer.render()
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值