原生小程序拍照水印

420 阅读2分钟

前言:最近因业务需求而开发拍照有水印信息,所以记录下,以便大家一起学习学习,各位大佬若觉得代码有什么错误或者有高效的方法,欢迎指点指点,让大家有更高效的开发代码。

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文件

  1. 引入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

  1. 导入util.js文件
  2. 导入qqmap-wx-jssdk.js,下载地址:lbs.qq.com/miniProgram…
  3. 填写申请后的密钥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
}

单行/多行效果

demo1.jpg demo2.jpg