uniapp 图片添加水印代码封装(优化版、图片上传压缩、生成文字根据页面自适应比例、增加文字背景色

本文主要是介绍uniapp 图片添加水印代码封装(优化版、图片上传压缩、生成文字根据页面自适应比例、增加文字背景色,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

uniapp 图片添加水印代码封装(优化版、图片上传压缩、生成文字根据页面自适应比例、增加文字背景色

多张照片上传封装

<template><view class="image-picker"><uni-file-picker v-model="imageValue" :auto-upload="false" :title="title" :limit="limit":image-styles="imageStyles" :file-mediatype="fileMediatype" :mode="mode" @select="select"><view v-if="loading" class="form-item-column-center"><u-loading-icon text="上传中" textSize="12" :vertical="true"></u-loading-icon></view><view v-else class="form-item-column-center"><u-icon name="camera" size="28"></u-icon><view :style="{ marginTop: '5px'}">上传照片</view></view></uni-file-picker><view class="watermark-canvas"><canvas id="watermark-canvas" :style="{ width: canvasWidth, height: canvasHeight }"canvas-id="watermark-canvas" v-if="flag" /></view></view>
</template><script>import {imageUpload,} from '@/api/system/applet.js' //图片上传import {imageChoose, //拿到后台图片上传链接} from '@/utils/public.js'export default {name: 'ImageWatermarkPicker',props: {limit: {type: [Number, String],default: 1,},title: {type: String,default: null,},mode: {type: String,default: 'grid',},fileMediatype: {type: String,default: 'image',},imageStyles: {type: Object,default: null,},watermark: {type: Boolean,default: true,},// #ifdef VUE3modelValue: {type: Array,default () {return []},},// #endif// #ifndef VUE3value: {type: Array,default () {return []},},// #endif},emits: ['input', 'update:modelValue'],data() {return {flag: false, //绘制显示imageValue: [],canvasWidth: '1080px',canvasHeight: '2160px',longitude: '', //坐标latitude: '', //y坐标addressName: '', //传入公司地址loading: false,oldImageslength: null, //上传时照片个数}},watch: {imageValue(newVal) {// #ifdef VUE3this.$emit('update:modelValue', newVal)// #endif// #ifndef VUE3this.$emit('input', newVal)// #endifthis.$emit('change', newVal)},// #ifndef VUE3value: {handler(newVal) {this.imageValue = newVal},immediate: true,},// #endif// #ifdef VUE3modelValue: {handler(newVal) {this.imageValue = newVal},immediate: true,},// #endif},methods: {// 检测图片,确保图片存在checkImage(url) {const checkNum = 5let currentCheckNum = 1return new Promise((resolve, reject) => {process()function process() {uni.getImageInfo({src: url,success: function(image) {resolve(image)},fail: function(err) {if (checkNum <= currentCheckNum) {uni.showToast({title: '图片上传失败',icon: 'none'})reject(err)} else {currentCheckNum++const timer = setTimeout(() => {clearTimeout(timer)process()}, 300)}},})}})},async select(e) {this.oldImageslength = e.tempFiles.lengthfor (let tempFile of e.tempFiles) {await this.watermarkProcess(tempFile)}},async watermarkProcess(tempFile) {const {name,size,extname,uuid,path} = tempFilelet url = nulllet photo = null// 添加水印if (this.watermark) {url = await this.addWatermark(path)}// 上传图片url = await this.uploadFile(url)// 检测图片,确保图片存在await this.checkImage(url)this.imageValue = [...this.imageValue,{name,extname,url,photo,size,uuid,},]},getHeightOffset(height, index, fontSize) {return index == 0 ? (height - fontSize) : (height - (index * fontSize) - fontSize) - (index * (fontSize /3))},// 异步添加水印async addWatermark(tempFilePath) {// #ifdef MP-WEIXINthis.addressName = '测试位置'this.latitude = 119.651this.longitude = 80.654// #endifthis.flag = trueif (this.loading == true) {uni.showLoading({title: "上传图片",mask: true,})}return new Promise((resolve, reject) => {uni.getImageInfo({src: tempFilePath,success: async (res) => {// 设置画布高度和宽度this.canvasWidth = `${res.width}px`this.canvasHeight = `${res.height}px`await this.sleep(200) // 某些平台 canvas 渲染慢,需要等待const ctx = uni.createCanvasContext('watermark-canvas', this)ctx.clearRect(0, 0, res.width, res.height)ctx.beginPath()ctx.drawImage(tempFilePath, 0, 0)// 第一个参数是图片 第二、三是图片在画布位置 第四、五是将图片绘制成多大宽高(不写四五就是原图宽高)let size// 根据图片纵横比设置字体大小,背景色相比一般ctx.fillStyle = 'rgba(0,0,0,0.1)'; // 设置背景色if (res.width / res.height > 1) {size = Math.floor(res.height / 26)//这个背景不一定适用,自行调整ctx.fillRect(0, res.height - (size*6), res.width, size*6); // 填充整个 Canvas 区域	} else {size = Math.floor(res.width / 26)ctx.fillRect(0, res.height - (size*7), res.width, size*7); // 填充整个 Canvas 区域	}let fontSize = sizectx.setFontSize(fontSize)ctx.shadowColor = "rgba(0,0,0,1.0)";//设置字体阴影,真机未生效ctx.shadowOffsetX = 5ctx.shadowOffsetY = 5let max = (res.width - fontSize) / fontSize //图片上一行能显示的最大字数let marks = []let address = "地址:" + this.addressNamelet location = "坐标:" + this.latitude + ',' + this.longitudelet fillTexts = [address, location, time]fillTexts.forEach((mark, index) => {//测量出最长文字的宽// console.log('文字宽:'+ctx.measureText(mark).width)if (mark.length <= max) {marks.push({mark: mark, //水印文字start: fontSize / 2 //第一个字的起点位置})} else {marks.push({mark: mark.substring(max),start: fontSize / 2 + fontSize *3 //第一个字的起点位置,+fontSize*3是因为此水印为当前mark的换行,因此缩进3字符})marks.push({mark: mark.substring(0, max),start: fontSize / 2 //第一个字的起点位置})}})// 绘制水印背景另外写法,实测不太好用// ctx.fillStyle = 'rgba(0,0,0,0.1)'; // 设置背景色// ctx.fillRect(0, this.getHeightOffset(res.height, 4, fontSize), res.width,this.getHeightOffset(res.height, 4, fontSize)); // 填充整个 Canvas 区域	//绘制水印文字marks.forEach((mark, index) => {ctx.setFillStyle("rgba(250, 250, 250,1.0)")ctx.fillText(mark.mark, mark.start, this.getHeightOffset(res.height, index, fontSize))});ctx.draw(false, async () => {await this.sleep(500) // 某些平台 canvas 渲染慢,需要等待uni.canvasToTempFilePath({canvasId: 'watermark-canvas',destWidth: res.width,destHeight: res.height,fileType: 'jpg',quality: 0.8,success: (fileRes) => {this.flag = falseresolve(fileRes.tempFilePath)},fail: (err) => {console.log('[Error draw]', err)uni.showToast({title: err.errMsg,icon: 'none'})reject()},},this,)})},fail: (err) => {console.log('[Error getImageInfo]', err)uni.showToast({title: err.errMsg,icon: 'none'})reject()},})})},//此位置为我上传后台的写法,具体可按照自己的填写async uploadFile(path) {let image = imageChoose(path)const res = await imageUpload(image).then(response => {this.oldImageslength--this.loading = this.oldImageslength == 0 ? false : truethis.oldImageslength == 0 ? uni.hideLoading() : ''return response.data.url})return res},sleep(millisecond) {return new Promise((resolve) => {setTimeout(resolve, millisecond)})},},}
</script><style lang="scss" scoped>canvas {position: absolute;left: 2000upx;}.image-picker {position: relative;.form-item-column-center {display: flex;align-items: center;justify-content: center;flex: 1;flex-direction: column;}.watermark-canvas {position: absolute;top: 5px;left: 5px;width: 1px;height: 1px;overflow: hidden;}}
</style>

应用实例

照片上传实例
<template><view><photoList   v-model="baseFormData.faceImgsFirst"  :limit="1"/></view>
</template>
<script>
import photoOne from '@/pages/public/photoOne/photoOne.vue'
export default{components: {photoOne},data(){return{baseFormData:{}}},methods:{}
}
</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"><photoList   v-model="baseFormData.faceImgsFirst"  :limit="1"/></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:{}
}
</script>

这篇关于uniapp 图片添加水印代码封装(优化版、图片上传压缩、生成文字根据页面自适应比例、增加文字背景色的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/983546

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建