做一个AR识别IP人物形象的微信小程序

本文涉及的产品
图像搜索,7款服务类型 1个月
简介: 做一个AR识别IP人物形象的微信小程序

一:先看效果

1685518204966.png链接

二: 整体思路以及用到的第三方图像识别算法

1.调用微信小程序的相机功能(主要使用实时帧数据,已附链接);

       CameraFrameListener | 微信开放文档


2.  将获取到的相机实时帧数据转成base64.调取第三方图像识别算法;

Docs


该文档里边有详细的介绍怎么使用去训练我们要识别的图片或者物体,如果有问题可以随时私信我!


3.第三方识别接口识别成功以后会告诉前端扫描的是什么,以便我们去判断该播放哪一个IP人物形象的序列帧动画;

4.提前准备好我们要用到的IP人物资源,我这里是用的序列帧动画(一张张帧照片拼接起来一个人物动画),这些资源建议放在服务器上;

5.创建画布,通过小程序的canvas对所有帧动画进行渲染以及播放;

三:附上全部代码

1.index.wxml

<view class="content">
    <block wx:if="{{!isShowCamera}}">
        <view class="scan" bindtap="open">
            <view class="pup">
                <view class="pupTitle">活动规则介绍</view>
                <view class="pupbox">
                    <view class="top">
                        <view class="list">
                            <image mode="aspectFit" src="../../img/1.png"></image>
                        </view>
                        <view class="list">
                            <image mode="aspectFit" src="../../img/2.png"></image>
                        </view>
                        <view class="list">
                            <image mode="aspectFit" src="../../img/3.png"></image>
                        </view>
                        <view class="list">
                            <image mode="aspectFit" src="../../img/4.png"></image>
                        </view>
                        <view class="list">
                            <image mode="aspectFit" src="../../img/5.png"></image>
                        </view>
                        <view class="list">
                            <image mode="aspectFit" src="../../img/6.png"></image>
                        </view>
                    </view>
                    <view>
                        <view class="pupbot">纸上的人物竟然还能动起来?</view>
                        <view class="pupbot">不信?!那就对着人物形象扫一扫</view>
                        <view class="pupbot">解锁更多精彩吧</view>
                    </view>
                </view>
            </view>
            <button>知道啦</button>
        </view>
    </block>
    <block wx:else>
        <view class="page-section page-section-spacing swiper" style="height: 100vh;">
            <swiper easing-function="easeOutCubic" bindchange="swiperChange" style="height: 100vh;" vertical="{{true}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
                <block>
                    <swiper-item style="height: 100vh;">
                        <block>
                            <view class="mask" style="height: 100vh;background: transparent;">
                                <camera class="camera" device-position="back" flash="off" frame-size="medium" bindinitdone="bindinitdone">
                                    <cover-view hidden="{{!show}}" class='scan-animation' animation="{{animation}}">
                                        <cover-image src="../../img/saomiao.png"></cover-image>
                                    </cover-view>
                                    <canvas class="prize-frame-canvas" type="2d" id="oneTitleFrameCanvas" style="width: {{width}}rpx;height: {{height}}rpx"></canvas>
                                    <block>
                                        <view style="display: flex;justify-content: center;">
                                            <text wx:if="{{!textShow}}" class="bottom">扫一扫,开启你的奇妙体验</text>
                                            <view wx:if="{{textShow}}" class="bottom2">
                                                <image class="shanghua" src="../../img/shanghua.png"></image>
                                                <text>上划发现更多精彩</text>
                                            </view>
                                            <view wx:if="{{textShow}}" class="left" hover-class="leftActive" bindtap="toIndex">再玩一次</view>
                                        </view>
                                    </block>
                                </camera>
                            </view>
                        </block>
                    </swiper-item>
                    <swiper-item wx:if="{{textShow}}" catchtouchmove='stopTouchMove' style="height: 100vh;">
                        <block>
                            <view class="box" style="background-color: block;">
                            </view>
                        </block>
                    </swiper-item>
                </block>
            </swiper>
        </view>
    </block>
</view>
<canvas canvas-id="myCanvas"></canvas>

2.md5.js(第三方识别接口需要用到)

/* 
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 
 * Digest Algorithm, as defined in RFC 1321. 
 * Version 1.1 Copyright (C) Paul Johnston 1999 - 2002. 
 * Code also contributed by Greg Holt 
 * See http://pajhome.org.uk/site/legal.html for details. 
 */  
/* 
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally 
 * to work around bugs in some JS interpreters. 
 */  
function safe_add(x, y)  
{  
 var lsw = (x & 0xFFFF) + (y & 0xFFFF)  
 var msw = (x >> 16) + (y >> 16) + (lsw >> 16)  
 return (msw << 16) | (lsw & 0xFFFF)  
}  
/* 
 * Bitwise rotate a 32-bit number to the left. 
 */  
function rol(num, cnt)  
{  
 return (num << cnt) | (num >>> (32 - cnt))  
}  
/* 
 * These functions implement the four basic operations the algorithm uses. 
 */  
function cmn(q, a, b, x, s, t)  
{  
 return safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)  
}  
function ff(a, b, c, d, x, s, t)  
{  
 return cmn((b & c) | ((~b) & d), a, b, x, s, t)  
}  
function gg(a, b, c, d, x, s, t)  
{  
 return cmn((b & d) | (c & (~d)), a, b, x, s, t)  
}  
function hh(a, b, c, d, x, s, t)  
{  
 return cmn(b ^ c ^ d, a, b, x, s, t)  
}  
function ii(a, b, c, d, x, s, t)  
{  
 return cmn(c ^ (b | (~d)), a, b, x, s, t)  
}  
/* 
 * Calculate the MD5 of an array of little-endian words, producing an array 
 * of little-endian words. 
 */  
function coreMD5(x)  
{  
 var a = 1732584193  
 var b = -271733879  
 var c = -1732584194  
 var d = 271733878  
 for(var i = 0; i < x.length; i += 16)  
 {  
  var olda = a  
  var oldb = b  
  var oldc = c  
  var oldd = d  
  a = ff(a, b, c, d, x[i+ 0], 7 , -680876936)  
  d = ff(d, a, b, c, x[i+ 1], 12, -389564586)  
  c = ff(c, d, a, b, x[i+ 2], 17, 606105819)  
  b = ff(b, c, d, a, x[i+ 3], 22, -1044525330)  
  a = ff(a, b, c, d, x[i+ 4], 7 , -176418897)  
  d = ff(d, a, b, c, x[i+ 5], 12, 1200080426)  
  c = ff(c, d, a, b, x[i+ 6], 17, -1473231341)  
  b = ff(b, c, d, a, x[i+ 7], 22, -45705983)  
  a = ff(a, b, c, d, x[i+ 8], 7 , 1770035416)  
  d = ff(d, a, b, c, x[i+ 9], 12, -1958414417)  
  c = ff(c, d, a, b, x[i+10], 17, -42063)  
  b = ff(b, c, d, a, x[i+11], 22, -1990404162)  
  a = ff(a, b, c, d, x[i+12], 7 , 1804603682)  
  d = ff(d, a, b, c, x[i+13], 12, -40341101)  
  c = ff(c, d, a, b, x[i+14], 17, -1502002290)  
  b = ff(b, c, d, a, x[i+15], 22, 1236535329)  
  a = gg(a, b, c, d, x[i+ 1], 5 , -165796510)  
  d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632)  
  c = gg(c, d, a, b, x[i+11], 14, 643717713)  
  b = gg(b, c, d, a, x[i+ 0], 20, -373897302)  
  a = gg(a, b, c, d, x[i+ 5], 5 , -701558691)  
  d = gg(d, a, b, c, x[i+10], 9 , 38016083)  
  c = gg(c, d, a, b, x[i+15], 14, -660478335)  
  b = gg(b, c, d, a, x[i+ 4], 20, -405537848)  
  a = gg(a, b, c, d, x[i+ 9], 5 , 568446438)  
  d = gg(d, a, b, c, x[i+14], 9 , -1019803690)  
  c = gg(c, d, a, b, x[i+ 3], 14, -187363961)  
  b = gg(b, c, d, a, x[i+ 8], 20, 1163531501)  
  a = gg(a, b, c, d, x[i+13], 5 , -1444681467)  
  d = gg(d, a, b, c, x[i+ 2], 9 , -51403784)  
  c = gg(c, d, a, b, x[i+ 7], 14, 1735328473)  
  b = gg(b, c, d, a, x[i+12], 20, -1926607734)  
  a = hh(a, b, c, d, x[i+ 5], 4 , -378558)  
  d = hh(d, a, b, c, x[i+ 8], 11, -2022574463)  
  c = hh(c, d, a, b, x[i+11], 16, 1839030562)  
  b = hh(b, c, d, a, x[i+14], 23, -35309556)  
  a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060)  
  d = hh(d, a, b, c, x[i+ 4], 11, 1272893353)  
  c = hh(c, d, a, b, x[i+ 7], 16, -155497632)  
  b = hh(b, c, d, a, x[i+10], 23, -1094730640)  
  a = hh(a, b, c, d, x[i+13], 4 , 681279174)  
  d = hh(d, a, b, c, x[i+ 0], 11, -358537222)  
  c = hh(c, d, a, b, x[i+ 3], 16, -722521979)  
  b = hh(b, c, d, a, x[i+ 6], 23, 76029189)  
  a = hh(a, b, c, d, x[i+ 9], 4 , -640364487)  
  d = hh(d, a, b, c, x[i+12], 11, -421815835)  
  c = hh(c, d, a, b, x[i+15], 16, 530742520)  
  b = hh(b, c, d, a, x[i+ 2], 23, -995338651)  
  a = ii(a, b, c, d, x[i+ 0], 6 , -198630844)  
  d = ii(d, a, b, c, x[i+ 7], 10, 1126891415)  
  c = ii(c, d, a, b, x[i+14], 15, -1416354905)  
  b = ii(b, c, d, a, x[i+ 5], 21, -57434055)  
  a = ii(a, b, c, d, x[i+12], 6 , 1700485571)  
  d = ii(d, a, b, c, x[i+ 3], 10, -1894986606)  
  c = ii(c, d, a, b, x[i+10], 15, -1051523)  
  b = ii(b, c, d, a, x[i+ 1], 21, -2054922799)  
  a = ii(a, b, c, d, x[i+ 8], 6 , 1873313359)  
  d = ii(d, a, b, c, x[i+15], 10, -30611744)  
  c = ii(c, d, a, b, x[i+ 6], 15, -1560198380)  
  b = ii(b, c, d, a, x[i+13], 21, 1309151649)  
  a = ii(a, b, c, d, x[i+ 4], 6 , -145523070)  
  d = ii(d, a, b, c, x[i+11], 10, -1120210379)  
  c = ii(c, d, a, b, x[i+ 2], 15, 718787259)  
  b = ii(b, c, d, a, x[i+ 9], 21, -343485551)  
  a = safe_add(a, olda)  
  b = safe_add(b, oldb)  
  c = safe_add(c, oldc)  
  d = safe_add(d, oldd)  
 }  
 return [a, b, c, d]  
}  
/* 
 * Convert an array of little-endian words to a hex string. 
 */  
function binl2hex(binarray)  
{  
 var hex_tab = "0123456789abcdef"  
 var str = ""  
 for(var i = 0; i < binarray.length * 4; i++)  
 {  
  str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +  
      hex_tab.charAt((binarray[i>>2] >> ((i%4)*8)) & 0xF)  
 }  
 return str  
}  
/* 
 * Convert an array of little-endian words to a base64 encoded string. 
 */  
function binl2b64(binarray)  
{  
 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"  
 var str = ""  
 for(var i = 0; i < binarray.length * 32; i += 6)  
 {  
  str += tab.charAt(((binarray[i>>5] << (i%32)) & 0x3F) |  
           ((binarray[i>>5+1] >> (32-i%32)) & 0x3F))  
 }  
 return str  
}  
/* 
 * Convert an 8-bit character string to a sequence of 16-word blocks, stored 
 * as an array, and append appropriate padding for MD4/5 calculation. 
 * If any of the characters are >255, the high byte is silently ignored. 
 */  
function str2binl(str)  
{  
 var nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks  
 var blks = new Array(nblk * 16)  
 for(var i = 0; i < nblk * 16; i++) blks[i] = 0  
 for(var i = 0; i < str.length; i++)  
  blks[i>>2] |= (str.charCodeAt(i) & 0xFF) << ((i%4) * 8)  
 blks[i>>2] |= 0x80 << ((i%4) * 8)  
 blks[nblk*16-2] = str.length * 8  
 return blks  
}  
/* 
 * Convert a wide-character string to a sequence of 16-word blocks, stored as 
 * an array, and append appropriate padding for MD4/5 calculation. 
 */  
function strw2binl(str)  
{  
 var nblk = ((str.length + 4) >> 5) + 1 // number of 16-word blocks  
 var blks = new Array(nblk * 16)  
 for(var i = 0; i < nblk * 16; i++) blks[i] = 0  
 for(var i = 0; i < str.length; i++)  
  blks[i>>1] |= str.charCodeAt(i) << ((i%2) * 16)  
 blks[i>>1] |= 0x80 << ((i%2) * 16)  
 blks[nblk*16-2] = str.length * 16  
 return blks  
}  
/* 
 * External interface 
 */  
function hexMD5 (str) { return binl2hex(coreMD5( str2binl(str))) }  
function hexMD5w(str) { return binl2hex(coreMD5(strw2binl(str))) }  
function b64MD5 (str) { return binl2b64(coreMD5( str2binl(str))) }  
function b64MD5w(str) { return binl2b64(coreMD5(strw2binl(str))) }  
/* Backward compatibility */  
function calcMD5(str) { return binl2hex(coreMD5( str2binl(str))) }  
module.exports = {  
 hexMD5: hexMD5  
}  

3.index.js(重点重点重点)

const app = getApp()
import {
    hexMD5
} from "../../utils/md5.js"
// 提示音
let innerAudioContext = wx.createInnerAudioContext()
innerAudioContext.src = '/img/scanvoice.mp3'
let animation = wx.createAnimation({});
let donghuaInterVal;
// 创建img标签
function createImage(canvas, url) {
    return new Promise((resolve, reject) => {
        const img = canvas.createImage();
        img.src = url;
        img.onload = res => {
            resolve(img);
        };
        img.onerror = err => {
            console.log('create image error', err, url)
            reject(err);
        };
    });
}
function querySelector(elementId, page) {
    const query = wx.createSelectorQuery();
    return new Promise(resove => {
        query
            .in(page)
            .select(/^#/.test(elementId) ? elementId : '#' + elementId)
            .fields({
                node: true,
                size: true,
                rect: true
            })
            .exec(res => {
                resove(res);
            });
    });
}
Page({
    data: {
        indicatorDots: true,
        autoplay: false,
        interval: 2000,
        duration: 500,
        isShowCamera: false,
        isShowScan: false,
        // 相机实例
        ctx: '',
        // 帧数据实例
        listener: '',
        // 锁
        lock: false,
        // 每n秒请求间隔
        fpsTime: 500,
        isHidden: true,
        num: 0,
        imgShow: false,
        isShow: true,
        imgList: [],
        name: '',
        tempImgUrl: '',
        i: 0,
        imgNum: '000',
        textShow: false,
        show: true,
        getframe: false,
        width: 1334,
        height: 750,
    },
    t: Date.now(),
    s: 0,
    changeIndicatorDots() {
        this.setData({
            indicatorDots: !this.data.indicatorDots
        })
    },
    changeAutoplay() {
        this.setData({
            autoplay: !this.data.autoplay
        })
    },
    intervalChange(e) {
        this.setData({
            interval: e.detail.value
        })
    },
    durationChange(e) {
        this.setData({
            duration: e.detail.value
        })
    },
    // 再玩一次
    toIndex() {
        wx.redirectTo({
            url: '/pages/index/index',
        })
    },
    // 分享
    onShareAppMessage(options) {
        return {
            title: '参与就有机会免费领取观影券',
            imageUrl: '/img/share.png',
            path: '/pages/index/index',
            success: function (res) {
                console.log(res, '成功')
                console.info(res + '成功');
                wx.showToast({
                    title: '分享成功',
                })
                // 转发成功
            },
            fail: function (res) {
                console.log(res + '失败');
                // 转发失败
            },
            complete: function (res) {
                // 不管成功失败都会执行
                console.log(res, '成功或失败')
                wx.showToast({
                    title: '成功或失败',
                })
            }
        }
    },
    onLoad() {
        // console.log('进入小程序');
        this.donghua()
        // 监听小程序内存
        wx.onMemoryWarning(function () {
            console.log('内存不足')
        })
    },
    // 修复方法:unload 中进行清理
    onUnload() {
        console.log('小程序销毁');
        this.fnStop()
        // clearInterval(this.data.timer)
        clearInterval(donghuaInterVal)
    },
    // 权限
    open() {
        wx.authorize({
            scope: 'scope.camera'
        }).then(res => {
            this.setData({
                isShowCamera: true
            })
        }).catch(() => {
            wx.getSetting().then(res => {
                if (!res.authSetting['scope.camera']) {
                    wx.showModal({
                        title: '是否授权摄像头',
                        content: '请确认授权,否则无法正常使用',
                        success: (tip) => {
                            if (tip.confirm)
                                wx.openSetting()
                        }
                    })
                }
            })
        })
    },
    // 1.相机初始化
    bindinitdone() {
        this.data.ctx = wx.createCameraContext()
        this.data.listener = this.data.ctx.onCameraFrame(frame => {
            if (!this.data.lock) {
                this.data.lock = true
                this.scan(frame)
            }
        })
        this.data.listener.start()
        this.setData({
            isShowScan: true
        })
    },
    // 2.相机实时帧数据转成base64,调取第三方图像识别算法
    scan(frame) {
        let that = this
        // console.log('222');
        console.log(frame)
        // 将像素数据绘制到画布
        let data = new Uint8ClampedArray(frame.data)
        let clamped = new Uint8ClampedArray(data)
        wx.canvasPutImageData({
            canvasId: 'myCanvas',
            x: 0,
            y: 0,
            width: frame.width,
            height: frame.height,
            data: clamped,
            success(res) {
                // 转换临时文件
                setTimeout(() => {
                    wx.canvasToTempFilePath({
                        x: 0,
                        y: 0,
                        width: frame.width,
                        height: frame.height,
                        canvasId: 'myCanvas',
                        fileType: 'jpg',
                        destWidth: frame.width,
                        destHeight: frame.height,
                        // 精度修改
                        quality: 0.5,
                        success(res) {
                            // 临时文件转base64
                            wx.getFileSystemManager().readFile({
                                filePath: res.tempFilePath, //选择图片返回的相对路径
                                encoding: 'base64', //编码格式
                                success: res => {
                                    // 保存base64
                                    // console.log(res.data);
                                    let base64 = 'data:image/jpeg;base64,' + res.data
                                    // console.log(base64);
                                    that.fnCloudDetect(base64)
                                }
                            })
                        },
                        fail(res) {
                            console.log(res);
                        }
                    }, that)
                    setTimeout(() => {
                        that.data.lock = false
                    }, that.data.fpsTime)
                }, 600)
            },
            fail(err) {
                console.log('图像数据到canvas失败', err)
            }
        })
        // }
    },
    // 3.第三方图像识别算法接口
    fnCloudDetect(base64) {
        let that = this
        const appId = '100000000628';
        const timestamp = String(Math.floor(Date.now() / 1000));
        const nonce = 'weopripowis';
        const requestId = 'cvjkxcvjxcvnm';
        const version = 'v2';
        const appKey = '954cnKRvf9P57JmL';
        const requestUrl = 'https://gw-ezxr.netease.com/pigeon-image/api/alg/pigeon/image/recog';
        const md5_string = "appId=" + appId + "&imageEncodingData=" + encodeURIComponent(base64) + "&nonce=" + encodeURIComponent(nonce) +
            "&requestId=" + encodeURIComponent(requestId) + "&timestamp=" + encodeURIComponent(timestamp) + "&appkey=" + appKey;
        const sign = hexMD5(md5_string).toString().toUpperCase();
        return new Promise((resolve, reject) => {
            wx.request({
                url: requestUrl,
                method: "POST",
                header: {
                    appId,
                    nonce,
                    timestamp,
                    sign,
                    version,
                },
                data: {
                    appId,
                    requestId,
                    imageEncodingData: base64,
                },
                success: (result) => {
                    // console.log("success", result);
                    if (result.data.detail.status === 1 && result.data.status === '000000') {
                        resolve(result.data)
                        if (!that.data.getframe) {
                            that.setData({
                                name: result.data.detail.returnData,
                                show: false,
                                getframe: true
                            })
                            that.initImgList(result.data.detail.returnData)
                            that.data.listener.stop();
                            clearInterval(donghuaInterVal)
                            innerAudioContext.play()
                            wx.showLoading({
                                title: '精彩即将呈现'
                            })
                            console.log('停止获取实时帧')
                        }
                    }
                    reject(result.data.desc);
                },
                fail: (err) => {
                    // console.log("fail", err);
                    reject("request faild");
                }
            })
        })
    },
    // 4.图片列表
    initImgList(name) {
        var tempList = [],
            baseurl, countNum = 0;
        if (name == '伯爵') {
            // baseurl = 'http://bronet.qiniu.bronet.cn/Dracula/Dracula_00' // 自己的
            baseurl = 'https://hpkxjar.una-ad.com/public/Dracula/Dracula_00' // 客户的
            countNum = 144
        } else if (name == '女婿') {
            // baseurl = 'http://bronet.qiniu.bronet.cn/Johnny/johnny_00'
            baseurl = 'https://hpkxjar.una-ad.com/public/Johnny/johnny_00'
            countNum = 103
        } else {
            // baseurl = 'http://bronet.qiniu.bronet.cn/Blobby/Blobby_00'
            baseurl = 'https://hpkxjar.una-ad.com/public/Blobby/Blobby_00'
            countNum = 139
        }
        for (let i = 0; i < countNum; i++) {
            let l = JSON.stringify(i).length
            let baseIndex = l == 1 ? ('00' + i) : l == 2 ? ('0' + i) : i;
            let tempUrl = baseurl + baseIndex + '.png'
            tempList.push(tempUrl)
        }
        this.initCanvas(tempList);
    },
    // 5.创建画布
    async initCanvas(imgs) {
        const canvasQuery = await querySelector('#oneTitleFrameCanvas', this);
        const cnv = canvasQuery[0].node;
        const ctx = cnv.getContext('2d');
        const dpr = wx.getSystemInfoSync().pixelRatio;
        cnv.width = cnv.width * dpr;
        cnv.height = cnv.height * dpr;
        this.cnv = cnv;
        this.ctx = ctx;
        const imgNodes = await Promise.all(imgs.map(v => createImage(cnv, v)));
        this.imgNodes = imgNodes;
        this.fnPlay();
    },
    // 6.序列帧动画播放
    fnPlay() {
        // console.log('开始播放');
        wx.hideLoading()
        this.tickCount = this.cnv.requestAnimationFrame(() => {
            if (Date.now() - this.t >= 1000 / 16) {
                this.t = Date.now();
                if (this.s > this.imgNodes.length) {
                    this.s = 0;
                    this.fnPlay();
                    this.setData({
                        textShow: true
                    })
                } else {
                    this.ctx.clearRect(0, 0, this.cnv.width, this.cnv.height);
                    if (this.imgNodes[this.s])
                        this.ctx.drawImage(
                            this.imgNodes[this.s],
                            0,
                            0,
                            this.cnv.width,
                            this.cnv.height
                        );
                    this.fnPlay();
                    this.setData({
                        textShow: true
                    })
                    this.s++;
                }
            } else {
                this.fnPlay();
            }
        });
    },
    // 释放序列帧
    fnStop() {
        console.log('停止播放序列帧');
        this.cnv.cancelAnimationFrame(this.tickCount);
    },
    // 禁止第二屏滑动
    stopTouchMove: function () {
        return true;
    },
    // 扫描动画
    donghua() {
        var that = this;
        // 控制向上还是向下移动
        let m = true
        donghuaInterVal = setInterval(function () {
            setTimeout(() => {
                if (m) {
                    animation.translateY(500).step({
                        duration: 2000
                    })
                    m = !m;
                } else {
                    animation.translateY(-500).step({
                        duration: 2000
                    })
                    m = !m;
                }
                that.setData({
                    animation: animation.export()
                })
            }, 1)
        }.bind(this), 3000)
    },
    // 上滑动画
    swiperChange(e) {
        this.fnStop()
        if (e.detail.current == 1) {
            wx.redirectTo({
                url: '/pages/video/video',
            })
        }
    }
})


目录
相关文章
|
6月前
|
小程序
微信小程序中识别HTML标签的方法
微信小程序中识别HTML标签的方法
|
6月前
|
小程序
微信小程序中长按识别二维码
微信小程序中长按识别二维码
194 0
|
小程序
微信小程序中长按识别二维码
微信小程序中长按识别二维码
158 0
|
小程序 定位技术 vr&ar
【微信小程序AR】基于Kivicube零代码实现微信小程序AR
话不多说,先看实现效果作者之前尝试过Apple公司的ARkit、Google公司的ARCore以及国产的EasyAR和SenseAR。Apple公司和Google公司的AR产品是市面上的主流,功能非常的完善,基本可以满足所有的程序载体,但是开发门槛非常的高。国内这两款AR产品还不错,但是主要针对的是WebAR,在微信小程序上功能不是很完善,作者在网上查找资源后发现国内弥知科技公司的Kivicube产品完美的适配于微信小程序,而且几乎上是零代码。非常适合小白新手。
455 0
|
小程序 前端开发 安全
【C#】 MVC4 开发小程序-实现人脸识别-本地和手机预览使用IP测试
小程序Camera组件拍照上传图片到指定的服务器(本地或者外网的IP服务器),然后C# MVC后台调用百度人脸识别接口,实现人脸识别功能呢
280 0
|
小程序
uniapp 微信小程序长按识别二维码,跳转小程序、个人微信
uniapp 微信小程序长按识别二维码,跳转小程序、个人微信
uniapp 微信小程序长按识别二维码,跳转小程序、个人微信
|
小程序 前端开发 API
微信小程序利用百度api达成植物识别
## 看完本文你可学会: - 如何使用百度智能云 - 如何在微信小程序中去接入百度api,达成植物识别的效果
|
文字识别 小程序 API
服务端调用微信小程序OCR识别接口实现(下)
服务端调用微信小程序OCR识别接口实现
227 0
服务端调用微信小程序OCR识别接口实现(下)
|
1天前
|
Go vr&ar 图形学
重塑体验:AR/VR技术在游戏与娱乐行业的创新应用
【10月更文挑战第29天】本文探讨了AR/VR技术如何改变游戏与娱乐行业,介绍了AR和VR的基本概念及其在游戏和娱乐中的应用实例,包括《精灵宝可梦GO》的AR开发和VR视频播放器的实现代码,并展望了未来的发展趋势。
12 2
|
5月前
|
人工智能 编解码 5G
虚拟现实(VR)与增强现实(AR)的融合:开启全新交互时代
【6月更文挑战第17天】虚拟现实(VR)与增强现实(AR)融合成混合现实(MR),打造全新交互体验。MR结合VR的沉浸感和AR的现实增强,应用于教育、游戏、设计和营销,带来创新教学方式、沉浸式游戏体验和高效设计工具。尽管面临技术挑战,随着5G和AI的发展,MR有望引领未来交互的革命。