uniapp 图片添加水印代码封装(单张、多张、动态表单)

uniapp 图片添加水印代码封装

多张照片上传封装

<template>
	<view>
		<view class="form-item">
			<view v-for="(photo,inde) in imagesLists" :key="inde" class="photo">
				<image :src="photo" v-model="imagelistChange" @click="preview(photo,imagesLists)">
				</image>
				<view class="closeA" @tap="deletePhoto(inde)">
					<u-icon name="close" color="#000000"></u-icon>
				</view>
			</view>
			<view class="btnAddPhoto" style="margin: 5px;" @click="Imageschoose()" v-if="imagesLists.length>
				<u-icon name="camera" size="28"></u-icon>
			</view>
		</view>
		<canvas :style="{width:canvasWidth,height:canvasHeight}" canvas-id="myCanvas" v-if="flag"></canvas>
	</view>
</template>
<script>
	import {
		imageUpload,
	} from '@/api/system/applet.js' //图片上传,按照自己照片放置位置更改接口
	import {
		dateFormat,//日期约束
		imageChoose,//拿到后台图片上传链接
		text,//文字换行
		previewPhoto,//图片展示
		getLocation//获取定位
	} from '@/utils/public.js'
	export default {
		props: {
			images:Array,//图片数组
			limit:Number,//图片限制张数
			index:String,
			imagesLists:Array,//父组件传过来的照片数组
		},
		data() {
			return {
				photoIndex: null, //图片上传元素下标
				canvasWidth: '', //绘制图片宽度
				canvasHeight: '', //绘制图片高度	
				imagesList: [], //定义一个数组存放原照片文件
				photoArray: [], //未添加水印图片数组
				flag:false,//绘制显示
				longitude: '', //坐标
				latitude: '', //y坐标
				addressName: '', //传入公司地址
				imagelistChange:this.images
			}
		},
		methods: {
			// 调用添加水印的函数
			callAddWaterMart() {
				this.addWaterMark(() => {
					if (this.photoIndex < this.photoArray.length - 1) {
						this.photoIndex++;
						this.callAddWaterMart()
					}else{
						uni.hideLoading()
					}
				})
			},
			//图片选中,默认只允许拍照
			Imageschoose() {
				this.photoIndex = 0;
				let num = this.limit - this.imagesList.length
				uni.chooseImage({
					count: num,
					sourceType: ['camera', 'album'], //默认相机
					sizeType: ["compressed"], //缩略图
					success: res => {
						this.photoArray = res.tempFilePaths;
						this.callAddWaterMart();
					}
				})
			},
			// 添加水印
			async addWaterMark(callback) {
				let location = await getLocation()
				this.addressName = location.address
				this.latitude = location.lat
				this.longitude = location.long
				this.flag = true
				uni.showLoading({
					title: "图片加载中..."
				})
				uni.getImageInfo({
					src: this.photoArray[this.photoIndex],
					success: res => {
						this.canvasWidth = `${res.width}px`;
						this.canvasHeight = `${res.height}px`;
						if (res.width > 400 && res.height > 400) {
							var ctx = uni.createCanvasContext('myCanvas', this);
							ctx.clearRect(0, 0, res.width, res.height); //清空指定区域的绘图
							ctx.beginPath(); //开始绘制
							ctx.drawImage(this.photoArray[this.photoIndex], 0, 0, res.width, res.height);
							// 为图片添加水印
							ctx.translate(0, res.height - 200);
							let clientNameWidth = 20;
							let clientNameHeight = 50
							let date = new Date()
							let time = dateFormat("YYYY-mm-dd HH:MM:SS", date);
							ctx.beginPath();
							ctx.setFontSize(30); //改字体
							ctx.setFillStyle("rgba(255,255,255,1)");
							ctx.fillText("时间" + ':' + time, clientNameWidth, clientNameHeight);
							ctx.fillText("坐标" + ':' + this.longitude + ',' + this.latitude,
								clientNameWidth, clientNameHeight + 35);
							let data = "地址" + ':' + this.addressName
							let result = text(data, res)
							for (let i = 0; i <= result.rows; i++) {
								ctx.fillText(data.slice(result.rowFontNum * (i - 1), result
									.rowFontNum * i), clientNameWidth, clientNameHeight + (i +
									1) * 35)
							}
							// 开始绘制添加水印的图片并显示在页面中
							ctx.draw(false, () => {
								setTimeout(() => {
									uni.canvasToTempFilePath({
										canvasId: "myCanvas",
										destWidth: res.width,
										destHeight: res.height,
										fileType: 'jpg',
										quality: 1,
										success: res => {
											//图片上传拿url
											let image = imageChoose(res
												.tempFilePath)
											imageUpload(image).then(
											response => {
												this.imagesList.push(
													response.data
													.url);
												this.$emit("list", this
													.imagesList)
												this.$emit("listIndex",
													this.index)
												this.flag = false
												callback();
											})
										}
									}, this)
								}, 500)
							});
						} else {
							uni.showToast({
								title: '图片太小,请重新选择',
								icon: 'none'
							})
							return
						}

					}
				})
			},
			// 预览图片
			preview(url, list) {
				previewPhoto(url, list)
			},
			// 删除图片
			deletePhoto(index) {
				this.imagesList.splice(index, 1);
			}
		}
	}
</script>
<style lang="scss">
	canvas {
		position: absolute;
		left: 2000upx;
	}
</style>
```###  公用部分的封装js
applit.js为图片上传模块,为接口项,暂不提供
```c
// 预览图片
export function previewPhoto(url, list) {
	uni.previewImage({
		current: url,
		urls: list.map(item => item)
	})
}
// 高德地圖封装
import amap from '@/utils/amap-wx.130.js'
const amapPlugin = new amap.AMapWX({
	key: ''//填写自己的高德地图key
});
export function getLocation() {
	var Location
	return new Promise((resolve, reject) => {
		uni.getSetting({
			success(res) {
				let location = {};
				// 如果没有授权
				if (!res.authSetting['scope.userLocation']) {
					// 则拉起授权窗口
					uni.authorize({
						scope: 'scope.userLocation',
						success() {
							// 已授权 
							amapPlugin.getRegeo({
								success(data) {
									// let address =`${data[0].regeocodeData.addressComponent.city}${data[0].regeocodeData.addressComponent.district}`;
									let address =
										`${data[0].regeocodeData.formatted_address}`;
									// _this.address 可根据自己的实际情况修改
									// address = `${datwww.cppcns.coma[0].regeocodeData.formatted_address}`;
									let lat = `${data[0].latitude}`;
									let long = `${data[0].longitude}`;
									let time = `${data[0]}`;
									location = {
										address: address,
										lat: lat,
										long: long,
									}
									resolve(location)
									uni.hideLoading();
									return location
								},
								fail(err) { //不加此字段控制台会报错
									uni.getLocation({
										type: 'gcj02', //返回可以用于uni.openLocation的经纬度
										success: function(res) {
											location = {
												lat: res.latitude,
												long: res.longitude,
												address: '授权过期,启用内置定位'
											}
											resolve(location)
											return location
										},
										fail(err) { //不加此字段控制台会报错
											uni.showToast({
												title: "获取位置失败",
												icon: "error"
											})
										}
									});
								}
							})
						},
						fail(error) {
							//点击了拒绝授权后--就一直会进入失败回调函数--此时就可以在这里重新拉起授权窗口
							uni.showModal({
								title: '提示',
								content: '需要授权位置信息,否则将无法使用',
								cancelText: '不授权',
								cancelColor: '#999',
								confirmText: '授权',
								confirmColor: '#f94218',
								success(res) {
									if (res.confirm) {
										// 选择弹框内授权
										uni.openSetting({
											success(res) {
												console.log(res.authSetting)
												return
											}
										})
									} else if (res.cancel) {
										// 选择弹框内 不授权
										console.log('用户点击不授权')
										return
									}
								}
							})
						}
					})
				} else {
					amapPlugin.getRegeo({
						success(data) {
							let address = `${data[0].regeocodeData.formatted_address}`;
							// address = `${datwww.cppcns.coma[0].regeocodeData.formatted_address}`;
							let lat = `${data[0].latitude}`;
							let long = `${data[0].longitude}`;
							Location = {
								address: address,
								lat: lat,
								long: long,
							}
							resolve(Location)
							uni.hideLoading();
							return location
						},
						fail(err) {
							uni.getLocation({
								type: 'gcj02', //返回可以用于uni.openLocation的经纬度
								success: function(res) {
									location = {
										lat: res.latitude,
										long: res.longitude,
										address: '授权过期,启用内置定位'
									}
									resolve(location)
									return location
								},
								fail(err) { //不加此字段控制台会报错
									uni.showToast({
										title: "获取位置失败",
										icon: "error"
									})
								}
							});
						}
					})
				}

			}
		})
	})
}
//换行
export function text(str, res) {
	// 画布总宽度 px单位
	let canvasWidth = res.width / 3
	// 字体大小 px单位
	let fontSize = 12
	// 每行所需字数 = 画布总宽度 / 单个字体大小
	let rowFontNum = Math.floor(canvasWidth / fontSize)
	// 字符串总长度
	let strLength = str.length
	// 所需行数 = 字符总长度 / 每行所需字数
	let rows = Math.ceil(strLength / rowFontNum)
	return {
		canvasWidth,
		fontSize,
		rowFontNum,
		strLength,
		rows
	}
}
// 图片添加标头区分位置
export function imageChoose(item) {
	let data = {
		filePath: item,
		formData: {
			isSystem: 'true'//保存位置分权
		}
	}
	return data
}
//日期格式,用于绘制图片添加内容---
export function dateFormat(fmt, date) {
	let ret;
	const opt = {
		"Y+": date.getFullYear().toString(), // 年
		"m+": (date.getMonth() + 1).toString(), // 月
		"d+": date.getDate().toString(), // 日
		"H+": date.getHours().toString(), // 时
		"M+": date.getMinutes().toString(), // 分
		"S+": date.getSeconds().toString() // 秒
		// 有其他格式化字符需求可以继续添加,必须转化成字符串
	};
	for (let k in opt) {
		ret = new RegExp("(" + k + ")").exec(fmt);
		if (ret) {
			fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1]
				.length, "0")))
		};
	};
	return fmt;
}

应用实例

单张上传实例
<template>
  <view>
    <photoList   :value="baseFormData.faceImgsFirst"  :imagesLists="baseFormData.faceImgsFirst" @list="firstImage" :limit="1"/>
  </view>
</template>
<script>
import photoOne from '@/pages/public/photoOne/photoOne.vue'
export default{
       components: {
			photoOne
		},
		data(){
		   return{
		       baseFormData:{}
		   }
		},
		methods:{
		  firstImage(val){
				this.baseFormData.faceImgsFirst=val
		  },
		}
}
</script>
多张上传

limit 控制张数

<template>
  <view>
    <photoList  :value="baseFormData.images" @list="imageList" :limit="9"  :imagesLists="baseFormData.images"/>
  </view>
</template>
<script>
import photoList from '@/pages/public/photoList/photoList.vue'
export default{
       components: {
			photoList
		},
		methods:{
		 imageList(val){
				this.baseFormData.images=val//此项为你接收数据项,
			},
		}
}
</script>

动态表单照片添加水印(直接使用)

注意imagelists必填,避免出现删除不一致现象,发送为父级数据


<template>
  <view>
    <uni-forms>
       <uni-forms-item label="照片" required :rules="[{required: true,errorMessage: '最少一张照片'}]":name="['inspectionCustodyWorkLogDetailBoList',index,'imagelist']" label-width="100rpx">
			<view class="form-item">
		        <photoLis :value="baseFormData.inspectionCustodyWorkLogDetailBoList[index].imagelist"  :imagesLists="baseFormData.inspectionCustodyWorkLogDetailBoList[index].imagelist" :limit="9"  :index="index" @listIndex="getIndex" @list="imageList"/>
			</view>
		</uni-forms-item>
    </uni-forms>
  </view>
</template>
<script>
import photoOne from '@/pages/public/photoOne/photoOne.vue'
export default{
       components: {
			photoOne
		},
		data(){
		    // 基础表单数据
			baseFormData: {
				inspectionCustodyWorkLogDetailBoList: [], //第三方服务机构工作日志检查记录
			},
		},
		methods:{
		  //获取下标
			getIndex(index){
				this.inde=index
			},
			async imageList(val){
				await this.getIndex()
				this.baseFormData.inspectionCustodyWorkLogDetailBoList[this.inde].imagelist=val
			},
			//获取后台数据
			getList(){
			  //获取自己的数据,按照实际情况填写
			}		  
		}
}
</script>


你可能感兴趣的:(前端,uniapp,小程序)