精华内容
下载资源
问答
  • 而且当前版本中也无法通过微信的sdk来创建视频,目前通过unity与微信小程序交互的方式调用微信小程序原生sdk来创建视频(目前仅支持覆盖在游戏界面上播放,无法做到类似videoplayer那样在场景中进行播放)。...

    本文基于minigame-unity-webgl-transform方案,此方案支持大部分Unity组件及方法,比较可惜的是目前版本不支持任何形式的Video播放(不管是MovieoTexture、VideoPlayer还是其他第三方的视频播放插件,比如AVPro、EasyMovieTexture)。

    而且当前版本中也无法通过微信的sdk来创建视频,目前通过unity与微信小程序交互的方式调用微信小程序原生sdk来创建视频(目前仅支持覆盖在游戏界面上播放,无法做到类似videoplayer那样在场景中进行播放)。

    第一步:在unity的Assets目录下创建Plugins文件夹,并在其中创建externFunction.jslib文件,内容如下:

    mergeInto(LibraryManager.library, {
    PlayVideos: function (_src) {
    	PlayVideo(Pointer_stringify(_src));
    }
    });

    第二步:创建一个C#脚本,其中添加如下内容:

        /// <summary>
        /// 按照视频名播放视频
        /// </summary>
        /// <param name="audioname"></param>
        [DllImport("__Internal")]
        private static extern void PlayVideos(string _src);
    
        public void PlayJsVideo(string _src)
        {
            PlayVideos(_src);
        }

    第三步:在场景中创建一个button,并将上面的PlayJsVideo事件添加到onclick事件上。

    第四步:保存场景,并将场景添加到BuildingSetting中,如下图所示:

    第五步:通过微信小游戏的插件导出WEBGL并转换为小游戏,如下图所示:

     转换完成后,在打包目录的minigame下找到webgl.wasm.framework.unityweb.js,并在文件开头添加如下内容:

    //获取屏幕长宽
    let { screenWidth, screenHeight } = wx.getSystemInfoSync();
    function PlayVideo(_src){
      var video = wx.createVideo({
        x: 0,
        y: 0,
        width: screenWidth,
        height: screenHeight,
        // 显示默认的视频控件
        controls: true,
        // 是否自动播放
        autoplay:true,
        // 传入视频地址
        src:_src
      });
      //全屏播放视频
      video.requestFullScreen(0);
      //监听视频播放状态,播放完毕后退出全屏并销毁视频
      video.onEnded(()=>{
        video.exitFullScreen();
        video.destroy();
      });
    }

     搞定收工~

    展开全文
  • 微信小程序

    2019-12-14 10:26:15
    自签名证书微信小程序样式iconfont矢量图标的使用网易云音乐轮播图apiBugssetData监听蓝牙&耳机连接数据处理数组相关添加对象滚动urlencodeJavascriptJava 正则表达式贪婪模式&非贪婪模式Javascript正则...

    小程序源码

    SSL&自签名证书

    • openssl
    • keytool

    微信小程序样式

    iconfont

    矢量图标的使用

    iconfont字体图标的使用

    • 选取图标
    • 添加到项目
    • 下载代码ok
    • demo.html

    open-data

    radius


    网易云音乐

    path: /discover
    

    轮播图api

    pc端实现(user_agent设置,but 微信小程序无法进行user agent设置)

    搭建HTTPS服务器实现

    Bugs

    setData

    原因:组件实例刚刚被创建好时, created 生命周期被触发。此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data 。 此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。

    操作从lyric.wxml redictTo music.wxml
    歌词页面跳转到详细歌单界面

    onShow —> (跳过onHide) —>onUnload

    从首页跳转到详情页,点击左上方的返回按钮,详情页的onHide不触发微信小程序

    • log
    lyricPage onLoad options={"id":"571463522","name":"生如逆旅(Cover 米津玄师)","bg":"http%3A%2F%2Fp1.music.126.net%2FhzlpZj9bzwyk1b0g7Deo0A%3D%3D%2F109951163335209234.jpg"}
    lyric.js? [sm]:149 lyricPage onShow
    playlists.js? [sm]:83 play ..... lyricPage=[object Object]
    lyric.js? [sm]:76 lyricPage lyric setDurations start
    lyric.js? [sm]:169 lyricPage onUnload
    playlists.js? [sm]:83 play ..... lyricPage=[object Object]
    lyric.js? [sm]:76 lyricPage lyric setDurations start
    

    onShow —> (跳过onHide) —>onUnload

    • JS
    console.log("lyricPage lyric setDurations start");
      var all;
    if (this.data.temp != 0)
        clearInterval(this.data.temp);
    this.data.temp =
      setInterval(() => {
         all = app.globalData.audioPlayer.duration;
         console.log("all= " + all + "\t temp_timer=" + this.data.temp);
         var mintues = Math.floor(all / 60);
         var seconds = Math.floor(all - mintues * 60);
         this.setData({
           durations: mintues > 9 ? mintues + ":" + (seconds > 9 ? seconds : "0" + seconds) : "0" + mintues + ":" + (seconds > 9 ? seconds : "0" + seconds)
         }, () => {
           //另外 尚未执行onLoad, onShow ....
           //逻辑????
           //此处不会执行
           console.log("------------------> " + this.data.durations + "\t" + all);
           if (all && all != 0)
             clearInterval(this.data.temp);
         });
      }, 50);
    

    监听蓝牙&耳机连接

    控制音乐播放…

    数据处理

    数组相关

    • splice

      splice(index, length,data...)   
      从index开始操作,将length个元素替换成data
      并返回length个元素
      
    • shift/unshift
      从数组头部删除/添加

    • pop/push
      从数组尾部删除添加

    添加对象

    1. JSON.parse()
    that.data.lyric_time.push(JSON.parse("{\"secs\":\"" + secs + "\",\"str\":\"" + str + "\"}"));
    
    1. ok
    that.data.lyric_time.push({
      secs: secs,
      str: str
    });
    

    方法一parse注意特殊字符… 字符串构造巨坑!!!

    滚动

    • transform
      布局文件
    <view style="transform: translateY({{(4-curIndex)*900/9}}rpx)" wx:for="{{lyric_time}}" wx:key="item" wx:for-item="item" wx:for-index="idx">
          <text class="{{lastTime==item.secs?'highlight':'common'}}" data-time="{{item.secs}}">{{item.str}}</text>
    </view>
    
    • order
      CSS层叠样式表
    .show {
      order: 1;
      mix-blend-mode: difference;
      filter: invert(1);
      -webkit-filter: invert(1);/**-webkit:表示chrome与safari特有属性  */
       color: green;
    }
    

    XML布局文件

    <text hidden="{{lastTime==item.secs?false:true}}" class="show" wx:key="item" wx:for="{{lyric_time}}" wx:for-item="item" wx:for-index="idx">{{item.str}}</text>
    
    • scroll-view
      可滚动视图区域。使用竖向滚动时,需要给<scroll-view>一个固定高度,通过 WXSS 设置 height。组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。
    属性类型默认值必填说明最低版本
    scroll-xbooleanfalse允许横向滚动1.0.0
    scroll-ybooleanfalse允许纵向滚动1.0.0
    upper-thresholdnumber/string50距顶部/左边多远时,触发 scrolltoupper 事件1.0.0
    lower-thresholdnumber/string50距底部/右边多远时,触发 scrolltolower 事件1.0.0
    scroll-topnumber/string设置竖向滚动条位置1.0.0
    scroll-leftnumber/string设置横向滚动条位置1.0.0
    scroll-into-viewstring值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素1.0.0
    scroll-with-animationbolleanfalse在设置滚动条位置时使用动画过渡1.0.0
    enable-back-to-topbolleanfalseiOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向1.0.0
    bindscrolltouppereventhandle滚动到顶部/左边时触发1.0.0
    bindscrolltolowereventhandle滚动到底部/右边时触发1.0.0
    bindscrolleventhandle滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
    • Tips
    1. 请勿在 scroll-view 中使用 textarea、map、canvas、video 组件
    2. scroll-into-view 的优先级高于 scroll-top
    3. 在滚动 scroll-view 时会阻止页面回弹,所以在 scroll-view 中滚动,是无法触发 onPullDownRefresh
    4. 若要使用下拉刷新,请使用页面的滚动,而不是 scroll-view ,这样也能通过点击顶部状态栏回到页面顶部

    urlencode

    problem: get url?param=value (value has character like ‘=’,’&'etc)

    Javascript

    • escape()
      采用ISO Latin字符集对指定的字符串进行编码。所有的 空格符、标点符号、特殊字符以及其他非ASCII字符 都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。比如,空格符对应的编码是%20。
      不会被此方法编码的字符: @ * / +

    • encodeURI()
      把URI字符串采用UTF-8编码格式转化成escape格式的字符串。
      不会被此方法编码的字符:! @ # $& * ( ) = : / ; ? + '

    • encodeURIComponent()
      把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码,比如 / 等字符。所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。
      不会被此方法编码的字符:! * ( ) '

    因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面的charset是一致的时候),只需要使用 escape。如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用encodeURI或者 encodeURIComponent。

    Java 正则表达式贪婪模式&非贪婪模式

    Pattern pattern = Pattern.compile("window.Gbanners =[\n|\r\n](\\[.*?]);", Pattern.DOTALL);   //非贪婪模式匹配... 假如:数组元素也是数组?? so how can i do it
    Matcher matcher = pattern.matcher(str);
    if (matcher.find()) {
       return matcher.group(1);
    }
    

    如果数组元素中也含有数组??? how ??

    private static void test() {
        Pattern p = Pattern.compile("window.Gbanners =\n(\\[.*?]);", Pattern.DOTALL);
        String str = "window.Gbanners =\n[hello, what happened ? [bye];....];endherehello[yue];";
        Matcher matcher = p.matcher(str);
        if (matcher.find())
            System.out.println(matcher.group(1));
        else
            System.out.println("???");
    }
    

    如何提取"[hello, what happened ? [bye];…]"??
    麻烦:

    String str = "window.Gbanners =\n[hello, what happened ? [bye];[yue];....];hello[yue];";
    p=Pattern.compile("window.Gbanners =\n(\\[[\\w\\d\\,\\?\\s]+(\\[\\w+\\];)+\\.+\\]);");
    Matcher matcher = p.matcher(str);
    matcher.find();
    System.out.println(matcher.group(1));
    

    Result: [hello, what happened ? [bye];[yue];…]

    Javascript正则表达式

    var patt1=/picUrl\s+:\s+\"([\w|\d|\\.|\\/|:|=]+)\"/g;
    var s="[{picUrl: \"http://p1.music.126.net/7FGoymx2D3EhcXHdRvEY6g==/109951163988241908.jpg\"}......{picUrl: \"http://p1.music.126.net/pyPxPCKnqDC_MgcAH2gqcA==/109951163988013828.jpg\",url: \"https://music.163.com/m/at/5cac89eda987b31a74b53324\",targetId: \"0\",backgroundUrl: \"http://p1.music.126.net/Wj7RwWtJHqZW1znWmZeUyA==/109951163988019180.jpg\",targetType: \"3000\",monitorType: \"\",monitorImpress: \"\",monitorClick: \"\"}, {picUrl: \"http://p1.music.126.net/9UHGYULLYF_ErmiGv_ilPA==/109951163987312687.jpg\",url: \"https://music.163.com/m/at/5cac4505a987b31a74b53247\",targetId: \"0\",backgroundUrl: \"http://p1.music.126.net/f6kKp_6tRoAfs8DcQ241CA==/109951163987307347.jpg\",targetType: \"3000\",monitorType: \"\",monitorImpress: \"\",monitorClick: \"\"}, {picUrl: \"http://p1.music.126.net/YxxZQkEa1Sf1fQdE7xmKQA==/109951163987278183.jpg\",url: \"/album?id=78399447\",targetId: \"78399447\",backgroundUrl: \"http://p1.music.126.net/0e8-38VasU3FF_dNQ1gezg==/109951163987283041.jpg\",targetType: \"10\",monitorType: \"\",monitorImpress: \"\",monitorClick: \"\"}]";
    
    var res=s.match(patt1);
    res[0]picUrl: \"http://p1.music.126.net/7FGoymx2D3EhcXHdRvEY6g==/109951163988241908.jpg\"
    // 继续正则表达式
    
    var re;
    for(re=patt1.exec(); re!=null; re=patt1.exec()){
      re[0]//picUrl: \"http://p1.music.126.net/7FGoymx2D3EhcXHdRvEY6g==/109951163988241908.jpg\"
      re[1]//http://p1.music.126.net/7FGoymx2D3EhcXHdRvEY6g==/109951163988241908.jpg
    }
    

    Javascript正则表达式不包含分组概念,使用regex.exec()—>类比分组概念,but 一次获取一个ok…
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uNaSH69S-1576289813452)(./js_regex.jpg )]


    GitHub

    api:登陆…
    由于github.com未在ICP备案因此微信小程序不可直接进行数据请求(自建服务器,不校验)

    登陆

    POST /session HTTP/1.1
    Host: github.com
    Content-Type: application/x-www-form-urlencoded
    
    utf8=%E2%9C%93&authenticity_token=3GKDT3%2BeaF8GThohy848CKypLgt%2FG3eZXFj%2BUorzX%2BVK07sS2%2BJLGTXfxux5W9ptA0epJVdMt%2B3Nl4kTdsy6mA%3D%3D&login=guanyue003%40gmail.com&password=hellogit123
    
    Response:
      Location: https://github.com/
    
    Redict:
      Request URL: https://github.com/
      Request Method: GET
    
    // Html 页面
    

    登出

    Request URL: https://github.com/logout
    Request Method: GET
    --&gt; 登出界面
    
    登出数据
    Request URL: https://github.com/logout
    Request Method: POST
    Content-Type: application/x-www-form-urlencoded
    
    utf8: ✓
    authenticity_token://html hidden TEnKx7MjccfdIgtcDe2ibrAxezbhqz5ZotsXiQjNr2BGzljGMSxhHlt4KWlj5Hw5lvz/DIN+5JBzIM53pxVyqg==
    
    Response:
    Location: https://github.com/
    

    stats请求: ???

    Request URL: https://api.github.com/_private/browser/stats
    Request Method: POST
    Content-Type: application/json; charset=utf-8
    
    data ......
    
    when logout:
    {"stats":[{"resourceTimings":[{"initiatorType":"link","nextHopProtocol":"h2","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":797.6999999955297,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"connectEnd":0,"secureConnectionStart":0,"requestStart":0,"responseStart":0,"responseEnd":1006.6999999980908,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"name":"https://github.githubassets.com/assets/mobile-8e8e5b12902d5f04bad25bdd1b689f64.css","entryType":"resource","startTime":797.6999999955297,"duration":209.00000000256114},{"initiatorType":"img","nextHopProtocol":"http/1.1","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":797.8999999759253,"domainLookupStart":797.8999999759253,"domainLookupEnd":797.8999999759253,"connectStart":797.8999999759253,"connectEnd":797.8999999759253,"secureConnectionStart":0,"requestStart":799.9999999883585,"responseStart":989.3999999912921,"responseEnd":989.899999985937,"transferSize":481,"encodedBodySize":0,"decodedBodySize":0,"name":"https://avatars2.githubusercontent.com/u/31913612?s=40&v=4","entryType":"resource","startTime":797.8999999759253,"duration":192.00000001001172},{"initiatorType":"script","nextHopProtocol":"h2","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":797.999999980675,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"connectEnd":0,"secureConnectionStart":0,"requestStart":0,"responseStart":0,"responseEnd":803.2999999995809,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"name":"https://github.githubassets.com/assets/mobile-bootstrap-6ccc3aa0.js","entryType":"resource","startTime":797.999999980675,"duration":5.300000018905848}],"timestamp":1555033117792},{"navigationTimings":[{"unloadEventStart":792.9999999760184,"unloadEventEnd":792.9999999760184,"domInteractive":800.199999997858,"domContentLoadedEventStart":800.3000000026077,"domContentLoadedEventEnd":800.3000000026077,"domComplete":1013.0999999819323,"loadEventStart":1013.0999999819323,"loadEventEnd":1013.1999999866821,"type":"navigate","redirectCount":0,"initiatorType":"navigation","nextHopProtocol":"http/1.1","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4.499999980907887,"domainLookupStart":6.599999993341044,"domainLookupEnd":6.599999993341044,"connectStart":6.599999993341044,"connectEnd":318.7999999790918,"secureConnectionStart":173.39999999967404,"requestStart":322.09999999031425,"responseStart":789.0999999945052,"responseEnd":792.3999999766238,"transferSize":6349,"encodedBodySize":3863,"decodedBodySize":11490,"name":"https://github.com/logout","entryType":"navigation","startTime":0,"duration":1013.1999999866821}],"timestamp":1555033117792}]}
    

    小程序请求Cookie

    请求后的数据

    {
      "data" : "",//response_body
      "header" : {},//response_header
      "statusCode" : 200,//状态码
      "cookies" : [],//set-Cookie格式化数据
      "errMsg" : "request:ok"
    }       
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRxg4YmG-1576289813453)(数据请求返回结果.jpg “数据请求返回结果”)]

    在这里插入图片描述

    Cookie相关

    在这里插入图片描述
    在这里插入图片描述

    由图可知
    cookies设置简化
    不用从header中setcookie查找分析

    res.cookies[{
      "name":"",//
      "value":"",//
      "path":"",//路径
      "expires":"",//租期
      .....
    }]
    

    Cookie设置

    wx.setStorageSync("sessionid", res.header["Set-Cookie"])
    header = {
        'cookie':wx.getStorageSync("sessionid")//读取cookie
    };    
    

    163Mail

    api: 登陆

    later


    Java 正则表达式介绍

    贪婪模式表达式:

    贪婪模式 * + {n,} 默认情况是贪婪模式匹配

    表达式含义
    X?X,一次或一次也没有
    X*X,零次或多次
    X+X,一次或多次
    X{n}X,恰好 n 次
    X{n,}X,至少 n 次
    X{n,m}X,至少 n 次,但是不超过 m 次

    非贪婪模式表达式:

    非贪婪模式,?跟在 * + {n,} 等的后面时,表示非贪婪模式,注意和子表达式后面的?区分开,子表达式后的?表示匹配0次或1次

    表达式含义
    X??X,一次或一次也没有
    X*?X,零次或多次
    X+?X,一次或多次
    X{n}?X,恰好 n 次
    X{n,}?X,至少 n 次
    X{n,m}?X,至少 n 次,但是不超过 m 次

    Problem

    in util/core.js

    var app=getApp();
    

    exception: app undefined … …

    App() 必须在 app.js 中注册,且不能注册多个。

    • 不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例。
    • 不要在 onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成。
    • 通过 getApp() 获取实例之后,不要私自调用生命周期函数。
    • 直接修改 this.data 而不调用 this.setData是无法改变页面的状态的,还会造成数据不一致。
    • 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
    • 请不要把 data 中任何一项的 value 设为 undefined,否则这一项将不被设置并可能遗留一些潜在问题。
    展开全文
  • 在写微信小程序时,有写到实现3D轮播图的效果,可以直接使用微信小程序中自带的组件swiper来实现 效果图如下: 1.swiper的相关属性 indicator-dots 是否显示小圆点,也可以自己重新设置小圆点 circular 是否衔接...

    在写微信小程序时,有写到实现3D轮播图的效果,可以直接使用微信小程序中自带的组件swiper来实现

    效果图如下:

    1.swiper的相关属性

    indicator-dots 是否显示小圆点,也可以自己重新设置小圆点 circular 是否衔接滑动,就是实现无限滚动 previous-margin 与上一张图片的间距 next-margin 与下一张图片的间距 autoplay 实现自动滚动

    这里主要利用了circular实现无限滚动,然后再加上前后间距,再设置图片的层级和透明度就可以实现了,将图片及容器的高度设置好就差不多可以实现了

    wxml文件

    
    <!--carousel/index.wxml-->
    <swiper class="imageContainer" bindchange="handleChange" previous-margin="50rpx" next-margin="50rpx" circular autoplay>
      <block wx:for="{{3}}" wx:key="{{index}}">
        <swiper-item class="item">
          <image class="itemImg {{currentIndex == index ? 'active': ''}}" src="../../../image/3.jpg"></image>
        </swiper-item>
      </block>
    </swiper>
    
    复制代码

    wxss文件

    
    /* carousel/index.wxss */
    page{
      background: #f7f7f7f7;
    }
    .imageContainer{
      width: 100%;
      height: 500rpx;
      background: #000;
    }
    .item{
      height: 500rpx;
    }
    .itemImg{
      position: absolute;
      width: 100%;
      height: 380rpx;
      border-radius: 15rpx;
      z-index: 5;
      opacity: 0.7;
      top: 13%;
    }
    .active{
      opacity: 1;
      z-index: 10;
      height: 430rpx;
      top: 7%;
      transition:all .2s ease-in 0s;
    }
    
    复制代码

    JS文件

    // carousel/index.js
    Page({
    
      data: {
        currentIndex: 0
      },
    
      onLoad: function (options) {
      
      },
      /* 这里实现控制中间凸显图片的样式 */
      handleChange: function(e) {
        this.setData({
          currentIndex: e.detail.current
        })
      },
    })
    复制代码

    这里推荐一下我的前端学习交流群:784783012,里面都是学习前端的,如果你想制作酷炫的网页,想学习编程。自己整理了一份2018最全面前端学习资料,从最基础的HTML+CSS+JS【炫酷特效,游戏,插件封装,设计模式】到移动端HTML5的项目实战的学习资料都有整理,送给每一位前端小伙伴,有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。

    转载于:https://juejin.im/post/5bcc7eb0e51d457a361f8a0a

    展开全文
  • 微信小程序开发实战

    千次阅读 2019-08-04 15:12:40
    微信小程序开发实战 ================================================= cemike@126.com 本文介绍了作者开发Swing English微信小程序的实践。从实践经验提出微信小程序开发的最佳实践步骤和常见问题的解决方法。...

    =================================================

    微信小程序开发实战

    =================================================

    cemike@126.com

    本文介绍了作者开发Swing English微信小程序的实践。从实践经验提出微信小程序开发的最佳实践步骤和常见问题的解决方法。

     

    现在真是个好时代。以前要搞个个人HomePage可以说非常麻烦,甚至是不可能。即使可能也得花相当可观的一笔钱。后来有了博客这些东西之后,写博客这种静态网页的时代来临了。但在博客上只能显示文字图片给用户看,用户顶多只能回复评论,不能有其他交互。

    现在腾讯(还有其他大佬,如阿里也提供云服务,新浪也有新浪云)提供了一个用户可以设计动态网页的的地方,叫做微信小程序。就是说,你可以自己决定在网页上显示些什么(像小孩玩积木一样,放哪些方块),怎么布局(方块放哪儿),怎么交互(用户点击了某个方块以后接下来做什么,如弹出个提示等等)。这下你可以折腾很久了。

    而且这一切都是免费的。

    这在以前就像是在做梦。以前我们都说天下没有免费的午餐。现在真有免费的午餐了!

    一、概述

    先简要介绍一下本文要说的Swing English微信小程序。

    1. Swing English微信小程序是一个致力于提高学生英语词汇和口语学习的应用,与Swing English微信公众号同步服务,与MyOral.Android手机apk相互配合使用。

    2. 通过WordQuiz测试(语音播放和图片卡片选择)让学生实现从最初级的简单英语单词到高级复杂英语句子的听力和理解。

    3. 通过ImageQuiz测试(看图从四个选项中选择正确单词)等练习巩固词汇学习。

    4. 通过Gallery输入关键词查询和展示相关图片,同时显示中英文对照的例句,提供图文并茂的富媒体的英语学习环境。

    二、说人话:微信小程序是什么,提供了什么,可以做什么,有什么限制

    微信小程序是什么?

    微信小程序就是可以在微信里运行的小程序。个人理解,微信小程序其实就是必须根据官方的标准设计,只能在微信平台上显示的一组网页。比微信公众号提供了更多可定制的交互方式,如界面按钮、文本框、列表等;而公众号基本上只能通过菜单和回复进行用户交互。

     

    提供了什么?

    微信小程序提供了一种机会和能力。有点儿像给你一个建立个人网页的地方。开发者可以在微信上向其他微信用户展示一些信息,完成交互,收集用户提供的数据或者在交互过程中生成的数据。

     

    可以做什么?

    能做些什么呢?几乎网页能做的大部分事情。用几乎是因为只能在微信上运行,商业竞争的关系还有腾讯的尿性,所以有诸多限制。无论如何,以前你在自己的电脑上玩静态网页设计能做的大部分事情都能做。尤其是可以使用类似JS(JavaScript)操控浏览器的能力(页面跳转,根据用户选择改变页面上显示的内容),这样就比较好玩了。

    有什么限制?

    如开头所说,微信小程序是腾讯老爷提供的免费午餐。但这免费午餐吃得滋味如何,吃过的人都知道。俗话说,吃人家的嘴软,拿人家的手软。吃免费午餐当然就得有各种限制。据我所知,微信小程序有以下限制:

    1. 小程序整个的开发打包的文件体积不能超过1M。

    现在随便拍张图片都几十M了。是啊,所以小程序上基本只能放代码(文本文件),别指望放很多图片,视频什么的更别想。

    这也太小气了点,你也许会说。但是你想象一下目前微信上上线的有多少小程序!不用看官方统计都知道,可以说是成千上万,犹如星辰大海。如果不限制大小,人人免费开发上传,马化腾也会肚子痛的。这也可以理解嘛。

    既然是人家施舍的,那还是忍了吧。

    2.只提供数据访问的能力,不提供数据访问的服务

    腾讯只给你提供存储并在微信里加载展示网页的地方。如果你要用到访问数据库什么的(从数据库查询数据,或者把用户的数据上传到数据库;少量的只是查询的话,可以硬编码在JS代码里,我就喜欢这么干),当然小程序提供这种访问的能力。谁给你提供这种数据存储和查询服务,那你就得另找高明了,如我用过leancloud(也是一部血泪史)。当然微信小程序现在推出了云开发可以在云函数中读写的 JSON 数据库(参考https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)。本人没用过,是否收费等等还不知道。

    3.封闭性

    限制或禁止访问外部网址。也就是说要跳转网页的话,就只有微信朋友圈里那些鸡汤文是畅通无阻的。如果你搞小心机,想要直接在微信里展示某个腾讯系统之外的网页,那对不起,好点的,弹出提示,用户允许后可以访问;运气不好的话直接禁止。

    这也是被无数键盘侠猛烈抨击的地方。腾讯几乎要被键盘侠们的口水淹没了。

    对此我不想说什么,既然前面的都忍了,那就再忍忍吧。

    4.不可预测性

    人在屋檐下,不得不低头。在比人的地盘上当然任人宰割。现在当然这些都是免费的。大家都乐呵呵。可是别忘了互联网上有个说法叫“割韭菜”。现在给你们这些吃瓜群众免费使用叫做培植用户土壤,扩大用户基数。等具备一定规模了(还有压制竞争对手),就要“割韭菜”了。到时想收费就收费。收多少都是大爷说了算。不爽?你可以滚蛋!

    所以要随时做好撤出腾讯系的准备(备份代码和数据),别到时候哭都来不及!

     

    三、微信小程序申请和开发环境搭建

    1. 微信小程序申请 https://mp.weixin.qq.com/

    这里就不展开了。网上有大把文章可参考。

     

    2. 开发环境搭建还是比较傻瓜化的,下载安装官方提供的微信开发者工具就可以了。

    开发环境下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

    四、Swing English微信小程序构架

    A. 第三方框架

    由于我们的小程序比较简单,所以没有使用第三方框架,直接使用的官方提供的开发工具。

    感兴趣的同学可以参考:小程序第三方框架对比 ( wepy / mpvue / taro )

    https://www.cnblogs.com/Smiled/p/9806781.html

    B. 导航

    1. 除非是功能非常单一的小程序(例如我之前练手时开发的英语音标学习小程序MyPhonetics), 一般我们需要一个导航栏。

    2. 开始时我采用了最简单的只有顶部两栏的一个导航设置。参考:微信小程序tab切换效果 https://jingyan.baidu.com/album/59703552b60db78fc0074036.html?picindex=7

    但是这种设计其实是一种伪导航,并不是真正的跳转到一个新页面。它是通过显示和隐藏底部的组件来实现的。所有内容其实都在一个页面上。所以随着内容越来越多,页面就会变得很臃肿。而且也不容易扩展。将两个栏目扩展成三栏四栏也不是不可能,但是肯定很麻烦。为了最大程度使各个页面解耦合,两栏不够用了之后就不用这种设计了。

    3. 后来尝试过官方自带的微信小程序底部导航Tabbar,参考

    https://www.cnblogs.com/huangjialin/p/6278429.html。但是觉得太丑,弃用。

    4. 开始打起自定义头部导航栏("navigationStyle": "custom")的主意。并且参照https://blog.csdn.net/hangGe0111/article/details/85232022改动做成了自己的。

    微信官方的顶部组件只能显示标题和右侧胶囊按钮。胶囊按钮里有三点的弹出菜单和关闭小程序按钮。

    自定义头部导航栏之后除了胶囊按钮仍然保留,其他的如增加背景图片、在左侧放入一个返回按钮甚至增加更复杂的页面元素可以完全自己定制。但是这个顶部的空间高度是有限制的,而且胶囊按钮不能去掉也不能挪动位置,所以可以发挥的空间还是有限。纠结之后还是决定只在左侧放一个返回按钮,然后在首页放上跳转到其他页面的按钮。

    这个定义头部导航栏有个好处就是灵活。通过设置js代码中的flag属性可以控制点击左侧按钮的三种不同的动作: 0表示无返回;1表示返回上一级;2表示返回home(首页)。

    这个定义头部导航栏设置有点儿复杂。每个页面都要做3方面的设置(以index页面为例):

    1) index.wxml里第一行增加以下内容,相当于包含进来一个组件。注意:每个页面都必须这样做,否则顶部风格就不统一了。

    <my-component my-property='{{aa}}' />

     

    2) index.js里增加以下内容:

    Page({

      data: {

        aa: {

          "bg_color": "orange",

          "color": "#000",

          "flag": 1, //flag 0:无返回;1:返回上一级;2:home

          "name": "我是标题独一无二天下无敌我是标题独一无二天下无敌"

        }

      },

    })

     

    3) index.json里增加以下内容:

    {

         "usingComponents": {

                     "my-component": "/components/custom-component"

        }

    }

     

    这个定义头部导航栏还用到了一种技术:用Base64编码字符串保存图片。你会注意到左侧的房子和左箭头按钮其实都是图片,但组件的定义里没有引用任何png或jpg图片文件。这样做的好处是可以节省文件的体积。这种技术对于总体积不能超过1M的尴尬限制来说非常有价值。更多用法可参考:

    Css中路径data:image/png;base64的用法详解 (转载)

    https://www.cnblogs.com/OpenCoder/p/7127256.html

    图片转换Base64

    http://imgbase64.duoshitong.com/

     

    5. 最后发现官方还有一种导航组件

    再改版时考虑尝试一下这种navigator导航组件。

    更多用法可参考:

    微信小程序导航组件官方文档navigator

    https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html

    微信小程序之导航组件

    https://www.jianshu.com/p/53ac270215cb

     

    C.数据

    (一)少量的数据

    1. 可以直接定义在Page的data里面,冒号:左边的相当于变量名称,不需要任何引号;冒号右边的相当于变量的值,字符串需要用单引号或者双引号包括,数字不需要引号:

    Page({

      data: {

        motto: "Let's Swing English",

         imageSrc1:'http://lc-GI3Digt4.cn-n1.lcfile.com/92f945005f25e192f75e.jpg',

         inputCon: {},

         map:app.globalData.map,

         entry:'',

         sentenceEn:'',

         sentenceCn:'',

         total:1,

         correct:0,

         rate:0,

         }

    }) 

     

    2. 在.wxml文件里引用的时候可以直接用双花括号包含变量名称{{motto}}

      <view class="usermotto">

        <text class="user-motto">{{motto}}</text>

      </view>

     

    3. 甚至可以在style属性里引用,如

    <view class='flex commonHead' style='color:{{myProperty.color?myProperty.color:"#000"}};background-color:{{myProperty.bg_color?myProperty.bg_color:"white"}}; height:{{commonHeadHeight.titleHeight}}px;'>

     

    4. 也可以放在data-[参数名]这样的属性里,如data-id定义了一个叫做id的参数,data-text定义了一个叫做text的参数,用作参数传给事件,如bindtap,bindinput,bindconfirm,bindchange等等,如bindtap="onViewClick"表示用户点击事件由onViewClick函数处理,bindchange="bindChange"表示文本框输入的文字改变事件由bindChange函数处理:

     

                     <view  class="item" data-id='1' bindtap="onViewClick">Gallery</view>

     

                     <view class="sentence" data-text='{{sentenceEn}}'  bindtap="playTTS2" >{{sentenceEn}}</view>

                     <view class="sentence" data-text='{{sentenceCn}}'  bindtap="playTTS2" >{{sentenceCn}}</view>

     

                     <view class="query-form">

                                 <input id="keyword"  confirm-type="search" placeholder-style="color:black;" placeholder-class="place-holder" class="keyword-input" placeholder=" Enter keyword" bindinput="bindChange" bindconfirm="query"/>

                                 <button class="query-btn"   loading="" plain="true" disabled="{{disabled}}" bindtap="query"> GO </button>

                     </view>

     

    bindChange函数则是定义在.js文件里:

     

      bindChange: function (e) {

        var id;

        var value;

        id = e.target.id;

        value = e.detail.value + '';

        this.data.inputCon[id] = value;

      },

     

    其中id = e.target.id;表示取出前面.wxml文件里定义的id参数。

     

    5. 数据也可以直接定义在app.js文件里App的globalData里面: 

    App({

      globalData: {

        userInfo: null,

        ctxPath: 'https://www.baidu.com',

         statusBarHeight:wx.getSystemInfoSync()['statusBarHeight'],

         map:[

                     {id:18, word:"accident", pos:"n.", meaning:"事故,意外的事", url:"http://lc-GI3Digt4.cn-n1.lcfile.com/f418c66cc34c4e986504.jpg", sentence:"The accident scared me out of sense. ", chinese:"那事故真把我吓死了。"},

                     {id:32, word:"actor", pos:"n.", meaning:"男演员", url:"http://lc-GI3Digt4.cn-n1.lcfile.com/ba0bcef519d5cddb9af3.jpg", sentence:"", chinese:""},

         ],

    })

     

    这样的好处就是,这样定义的变量是全局的,可以在任意页面里引用。如可以在任意页面用app.globalData.ctxPath引用app.js文件里定义的ctxPath变量:

         var app = getApp();

         that.setData({

            web_src: app.globalData.ctxPath,//ctxPath

        })

     

    6. 除了data,globalData这种常用的变量命名,也可以定义自己特有的变量名:

    Component({

      properties: {

        myProperty: {

          type: Object,

          value: {

            "bg_color": "white",

            "color": "#000",

            "flag": 1,

            "name": "我是标题"

          }

        },

        commonHeadHeight: {

          type: Object,

          value: {}

        }

      },

    })

     

    其中myProperty,commonHeadHeight都是自定义的对象类型的变量。可以在js代码里操作:

     

     ready: function () {

        var that = this;

        wx.getSystemInfo({

          success(res) {

            that.setData({

              "commonHeadHeight.statusBarHeight": (34 * 2),

              "commonHeadHeight.titleHeight": res.statusBarHeight + 46

            });

     

          }

        })

      },

     

    7.还有些数据是定义在.json文件里,如app.json文件里。

    {

      "pages": [

        "pages/index/index",

        "pages/user/user",

        "pages/setting/setting"

     

      ],

      "window": {

        "backgroundTextStyle": "light",

        "navigationBarBackgroundColor": "#fff",

        "navigationBarTitleText": "WeChat",

        "navigationBarTextStyle": "black",

        "navigationStyle": "custom"

      },

      "plugins": {

        "WechatSI": {

          "version": "0.2.2",

          "provider": "wx069ba97219f66d99"

        }

      },

      "sitemapLocation": "sitemap.json"

    }

     

    其中:pages数组的第一条就是默认的首页(小程序默认加载的页面);一些插件如同声传译(文本转语音/朗读)插件WechatSI就是定义在这里。

     

    (二)大量的数据

    超大规模大量的数据还有依赖大量图片的小程序当然是要通过第三方提供的数据库服务如leancloud进行查询。

    但是如果规模不是很巨大,也是可以硬编码在js代码中的。如下面这个map数组里我存储了4000多条词典数据,上线运行以后仍然非常流畅,并没有预期的卡顿现象。

    考虑到第三方数据服务不是永远可靠,而且动辄收费,硬编码的数据其实是一个较好的折衷选择,尤其是对于只需查询,不需要日常更新的数据。

     

    App({

      globalData: {

         map:[

                     {id:18, word:"accident", pos:"n.", meaning:"事故,意外的事", url:"http://lc-GI3Digt4.cn-n1.lcfile.com/f418c66cc34c4e986504.jpg", sentence:"The accident scared me out of sense. ", chinese:"那事故真把我吓死了。"},

                     {id:32, word:"actor", pos:"n.", meaning:"男演员", url:"http://lc-GI3Digt4.cn-n1.lcfile.com/ba0bcef519d5cddb9af3.jpg", sentence:"", chinese:""},

                     //more

         ],

    })

    D.  查询

    查询第三方提供的数据库服务,这个另开一篇文章专门说明。

     

    五、踩过的坑和解决方法

    (一)开发环境的坑:调试不通过我很开心

    查询存储在leancloud上的数据,真机调试时通过,上线版本无响应(不显示图片)。微信小程序这个报错是什么原因?怎么解决?

    报错提示如下:

    VM45:1 Error: Request has been terminated

    Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc. [N/A POST https://gi3digt4.api.lncld.net/1.1/users]

    注:使用了leancloud

    我在微信开放社区(https://developers.weixin.qq.com/community/develop/question)提问,有人回答说没配置安全域名。这个应该不可能。已经配置安全域名。再说,如果没配置,真机调试时就不可能通过。

    有人回答说Access-Control-Allow-Origin  发生跨域了。这个的确很有误导性,因为报错提示中的确提到Origin is not allowed by Access-Control-Allow-Origin。

    我开始以为是因为访问了leancloud。但是我是根据leancloud的样板工程代码改的啊,样板工程为什么就能运行正常呢?

    经过无数种尝试,所有可能的组合我都试过了,还是解决不了问题。最后我咬着牙把开发环境升级了。因为一般不到万不得已我是不会这么做的。对于软件,这么多年的经验告诉我,能用就不要升级。升级后即使体验好了也会使软件体积急剧膨胀。还有很多时候升级了就没法用了。尤其是那些破解的收费软件,千万不能升级。

    升级之后终于开发环境调试也无法通过了。这是什么话?别人都指望调试能通过。我却因为调试我通过而开心。因为至少本地的和上线版本的表现一致了。这比本地好好的,上线就出错,让人百思不得其解的痛苦少一些。

    我终于搞明白了。和新版本的开发环境相比,一定是旧版本各种安全检查少一些,还存在一些漏洞。所以旧版本真机调试能通过。但是线上版本的运行环境一定是和最新版本的开发环境是一致的。所以才导致以上如此诡异的现象。

     

    (二)函数/方法

    微信小程序的自定义方法都是定义在.js文件里。

    注意:

    1. 方法其实有两种定义格式:App({...})或者Page({...})里面的和外面的。

    2. App({...})或者Page({...})里面的格式:先方法名bindChange,冒号后面才是 function,然后是参数列表,最后花括号包住方法体,如

      bindChange: function (e) {

        var id;

        var value;

        id = e.target.id;

        value = e.detail.value + '';

        this.data.inputCon[id] = value;

      },

    3. App({...})或者Page({...})里面的方法前后都要有英文逗号,否则报错。

    因为小程序整个的这种代码组织架构,都是json模式化的,不管是数据还是方法都这样。这好像已经成了一种潮流。

    其实第一个这么干的不是json(LISP语言的S表达式是Lisp语言的鲜明特点,使数据和代码形式统一)。想当初LISP语言(LISP,List Processing,1958年诞生)大行其道的时候,现在主流的那些编程语言(C,1970年;C++,1985年;Perl,1987年;Python,1994年;PHP,1995年;Java,1996年;参考:当编程语言都变成女孩子 https://www.oschina.net/news/53201/programming-language-as-a-girl)都还没诞生。

    可惜LISP风光不再( 许多人对Lisp语言的第一印象就是一层层的括号,很老的关于苏联黑客偷到Lisp源码的最后一页全是括号的笑话就不用再说了。参考:Lisp永远成不了编程主流语言 https://www.cnblogs.com/tkt2016/p/5755974.html),没想到它的这种极简的语法风格倒是被json(严格来说不是一种语言)这样的后辈继承了,现在又因为在网络编程中广泛运用而变一种样式火了起来。

    《Lisp神化之路》这篇文章中说:如今越来越多的Lisp特性被加入到大家使用的编程语言中了。Python有了列表comprehensions。C#有了Linq。Ruby有了…,好吧,Ruby就是一种Lisp。

    参考:https://blog.csdn.net/code_for_fun/article/details/83304873

     

    4. 如果不在App({...})或者Page({...})里面那么就是以前为浏览器网页编写js方法那种格式:function关键字后面跟方法名,如

    function playTTS(text) {

      //need to add WXAPP plug-in unit: WechatSI

      plugin.textToSpeech({

        lang: "zh_CN",

        tts: true,

        content: text,

        success: function (res) {

          //log("succ tts", res.filename)

          innerAudioContext.src = res.filename;

          innerAudioContext.play()

        },

        fail: function (res) {

          //log("fail tts", res)

        }

      })

    }

     

    5. 两种格式定义的方法,调用方式也不一样。

    在App({...})或者Page({...})里面定义的方法,必须在前面加上this.否则报找不到方法的错误(这个坑浪费了我大半天的时间,sigh!)

    onReady: function () {

        this.playTTS(this.data.stem);

      },

    在App({...})或者Page({...})外面定义的方法,不要在前面加上this.  。 

    (三)that = this ?

    这不是文字游戏!前面提到微信小程序.js文件App({...})或者Page({...})里面引用变量和方法都要在前面加上this. 。

    但是我们也经常看到网上复制下来的代码有下面这种赋值操作: var that = this;。这是在搞笑吗?还是作者故弄悬殊?其实不是的,听我慢慢道来。

    如果不是方法里嵌套方法,用this.是没有问题的。但是如果是像下面这样setTimeout()方法里面再嵌套一层function () {}再用this.就不起作用了。

    这时用上面那句类似巫术一样的代码并且在内嵌的方法中用that.引用自己定义的变量和方法就又起作用了。这里面有一些原理,我就不去深究了,代码能用就行。

     

      var that = this;

        setTimeout(function () {

          //要延时执行的代码                   

          //语音朗读

          that.playTTS(that.data.stem);

     

        }, 1500) //延迟时间 这里是1秒

     

    六、小程序发布:开发版、体验版、审核版、上线版和建议

    小程序界面设计得差不多了就要调试。实际上调试占了小程序开发的大部分时间。

    1. 先在开发环境了调试。然后真机调试。真机调试这一步不能少。有些特性在开发环境上和真机上表现是不一致的。例如,弹出提示框里的文字换行\r\n,在开发环境上看不到换行效果。但在手机上就能换行。

     

    2. 最后终于要上传发布了。发布分很多版本:开发版(真机调试的版本)、体验版(通过微信开发者工具菜单:工具>上传 上传的版本)、审核版(登录微信公众平台https://mp.weixin.qq.com在版本管理页面开发版本一栏点击“提交审核”该版本就成为审核版)、上线版(审核通过后上线的版本,所有人都能访问)。

     

    3. 其中体验版只有你登录微信公众平台https://mp.weixin.qq.com在成员管理页面体验成员一栏指定的微信用户能访问。版本管理页面开发版本一栏点击带二维码的按钮弹出的页面有小程序二维码,可以自己下载二维码发给体验成员。

     

    4. 审核这个环节要耐心等待,且做好多次修改提交审核的准备。根据个人经验,腾讯这方面很不厚道。审核非常挑剔,经常找茬让你通不过。说是鸡蛋里挑骨头也不为过。

    以下是几次我经历的审核未通过的原因:

    (1)  功能不完善/功能不完整。

    第一次开发的英语音标学习小程序MyPhonetics只有一个页面。被认为功能不完整拒绝通过。费了一番口舌才让通过。

    (2) 存在诱导类行为,包括但不限于诱导消费、诱导分享;

    这个很无语,我猜了半天,估计是因为用的模板工程中有一个命名为pay的页面,事实上英语音标学习小程序MyPhonetics根本没有用到这个页面。删除之后才给通过。

    (3) 在版本描述处详细说明提供“IT科技-软件服务提供商”插件的实际使用场景和用途。

    因为用了同声传译插件和leancload服务,说明了以后给通过。

    更多信息可参考:

    微信小程序10个最常见的审核的核不通过的原因 https://www.jianshu.com/p/3d765ef6cd7d

     

    七、其他

    1.  微信小程序显示加载弹窗 https://blog.csdn.net/henryhu712/article/details/80335351

    2. 微信小程序取 dataset 值、取其他页面传过来的值 https://blog.csdn.net/rolan1993/article/details/79742653

    3. 微信小程序——页面跳转三种方法

    https://blog.csdn.net/wl1769127285/article/details/53691551

    4. 微信同声传译插件(文本转语音)

    https://developers.weixin.qq.com/community/develop/doc/0004aa70d609e099c1d671b2a56009

    github:Tencent/Face2FaceTranslator

    https://github.com/Tencent/Face2FaceTranslator

     

    参考文献

    1. 微信公众平台 https://mp.weixin.qq.com/

    2. 开发环境下载地址 https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

    3. 微信小程序tab切换效果 https://jingyan.baidu.com/album/59703552b60db78fc0074036.html?picindex=7

    4. 小程序第三方框架对比 ( wepy / mpvue / taro ) https://www.cnblogs.com/Smiled/p/9806781.html

    5. 微信云开发 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html

    6. 微信小程序底部导航Tabbar https://www.cnblogs.com/huangjialin/p/6278429.html

    7. 微信小程序导航组件官方文档navigator https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html

    8. 微信小程序之导航组件 https://www.jianshu.com/p/53ac270215cb

    9. Css中路径data:image/png;base64的用法详解 (转载) https://www.cnblogs.com/OpenCoder/p/7127256.html

    10. 图片转换Base64 http://imgbase64.duoshitong.com/

    11. 微信开放社区 https://developers.weixin.qq.com/community/develop/question

    12. 主流编程语言拟人化 https://www.oschina.net/news/53201/programming-language-as-a-girl

    13. Lisp永远成不了编程主流语言 https://www.cnblogs.com/tkt2016/p/5755974.html

    14. 《Lisp神化之路》 https://blog.csdn.net/code_for_fun/article/details/83304873

    15. 微信小程序10个最常见的审核的核不通过的原因 https://www.jianshu.com/p/3d765ef6cd7d

    16. 微信小程序显示加载弹窗 https://blog.csdn.net/henryhu712/article/details/80335351

    17. 微信小程序取 dataset 值、取其他页面传过来的值 https://blog.csdn.net/rolan1993/article/details/79742653

    18. 微信小程序——页面跳转三种方法 https://blog.csdn.net/wl1769127285/article/details/53691551

    19. 微信同声传译插件(文本转语音) https://developers.weixin.qq.com/community/develop/doc/0004aa70d609e099c1d671b2a56009

    20. 微信同声传译插件github:Tencent/Face2FaceTranslator https://github.com/Tencent/Face2FaceTranslator

     

    联系我们

    -------------------------------------------------

    cemike@126.com

    欢迎交流。

    展开全文
  • 主要为大家详细介绍了微信小程序实现翻牌抽奖动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 微信小程序开发

    2016-09-29 10:02:55
    1.这个是视频教程-微信小程序开发实战  http://edu.csdn.net/course/detail/3011  2.github上开源的音乐播放器  https://github.com/Sioxas/AppleMusic  3.微信小程序怎么开发  http://www.ifanr.c
  • 这个压缩包里面包含three.js在微信小程序端加载3D动画fbx模型的代码。 得到了fbx模型的http链接,使其加载在小程序端,都是适配小程序版本的代码 其中three_new.js是小程序版的3D加载库文件 FBXLoader_new是小...
  • 微信小程序分析见解

    千次阅读 2016-11-06 19:04:03
    前两天朋友圈都快被小程序给刷爆了;  对于小程序这方面, 由于没有公测的资格。所以翻阅了许许多多的资料,来了解一下小程序;  在今天决定写一个自己对小程序的了解。 微信小程序
  • 微信小程序怎么用和小程序有什么用的问题是从微信小程序一出来就伴随着的。微信小程序怎么用:**1、打开微信的『发现』,在最底下有『小程序』,进入界面后搜索对应的小程序名称,如:极乐商店 2、在极乐小程序商店...
  • 微信小程序最新学习参考demo源码集合,仅供参考学习用途!!! 面对面翻译 微信小程序源码下载,语音翻译类小程序工具http://www.henkuai.com/thread-37499-1-1.html 开源微信小程序,小团队管理小程序下载 :...
  • 小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java实时BUG监控。真的是一个很好用的bug监控费服务,众多大佬公司都在使用。 前言 开发项目时,实际遇到的一些功能需求和问题汇总。列出...
  • 分享一个博主的公众号,我发现真的是良心博主,一步一步的带着开发小白设计开发微信小程序,这是他的公众号: MiniApplet 入门链接: https://mp.weixin.qq.com/s?__biz=MzIxMDQzNjc1OQ==&mid=100000114&...
  • 微信小程序的模块化

    2020-03-09 23:54:21
    模块化 模块化: 可以将一些公共的代码抽离成为一个...使用微信小程序构建新闻列表的代码来讲解模块化 创建data目录,新建posts-data.js文件 posts-data.js 代码如下: var local_database = [ { date: "Sep 18...
  • 微信小程序数据填充新闻详情页面

    千次阅读 2020-03-10 17:50:28
    微信小程序带参的页面跳转 微信小程序新闻详情页面效果实现 上面已经实现了页面的跳转和详情页效果实现,接下来将数据填充到详情页面 post-detail.js 中引入posts-data.js,posts-data.js中有所有数据信息。 // ...
  • 第1章 微信小程序简介 本章我们将介绍小程序的一些基本概念及特性,让大家在正式学习小程序开发前,对小程序有一个整体的认知。当然,本章你也可以完全跳过,因为它不会涉及任何“代码”方面的内容。但笔者还是建议...
  • 之前小白推荐过600个小程序,都是由微信小程序商店-极乐小程序商店(极乐store)中来的,今天接着人微信小程序商店中推荐100个。 小白的想法是把微信小程序商店中所有小程序推荐一次之后,我要每一个都体验一次后,...
  • 如何制作APP-微信小程序

    千次阅读 2019-09-03 23:20:55
    如何制作APP-微信小程序 : Q2198-1373-58 目 录 一、 关于产品————————————————————1 二、 产品展示————————————————————1 H5游戏前端界面展示 APP游戏前端界面...
  • 【小程序】微信小程序翻牌小功能

    千次阅读 2018-10-31 13:24:48
    微信小程序翻牌小功能 页面 &lt;view id="container"&gt; &lt;view wx:for="{{newArr}}" class='cards'&gt; &lt;view class="card card_a" style='display:{{...
  • 微信小程序与Web 网站在技术层面的主要区别是什么?”我相信你也有类似的困惑,因为在编程语言和编程习惯上,小程序开发与Web 前端开发非常相似(比如都用JavaScript语言、与HTML/CSS 非常相似的WXML/WXSS 等),可...
  • 口袋奇兵小程序是一款精彩好玩的特色策略建造小游戏,玩家们需要在全新的世界中打造自己的军队,口袋奇兵小程序无需下载在线就可以排列你的建造阵容和冒险模式,点击各种互动玩法开始新的休闲策略体验,和你的朋友在...
  • 微信小程序----全局变量 ...1. 在微信小程序开发中使用高德地图的微信小程序开发,其中key值就需要在多个页面使用; 2. 在微信小程序开发电商平台时同样,比如客服电话,就需...
  • 微信小程序开发文档里,组件模块,视图容器分类下,有swiper和swiper-item组件,这就是用来实现轮播图的组件,并且官方还提供了示例代码和演示效果 swiper 官方示例代码 Page({ onShareAppMessage() { return { ...
  • 微信小程序刮刮乐

    万次阅读 2019-07-08 14:45:18
    个人对scratch.js做了一些修改,设置清除面积达到一定值时(if (clearNum > .2) ),使刮卡刮干净,并触发(结果交互)方法; 测试时 调试基础库(project.config.json 文件中参数:"lib...
  • 利用Layabox1.0 开发的3D微信小游戏案例,从Unity导出场景到在Layabox里应用,再到开发,本课程适合想入门微信3d游戏的开发者。 注:只提供美术资源,不提供源代码,源代码需另购买。 源代码地址:...
  • 微信小程序入门教程+案例demo

    千次阅读 2018-05-28 17:56:59
    微信小程序入门教程+案例demo尊重原创,转载请注明...认清微信小程序开发其实,我觉得小程序就是将微信官方提供20+个基础组件(目前有26个)进行排列组合,然后加上一些css样式,对用户的操作进行反馈(调微信官方提...
  • console.log('代码片段是一种迷你、可分享的小程序或小游戏项目,可用于分享小程序和小游戏的开发经验、展示组件和 API 的使用、复现开发问题和 Bug 等。可点击以下链接查看代码片段的详细文档:') console.log('...
  • 小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java实时BUG监控。真的是一个很好用的bug监控费服务,众多大佬公司都在使用。 今天我们说下微信小程序左滑删除效果的实现,现在市场上很多...
  • 因为李安想要挑战前所未有的技术难题:以120帧每秒的速度、4K、3D技术全面结合,来掀起一场电影视觉革命。什么意思?所谓“电影是24格每秒的谎言”,其中的24格,就是帧数。", collection: 92, dateTime: "24小时前...
  • 微信小程序差不多已经推出了两年半的时间,对于还没有入坑或刚准备动手的开发同学,本文档将尝试在几分钟内让你快速的了解其基本开发生态,虽嫌蜻蜓点水零零碎碎,但应该可对接下来的开发做出合理的抉择。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,486
精华内容 2,194
关键字:

微信小程序3d游戏

微信小程序 订阅