1.实例演示
小程序集成Three.js,利用raycaster实现对象的
2.源码
(1)引入库并声明变量
import * as THREE from '../../libs/three.weapp.js'
import {
OrbitControls
} from '../../jsm/controls/OrbitControls'
const app = getApp()
// 声明一个二维坐标,用于设置webGl的坐标
let mouse = new THREE.Vector2()
//声明相机,场景,渲染器,控制器
let camera, scene, renderer, controls
//声明raycastor,用于进行射线检测
let raycaster = new THREE.Raycaster()
// 声明一个用于检测被raycaster射线穿过物体的几何
let INTERSECTED = null
//声明三个物体,用于射线的识别
let sphere, cylinder, cube
//声明canvas的高度,初始化时予以赋值
let canvasHeight
(2)初始化场景
onLoad: function () {
wx.createSelectorQuery()
.select('#webgl')
.node()
.exec((res) => {
console.log(res[0])
let canvasId = String(res[0].node.id)
const canvas = THREE.global.registerCanvas(canvasId, res[0].node)
canvasHeight = canvas.height
this.setData({
canvasId: canvasId
})
//相机
camera = new THREE.PerspectiveCamera(70, canvas.width / canvas.height, 1, 1000);
//场景
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
//渲染器
renderer = new THREE.WebGLRenderer({
antialias: true
});
camera.position.set(30, 40, 90);
//控制器
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.update();
//正方体1
const geometry = new THREE.BoxBufferGeometry(10, 10, 10);
const material = new THREE.MeshBasicMaterial({
color: 0x2a5a5
});
cube = new THREE.Mesh(geometry, material);
cube.position.x = 0
cube.name = '正方体cube'
scene.add(cube);
//圆球
const sphereGeometry = new THREE.SphereGeometry(5, 20, 20)
const sphereMaterial = new THREE.MeshBasicMaterial({
color: 0x341de0,
side: THREE.DoubleSide
})
sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
sphere.position.x = 30
sphere.name = '圆球sphere'
scene.add(sphere)
//柱体
const cylinderGeometry = new THREE.CylinderGeometry(8, 8, 20, 10, 10)
const cylinderMaterial = new THREE.MeshBasicMaterial({
color: 0xe1d11c,
side: THREE.DoubleSide
})
cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
cylinder.position.x = -30
cylinder.name = '圆柱cylinder'
scene.add(cylinder)
//平面
const planeGeometry = new THREE.PlaneGeometry(200, 150, 20, 20);
const planeMaterial = new THREE.MeshBasicMaterial({
color: 0xc7c7c7,
wireframe: true
});
planeMaterial.side = THREE.DoubleSide;
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.rotation.x = Math.PI / 2
plane.position.y = -20
scene.add(plane)
//辅助线
const axesHelper = new THREE.AxesHelper(500);
scene.add(axesHelper)
renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
renderer.setSize(canvas.width, canvas.height);
function render() {
canvas.requestAnimationFrame(render);
//更新控制器
controls.update();
renderer.render(scene, camera);
}
render()
})
},
初始化场景只是建立了3个物体.
检测点击识别物体的代码是通过绑定了canvas的 bindtouchstart 事件来实现的。
下面是wxml中<canvas>的代码
<canvas type="webgl" id="webgl" style="width:100vw;height: 60vh;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" bindtouchcancel="touchCancel" bindlongtap="longTap" bindtap="tap">
我们给 bindtouchstart 事件绑定了 touchStart 函数。
下面是 touchStart 函数源码
touchStart(e) {
//console.log('canvas', e)
THREE.global.touchEventHandlerFactory('canvas', 'touchstart')(e)
//给mouse的x,y坐标赋值
let x = (e.touches[0].x / wx.getWindowInfo().windowWidth) * 2 - 1;
let y = -(e.touches[0].y / canvasHeight) * 2 + 1;
mouse.x = x
mouse.y = y
raycaster.setFromCamera(mouse, camera)
let intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
if (intersects.length > 0) {
console.log(intersects)
if (INTERSECTED != intersects[0].object) {
INTERSECTED = intersects[0].object;
console.log(INTERSECTED.name)
wx.showToast({
title:INTERSECTED.name,
icon:'none'
})
}
} else {
INTERSECTED = null;
}
},
上面代码中,首先通过坐标转换,将点击屏幕的二维坐标,转换为raycastor可用的坐标。
然后将三个物体作为raycaster的检测对象。
当检测对象数组中的数量大于0,说明检测到了对象。
对象数组中第0个对象,即是我们点击的那个
3.小程序演示
ThreeJS开发指南及模型下载