Samples 工程配置

EasyAR插件基于微信小程序的3D引擎xr-frame制作而成,请在使用前确保您对3D引擎和微信小程序的开发流程和基础知识具备足够多的了解。

如果您对微信小程序的xr-frame还不了解,请先查看 微信官方文档

1. 添加插件引用

在app.json中添加插件配置

"lazyCodeLoading": "requiredComponents",
"plugins": {
    "EasyARMega": {
        "version": "1.1.0",
        "provider": "wx27fa3b52b5462e8f"
    }
}

2. 使用插件

2.1 更新Mega配置信息

配置Mega服务的必要信息(miniprogram/components/data/mega-config.js), 如何获取? 请查看 说明。

export const megaConfig = {
    apiKey: '***填入你的 API Key***',
    apiSecret: '***填入你的 API Secret***',
    serverAddress: '***填入你的Mega云定位服务库的 Server Address***',
    appID: '***填入你的Mega云定位服务库的 app id***',
    licenseKey: "***填入你的 license key***",
}
export const araID = "***填入你的标注数据ID***"

2.2 引入插件

在你需要使用Mega服务的js/ts文件中引入插件

const EasyAR = requirePlugin("EasyARMega");

插件开放的类型参考 IEasyAR

2.3 确保正确的场景设置

由于插件需要使用小程序提供的AR系统相关功能,请确保正确的场景设置,否则将可能影响xr-frame引擎的运行以及插件的使用。

<xr-scene id="xr-scene" ar-system="modes:Plane" >
    <xr-node node-id="camera-target" ></xr-node>
    <xr-ar-tracker mode="Plane" ></xr-ar-tracker>
    <xr-camera id="camera" node-id="camera" background="ar" is-ar-camera ></xr-camera>
    <xr-shadow id="shadow-root" ></xr-shadow>
</xr-scene>

至少需要设置的场景组件及属性:

1. 配置xr-scene,设置ar-system为"modes:Plane";
2. 配置一个xr-ar-tracker并设置mode为"Plane";
3. 配置一个xr-camera,并且
设置一个id;
设置background="ar";
设置is-ar-camera;
4. 配置一个xr-shadow并设置id;

其他组件和属性的设置请根据需求,参考微信小程序官方文档进行设置。

2.4 添加Mega标签

在你需要使用Mega服务的wxml文件中添加,属性说明请查看 API参考手册

<xr-easyar-session id="easyar-session"
    api-key="{{apiKey}}"
    api-secret="{{apiSecret}}"
    server-address="{{serverAddress}}"
    app-id="{{appID}}"
    license-key="{{licenseKey}}"
    camera="camera"
    shadow-root="shadow-root"
    bind:ready="onMegaReady"
    bind:megaError="onMegaError"
    bind:license="onLicenseResult"
    bind:localization="onLocalizationResult">
</xr-easyar-session>

xr-easyar-session 标签作为 xr-frame 场景中的一个 Element ,必须添加到 xr-scene 标签的下面;同时由于组件内部实现原因,不允许开发者在 xr-easyar-session 下添加其他标签。

将前面配置的 xr-camera 和 xr-shadow 的id分别设置到 xr-easyar-session 上的 camera 和 shadow-root 。

属性说明请参考 EasyARSessionDataMapping 以及 IEasyARSessionData 。 事件说明请参考 EasyARSession Event

2.5 实现已添加的事件回调

// EasyAR 插件启动
onMegaReady(p) {
    console.log("mega ready", event.detail.value);
    this.session = event.detail.value;
}

// EasyAR插件启动报错
onMegaError(err) {
    console.info(err);
},

// License 认证回调
onLicenseResult(event) {
    console.log("license", event.detail.value);
},

// Mega 定位结果回调
onLocalizationResult(event) {
    console.log(event.detail.value);
},

2.6 Samples说明

samples下载,请登录到开发中心

插件标签使用说明:

<xr-scene id="xr-scene" ar-system="modes:Plane" bind:ready="handleReady">
    <!-- 这里引用EasyAR Mega插件,部分属性可以不传入,请查看API参考手册 -->
    <xr-easyar-session id="easyar-session"
        license-key="{{licenseKey}}"
        api-key="{{apiKey}}"
        api-secret="{{apiSecret}}"
        server-address="{{serverAddress}}"
        app-id="{{appID}}"
        camera="camera"
        shadow-root="shadow-root"
        bind:ready="onMegaReady"
        bind:megaError="onMegaError">
    </xr-easyar-session>

    <xr-node node-id="camera-target" position="0 0 0"></xr-node>
    <xr-ar-tracker mode="Plane"></xr-ar-tracker>
    <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 node-id="lights">
        <xr-light type="ambient" color="1 1 1" intensity="0.3" />
        <xr-light type="directional" rotation="40 170 0" color="1 1 1" intensity="1" />
    </xr-node>
    <xr-shadow id="shadow-root"></xr-shadow>
</xr-scene>

2.6.1 EasyAR-Mega Ema加载

Ema(标注数据)加载成功后,在回调中需要将模型等资源信息添加到对应的节点下,定位成功后,将会叠加到相机画面上。

在wxml文件的 xr-easyar-session 标签中添加 ara-id(标注数据id)及 bind:emaLoaded,如:

<xr-easyar-session id="easyar-session"
    license-key="{{licenseKey}}"
    api-key="{{apiKey}}"
    api-secret="{{apiSecret}}"
    server-address="{{serverAddress}}"
    app-id="{{appId}}"
    ara-id="{{araId}}"
    bind:emaLoaded="onEmaLoaded"
    enable-remote-debug="{{remoteDebug}}"
    ...
>
</xr-easyar-session>

enable-remote-debug: 是否开启远程调试,开发调试时可以开启,发布到生产环境请务必设置为 false

在回调事件中添加模型等信息:

// 完整代码请查看sample
onEmaLoaded(event) {
    const scene = this.scene;

    const annotations = event.detail.value.annotations
    /**模型资源信息 */
    // 完整内容请查看sample中代码
    const assetConfigs = {};

    /**annotation与模型资源的对应表,id为一个annotation(标注点位)的id*/
    // 完整内容请查看sample中代码
    const metaData = {};

    //遍历生成的所有Annotation组件,Annotation继承于xr-frame的compoennt
    annotations.forEach(anno => {
        let annotationId = anno.info.id;
        let meta = metaData[annotationId];
        let model = null;
        // 如果在模型资源的对应表找到,则添加模型到节点下
        if (meta) {
            let asset = assetConfigs[meta.assetId];
            if (asset) {
                // 在xr-frame中,相同的URL仅能加载一次,这里先检测相同的资源是否已加载
                let status = scene.assets.getAssetWithState(asset.type, asset.assetId);
                if (status.state == 0) {
                    scene.assets.loadAsset(asset);
                }
                model = scene.createElement(xrFrameSystem.XRGLTF, { "model": asset.assetId, "anim-autoplay": "" });
            }
        }
        // 如果没有对就的资源,添加一个cube展示
        if (!model) {
            model = scene.createElement(xrFrameSystem.XRMesh, { geometry: "cube" });
        }
        anno.el.addChild(model);
        let transform = model.getComponent(xrFrameSystem.Transform);
        transform.position.setValue(0, 0, 0);
        transform.rotation.setValue(0, 0, 0);
        transform.scale.setValue(1, 1, 1);
    });
}

2.6.2 EasyAR-Mega Ema加载-JS

EasyAR Mega插件初始化成功后,手动加载Ema数据,可以在onMegaReady事件中,或其它事件中调用,如:

// 完整代码请查看sample
onMegaReady(event) {
    const scene = this.scene;
    const session = this.session = event.detail.value;

    /**模型资源信息 */
    // 完整内容请查看sample中代码
    const assetConfigs = {};

    /**annotation与模型资源的对应表,id为一个annotation(标注点位)的id*/
    // 完整内容请查看sample中代码
    const metaData = {};

    //遍历生成的所有Annotation组件,Annotation继承于xr-frame的compoennt
    session.queryEma(araID)
        .then(ema => {
            session.holdEma(ema, {clearPrevious: false});
            session.getBlockHolder().annotations.forEach(anno => {
                let annotationId = anno.info.id;
                let meta = metaData[annotationId];
                let model = null;
                if (meta) {
                    let asset = assetConfigs[meta.assetId];
                    if (asset) {
                        let status = scene.assets.getAssetWithState(asset.type, asset.assetId);
                        if (status.state == 0) {
                            scene.assets.loadAsset(asset);
                        }
                        model = scene.createElement(xrFrameSystem.XRGLTF, { "model": asset.assetId, "anim-autoplay": "" });
                    }
                }
                if (!model) {
                    //创建xr-frame内置几何体
                    model = scene.createElement(xrFrameSystem.XRMesh, { geometry: "cube" });
                }
                anno.el.addChild(model);
                let transform = model.getComponent(xrFrameSystem.Transform);
                transform.position.setValue(0, 0, 0);
                transform.rotation.setValue(0, 0, 0);
                transform.scale.setValue(1, 1, 1);
            });
        });
}

2.6.3 EasyAR 分享功能

截图并保存到相册及分享功能, 详细说明请查看微信官方文档

检测微信版本是否支持分享功能:

if (!scene.share.supported) {
    wx.showModal({
        content: '你的微信版本不支持分享功能',
        showCancel: false,
    });
}

获取图片数据:

const options: XrFrame.IShareCaptureOptions = {type: 'jpg', quality: 0.8};

// 直接唤起分享图片给好友
scene.share.captureToFriends(options);

// 获取原始的`base64`字符串
const base64 = scene.share.captureToDataURL(options);

// 直接获取转换后的`ArrayBuffer`
const buffer = scene.share.captureToArrayBuffer(options);

// 保存图片数据到相册
const filename = `${wx.env.USER_DATA_PATH}/mega.jpg`;
wx.getFileSystemManager().writeFile({
    filePath: filename,
    data: base64.split(',').pop(), // 如果是base64格式,要去掉前缀
    encoding: 'base64',
    success: () => {
        wx.saveImageToPhotosAlbum({
            filePath: filename,
            success: () => wx.showToast({title: '已保存到相册'}),
            fail: (err) => {
                wx.showToast({icon: 'error', title: '保存到相册失败'});
            },
        });
    },
    fail: (err) => {
        wx.showToast({icon: 'error', title: '保存文件错误'});
    },
});

2.6.4 EasyAR 播放透明视频

播放透明视频,支持左右及上下透明视频。

引入插件并注册对应的视频模式:

const EasyAR = requirePlugin("EasyARMega");
// 左右模式
wx.getXrFrameSystem().registerMaterial("videoTransparentSideBySide", scene => scene.createMaterial(scene.assets.getAsset("effect", "easyar-video-tsbs")));
// 上下模式
wx.getXrFrameSystem().registerMaterial("videoTransparentTopByBottom", scene => scene.createMaterial(scene.assets.getAsset("effect", "easyar-video-ttbb")));

将视频绑定到cube上:

// 左右模式
scene.assets.loadAsset({
    type: "video-texture",
    assetId: "vsbs",
    src: "https://sightppp.oss-cn-shanghai.aliyuncs.com/public/resource/default/fireball.mp4",
    options: { autoPlay: true, loop: true }
});
// 上下模式
scene.assets.loadAsset({
    type: "video-texture",
    assetId: "vtbb",
    src: "https://sightppp.oss-cn-shanghai.aliyuncs.com/miniprogramTest/waitan-h264.mp4",
    options: { autoPlay: true, loop: true }
});

const vCube1 = scene.createElement(wx.getXrFrameSystem().XRMesh, {
    geometry: "cube",
    material: "videoTransparentTopByBottom",
    uniforms: "u_baseColorMap:video-vtbb",
});
shadowRoot.addChild(vCube1);

const vCube2 = scene.createElement(wx.getXrFrameSystem().XRMesh, {
    geometry: "cube",
    material: "videoTransparentSideBySide",
    uniforms: "u_baseColorMap:video-vsbs",
});
shadowRoot.addChild(vCube2);
vCube2.getComponent(wx.getXrFrameSystem().Transform).position.setValue(0, 0, -2);

特别提示:视频有随机播放失败的情况,为微信xr-frame已知问题

2.6.5 EasyAR Occlusion 遮挡剔除效果

遮挡剔除模型的部分内容

在 wxml 中添加模型:

<xr-mesh scale="1 1 1" position="0 0.5 -0.5" geometry="cube" />

引入插件并注册对应的材质:

const EasyAR = requirePlugin("EasyARMega");
wx.getXrFrameSystem().registerMaterial("occlusion", scene => scene.createMaterial(scene.assets.getAsset("effect", "easyar-occlusion")));

添加遮挡剔除效果:

const cube = scene.createElement(wx.getXrFrameSystem().XRMesh, {
    geometry: "cube",
    material: "occlusion",
});
shadowRoot.addChild(cube);
cube.getComponent(wx.getXrFrameSystem().Transform).position.setValue(-0.5, 0, 0);

更多API使用说明 请查看API参考手册