задний план
1 октября 2019 года, по случаю 70-летия Родины, круг друзей WeChat пролистали все @ официальное лицо WeChat с просьбой о национальном флаге Во время празднования дня рождения Родины было очень весело.
25 сентября по прихоти я решил разработать мини-программу WeChat для смены аватарки перед Днем нации в подарок к 70-летию Родины! Наконец, в преддверии Национального дня в сети была запущена небольшая программа для создания аватаров — [Карта дельфинов], которая помогла более чем 10 000 друзей успешно сменить аватарку с национальным флагом.
Хотя апплет уже запущен, я надеюсь обобщить некоторые интересные технические моменты в процессе разработки апплета [Карта развлечений дельфинов] и поделиться ими с вами.
Основные шаги
- Получить аватар пользователя
- шаблон изображения
- синтез изображений
Получить аватар пользователя
Первым шагом в создании собственного аватара является выбор изображения. В дизайне взаимодействия [Карта развлечений с дельфинами] у пользователей есть три способа выбора изображений: аватар WeChat, локальный фотоальбом и съемка камерой. Дизайн продукта для получения пользовательских аватаров показан на следующем рисунке:
Так как WeChat официально больше не поддерживает получение информации о пользователе через интерфейс wx.getUserInfo, мы должны использоватьbuttonкомпонент иopen-typeНазначен какgetUserInfoВведите, чтобы получить или отобразить информацию о пользователе.
Чтобы оптимизировать взаимодействие с пользователем, метод разработки с использованием интерфейса wx.getUserInfo для прямого всплывающего окна авторизации постепенно перестанет поддерживаться. Начиная с 30 апреля 2018 г., когда пробная версия и версия для разработки мини-программ и мини-игр вызывают интерфейс 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Вставьте пользовательский контент в лист действий, напримерbutton,navigatorЖдать.
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Это решает проблему, которую не может быть указан наборных действийbutton, так что аватар пользователя WeChat не может быть получен.
Компонент, который я опубликовал в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
})
})
}
вопрос
Здесь нет проблем с логикой получения шаблона, но в процессе разработки возникла проблема. Я использую идентификатор облачного файла для ссылки изображения шаблона.При параллельной загрузке большого количества изображений может отображаться только часть изображений.Я проверил, что узел dom на самом деле уже существует, и адрес src файла картинка тоже правильная.
Официальные лица WECHAT были поддержаны в изображении для использования идентификатора облачного файла в изображении. Формат идентификатора облачного файла:
cloud://xxx.xxx/templates/01.png.
Я предполагаю, что это может быть вызвано слишком большим количеством одновременных запросов к облачному хранилищу WeChat (некоторые студенты, которые знают об этом, могут сказать мне), потому что я попытался изменить идентификатор облачного файла на обычную ссылку HTTPS, и это не было проблемой.
Исходя из этого, можно придумать три возможных решения:
- Сохраните шаблон изображения на внешнем OSS и используйте ссылку протокола https.
- использовать
wx.getTempFileURLОбменяйте идентификатор облачного файла на настоящую ссылку, то есть на ссылку в виде https. - Управляет количеством параллельных загрузок для графа. Моя практика заключается в том, чтобы контролировать количество параллельных загрузок до 20 и инициировать следующий запрос, когда пользователь прокручивает страницу.
Суммировать
Вышеизложенное в основном касалось реализации функций получения аватара пользователя и шаблона изображения, а также некоторых возникающих проблем. Синтез картинок — основная функция всего апплета, следующая статья будет отдельно, чтобы рассказать об идеях реализации и потенциальных проблемах. Следите за обновлениями!
Опыт сканирования кода
Читатели могут отсканировать код, чтобы ознакомиться с двумя описанными нами функциональными точками:
- Пользовательский компонент таблицы действий
- Загрузка шаблона изображения
насчет нас
Передовая команда Kuaigou Taxi занимается обменом передовыми технологиями и регулярно публикует высококачественные статьи. Добро пожаловать, обратите внимание и лайкните. Статья будет опубликована в паблике одновременно, если вы хотите получать актуальную информацию как можно быстрее, просто отсканируйте ее!