xr-frame 模型摆放与手势控制,支持缩放旋转
wxml
<xr-scene ar-system="modes:Plane" bind:ready="handleReady" bind:ar-ready="handleARReady">
<xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoaded">
<xr-asset-load type="gltf" asset-id="gltf-item" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/just_a_girl/index.glb" />
<xr-asset-load type="gltf" asset-id="anchor" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/ar-plane-marker.glb" />
<xr-asset-material asset-id="standard-mat" effect="standard" />
</xr-assets>
<xr-node>
<xr-ar-tracker mode="Plane">
<xr-gltf id="anchor" model="anchor"></xr-gltf>
</xr-ar-tracker>
<xr-node node-id="setitem" visible="false">
<xr-node id="preview-model">
<xr-node id="preview-model-sub" scale="0.005 0.005 0.005">
<xr-gltf id="setitem-gltf" model="gltf-item" never-cull/>
</xr-node>
</xr-node>
</xr-node>
<xr-camera
id="camera" node-id="camera" clear-color="0.925 0.925 0.925 1"
background="ar" is-ar-camera
></xr-camera>
</xr-node>
<xr-node node-id="lights">
<xr-light type="ambient" color="1 1 1" intensity="1" />
<xr-light type="directional" rotation="180 0 0" color="1 1 1" intensity="3" />
</xr-node>
</xr-scene>
js
const STATE = {
NONE: -1,
MOVE: 0,
ZOOM_OR_PAN: 1
}
Component({
behaviors: [require('../../common/share-behavior').default],
properties: {
a: Number,
},
data: {
loaded: false,
arReady: false,
},
lifetimes: {
async attached() {
console.log('data', this.data)
}
},
methods: {
handleReady({detail}) {
const xrScene = this.scene = detail.value;
this.mat = new (wx.getXrFrameSystem().Matrix4)();
console.log('xr-scene', xrScene);
const { width, height } = this.scene
// 旋转缩放相关配置
this.radius = (width + height) / 4
this.rotateSpeed = 5
this.handleTouchStart = (event) => {
this.mouseInfo = { startX: 0, startY: 0, isDown: false, startPointerDistance: 0, state: STATE.NONE }
this.mouseInfo.isDown = true
const touch0 = event.touches[0]
const touch1 = event.touches[1]
if (event.touches.length === 1) {
this.mouseInfo.startX = touch0.pageX
this.mouseInfo.startY = touch0.pageY
this.mouseInfo.state = STATE.MOVE
} else if (event.touches.length === 2) {
const dx = (touch0.pageX - touch1.pageX)
const dy = (touch0.pageY - touch1.pageY)
this.mouseInfo.startPointerDistance = Math.sqrt(dx * dx + dy * dy)
this.mouseInfo.startX = (touch0.pageX + touch1.pageX) / 2
this.mouseInfo.startY = (touch0.pageY + touch1.pageY) / 2
this.mouseInfo.state = STATE.ZOOM_OR_PAN
}
this.scene.event.add('touchmove', this.handleTouchMove.bind(this))
this.scene.event.addOnce('touchend', this.handleTouchEnd.bind(this))
},
this.handleTouchMove = (event) => {
const mouseInfo = this.mouseInfo
if (!mouseInfo.isDown) {
return
}
switch (mouseInfo.state) {
case STATE.MOVE:
if (event.touches.length === 1) {
this.handleRotate(event)
} else if (event.touches.length === 2) {
// 支持单指变双指,兼容双指操作但是两根手指触屏时间不一致的情况
this.scene.event.remove('touchmove', this.handleTouchMove)
this.scene.event.remove('touchend', this.handleTouchEnd)
this.handleTouchStart(event)
}
break
case STATE.ZOOM_OR_PAN:
if (event.touches.length === 1) {
// 感觉双指松掉一指的行为还是不要自动切换成旋转了,实际操作有点奇怪
}
else if (event.touches.length === 2) {
this.handleZoomOrPan(event)
}
break
default:
break
}
}
this.handleTouchEnd = (event) => {
this.mouseInfo.isDown = false
this.mouseInfo.state = STATE.NONE
this.scene.event.remove('touchmove', this.handleTouchMove)
this.scene.event.addOnce('touchstart', this.handleTouchStart)
}
this.handleRotate = (event) => {
const x = event.touches[0].pageX
const y = event.touches[0].pageY
const { startX, startY } = this.mouseInfo
const theta = (x - startX) / this.radius * - this.rotateSpeed
const phi = (y - startY) / this.radius * - this.rotateSpeed
if (Math.abs(theta) < .01 && Math.abs(phi) < .01) {
return
}
this.gltfItemTRS.rotation.x -= phi
this.gltfItemSubTRS.rotation.y -= theta
this.mouseInfo.startX = x
this.mouseInfo.startY = y
}
this.handleZoomOrPan = (event) => {
const touch0 = event.touches[0]
const touch1 = event.touches[1]
const dx = (touch0.pageX - touch1.pageX)
const dy = (touch0.pageY - touch1.pageY)
const distance = Math.sqrt(dx * dx + dy * dy)
let deltaScale = distance - this.mouseInfo.startPointerDistance
this.mouseInfo.startPointerDistance = distance
this.mouseInfo.startX = (touch0.pageX + touch1.pageX) / 2
this.mouseInfo.startY = (touch0.pageY + touch1.pageY) / 2
if (deltaScale < -2) {
deltaScale = -2
} else if (deltaScale > 2) {
deltaScale = 2
}
const s = deltaScale * 0.02 + 1
// 缩小
this.gltfItemTRS.scale.x *= s
this.gltfItemTRS.scale.y *= s
this.gltfItemTRS.scale.z *= s
}
},
handleAssetsProgress: function({detail}) {
console.log('assets progress', detail.value);
},
handleAssetsLoaded: function({detail}) {
console.log('assets loaded', detail.value);
// this.setData({loaded: true});
this.placedFlag = false;
this.scene.event.addOnce('touchstart', this.placeNode.bind(this));
},
handleARReady: function({detail}) {
console.log('arReady', this.scene.ar.arVersion);
},
placeNode(event) {
if (this.placedFlag) {
return;
}
const xrFrameSystem = wx.getXrFrameSystem()
this.placedFlag = true;
this.scene.ar.placeHere('setitem', true)
const anchorTRS = this.scene.getElementById('anchor').getComponent(xrFrameSystem.Transform)
anchorTRS.setData({ visible: false })
anchorTRS.scale.x = 0
anchorTRS.scale.y = 0
anchorTRS.scale.z = 0
wx.setKeepScreenOn({ keepScreenOn: true })
// 获取改动元素
this.gltfItemTRS = this.scene.getElementById('preview-model').getComponent(xrFrameSystem.Transform)
this.gltfItemSubTRS = this.scene.getElementById('preview-model-sub').getComponent(xrFrameSystem.Transform)
// 开启旋转缩放逻辑
this.scene.event.addOnce('touchstart', this.handleTouchStart)
}
}
})
原文地址:https://blog.csdn.net/dabaooooq/article/details/145248466
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!