Files

257 lines
6.0 KiB
JavaScript
Raw Permalink Normal View History

2025-10-26 13:15:04 +08:00
// 头像组件逻辑
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
});
});
}
}
});