目錄
說明?
?創(chuàng)建兩個(gè)模型
基礎(chǔ)代碼?
基礎(chǔ)代碼效果圖如下:
重點(diǎn)?。?!?
?創(chuàng)建光線投射Raycaster實(shí)例步驟
1.準(zhǔn)備一個(gè)盒子,用來展示模型的長寬高信息,初始化時(shí)先隱藏該盒子
2.創(chuàng)建光線投射Raycaster實(shí)例
????????1.創(chuàng)建 Raycaster 實(shí)例?
????????? 2.為窗口綁定事件 pointermove 想使用點(diǎn)擊事件 click 的可以自行修改
????????3.定義窗口觸發(fā) pointermove 事件所執(zhí)行的回調(diào)函數(shù) onPointerMove?
????????4.通過攝像機(jī)和鼠標(biāo)位置更新射線
完整代碼如下:
效果圖如下 :
?結(jié)尾
說明?
說明:該案例是基于Vue2創(chuàng)建,如果未使用Ve2請自行修改代碼,另外由于使用的是已經(jīng)下載的Three.js,所以運(yùn)行前請確保已安裝Three.js以方便引入,未安裝可以使用 npm install three 進(jìn)行安裝
?創(chuàng)建兩個(gè)模型
先創(chuàng)建兩個(gè)基本模型為?光線投射Raycaster 做鋪墊
下面是一個(gè)名為 model 組件的編寫,讀者可以自行掛載在Vue示例上??
另外如果有?model 命名帶來的錯(cuò)誤,可以在文件?vue.config.js 中添加配置 lintOnSave: false
基礎(chǔ)代碼?
<template>
<div ref="container">
</div>
</template>
<script>
import * as THREE from "three";
import {OrbitControls} from "three/addons/controls/OrbitControls.js";
export default {
name: "model",
data() {
return {
//場景
scene: null,
//攝影機(jī)
camera: null,
//渲染器
renderer: null,
//相機(jī)控件
controls: null,
}
},
mounted() {
// 調(diào)用方法創(chuàng)建場景、相機(jī)、渲染器和相機(jī)控件
this.createScene();
this.createCamera();
this.createRenderer();
this.createControls();
// 創(chuàng)建兩個(gè)不同大小的立方體模型,材質(zhì)使用不受光照影響的 MeshBasicMaterial 材質(zhì)
const cube1 = new THREE.Mesh(
new THREE.BoxGeometry(3, 2, 1),
new THREE.MeshBasicMaterial({color: 0xff0000})
);
const cube2 = new THREE.Mesh(
new THREE.BoxGeometry(1, 2, 3),
new THREE.MeshBasicMaterial({color: 0x00ff00})
);
cube1.position.set(-2, 0, 0);
cube2.position.set(2, 0, 0);
this.scene.add(cube1, cube2);
const render = () => {
//手動(dòng)更改相機(jī)的變換后,必須調(diào)用controls.update()
this.controls.update()
this.renderer.render(this.scene, this.camera);
requestAnimationFrame(render);
};
render();
},
methods: {
//創(chuàng)建場景
createScene() {
this.scene = new THREE.Scene();
},
//創(chuàng)建相機(jī)
createCamera() {
this.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
1000
);
this.camera.position.set(0, 0, 5);
},
//創(chuàng)建渲染器
createRenderer() {
this.renderer = new THREE.WebGLRenderer({antialias: true}); //antialias:是否執(zhí)行抗鋸齒,默認(rèn)為false.
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.$refs.container.appendChild(this.renderer.domElement);
},
//創(chuàng)建相機(jī)控件
createControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
}
}
};
</script>
<style scoped>
</style>
基礎(chǔ)代碼效果圖如下:
重點(diǎn)?。?!?
?創(chuàng)建光線投射Raycaster實(shí)例步驟
1.準(zhǔn)備一個(gè)盒子,用來展示模型的長寬高信息,初始化時(shí)先隱藏該盒子
template>
<div ref="container">
<div id="infoBox"></div>
</div>
</template>
//盒子樣式如下: (要是覺得盒子丑大家可以自己修改,哈哈)
#infoBox{
display: none;
position: absolute;
top: 0;
left: 0;
background-color: #fff;
border:1px solid #ccc;
padding: 5px;
}
2.創(chuàng)建光線投射Raycaster實(shí)例
為了大家方便對照官方文檔學(xué)習(xí),所以我直接引用了官文文檔的源碼,大家可以對照官文修改代碼進(jìn)行實(shí)驗(yàn)加深理解?
官網(wǎng)地址:https://threejs.org/docs/index.html#api/zh/core/Raycaster
????????1.創(chuàng)建 Raycaster 實(shí)例?
const raycaster = new THREE.Raycaster();
//創(chuàng)建一個(gè)二維向量為后面 Raycaster 實(shí)例調(diào)用 .setFromCamera 方法做準(zhǔn)備
const pointer = new THREE.Vector2();
?????????2.為窗口綁定事件 pointermove 想使用點(diǎn)擊事件 click 的可以自行修改
window.addEventListener('pointermove', onPointerMove);
????????3.定義窗口觸發(fā) pointermove 事件所執(zhí)行的回調(diào)函數(shù) onPointerMove?
const infoBox = document.querySelector('#infoBox') //獲取Dom元素
const onPointerMove = (event) => { //如果不使用箭頭函數(shù)需要注意this指向問題
// 修改 pointer 的值:將鼠標(biāo)位置歸一化為設(shè)備坐標(biāo)。x 和 y 方向的取值范圍是 (-1 to +1)
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
//計(jì)算物體和射線的焦點(diǎn)
// 方法 .intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array
// 作用:檢測所有在射線與這些物體之間,包括或不包括后代的相交部分。返回結(jié)果時(shí),相交部分將按距離進(jìn)行排序,最近的位于第一個(gè)),
// 相交部分和.intersectObject所返回的格式是相同的。
const intersects = raycaster.intersectObjects(this.scene.children);//返回和射線相交的一組物體,值為數(shù)組
//沒有相交物體時(shí)
if (intersects.length === 0) {
console.log('隱藏');
infoBox.style.display = "none";
return;
}
//有相交物體時(shí)
if (intersects.length > 0) { //其中數(shù)組第一個(gè)值的 object屬性值就是鼠標(biāo)放在屏幕上離我們最近的模型
console.log('顯示');
//設(shè)置信息
infoBox.innerHTML = `長:${intersects[0].object.geometry.parameters.depth}
<br>寬:${intersects[0].object.geometry.parameters.width}<br>
高:${intersects[0].object.geometry.parameters.height}`;
infoBox.style.display = "block";
console.log(event.clientX);
infoBox.style.left = event.clientX + "px"; //記得一定要拼接 px 我就是開始忘記了,導(dǎo)致信息框不移動(dòng)
infoBox.style.top = event.clientY + "px"
}
}
????????4.通過攝像機(jī)和鼠標(biāo)位置更新射線
raycaster.setFromCamera(pointer, this.camera);
以上就是?光線投射Raycaster 的使用步驟
完整代碼如下:
<template>
<div ref="container">
<div id="infoBox"></div>
</div>
</template>
<script>
import * as THREE from "three";
import {OrbitControls} from "three/addons/controls/OrbitControls.js";
export default {
name: "model",
data() {
return {
//場景
scene: null,
//攝影機(jī)
camera: null,
//渲染器
renderer: null,
//相機(jī)控件
controls: null,
}
},
mounted() {
// 調(diào)用方法創(chuàng)建場景、相機(jī)、渲染器和相機(jī)控件
this.createScene();
this.createCamera();
this.createRenderer();
this.createControls();
// 創(chuàng)建兩個(gè)不同大小的立方體模型,材質(zhì)使用不受光照影響的 MeshBasicMaterial 材質(zhì)
const cube1 = new THREE.Mesh(
new THREE.BoxGeometry(3, 2, 1),
new THREE.MeshBasicMaterial({color: 0xff0000})
);
const cube2 = new THREE.Mesh(
new THREE.BoxGeometry(1, 2, 3),
new THREE.MeshBasicMaterial({color: 0x00ff00})
);
cube1.position.set(-2, 0, 0);
cube2.position.set(2, 0, 0);
this.scene.add(cube1, cube2);
//1.創(chuàng)建 Raycaster 實(shí)例
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2(); //創(chuàng)建一個(gè)二維向量為后面 Raycaster 實(shí)例調(diào)用 .setFromCamera 方法做準(zhǔn)備
//3.定義窗口觸發(fā) pointermove 事件所執(zhí)行的回調(diào)函數(shù) onPointerMove
const infoBox = document.querySelector('#infoBox') //獲取Dom元素
const onPointerMove = (event) => { //如果不使用箭頭函數(shù)需要注意this指向問題
// 修改 pointer 的值:將鼠標(biāo)位置歸一化為設(shè)備坐標(biāo)。x 和 y 方向的取值范圍是 (-1 to +1)
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
//計(jì)算物體和射線的焦點(diǎn)
// 方法 .intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array
// 作用:檢測所有在射線與這些物體之間,包括或不包括后代的相交部分。返回結(jié)果時(shí),相交部分將按距離進(jìn)行排序,最近的位于第一個(gè)),
// 相交部分和.intersectObject所返回的格式是相同的。
const intersects = raycaster.intersectObjects(this.scene.children);//返回和射線相交的一組物體,值為數(shù)組
//沒有相交物體時(shí)
if (intersects.length === 0) {
console.log('隱藏');
infoBox.style.display = "none";
return;
}
//有相交物體時(shí)
if (intersects.length > 0) { //其中數(shù)組第一個(gè)值的 object屬性值就是鼠標(biāo)放在屏幕上離我們最近的模型
console.log('顯示');
//設(shè)置信息
infoBox.innerHTML = `長:${intersects[0].object.geometry.parameters.depth}
<br>寬:${intersects[0].object.geometry.parameters.width}<br>
高:${intersects[0].object.geometry.parameters.height}`;
infoBox.style.display = "block";
console.log(event.clientX);
infoBox.style.left = event.clientX + "px"; //記得一定要拼接 px 我就是開始忘記了,導(dǎo)致信息框不移動(dòng)
infoBox.style.top = event.clientY + "px"
}
}
//2.為窗口綁定事件 pointermove 想使用點(diǎn)擊事件 click 的可以自行修改
window.addEventListener('pointermove', onPointerMove);
const render = () => {
// 4.通過攝像機(jī)和鼠標(biāo)位置更新射線
raycaster.setFromCamera(pointer, this.camera);
//手動(dòng)更改相機(jī)的變換后,必須調(diào)用controls.update()
this.controls.update()
this.renderer.render(this.scene, this.camera);
requestAnimationFrame(render);
};
render();
},
methods: {
//創(chuàng)建場景
createScene() {
this.scene = new THREE.Scene();
},
//創(chuàng)建相機(jī)
createCamera() {
this.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
1000
);
this.camera.position.set(0, 0, 5);
},
//創(chuàng)建渲染器
createRenderer() {
this.renderer = new THREE.WebGLRenderer({antialias: true}); //antialias:是否執(zhí)行抗鋸齒,默認(rèn)為false.
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.$refs.container.appendChild(this.renderer.domElement);
},
//創(chuàng)建相機(jī)控件
createControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
}
}
};
</script>
<style scoped>
#infoBox {
display: none;
position: absolute;
top: 0;
left: 0;
background-color: #fff;
border: 1px solid #ccc;
padding: 5px;
}
</style>
效果圖如下 :
?結(jié)尾
要是讀者覺得幫到你們了,麻煩點(diǎn)個(gè)贊鼓勵(lì)一下,以便鼓舞我這個(gè)新手小白,謝謝大家文章來源:http://www.zghlxwxcb.cn/news/detail-753955.html
另外大家要有什么疑問或者是指教都可以在評論區(qū)發(fā)出來,作者看到一定回復(fù),謝謝大家文章來源地址http://www.zghlxwxcb.cn/news/detail-753955.html
到了這里,關(guān)于Three.js中光線投射Raycaster的簡單使用案例 與模型的交互,當(dāng)鼠標(biāo)移動(dòng)到模型時(shí)出現(xiàn)信息框的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!