效果展示
点击“拍照”,拍照成功后在底部生成已经添加上水印的图片,点击图片查看图片
结构与样式
结构
<template>
<view>
<camera :device-position="device" :flash="flash" @error="error" :style="{ width: '100%',position: 'relative', height: getHeight + 'px' }">
<cover-view class="topBox">
<!-- 时间 -->
<cover-view class="topItem">{{nowTime2}}</cover-view>
<!-- 日期 -->
<cover-view class="topItem">{{nowTime}}</cover-view>
<!-- 地址 -->
<cover-view class="topItem">{{address}}</cover-view>
</cover-view>
<!-- 旋转摄像头 -->
<cover-image @click="xzBtn" class="xzImg" src="https://cdn.zhoukaiwen.com/xz.png"></cover-image>
<!-- 打开/关闭 闪关灯 -->
<cover-image @click="sgdBtn" class="sgdImg" :src="sgdUrl"></cover-image>
<!-- 拍照 -->
<cover-view class="cameraBtn" @click="takePhoto">
<cover-view class="cameraBtn2"></cover-view>
</cover-view>
<!-- 底部预览生成图片 -->
<cover-view class="bottomBg" v-if="imgList.length > 0">
<cover-view>
<cover-view @click="ViewImage(index)" class="imgBox" v-for="(item,index) in imgList" :key="index">
<cover-image class="imgItem" :src="item.src" mode="aspectFill"></cover-image>
<cover-view class="cu-tag" @tap.stop="DelImg" :data-index="index">
<cover-image class="iconClose" src="https://cdn.zhoukaiwen.com/icon_close.png" mode="aspectFill"></cover-image>
</cover-view>
</cover-view>
</cover-view>
</cover-view>
</camera>
<!-- canvas元素,利用它的功能,实现添加水印 -->
<view style="position: absolute;top: -999999px;">
<view>
<canvas :style="{ width: w, height: h }" canvas-id="firstCanvas"></canvas>
</view>
</view>
</view>
</template>
为了让自定义的按钮如:旋转镜头、打开/关闭 闪光灯、拍摄等能够位于camera
组件上层,所以容器都采用 cover-view、cover-image
样式
.topBox {
width: 750rpx;
box-sizing: border-box;
padding: 30rpx;
color: #EEEEEE;
font-size: 34rpx;
.topItem {
width: 100%;
white-space: pre-wrap;
margin-bottom: 15rpx;
}
}
.cameraBtn {
width: 120rpx;
height: 120rpx;
line-height: 120rpx;
border: 6rpx #FFFFFF solid;
border-radius: 50%;
padding: 8rpx;
position: absolute;
left: calc(50% - 60rpx);
bottom: 210rpx;
}
.cameraBtn2 {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #FFFFFF;
text-align: center;
color: #007AFF;
}
.xzImg {
width: 52rpx;
height: auto;
position: absolute;
right: 44rpx;
bottom: 580rpx;
}
.sgdImg {
width: 40rpx;
height: auto;
position: absolute;
right: 50rpx;
bottom: 450rpx;
}
.bottomBtn {
width: 100%;
height: 150rpx;
padding-bottom: 15rpx;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
display: flex;
justify-content: space-between;
.btn {
width: 30%;
height: 150rpx;
font-size: 34rpx;
color: #FFFFFF;
line-height: 150rpx;
}
}
.bottomBg {
width: 100%;
height: 170rpx;
box-sizing: border-box;
padding: 20rpx 30rpx 40rpx;
position: absolute;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .8);
display: flex;
justify-content: space-between;
align-items: center;
.imgBox {
width: 110rpx;
height: 110rpx;
float: left;
margin-right: 40rpx;
position: relative;
.cu-tag {
position: absolute;
right: 0;
top: 0;
border-bottom-left-radius: 2px;
padding: 3px 5px;
height: auto;
background-color: rgba(0, 0, 0, 0.5);
font-size: 10px;
vertical-align: middle;
font-family: Helvetica Neue, Helvetica, sans-serif;
white-space: nowrap;
color: #ffffff;
}
}
.imgItem {
width: 110rpx;
height: 110rpx;
}
}
.iconClose {
width: 20rpx;
height: 20rpx;
}
绑定数据
data() {
return {
getHeight: '200', // camera 组件高度
device: 'back', //前置或后置摄像头,值为front, back
flash: 'off', // 闪光灯,值为auto, on, off
nowTime: '', //日期
nowTime2: '', //时间
address: '', //当前地址信息
sgdUrl: 'https://cdn.zhoukaiwen.com/sgd.png', // 闪光灯图片地址
imgList: [ // 底部预览图片的列表
// {
// src: "https://cdn.zhoukaiwen.com/angular.jpg"
// }
],
w: '', // canvas 元素宽度
h: '' // canvas 元素高度
}
},
逻辑代码
需要提前下载腾讯地图微信小程序JavaScript SDK,实现定位功能
// 引入微信小程序JavaScript SDK
import QQMapWX from "@/common/qqmap-wx-jssdk";
onLoad() {
const that = this;
var qqmapsdk;
// 获取系统信息,为 camera 组件设置高度
uni.getSystemInfo({
success: function(res) {
that.getHeight = res.windowHeight;
}
});
// 获取当前日期时间
this.getTime();
// 获取当前位置信息
uni.getLocation({
type: 'wgs84',
success: function(res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
qqmapsdk = new QQMapWX({
key: "xxxxxxxxxxxxxxxxxxx" //自己申请的腾讯地图key
});
// 根据经纬度反解析出地址名称
qqmapsdk.reverseGeocoder({
location: {
latitude: res.latitude,
longitude: res.longitude
},
success(addressRes) {
that.address = addressRes.result.address;
},
fail(res) {}
});
}
});
},
methods: {
// 旋转摄像头
xzBtn() {
if (this.device == 'front') {
this.device = 'back'
} else {
this.device = 'front'
}
},
// 打开/关闭 闪光灯
sgdBtn() {
if (this.flash == 'off') {
this.flash = 'on'
this.sgdUrl = 'https://cdn.zhoukaiwen.com/sgd_on.png'
} else {
this.flash = 'off'
this.sgdUrl = 'https://cdn.zhoukaiwen.com/sgd.png'
}
},
// 删除水印照片
DelImg(e) {
uni.showModal({
content: '确定要删除这张照片吗?',
cancelText: '取消',
confirmText: '确认',
success: res => {
if (res.confirm) {
this.imgList.splice(e.currentTarget.dataset.index, 1)
}
}
})
},
// 查看照片
ViewImage(index) {
const imgList = [this.imgList[index].src];
uni.previewImage({
urls: imgList
});
},
// 点击拍照
takePhoto() {
var that = this;
if (this.imgList.length < 3) {
// 创建并返回 camera 组件的上下文 cameraContext 对象
const ctx = uni.createCameraContext();
// 拍照
ctx.takePhoto({
quality: 'high', // 图片质量高
success: (res) => {
var tempImagePath = res.tempImagePath; // 临时图片路径
// 获取图片信息
uni.getImageInfo({
src: res.tempImagePath,
success: ress => {
that.w = ress.width / 3 + 'px'; // 设置 canvas 元素宽度
that.h = ress.height / 3.01 + 'px'; // 设置 canvas 元素高度
let ctx = uni.createCanvasContext('firstCanvas'); /** 创建画布 */
//将图片绘制到cancas内
ctx.drawImage(res.tempImagePath, 0, 0, ress.width / 3, ress.height / 3);
ctx.setFontSize(10); // 设置字体大小为 10px
ctx.setFillStyle('#FFFFFF'); // 设置颜色为白色
let textToWidth = (ress.width / 3) * 0.03; // 绘制文本的左上角x坐标位置
let textToHeight1 = (ress.height / 3) * 0.94; // 绘制文本的左上角y坐标位置
let textToHeight2 = (ress.height / 3) * 0.98;
// 绘制日期和时间
ctx.fillText(that.nowTime + ' ' + that.nowTime2, textToWidth, textToHeight1);
// 绘制地址
ctx.fillText(that.address, textToWidth, textToHeight2);
// 绘制完成后,在下一个事件循环将 canvas 内容导出为临时图片地址
ctx.draw(false, () => {
setTimeout(() => {
uni.canvasToTempFilePath({
canvasId: 'firstCanvas',
success: res1 => {
tempImagePath = res1.tempFilePath
this.imgList.push({
src: tempImagePath
})
}
});
}, 1000);
});
}
});
}
});
} else {
uni.showToast({
title: '最大上传3张照片',
duration: 2000,
icon: 'none'
});
}
},
// 用户不允许使用摄像头时触发
error(e) {
console.log(e.detail);
},
// 获取日期时间
getTime: function() {
var date = new Date(),
year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate(),
hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(),
minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(),
second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
month >= 1 && month <= 9 ? (month = "0" + month) : "";
day >= 0 && day <= 9 ? (day = "0" + day) : "";
var timer = year + '年' + month + '月' + day + '日';
var timer2 = hour + ':' + minute + ':' + second;
this.nowTime = timer;
this.nowTime2 = timer2;
}
}