效果(听很多童鞋反馈,代码复制到自己的项目中没法打开,或者存在其它问题,对此我用官方demo框架写了一个demo,可以去我的资源里面的看‘微信AR识别特定图片出现glb模型代码’,希望可以帮助到大家~~~~) demo页面(需要真机预览调试,注意更换自己的项目的appid)

ar案例视频

准备:需要准备要扫描的图片地址和扫描成功后显示的模型 1.在components创建组件 index.js文件代码

Component({

properties: {

title: {

type: String,

value: '',

},

intro: {

type: String,

value: '',

},

hint: {

type: String,

value: '',

},

code: {

type: String,

value: '',

},

json: {

type: String,

value: '',

},

js: {

type: String,

value: '',

},

showBackBtn: {

type: Boolean,

value: false,

},

},

data: {

},

lifetimes: {

attached() {

wx.xrTitle = this.data.title;

}

},

methods: {

onClickBack() {

wx.navigateBack()

},

}

})

index.json代码

{

"component": true,

"usingComponents": {}

}

index.wxml代码

{{title}}

{{intro}}

{{hint}}

代码演示

脚本演示

动画数据结构

index.wxss代码

.demo-wrap {

position: absolute;

left: 0;

top: 0;

width: 100%;

height: 100%;

}

.demo-viewer {

position: absolute;

left: 0;

top: 0;

width: 100%;

height: 100%;

}

.holder {

height: 60rpx;

}

.hint-wrap {

text-align: center;

}

.hint-words {

display: inline-block;

color: #000;

text-align:center;

font-weight:bold;

max-width: 300px;

padding: 10px 20px;

border: 2px dashed #000;

background-color: #fff;

}

.intro {

display: block;

margin: 20rpx 0;

background: #fff;

}

.intro .title {

font-size: 36rpx;

padding-bottom: 20rpx;

}

.intro .description {

color: #8f8f8f;

font-size: 28rpx;

}

.intro-detail {

padding: 30rpx;

}

.code-inner {

margin: 0rpx;

padding: 30rpx;

font-size: 30rpx;

background-color: #f9f9fa;

}

.code-inner rich-text {

word-wrap: break-word;

}

.block-name {

display: inline-block;

color: #b457ff;

}

.attr-name {

display: inline-block;

color: #ff4d00;

}

.ml20 {

margin-left: 20rpx;

}

.intro-title {

font-size: 30rpx;

font-weight: bold;

display: flex;

justify-content: space-between;

align-items: baseline;

margin-bottom: 24rpx;

}

.share {

margin: 0 !important;

margin-left: 0 !important;

margin-right: 0 !important;

padding: 0;

width: 160rpx !important;

background: none;

font-size: 28rpx;

color: #ff4d00;

}

.back-btn-wrap {

position: absolute;

left: 30rpx;

top: 100rpx;

width: 90rpx;

height: 80rpx;

}

.back-line-t {

position: absolute;

left: 20rpx;

top: 15rpx;

width: 30rpx;

height: 6rpx;

background-color: #000;

transform: rotate(-45deg);

border-radius: 5rpx;

}

.back-line-b {

position: absolute;

left: 20rpx;

top: 32rpx;

width: 30rpx;

height: 6rpx;

background-color: #000;

transform: rotate(45deg);

border-radius: 5rpx;

}

2.继续在components里面创建xr-ar-oceanWorld组件 index.js文件代码

Component({

behaviors: [require('../common/share-behavior').default],//路径按照自己项目路径来

miku: null,

mikuTransform: null,

mikuAnimator: null,

animationRuning: false,

isShow: false,

properties: {

//是否显示文字贴图默认不显示

isShowDolphin: {

type: false

},

},

wxball: null,

time1: null,

time2: null,

data: {

loaded: false,

arReady: false,

},

lifetimes: {

async attached() {

// console.log('data', this.data);

}

},

methods: {

handleReady({

detail

}) {

const xrScene = this.scene = detail.value;

const xrFrameSystem = wx.getXrFrameSystem();

},

handleAssetsProgress: function ({

detail

}) {

},

handleAssetsLoaded: function ({

detail

}) {

// console.log('assets loaded', detail.value);

this.setData({

loaded: true

});

},

handleTouchmiku: function() {

// console.log('miku TOUCH', this.animationRuning);

// if (!this.animationRuning) {

//

// this.animationRuning = true;

// this.mikuAnimator.pauseToFrame('gltfAnimation', 1);

// this.mikuAnimator.pauseToFrame('gltfAnimation#0', 1);

// this.mikuAnimator.resume('gltfAnimation');

// this.mikuAnimator.resume('gltfAnimation#0');

// }

},

handleAnimationStop: function() {

console.log('animation Stop');

},

// 识别模型状态

handleARTrackerState({detail}) {

// 事件的值即为`ARTracker`实例

const tracker = detail.value;

// 获取当前状态和错误信息

const {state, errorMessage} = tracker;

// const video = this.scene.assets.getAsset('video-texture', 'hikari', 'white');

console.log(state==2);

if(state==2){

console.log("状态识别成功", state)

this.time1 = setTimeout(() => {

this.setData({

isShow: true

})

}, 1000)

// this.time2 = setTimeout(() => {

// console.log("暂停动画")

// const animator1 = this.scene.getElementById('wxball-1').getComponent("animator");

// animator1.pause();

// const animator2 = this.scene.getElementById('wxball-2').getComponent("animator");

// animator2.pause();

// }, 7000)

}else{

// clearTimeout(this.time1);

// clearTimeout(this.time2);

this.setData({

isShow: false

})

}

},

// 识别海豚

handleARTrackerState1({detail}) {

// 事件的值即为`ARTracker`实例

const tracker = detail.value;

// 获取当前状态和错误信息

const {state, errorMessage} = tracker;

// const video = this.scene.assets.getAsset('video-texture', 'hikari', 'white');

console.log(state==2);

if(state==2){

console.log("识别海豚", state);

// this.triggerEvent('传递给父组件的自定义事件名称 newValue',传给父组件的数据 valueText)

this.time1 = setTimeout(() => {

this.triggerEvent('changeDolphin',{isShowDolphin:true})

this.setData({

isShow: true,

isShowDolphin:true

})

}, 1000)

// this.time2 = setTimeout(() => {

// console.log("暂停动画")

// const animator1 = this.scene.getElementById('wxball-1').getComponent("animator");

// animator1.pause();

// const animator2 = this.scene.getElementById('wxball-2').getComponent("animator");

// animator2.pause();

// }, 7000)

}else{

this.triggerEvent('changeDolphin',{isShowDolphin:false})

// clearTimeout(this.time1);

// clearTimeout(this.time2);

this.setData({

isShow: false

})

}

},

handleARReady({detail}) {

const xrFrameSystem = wx.getXrFrameSystem();

const tracker = this.scene.getElementById('ar-tracker').getComponent(xrFrameSystem.ARTracker);

// 初始状态

const {state, errorMessage} = tracker;

// 绑定事件

tracker.el.event.add('ar-tracker-state', tracker => {

const {state, errorMessage} = tracker;

});

},

handleGLTFLoaded({detail}) {

// console.log("进来了")

// const el = detail.value.target;

// const animator = el.getComponent("animator");

// console.log("1111",animator)

// setTimeout(function(){

// console.log("暂停了")

// animator.pause();

// },3000)

}

}

})

index.json文件代码

{

"component": true,

"usingComponents": {

"xr-demo-viewer": "../xr-demo-viewer/index"

},

"renderer": "xr-frame"

}

index.wxml

id="camera" node-id="camera" position="1 1 1" clear-color="0.925 0.925 0.925 1"

far="2000" background="ar" is-ar-camera

>

3.pages文件夹里创建scene-ar-oceanWorld文件 index.js代码

var sceneReadyBehavior = require('../../behavior-scene/scene-ready');//路径按照自己项目路径来

Page({

behaviors: [sceneReadyBehavior],

data: {

isShowDolphin:false,//默认不是海豚

isShow: false,

show: false,

video: false,

progressFlag: 0,

loadingAni: false,

isbegin: true,

time1: null,

time2: null,

time3: null,

rotation: {

x:0,

y: 0,

z: 0,

},

op_n:0,

meshCount: 0,

loading: 0,

barIsShow: true,

endShow:false,

timer:"",

deflautWidth:0,

musicbg:null

},

onUnload(){

this.musicbg.stop();

// 清除video定时器

// clearTimeout(this.data.time3);

},

onLoad(options) {

wx.setNavigationBarTitle({

title: "潜入海洋的梦里"

})

let that = this;

// 背景音乐

this.musicbg = wx.createInnerAudioContext()

this.musicbg.src ="背景音乐地址";

this.musicbg.volume=0.6;

this.musicbg.loop = true;

this.musicbg.play();

let index = 0;

this.data.timer=setInterval(() => { //注意箭头函数!!

index += 1;

that.setData({

deflautWidth: index

})

if (that.data.deflautWidth == 100) {

clearInterval(this.data.timer);

}

}, 1000);

setTimeout(res=>{

that.setData({

deflautWidth: 100

})

},3000)

// 关闭主页按钮

wx.hideHomeButton();

},

// 场景加载成功回调

loadedInfo(){

},

//获取海豚状态

changeDolphin(e){

console.log('获取海豚状态',e.detail);

this.setData({

isShowDolphin:e.detail.isShowDolphin

})

},

end() {

console.log("1111")

},

// 获取微信头像

handleReady: function ({detail}) {

this.scene = detail.value;

// 该接口已废弃,请授权后,采用 getUserInfo 代替。

wx.getUserInfo()({

desc: '获取头像',

success: (res) => {

console.log("微信授权", res);

this.scene.assets.loadAsset({

type: 'texture', assetId: 'avatar', src: res.userInfo.avatarUrl

}).then(() => this.setData({avatarTextureId: 'avatar'}));

}

})

},

/**

* 获取识别状态

* Detected识别成功

* Detecting未识别

*/

handleARTrackerState({

detail}) {

console.log(detail,"识别");

const {

state,

error

} = detail;

this.tracker = wx.getXrFrameSystem().ARTracker

const {

gesture

} = this.tracker;

this.gesture = gesture;

let states = wx.getXrFrameSystem().EARTrackerState[state];

if (states == "Detected") {

// if (this.data.progressFlag == 0) {

this.setData({

progressFlag: 1

})

// 修改加载界面展示

this.setData({

show: true

})

//识别成功

this.data.time1 = setTimeout(() => {

this.setData({

show: false

})

}, 1000)

//识别成功

// this.data.time2 = setTimeout(() => {

// this.setData({

// isShow: true,

// });

// // 在定时器回调中判断 isShow 的值

// if (this.data.isShow) {

// this.data.time3 = setTimeout(() => {

// console.log("进入if");

// this.setData({

// video: true,

// });

// // 关闭音乐

// this.musicbg.stop();

// }, 4500);

// }

// }, 10000);

// } else{

// this.setData({

// show: false

// })

// }

} else {

//识别失败

console.log("识别失败", states);

this.setData({

show: false,

// isShow:false,

// video: false

});

clearTimeout(this.data.time1);

clearTimeout(this.data.time2);

}

},

/**

* 生命周期函数--监听页面初次渲染完成

*/

onReady() {

},

onShow() {

/**

* 设置页面常亮

*/

wx.setKeepScreenOn({

keepScreenOn: true,

fail() {

//如果失败 再进行调用

wx.setKeepScreenOn({

keepScreenOn: true

});

}

});

},

onHide() {

this.musicbg.stop();

},

/**

* 页面相关事件处理函数--监听用户下拉动作

*/

onPullDownRefresh() {

},

/**

* 页面上拉触底事件的处理函数

*/

onReachBottom() {

},

/**

* 用户点击右上角分享

*/

onShareAppMessage() {

}

})

index.json代码

{

"usingComponents": {

"xr-demo-viewer": "../../../components/xr-demo-viewer/index",//路径按照自己项目路径来

"xr-ar-oceanWorld": "../../../components/xr-ar-oceanWorld/index"//路径按照自己项目路径来

},

"disableScroll": true

}

index.wxml文件代码

isShowDolphin="{{isShowDolphin}}"

bindchangeDolphin="changeDolphin"

disable-scroll

id="main-frame"

width="{{renderWidth}}"

height="{{renderHeight}}"

style="width:{{width}}px;height:{{height}}px;top:{{top}}px;left:{{left}}px;display:block;"

bind:arTrackerState="handleARTrackerState"

/>

index.wxss代码

page{width: 100%;height: 100%;}

.mask_bg{width: 100%;height: 100%; background: rgba(0,0,0,0.3); position: absolute; top:0; left: 0; z-index: 10;}

.mask_Img{width: 100%; height: 100%;}

.mask_Box{width: 100%; position: relative; }

.rote{width: 100%; height: 100%;position: absolute; top:0;left: 0;}

.rote image{width: 95%;animation:rotate_music 5s linear infinite; transform-origin: 50% 50%;}

@keyframes rotate_music{0%{transform: rotate(0deg);} 50%{transform: rotate(180deg);} 100%{transform: rotate(360deg);}}

.Detecting{position: absolute;top:0; left: 0; width: 100%; height: 100%; overflow: hidden; border-radius: 100%;}

.Detecting image{animation:d1 4s linear infinite;}

@keyframes d1{0%,100%{transform: translateY(0);} 50%{transform: translateY(65vw);}}

.ar3d{width: 100%; height: 100%; position: absolute;top:0;left: 0; z-index: 10; display: none; }

.ar3d_box{width: 100%; height:90%;perspective:1px; perspective-origin:center center;}

.ar3d_box text{font-size: 1em;animation:tz 5s linear infinite; color:#fff;}

@keyframes tz{0%{transform: translateZ(-3px);} 100%{transform: translateZ(1px);}}

.loading{width: 100%; text-align: center; margin-top: 20%;}

.loading .box{width: 60%; margin: 0 auto; position: relative;}

.loading .bar{width: 100%; position: absolute; bottom: 2%; left: 0; height:40%;}

.loading .bar_loading{width: 100%; height: 100%; }

.tips{width: 100%; text-align: center; margin-top: 5%;}

.tips image{width: 70%;}

.EndBox{position: absolute;top:0; left: 0; z-index: 2; width: 100%;height: 100%;}

.EndBox .box{width: 100%; height: 100%; background: url(https://cyvideo.i-oranges.com/ar/cdxg/index/ai1.gif) center no-repeat; background-size:cover}

.faceMask{width: 100%; height: 100%;position: absolute;top:0;left: 0; z-index: 999999;}

/* .faceMask .head1{position: absolute;top:0; left: 0; width: 20%;} */

.faceMask .bottom1{position: absolute;bottom:0; left: 0; width: 100%;}

.faceMask .bottom1 image{vertical-align: middle;}

.faceMask .tips{position: absolute; bottom: 5%; width: 100%;}

.faceMask .tips .box{width: 45%; position: relative; margin: 0 auto;}

.faceMask .tips .close{position: absolute; width: 20%; right: -7%; top:-30%;}

4.在components组件里面创建common文件share-behavior.js share-behavior.js代码

export default Behavior({

created: function () {

this.checkInitShare();

},

methods: {

checkInitShare() {

wx.xrScene = undefined;

if (!this.scene) {

setTimeout(() => {

this.checkInitShare()

}, 100);

return;

}

if (this.scene.ar) {

if (this.scene.ar.ready) {

this.initARTrackerState(this.scene);

} else {

this.scene.event.add('ar-ready', () => this.initARTrackerState(this.scene));

}

}

if (!this.scene.share.supported) {

console.warn('Not support xr-frame share system now!');

return;

}

this.sharing = false;

wx.xrScene = this.scene;

},

initARTrackerState(scene) {

const xrFrameSystem = wx.getXrFrameSystem();

scene.dfs(() => {}, undefined, true, el => {

const comp = el.getComponent(xrFrameSystem.ARTracker);

if (comp) {

if (typeof comp.state === 'number') {

this.triggerEvent('arTrackerState', {state: comp.state, error: comp.errorMessage});

el.event.add('ar-tracker-state', tracker => {

this.triggerEvent('arTrackerState', {state: tracker.state, error: tracker.errorMessage});

});

}

return true;

}

});

}

}

})

4.在pages中创建behavior-scene项目 scene-ready.js文件代码

module.exports = Behavior({

behaviors: [],

properties: {

},

data: {

left: 0,

top: 0,

width: 0,

height: 0,

renderWidth: 0,

renderHeight: 0,

windowHeight: 1000,

heightScale: 1,

showBackBtn: false,

activeValues: [1],

arTrackerShow: false,

arTrackerState: 'Init',

arTrackerError: ''

},

attached: function(){},

ready() {

const info = wx.getSystemInfoSync();

const width = info.windowWidth;

const windowHeight = info.windowHeight;

const height = windowHeight * this.data.heightScale;

const dpi = info.pixelRatio;

this.setData({

width,

height,

renderWidth: width * dpi,

renderHeight: height * dpi,

windowHeight

});

},

methods: {

onLoad(options) {

wx.reportEvent("xr_frame", {

"xr_page_path": options.path

});

},

// onShareAppMessage() {

// try {

// if (wx.xrScene) {

// const buffer = wx.xrScene.share.captureToArrayBuffer({quality: 0.5});

// const fp = `${wx.env.USER_DATA_PATH}/xr-frame-share.jpg`;

// wx.getFileSystemManager().writeFileSync(fp, buffer, 'binary');

// return {

// title: this.getTitle(),

// imageUrl: fp

// };

// }

// } catch (e) {

// return {

// title: this.getTitle()

// };

// }

// },

// onShareTimeline() {

// try {

// if (wx.xrScene) {

// const buffer = wx.xrScene.share.captureToArrayBuffer({quality: 0.5});

// const fp = `${wx.env.USER_DATA_PATH}/xr-frame-share.jpg`;

// wx.getFileSystemManager().writeFileSync(fp, buffer, 'binary');

// return {

// title: this.getTitle(),

// imageUrl: fp

// };

// }

// } catch (e) {

// return {

// title: this.getTitle()

// }

// }

// },

getTitle() {

return wx.xrTitle ? `${wx.xrTitle}` : 'AR';

},

handleARTrackerState({detail}) {

const {state, error} = detail;

this.setData({

arTrackerShow: true,

arTrackerState: wx.getXrFrameSystem().EARTrackerState[state],

arTrackerError: error

});

}

}

})

utils.js代码

var handleDecodedXML = function(decodedXml) {

let rerurnXml = '';

const blockArr = decodedXml.split('<');

for (let i = 0; i < blockArr.length; i++) {

let blockStr = blockArr[i];

let handleBlockStr = '';

let returnBlockStr = '';

const sliceBlockStr = blockStr.split(' ');

for(let j = 0; j < sliceBlockStr.length; j++) {

const subBlockStr = sliceBlockStr[j];

const eIndex = subBlockStr.indexOf('=');

if (eIndex !== -1) {

handleBlockStr += ' ' + subBlockStr.slice(0, eIndex) +'' + subBlockStr.slice(eIndex);

} else {

handleBlockStr += subBlockStr;

}

}

// console.log(sliceBlockStr);

const blockEndIndexB = handleBlockStr.indexOf(' ');

const blockEndIndexR = handleBlockStr.indexOf('>');

// Handle XMLTag

if (blockEndIndexB === -1 && blockEndIndexR === -1) {

continue;

}

const endBlockFlag = handleBlockStr[0] === '/';

if (blockEndIndexR !== -1) {

handleBlockStr += '
'

}

if (blockEndIndexR < blockEndIndexB) {

returnBlockStr = '<' + (endBlockFlag ? '/' : '') + '' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexR) + '' + handleBlockStr.slice(blockEndIndexR);

} else if (blockEndIndexB !== -1) {

returnBlockStr = '<' + (endBlockFlag ? '/' : '') +'' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexB) + '' + handleBlockStr.slice(blockEndIndexB);

} else if (blockEndIndexR !== -1) {

returnBlockStr = '<' + (endBlockFlag ? '/' : '') + '' + handleBlockStr.slice(endBlockFlag ? 1 : 0, blockEndIndexR) + '' + handleBlockStr.slice(blockEndIndexR);

}

rerurnXml += returnBlockStr;

}

return rerurnXml;

}

var escapeMarkup = function(dangerousInput) {

const dangerousString = String(dangerousInput);

const matchHtmlRegExp = /["'&<>]/;

const match = matchHtmlRegExp.exec(dangerousString);

if (!match) {

return dangerousInput;

}

const encodedSymbolMap = {

'"': '"',

'\'': ''',

'&': '&',

'<': '<',

'>': '>'

};

const dangerousCharacters = dangerousString.split('');

const safeCharacters = dangerousCharacters.map(function (character) {

return encodedSymbolMap[character] || character;

});

const safeString = safeCharacters.join('');

return safeString;

}

module.exports = {

handleDecodedXML,

escapeMarkup

}

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: