前言:最近因业务需求而开发拍照有水印信息,所以记录下,以便大家一起学习学习,各位大佬若觉得代码有什么错误或者有高效的方法,欢迎指点指点,让大家有更高效的开发代码。
1.创建wxml页面
<button type="default" bindtap="selectPhoto">选择图片</button>
<view wx:if="{{originalUrl}}" style="padding: 20rpx;">原图:</view>
<image wx:if="{{originalUrl}}" src="{{originalUrl}}" style="width: 300px;display: block;margin: 0 auto;padding: 20rpx 0;" mode="widthFix" bindtap="previewImage" data-type="originalUrl"></image>
<view wx:if="{{fileUrl}}" style="padding: 20rpx;">添加水印后:</view>
<image wx:if="{{fileUrl}}" src="{{fileUrl}}" style="width: 300px;display: block;margin: 0 auto;padding: 20rpx 0;" mode="widthFix" bindtap="previewImage" data-type="fileUrl"></image>
<canvas style="position: fixed;top:10000px;width: {{canvasWidth}}px;height: {{canvasHeight}}px" canvas-id="watermarkCanvas"></canvas>
2.js文件
- 引入photoWatermark.js文件
import photoWatermark from '../../utils/photoWatermark';
Page({
data: {
canvasWidth: 0,
canvasHeight: 0,
fileUrl: '',
originalUrl: '',
timer: null,
},
async selectPhoto() {
try {
let photoData = await photoWatermark.addWatermark(this, 'watermarkCanvas')
this.setData({
originalUrl: photoData.imageInfo.path,
fileUrl: photoData.fileUrl,
})
wx.hideLoading();
} catch (error) {
wx.hideLoading();
}
},
previewImage(e) {
let type = e.target.dataset.type;
let urls = [];
switch (type) {
case 'originalUrl':
urls = [this.data.originalUrl];
break;
case 'fileUrl':
urls = [this.data.fileUrl];
break;
}
wx.previewImage({
current: 0,
urls,
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
},
onLoad(options) {
},
onReady() {
},
onShow() {
},
onHide() {
},
onUnload() {
},
onShareAppMessage() {
return {
title: '',
};
},
});
3.photoWatermark.js
- 导入util.js文件
- 导入qqmap-wx-jssdk.js,下载地址:lbs.qq.com/miniProgram…
- 填写申请后的密钥key
import QQMapWX from './qqmap-wx-jssdk';
import util from './util';
var watermarkTimer = null;
// 画布文字自动换行
const canvasTextAutoLine = (ctx, text, x, y, maxWidth, lineHeight) => {
let lineWidth = 0
let lastSubStrIndex = 0
let textWidth = ctx.measureText(text).width;
if (Math.ceil(textWidth/maxWidth) === 2) {
y = y -20
}else if (Math.ceil(textWidth/maxWidth) > 2) {
y = y -40
}
for (let i = 0; i < text.length; i++) {
lineWidth += ctx.measureText(text[i]).width
if (lineWidth > maxWidth) {
ctx.fillText(text.substring(lastSubStrIndex, i), x, y)
y += lineHeight
lineWidth = 0
lastSubStrIndex = i
}
if (i === text.length - 1) {
ctx.fillText(text.substring(lastSubStrIndex, i + 1), x, y)
}
}
}
// 获取当前位置详细信息
const getLocationDetail = ()=> {
return new Promise((resolve)=>{
wx.getLocation({
type: 'gcj02',
isHighAccuracy: true,
success(res_Location) {
// 腾讯地图Api
const qqmapsdk = new QQMapWX({
key: 'xxxxx' //这里填写自己申请的key
});
qqmapsdk.reverseGeocoder({
location: {
longitude: res_Location.longitude,
latitude: res_Location.latitude,
},
success(res) {
resolve(res.result)
},
});
},
fail() {
wx.showToast({
title: '获取定位是失败',
icon: 'none',
duration: 2000
})
wx.hideLoading();
}
})
})
}
// 选择照片并获取照片信息
const getImageInfo = ()=> {
return new Promise((resolve, reject)=>{
wx.chooseImage({
count: 1,
sizeType: ['original'],
sourceType: ['camera'],
success: async(res_chooseImage) => {
wx.showLoading({
title: "上传中...",
});
let locationDetail = await getLocationDetail()
if (res_chooseImage.tempFiles[0].size > 1024*1024*10) {
wx.hideLoading();
wx.showToast({
title: '照片大小不得超过10M',
icon: 'none',
duration: 2000
})
reject({ msg: '照片大小不得超过10M'});
return false
}
wx.getImageInfo({
src: res_chooseImage.tempFiles[0].path,
success(res_imageInfo){
resolve({
locationDetail,
imageInfo: res_imageInfo
})
},
fail(error) {
wx.hideLoading();
reject(error);
}
})
},
fail(error){
wx.hideLoading();
reject(error);
}
})
})
}
// 照片添加水印
export const addWatermark = (that = {}, canvasId = null) => {
return new Promise(async(resolve, reject)=>{
try {
let { locationDetail, imageInfo } = await getImageInfo();
// 将画布的大小设置宽度为600,高度自适应
let canvasWidth = 600;
let canvasHeight = parseInt(imageInfo.height/(imageInfo.width/600))
that.setData({
canvasWidth,
canvasHeight,
}, () => {
const ctx = wx.createCanvasContext(canvasId, that);
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
ctx.beginPath();
ctx.drawImage(imageInfo.path, 0, 0, canvasWidth, canvasHeight);
ctx.fillStyle = '#fff';
ctx.shadowOffsetX = 3;
ctx.shadowOffsetX = 3;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
ctx.font = 'bold 40px Medium';
ctx.fillText(util.formatterDate(new Date(), 'hh:mm'), 20, canvasHeight-50)
ctx.font = "20px Medium";
ctx.fillText(util.formatterDate(new Date(), 'yyyy.MM.dd'), 20, canvasHeight-20)
ctx.fillRect(150, canvasHeight-85, 2, 70)
canvasTextAutoLine(ctx, locationDetail.address, 170, canvasHeight-40, 280, 26)
ctx.fill()
clearTimeout(watermarkTimer);
ctx.draw(false, watermarkTimer = setTimeout(()=>{
wx.canvasToTempFilePath({
canvasId,
fileType: 'jpg',
quality: 1,
success(fileRes){
resolve({
locationDetail,
imageInfo,
fileUrl: fileRes.tempFilePath,
})
},
fail(error) {
if (error.errMsg) {
wx.showToast({
title: error.errMsg,
icon: 'none',
duration: 2000
})
}
reject(error)
wx.hideLoading();
}
})
}, 2000));
})
} catch (error) {
console.log(error, 'error1错误');
}
})
}
module.exports = {
canvasTextAutoLine,
getLocationDetail,
getImageInfo,
addWatermark,
};
util.js
// 格式化时间
const formatterDate = (date, type = 'yyyy-MM-dd') => {
const time = new Date(date);
let year = time.getFullYear();
let mouth = time.getMonth() + 1;
let day = time.getDate();
let hours = time.getHours();
let minutes = time.getMinutes();
let seconds = time.getSeconds();
mouth = addZero(mouth);
day = addZero(day);
hours = addZero(hours);
minutes = addZero(minutes);
seconds = addZero(seconds);
let value = '';
switch (type) {
case 'yyyy-MM-dd':
value = `${year}-${mouth}-${day}`
break;
case 'yyyy.MM.dd':
value = `${year}-${mouth}-${day}`
break;
case 'hh:mm':
value = `${hours}:${minutes}`
break;
case 'hh:mm:ss':
value = `${hours}:${minutes}:${seconds}`
break;
case 'yyyy-MM-dd hh:mm:ss':
value = `${year}-${mouth}-${day} ${hours}:${minutes}:${seconds}`
break;
}
return value
}
// 处理 小于10
const addZero = (i) => {
i = typeof i === 'string' ? Number(i) : i;
return i < 10 ? "0" + i : "" + i;
}
module.exports = {
formatterDate,
addZero
}