THREE.Raycaster射线检测在小程序里兼容问题
前提
在做淘宝小程序涉及3d需要用到threeJs来实现,实现完成之后发现进行射线检测的时候在安卓机里面可以正常使用,在iOS里面点击具体的mesh返回值有问题,在打印了具体的canvas的width和height,以及系统的信息之后,发现和手机的分辨率是有关系的,需要改变射线检测的值,来正确的渲染。
不同系统、不同手机渲染的信息不一样
下面是华为mate30pro和iPhone8和iphone6plus的系统信息值:
mate30pro
{
"apiLevel": 29,
"app": "TB",
"brand": "HUAWEI",
"currentBattery": "90%",
"fontSizeSetting": 16,
"language": "cn",
"model": "HUAWEI VOG-AL10",
"performance": "middle",
"pixelRatio": 3,
"platform": "Android",
"screenHeight": 2265,
"screenWidth": 1080,
"statusBarHeight": 25,
"storage": "247 GB",
"system": "10",
"titleBarHeight": 48,
"transparentTitle": true,
"version": "9.9.1",
"windowHeight": 780,
"windowWidth": 360
}
iPhone8:
{
"fontSizeSetting": 17,
"system": "13.1.2",
"version": "9.8.0",
"brand": "iPhone",
"currentBattery": "38%",
"windowHeight": 667,
"pixelRatio": 2,
"platform": "iOS",
"screenHeight": 667,
"statusBarHeight": 20,
"language": "zh_CN",
"storage": "59.59 GB",
"app": "TB",
"titleBarHeight": 44,
"model": "iPhone10,1",
"screenWidth": 375,
"windowWidth": 375,
"isIphoneXSeries": false
}
iphone6plus
{
"fontSizeSetting": 17,
"system": "12.1.4",
"version": "9.8.0",
"brand": "iPhone",
"currentBattery": "80%",
"windowHeight": 736,
"pixelRatio": 3,
"platform": "iOS",
"screenHeight": 736,
"statusBarHeight": 20,
"language": "zh_CN",
"storage": "119.20 GB",
"app": "TB",
"titleBarHeight": 44,
"model": "iPhone8,2",
"screenWidth": 414,
"windowWidth": 414,
"isIphoneXSeries": false
}
可以看出在不同系统、不同手机之间所渲染的windowWidth、windowHeight、canvas.width、canvas.height的值是不一样的,所以如果在对THREE.Raycaster处理的时候需要进行不同的处理方式。
获取与射线相交的对象数组
// 获取与射线相交的对象数组
function getIntersects(event) {
//获取 二维坐标系
let mouse = new THREE.Vector2();
//获取淘宝小程序的系统信息
let SystemInfoSync = my.getSystemInfoSync()
//获取 不同系统下、不同手机下的宽和高
// canvas的width的一半 除以 (canvas的width 除以 系统的windowWidth)
let Cwidth = (canvas.width / 2 ) / (canvas.width / SystemInfoSync.windowWidth)
// canvas的height的一半 除以 (canvas的height 除以 系统的windowHeight)
let Cheight = (canvas.height / 2 ) / (canvas.height / SystemInfoSync.windowHeight)
mouse.x = (event.changedTouches[0].x - (Cwidth)) / (Cwidth)
mouse.y = -(event.changedTouches[0].y - (Cheight)) / (Cheight)
let vector = new THREE.Vector3(mouse.x, mouse.y,0.5).unproject(camera);
let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
let intersects = raycaster.intersectObjects(scene.children, true);
return intersects
}
根据返回值进行判断和渲染
let intersects = getIntersects(touchObj)
//判断返回值是否为空,返回值最后一个对象是否为mesh。
if (intersects.length != 0 && intersects[intersects.length - 1].object instanceof THREE.Mesh) {
// do something
} else {
// do something
}
总结
在不同手机不同系统上的分辨率和渲染的canvas的宽高不同,所进行的mouse的x、y的值也不同,所需要除以的宽高也不同,对不同的系统的值进行不同的处理即可。