Обзор прошлой ситуации
мой предыдущий пост《如何实现微信小程序换头像?三步帮你搞定! 》, упомянул, что для изменения аватара апплета WeChat требуется три шага:
- Получить аватар пользователя
- шаблон изображения
- синтез изображений
В предыдущей статье были описаны два этапа получения аватара пользователя и шаблона изображения, а в этой статье подробно объясняется, как синтезировать изображения.
Очень важной функцией в процессе синтеза изображения является вырезание изображения. Функциональная точка очень фиксированная.Большинство картинок перетаскиваются и масштабируются, а затем картинка с фиксированной длиной и шириной вырезается в определенной области. В приложении и H5 есть много зрелых плагинов для такого рода функций.Далее давайте посмотрим, как реализован плагин вырезания аватара в апплете Dolphin Funtu.Комментарии приветствуются.
Чтобы лучше понять следующий код, рекомендуется сначала отсканировать и испытать эффект обрезки изображения.
добиться эффекта
реализация интерфейса
В H5 требуется много кода для реализации перетаскивания и масштабирования изображений, и в Интернете есть много конкретных реализаций. Реализация небольшой программы намного проще, за счет<movable-area>
а также<movable-view>
для достижения вышеуказанных функций
<view class="clip-view">
<!--
clipHeight、clipWidth 分别为剪切框的高和宽
imgHeight、imgWidth 分别对应图片的初始高和宽
imgUrl 为剪切图片的url地址
-->
<movable-area class="moveare" style="height: {{clipHeight}}rpx; width: {{clipWidth}}rpx; ">
<movable-view scale="true" scale-min="{{1}}" damping="1000" style="height: {{imgHeight}}px; width: {{imgWidth}}px; " direction="all" x="{{x}}" y="{{y}}" bindchange="_onChange" bindscale="_onScale">
<image class="clip-img" src="{{imgUrl}}" />
</movable-view>
</movable-area>
<!--剪切框 装饰用-->
<view class="clip-box" style="height: {{clipHeight}}rpx; width: {{clipWidth}}rpx; ">
<!--剪切框四个角-->
<view class="clip-border clip-border-lt"></view>
<view class="clip-border clip-border-rt"></view>
<view class="clip-border clip-border-lb"></view>
<view class="clip-border clip-border-rb"></view>
</view>
<!--剪切图片用的canvas-->
<canvas class="clip-canvas" id="img_clip_canvas" canvas-id="img_clip_canvas" style="height: {{clipHeight}}rpx; width: {{clipWidth}}rpx; "></canvas>
</view>
свойства компонента
Входным параметрам компонента нужен только адрес исходного изображения, а также ширина и высота поля обрезки изображения.
/**
* 组件的属性列表
*/
properties: {
// 原始图片路径(要剪切的图片)
imgUrl: {
type: String,
value: ''
},
// 剪切的宽度 (rpx)
clipWidth: {
type: Number,
value: 500
},
// 截切的高度 (rpx)
clipHeight: {
type: Number,
value: 500
}
}
данные компонента
Данные компонента будут записывать больше данных для перетаскивания изображения.Следует отметить, что начальное положение изображения и положение перетаскивания изображения не сохраняются в одной и той же переменной, чтобы предотвратить дрожание в процессе перетаскивания.
/**
* 组件的初始数据
*/
data: {
baseScale: 1,
imgPath: '',
imgWidth: 0, // 图片宽
imgHeight: 0, // 图片高
x: 0, // 图片初始时x轴位置
y: 0, // 图片初始时y轴位置,之所以不和top共用一个变量,是因为如果频繁改变y值,图片会闪烁,x同理
left: 0, // 图片拖拽后的x轴位置
top: 0, // 图片拖拽后的y轴位置
scale: 1 // 拖拽后的缩放比例
}
Инициализация компонента
Метод инициализации компонента используется для масштабирования изображения до соответствующего размера и создания выреза в центре изображения.
/**
* 初始化方法
* 获取图片宽高后,把图片缩放至剪切框大小,
* 并使剪切框位于图片中央
**/
_init() {
if (!this.data.imgUrl) return
// 获取屏幕宽度
let {
screenWidth
} = wx.getSystemInfoSync()
// 计算屏幕rpx
const rpx = screenWidth / 750
// 获取图片宽高,然后缩放至剪切框大小
wx.getImageInfo({
src: this.data.imgUrl,
success: ({
width,
height,
path
}) => {
const cw = this.data.clipWidth * rpx
const ch = this.data.clipHeight * rpx
let scale = Math.max(cw / width, ch / height)
const imgWidth = width * scale
const imgHeight = height * scale
this.setData({
imgPath: path,
imgWidth,
imgHeight,
baseScale: scale,
x: (cw - imgWidth) / 2,
y: (ch - imgHeight) / 2
})
}
})
}
Обработка перетаскивания изображений
После завершения инициализации вы можете отслеживать операции перетаскивания и масштабирования пользователя, в основном для записи положения перетаскивания и коэффициента масштабирования.В частности, реализация кода предназначена для мониторинга<movable-view>
Тянуть (bindchange
) И увеличить (bindscale
)мероприятие
// 拖拽事件响应函数
_onChange: function(e) {
this.setData({
x: e.detail.x,
y: e.detail.y
})
}
// 缩放事件响应函数
_onScale: function(e) {
this.setData({
x: e.detail.x,
y: e.detail.y,
scale: e.detail.scale
})
}
Реализация резки изображения
После завершения перетаскивания и масштабирования он обрезается, и разрез используется<canvas>
Перерисуйте область отсечения изображения, сохраните его во временном каталоге WeChat и вернитесь к пути сохранения. Следует отметить, что положение отсечения записанного изображения после перетаскивания и масштабирования не является положением исходного изображения.canvas
изdrawImage
При рисунке ему необходимо преобразовать в исходное положение изображения или сначалаcanvas
Система координат масштабируется.Примечание. Вызывается в пользовательском компоненте.wx.createCanvasContext(string canvasId, Object this)
метод, второй параметр this нельзя опускать, иначе рисунок холста не будет реагировать
/**
* 图片剪切入口方法
*/
clip() {
const scale = this.data._scale * this.data._baseScale
const canvasId = 'img_clip_canvas'
imageClip(canvasId, this.data.imgPath, {
x: this.data._left * -1,
y: this.data._top * -1,
scale,
width: this.data.clipWidth,
height: this.data.clipHeight
}, this)
}
/**
* 图片剪切
*
* @param canvas canvas组件id,用于绘制剪切图片
* @param img 要剪切的图片
* @param option 剪切的位置宽高等信息
* @param option.left 剪切图片左边距
* @param option.top 剪切图片上边距
* @param option.width 剪切图片宽度
* @param option.height 剪切图片高度
* @param context 组件实例对象
*
* @return new Promise(resolve=>ctx)
*/
imageClip(canvas, img, option, context) {
return new Promise((resolve, reject) => {
option = Object.assign({
left: 0,
top: 0,
scale: 1,
width: 0,
height: 0
}, option)
let x = option.left / option.scale
let y = option.top / option.scale
let clipW = option.width / option.scale
let clipH = option.height / option.scale
const ctx = wx.createCanvasContext(canvas, context)
ctx.drawImage(img,
x,
y,
clipW,
clipH,
0,
0,
option.width,
option.height)
ctx.draw(false, (e) => {
console.log(e)
resolve()
})
})
},
/**
* canvas 保存为临时文件
*/
function saveCanvasToTemp(canvas, option) {
return new Promise((resolve, reject)=>{
wx.canvasToTempFilePath({
...option,
canvasId: canvas,
success:resolve,
fail:reject
}, this)
})
}
напиши в конце
Это основная кодовая реализация вырезания картинок в версии апплета, есть еще небольшие моменты, на которые стоит обратить внимание
-
<movable-view>
Значение демпфирования должно быть установлено в верхнем регистре, иначе оно может быть перетащено за пределы - Вызывается под пользовательским компонентом
wx.createCanvasContext(string canvasId, Object this)
метод, второй параметр this нельзя опускать, иначе рисунок холста не будет реагировать - Не забудьте преобразовать в фактический размер изображения при вырезании изображения.
насчет нас
Передовая команда Kuaigou Taxi занимается обменом передовыми технологиями и регулярно публикует высококачественные статьи. Добро пожаловать, обратите внимание и лайкните. Статья будет опубликована в паблике одновременно, если вы хотите получать актуальную информацию как можно быстрее, просто отсканируйте ее!