THREE.Raycaster射线检测在小程序里面IOS和安卓机兼容的问题

395 阅读2分钟

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的值也不同,所需要除以的宽高也不同,对不同的系统的值进行不同的处理即可。