257 lines
6.0 KiB
JavaScript
257 lines
6.0 KiB
JavaScript
// 头像组件逻辑
|
||
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
|
||
});
|
||
});
|
||
}
|
||
}
|
||
}); |