前言
一款智能水印相机,拍照自动添加时间、地点、经纬度等水印文字,可用于工作考勤、学习打卡、工作取证等,支持自定义内容以及给现有照片添加水印。无需安装,无需注册,即开即用。
原理
主要是通过canvas给图片上添加上时间水印地点信息。首先通过官方API(chooseLocation)获取到位置信息,然后利用JS获取本地时间,最后绘制到canvas上通过canvasToTempFilePath生成图片。
获取位置信息
这个接口在去年开始就需要用户手动申请,在小程序管理页面申请,如果申请按钮无法点击,在提交代码时会弹窗申请弹窗,之后就可以申请了。通过后才可以上线小程序。代码如下:
- /**
- * 获取地址信息
- */
- getLocation: function () {
- wx.getLocation({
- success: res => {
- qqmapsdk.reverseGeocoder({
- location: {
- latitude: res.latitude,
- longitude: res.longitude
- },
- success: res => {
- let address = res.result.address;
- this.setData({
- address
- })
- }
- })
- }
- })
- },
- /**
- * 手动选择地点
- */
- chooseLocation: function () {
- wx.chooseLocation({
- success: res => {
- console.log(res)
- this.setData({
- address: res.address
- })
- },
- fail: err => {
- console.log(err)
- }
- })
- }
其中qqmapsdk使用的是腾讯位置服务的sdk,需要去官方下载并申请key,然后再页面中加上如下代码:
- var QQMapWX = require(‘../../libs/qqmap-wx-jssdk.js’);
- var qqmapsdk = new QQMapWX({
- key: ” // 这里填写你的key
- });
获取时间信息
时间信息就很简单了,这里给大家提供封装了一下,如下代码:
- export const formatTime = () => {
- const date = new Date();
- const year = date.getFullYear()
- const month = date.getMonth() + 1
- const day = date.getDate()
- const weekDay = [‘日’, ‘一’, ‘二’, ‘三’, ‘四’, ‘五’, ‘六’][date.getDay()]
- const hour = date.getHours()
- const minute = date.getMinutes()
- const second = date.getSeconds()
- return {
- date: [year, month, day].map(formatNumber).join(‘-‘),
- time:[hour, minute, second].map(formatNumber).join(‘:’),
- week: ‘星期’+weekDay
- }
- }
- const formatNumber = (n) => {
- const s = n.toString()
- return s[1] ? s : ‘0’ + s
- }
绘制图片
这里说明一下,目前 wx.createCanvasContext接口以及弃用了,所以我们采用Canvas.getContext代替,首先我们需要添加canvas,在wxml页面中添加如下代码,一定要设置好宽高,可以是动态的,但是必须设定好,不然很容易出现画面模糊的问题。
- <canvas type=“2d” id=“canvas” style=“position: fixed; top: -10000px; left: -10000px; width: {{canvasWidth}}px;height: {{canvasHeight}}px;”></canvas>
然后动态设置宽高可以根据相机或者图片的宽高自定设置,然后我们将时间、位置和图片等信息一起绘制在canvas上。
- /**
- * 给图片添加水印
- */
- addWatermark: function (imageUrl) {
- console.log(imageUrl)
- return new Promise((resolve, reject) => {
- wx.showLoading({
- title: ‘图片生成中…’,
- })
- const query = wx.createSelectorQuery();
- query.select(‘#canvas’).fields({
- node: true,
- size: true
- }).exec((res) => {
- console.log(res)
- const canvas = res[0].node;
- const ctx = canvas.getContext(‘2d’);
- const dpr = wx.getSystemInfoSync().pixelRatio;
- const {
- canvasWidth,
- canvasHeight
- } = this.data;
- canvas.width = canvasWidth * 1.5
- canvas.height = canvasHeight * 1.5
- ctx.scale(1.5, 1.5)
- // 绘制背景图片
- const image = canvas.createImage();
- image.onload = () => {
- ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
- ctx.font = ‘normal 28px null’;
- ctx.fillStyle = ‘#ffffff’;
- ctx.textBaseline = ‘bottom’;
- // 绘制地址
- ctx.fillText(this.data.address, 20, canvasHeight – 20);
- // 绘制时间
- ctx.fillText(this.data.date + ‘ ‘ + this.data.time, 20, canvasHeight – 65);
- // 绘制星期
- ctx.fillText(this.data.week, 20, canvasHeight – 115);
- wx.canvasToTempFilePath({
- canvas,
- success: (res) => {
- wx.hideLoading()
- resolve(res.tempFilePath);
- },
- fail: () => {
- wx.hideLoading()
- reject(new Error(‘转换为图片失败’));
- }
- });
- }
- image.src = imageUrl;
- });
- });
- },
这里直接用Promise封装了一下,方便调用。其中iamgeUrl为相机的照片或者用户自己上传的图片地址。
以上就是大致的流程,具体如何操作,可以看我开源的智能水印相机的代码: