用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 查看內容

如何實現微信小程序換頭像?三步幫你搞定!

Rolan 2019-10-17 00:52

背景 2019年10月1日在祖國70周年大慶之際,微信朋友圈被大家紛紛@微信官方要國旗的景象給刷屏了,在為祖國慶生的同時,玩的不亦樂乎。 在9月25日,我心血來潮決定在國慶前開發一個換頭像的微信小程序為祖國70周年獻 ...

背景

2019年10月1日在祖國70周年大慶之際,微信朋友圈被大家紛紛@微信官方要國旗的景象給刷屏了,在為祖國慶生的同時,玩的不亦樂乎。

在9月25日,我心血來潮決定在國慶前開發一個換頭像的微信小程序為祖國70周年獻禮!最終在國慶前夕上線發布了制作頭像的小程序-【海豚趣圖】,幫助10000多名小伙伴成功換上了國旗頭像。

小程序雖然已經上線,但在【海豚趣圖】這個小程序開發過程中的一些有意思的技術點我希望能總結一下和大家進行分享。

主要步驟

  • 獲取用戶頭像
  • 圖片模板
  • 圖片合成

獲取用戶頭像

制作自定義頭像的第一步就是先選擇圖片。在【海豚趣圖】的交互設計中,用戶有三種選擇圖片的方式:微信頭像、本地相冊和相機拍攝。獲取用戶頭像的產品設計如下圖所示:

由于微信官方不再支持通過 wx.getUserInfo 接口來獲取用戶信息,我們必須通過使用 button 組件并將 open-type 指定為 getUserInfo 類型來獲取或展示用戶信息。

為優化用戶體驗,使用 wx.getUserInfo 接口直接彈出授權框的開發方式將逐步不再支持。從2018年4月30日開始,小程序與小游戲的體驗版、開發版調用 wx.getUserInfo 接口,將無法彈出授權詢問框,默認調用失敗。正式版暫不受影響。

上圖中彈出底部菜單的交互方式無法通過 wx.showActionSheet 來實現(因為該接口只能指定字符串文本,不能使用 button, navigator 等組件)。

因此,只能通過自定義 actionSheet 組件來實現以上功能。

mmp-action-sheet 組件

以下是 mmp-action-sheet 組件的代碼。

index.wxml

<view hidden="{{!actionShow}}" class="mask {{mask}}" bindtap="actionHide">
  <view class="actionSheet animated {{animation}}">
    <slot></slot>
    <button class="close" bindtap="actionHide">{{closeText}}</button>
  </view>
</view>
復制代碼

通過 slot 在 action-sheet 中插入自定義的內容,比如 buttonnavigator 等。

index.wxss

.mask{
  position: fixed;
  top: 0;
  left: 0;
  width:100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 999;
}
.actionSheet{
  width: 100%;
  position: absolute;
  top: 100%;
  z-index: 1000;
  overflow: hidden;
}
.actionSheet button,
.actionSheet navigator{
  color: #000;
  text-align: center;
  background: #fff;
  border-radius: 0;
  line-height: 3.5;
  font-size: 32rpx;
  border-bottom: 1rpx solid rgb(236, 236, 236);
  opacity: 1;
}
.actionSheet button:active,
.actionSheet navigator:active{
  color:#000;
  background: rgb(236, 236, 236);
}
.actionSheet button::after,
.actionSheet navigator::after
{
  border: none;
  border-radius: 0;
}
.actionSheet .close{
  border-bottom: none;
  border-bottom: 50rpx solid #fff;
  border-top: 16rpx solid rgb(236, 236, 236);
}
.animated {
  animation-timing-function: ease-out;
  animation-duration: 0.2s;
  animation-fill-mode: both;
}


@keyframes fadeInBottom {
from{
   transform: translate3d(0, 0, 0);
 }
  to {
    transform: translate3d(0, -100%, 0);
  }
}
.fadeInBottom {
  animation-name: fadeInBottom;
}

@keyframes fadeOutBottom {
from{
   transform: translate3d(0, -100%, 0);
 }
  to {
    transform: translate3d(0, 0, 0);
  }
}
.fadeOutBottom {
  animation-name: fadeOutBottom;
}

@keyframes fadeIn {
from{
   opacity: 0;
 }
  to {
     opacity: 1;
  }
}
.fadeIn {
  animation-name: fadeIn;
}

@keyframes fadeOut {
from{
   opacity: 1;
 }
  to {
     opacity: 0;
  }
}
.fadeOut {
  animation-name: fadeOut;
}
復制代碼

index.js

Component({
  properties: {
    actionSheetStatus: {
      type: Boolean,
      value: false,
      observer(newVal) {
        if (newVal) {
          this.setData({
            actionSheetStatus: true,
            animationMask: 'fadeIn',
            animationSheet: 'fadeInBottom'
          })
        } else {
          this.setData({
            actionSheetStatus: false,
            animationMask: 'fadeOut',
            animationSheet: 'fadeOutBottom'
          })
        }
      }
    },
    closeText: {
      type: String,
      value: '取消'
    }
  },

  data: {
    animationMask: 'fadeIn',
    animationSheet: 'fadeInBottom'
  },

  methods: {
    closeActionSheet() {
      this.setData({
        animationMask: 'fadeOut',
        animationSheet: 'fadeOutBottom'
      })
      setTimeout(() => {
        this.setData({actionSheetStatus: false})
      }, 300)
    }
  }
})
復制代碼

組件只有兩個參數:

  • actionSheetStatus 指定組件的初始展示狀態,默認為false,表示不顯示組件。
  • closeText 指定關閉按鈕的名字,默認為 取消

index.json

{
  "component": true,
  "usingComponents": {}
}
復制代碼

接下來在頁面中調用組件,在組件中插入了3個 button 組件來實現來獲取用戶頭像:

<action-sheet actionSheetStatus="{{actionSheetStatus}}">
    <button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">使用微信頭像</button>
    <button bindtap="pickPic" data-source-type="album">使用本地相冊</button>
    <button bindtap="pickPic" data-source-type="camera">拍照</button>
  </action-sheet>
復制代碼

以上我們通過自定義組件 mmp-action-sheet 就解決了原生的 actionsheet 無法指定 button,從而無法獲取用戶微信頭像的問題。

該組件我已經發布到 npm 包,需要用到的同學可以通過 npm 安裝,也可以在 github 上查看源碼和使用文檔。

圖片模板

有了原圖,接下來我們需要選擇圖片模板。如果模板數量不多或者模板變化不頻繁,我們可以直接把模板放在本地。鑒于我提供的模板比較多,放在本地會增大小程序源碼的大小,我把模板上傳到了小程序的云存儲中,通過云函數來動態獲取圖片模板,方便以后模板擴展。

云函數 tpl 的代碼如下:

// 云函數入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函數入口函數
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  // 1. 獲取數據庫引用
  const db = cloud.database()
  const MAX_LIMIT = 100
  // 2. 構造查詢語句
  const countResult = await db.collection('template').count()
  const total = countResult.total
  // 計算需分幾次取
  const batchTimes = Math.ceil(total / 100)
  const tasks = []
  for (let i = 0; i < batchTimes; i++) {
    const promise = db.collection('template').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }

  return (await Promise.all(tasks)).reduce((acc, cur) => {
    return {
      data: acc.data.concat(cur.data),
      errMsg: acc.errMsg,
    }
  })
}
復制代碼

頁面中調用云函數拉取模板:

getTpl() {
    const self = this
    // 調用云函數獲取圖片模板
    wx.cloud.callFunction({
      name: 'tpl'
    }).then(res => {
      self.setData({
        templates: res.result.data
      })
    })
}
復制代碼

問題

到這里模板的獲取邏輯已經沒有問題了,但在開發過程中遇到了一個問題。模板圖片的鏈接我使用的是云文件ID,當有大量圖片并行加載的時候,只有部分圖片能夠顯示,我看了一下dom節點其實都已經存在了,image的src的地址也都是正確的。

微信官方自2.3.0開始已經支持在image中使用云文件ID。云文件ID的格式為: cloud://xxx.xxx/templates/01.png

我猜測可能是對微信云存儲并發請求過多導致的(有知道的同學可以告知),因為我試了一下將云文件ID換成正常的HTTPS的鏈接是沒問題的。

由此可知,可以想到有三種可行的解決方案:

  1. 將圖片模板存儲到外部OSS,使用https協議的鏈接。
  2. 使用 wx.getTempFileURL 用云文件 ID 換取真實鏈接,也就是https形式的鏈接。
  3. 控制圖的并行加載數量。我的實踐是將并行加載數量控制在20,當用戶滾動的時候再發起下一次請求。

總結

以上主要分享了用戶頭像獲取以及圖片模板功能的實現及所遇到的一些問題。關于圖片的合成是整個小程序的核心功能,下一篇單獨拉出來說一下實現思路和潛在的問題。敬請期待!

掃碼體驗

讀者可以掃碼體驗我們所講述的兩個功能點:

  1. 自定義actionsheet組件
  2. 圖片模板加載




鮮花
鮮花
雞蛋
雞蛋
分享至 : QQ空間
收藏
原作者: 快狗打車前端團隊 來自: 掘金
不朽的浪漫援彩金
球探比分下载苹果 云南快乐十分前三 安徽体彩十一选五走 福建22选5开奖走势 信彩分分彩官方网站 内蒙古快3专家推荐号 安徽11选5开奖记 竞彩足球比分最高奖金封顶是多少 直选能对组选么 亿富配资 王者捕鱼下载 今天江苏快三豹子推荐 100送100真人百家乐4倍流水 pc蛋蛋技巧 上海快3开奖结 秒速赛车看号技巧规律