Files
WXProgram/miniprogram/components/avatar/avatar.js
2025-10-26 13:15:04 +08:00

257 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 头像组件逻辑
Component({
properties: {
// 头像URL
avatarUrl: {
type: String,
value: ''
},
// 头像尺寸rpx
size: {
type: Number,
value: 120
},
// 占位符文本
placeholderText: {
type: String,
value: '👤'
},
// 占位符文本大小
textSize: {
type: Number,
value: 40
},
// 是否可编辑
editable: {
type: Boolean,
value: false
},
// 头像形状circle圆形或 square方形
shape: {
type: String,
value: 'circle'
},
// 是否显示边框
bordered: {
type: Boolean,
value: false
},
// 是否显示阴影
shadow: {
type: Boolean,
value: false
}
},
data: {
showAvatarModal: false // 是否显示头像选择弹窗
},
methods: {
// 头像点击事件
onAvatarTap() {
if (this.properties.editable) {
this.showAvatarModal();
}
this.triggerEvent('tap', {
avatarUrl: this.properties.avatarUrl
});
},
// 显示头像选择弹窗
showAvatarModal() {
this.setData({
showAvatarModal: true
});
},
// 隐藏头像选择弹窗
hideAvatarModal() {
this.setData({
showAvatarModal: false
});
},
// 拍照
takePhoto() {
this.hideAvatarModal();
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'],
camera: 'front',
success: (res) => {
if (res.tempFiles && res.tempFiles.length > 0) {
this.processImage(res.tempFiles[0].tempFilePath);
}
},
fail: (err) => {
console.error('拍照失败:', err);
wx.showToast({
title: '拍照失败',
icon: 'none'
});
}
});
},
// 从相册选择
chooseImage() {
this.hideAvatarModal();
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album'],
success: (res) => {
if (res.tempFiles && res.tempFiles.length > 0) {
this.processImage(res.tempFiles[0].tempFilePath);
}
},
fail: (err) => {
console.error('选择图片失败:', err);
wx.showToast({
title: '选择图片失败',
icon: 'none'
});
}
});
},
// 使用默认头像
useDefaultAvatar() {
this.hideAvatarModal();
// 触发默认头像选择事件
this.triggerEvent('change', {
avatarUrl: '',
isDefault: true
});
},
// 处理图片
processImage(tempFilePath) {
wx.showLoading({
title: '处理中...'
});
// 压缩图片
wx.compressImage({
src: tempFilePath,
quality: 80,
success: (res) => {
// 裁剪图片为正方形
this.cropImage(res.tempFilePath);
},
fail: (err) => {
console.error('图片压缩失败:', err);
wx.hideLoading();
wx.showToast({
title: '图片处理失败',
icon: 'none'
});
}
});
},
// 裁剪图片
cropImage(tempFilePath) {
// 获取图片信息
wx.getImageInfo({
src: tempFilePath,
success: (infoRes) => {
const { width, height } = infoRes;
const size = Math.min(width, height);
const x = (width - size) / 2;
const y = (height - size) / 2;
// 创建画布进行裁剪
const ctx = wx.createCanvasContext('avatar-canvas');
// 绘制圆形裁剪区域
ctx.save();
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
ctx.clip();
// 绘制图片
ctx.drawImage(tempFilePath, x, y, size, size, 0, 0, size, size);
ctx.restore();
// 将画布内容导出为图片
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'avatar-canvas',
success: (canvasRes) => {
wx.hideLoading();
// 触发头像改变事件
this.triggerEvent('change', {
avatarUrl: canvasRes.tempFilePath,
isDefault: false
});
},
fail: (err) => {
console.error('画布导出失败:', err);
wx.hideLoading();
wx.showToast({
title: '头像处理失败',
icon: 'none'
});
}
});
});
},
fail: (err) => {
console.error('获取图片信息失败:', err);
wx.hideLoading();
wx.showToast({
title: '图片处理失败',
icon: 'none'
});
}
});
},
// 生成头像缩略图
generateThumbnail(avatarUrl, size = 60) {
return new Promise((resolve, reject) => {
if (!avatarUrl) {
resolve('');
return;
}
wx.getImageInfo({
src: avatarUrl,
success: (infoRes) => {
const ctx = wx.createCanvasContext('thumbnail-canvas');
// 绘制圆形缩略图
ctx.save();
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(avatarUrl, 0, 0, size, size);
ctx.restore();
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'thumbnail-canvas',
destWidth: size,
destHeight: size,
success: (res) => {
resolve(res.tempFilePath);
},
fail: (err) => {
reject(err);
}
});
});
},
fail: reject
});
});
}
}
});