uniapp小程序上传照片加水印

文章描述了一个在HTML页面中使用uni-app的API进行图片选择、缩放、添加水印以及将处理后的图片转换为临时文件路径并上传的过程。具体涉及uni.chooseImage选择图片,getImageInfo获取图片信息,createCanvasContext创建画布,drawImage绘制图片,fillText添加文字水印,以及canvasToTempFilePath生成带水印的图片文件并调用uploadImages函数进行上传。

html 页面

<view style="width: 0;height: 0;overflow: hidden;" >
            <canvas  canvas-id="firstCanvas"  style="" :style="{ width: width, height: height}" class="canvas"></canvas>
        </view>

changeImage(index) {
            let that = this;
            uni.chooseImage({
                count: 1, //默认9
                sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
                sourceType: ['album'], //从相册选择
                loop: true,
                success: res => {
                    console.log(res);
                    uni.getImageInfo({  //获取拿到图片的信息
                        src: res.tempFilePaths[0],
                        success: result => {
                            console.log(result.path);
                            console.log(result);
                            this.width = result.width + 'rpx';
                            this.height = result.height + 'rpx';
                            let address = '顾仁陪诊';  //传入的水印名称
                            const ctx = uni.createCanvasContext('firstCanvas');  //创建一个画布
                            ctx.drawImage(result.path, 0, 0, result.width / 2, result.height / 2);  //把拿到的图片放进去  最后两个属性是图片的大小
                            ctx.setFillStyle('#fff');  //水印的颜色
                            ctx.setFontSize(16);   //水印的大小
                            ctx.fillText(address, 20, result.height / 2 - 10);   //水印名称放进去  后面是水印的位置
                            //注意:设置文字大小必须放在填充文字之前,否则不生效
                            
                            ctx.draw(false, function() {
                                setTimeout(function() {
                                    //绘画完成回调
                                    
                                    uni.canvasToTempFilePath({  //生成图片
                                        quality: 1,
                                        fileType: 'jpg',
                                        canvasId: 'firstCanvas',
                                        success: function(ress) {
                                            
                                            // console.log(ress.tempFilePath); //ress.tempFilePath就是带有水印的图片路径
                                            
                                            let data = {
                                                file: ress.tempFilePath, //你要传的临时文件
                                                type: 1
                                            };
                                            uploadImages(data).then(ress => {
                                                if (ress.code == 200) {
                                                    if(index==1){
                                                        that.jsonData.idCarImageFront=ress.body
                                                    }else if(index==2){
                                                        that.jsonData.idCarImageOpposite=ress.body
                                                    }
                                                }
                                            });
                                        }
                                    });
                                }, 600);
                            });
                        }
                    });
                    // 
                }
            });
        },

<think>我们正在开发一个UniApp微信小程序,需要实现图片水印功能,并且要求水印图片不会被切割(即保持原图完整显示)。以下是实现步骤和注意事项:1.**使用Canvas绘制**:在微信小程序中,我们可以通过Canvas来绘制图片水印。Canvas提供了强大的绘图能力,可以保证在绘制过程中保持图片的原始比例。2.**步骤概述**:a.创建一个Canvas上下文。b.将图片绘制到Canvas上。c.在图片上绘制水印(文字或图片水印)。d.将Canvas内容导出为临时图片路径。e.将导出的图片展示或保存。3.**关键点:保持图片不被切割**-我们需要获取图片的原始宽高,然后根据Canvas的尺寸调整图片的绘制位置和大小,确保图片完整显示且不变形。-通常做法:计算图片的宽高比,然后根据Canvas的宽度或高度按比例缩放图片,使得图片完整显示在Canvas内。4.**具体实现代码示例**:```javascript//在uniapp中,我们可以使用uni.createCanvasContext创建画布上下文//假设我们在页面上有一个canvas组件,设置其大小(建议设置成与图片相同的宽高比,或者根据图片动态设置)//注意:canvas的大小要足够容纳图片,否则图片会被裁剪//步骤1:获取图片信息uni.getImageInfo({src:'图片路径',success:(res)=>{constimgWidth=res.width;constimgHeight=res.height;//步骤2:创建Canvas上下文constctx=uni.createCanvasContext('myCanvas');//myCanvas是canvas组件的id//步骤3:计算绘制图片的尺寸,保持原图比例,完整显示//假设我们的画布宽为300,高为200(实际中可以根据需要设置,或者根据图片比例动态设置画布大小)constcanvasWidth=300;//画布宽度constcanvasHeight=200;//画布高度//计算图片适应画布后的尺寸letdrawWidth,drawHeight;constratio=imgWidth/imgHeight;if(imgWidth/imgHeight>canvasWidth/canvasHeight){//图片宽高比大于画布宽高比,则按画布宽度缩放图片drawWidth=canvasWidth;drawHeight=canvasWidth/ratio;}else{//否则按画布高度缩放drawHeight=canvasHeight;drawWidth=canvasHeight*ratio;}//居中绘制图片constx=(canvasWidth-drawWidth)/2;consty=(canvasHeight-drawHeight)/2;//绘制图片ctx.drawImage(res.path,x,y,drawWidth,drawHeight);//步骤4:绘制水印(文字水印示例)ctx.setFontSize(20);ctx.setFillStyle('rgba(255,255,255,0.5)');ctx.fillText('我的水印',20,30);//水印位置可以根据需要调整//步骤5:绘制完成,导出图片ctx.draw(false,()=>{uni.canvasToTempFilePath({canvasId:'myCanvas',success:(res)=>{//导出的临时文件路径consttempFilePath=res.tempFilePath;//这里可以将tempFilePath赋值给image组件的src,或者上传服务器等console.log(tempFilePath);},fail:(err)=>{console.log(err);}});});}});```5.**注意事项**:-**Canvas尺寸设置**:为了避免图片被切割,我们动态计算了图片在Canvas中的绘制尺寸,确保图片完整显示。同时,Canvas本身的大小应该设置成足够大以容纳图片(或者根据图片大小动态设置Canvas大小)。-**水印位置**:水印位置可以根据需要调整,比如重复平铺、居中、角落等。-**性能问题**:绘制大图片可能会造成性能问题,建议对图片进行适当压缩或限制最大尺寸。-**真机调试**:在微信开发者工具中可能正常,但真机上可能由于Canvas层级问题导致显示异常,需要注意Canvas的层级是最高的,可能会覆盖其他组件,通常我们会在绘制完成后隐藏Canvas。-**隐藏Canvas**:我们可以在页面上放置一个隐藏的Canvas(使用绝对定位并移到屏幕外,或者设置宽高为0),避免影响页面布局。6.**关于动态设置Canvas大小**:如果原图很大,我们可能需要根据原图尺寸动态设置Canvas的宽高,但是注意微信小程序的Canvas有最大尺寸限制(具体限制参考官方文档)。因此,如果原图过大,我们可以按比例缩小Canvas,或者先压缩图片再绘制。7.**文字水印平铺**:如果需要平铺水印,可以使用循环绘制,但要注意性能。8.**图片水印**:如果是图片水印,可以使用`drawImage`方法绘制水印图片,同样需要调整位置和大小。以上方法可以保证图片不被切割,并且添水印。根据实际需求调整水印的样式和位置即可。§§相关问题§§1.如何动态调整Canvas的大小以适应不同尺寸的图片?2.如何实现平铺水印效果(文字或图片)?3.如何解决Canvas在真机上可能出现的层级问题?4.如何对图片进行压缩以避免绘制大图时的性能问题?</think>### UniApp 微信小程序实现图片水印(不切割图片)的方法 在 UniApp 中实现图片水印且不切割图片的核心思路是**使用 Canvas 绘制**,通过精确计算保持原始图片比例。以下是具体实现步骤: --- #### 一、实现步骤 1. **创建 Canvas 画布** ```html <!-- 页面中放置隐藏的 Canvas --> <canvas canvas-id="watermarkCanvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', position: 'absolute', left: '-9999px' }"/> ``` 2. **计算画布尺寸(关键步骤)** ```javascript // 获取图片原始宽高 uni.getImageInfo({ src: 'your-image-path', success: (res) => { const imgWidth = res.width; const imgHeight = res.height; // 设置画布尺寸 = 图片原始尺寸 this.canvasWidth = imgWidth; this.canvasHeight = imgHeight; } }); ``` 3. **绘制图片水印** ```javascript const ctx = uni.createCanvasContext('watermarkCanvas', this); // 1. 绘制原始图片(完整尺寸) ctx.drawImage('your-image-path', 0, 0, this.canvasWidth, this.canvasHeight); // 2. 添文字水印(示例) ctx.setFontSize(20); ctx.setFillStyle('rgba(255,255,255,0.7)'); ctx.fillText('你的水印文字', this.canvasWidth - 150, this.canvasHeight - 30); // 3. 导出图片(不切割的关键) ctx.draw(false, () => { uni.canvasToTempFilePath({ canvasId: 'watermarkCanvas', success: (res) => { this.watermarkedImg = res.tempFilePath; // 获取水印图片 } }); }); ``` --- #### 二、避免图片切割的关键点 1. **画布尺寸匹配** 设置 `canvasWidth` 和 `canvasHeight` 等于图片原始尺寸,确保画布能完整容纳图片。 2. **使用 `drawImage` 的完整参数** ```javascript // 格式:drawImage(image, x, y, width, height) ctx.drawImage(src, 0, 0, canvasWidth, canvasHeight); ``` 3. **水印位置动态计算** 根据画布尺寸动态定位水印: ```javascript // 右下角水印示例 const watermarkX = canvasWidth - textWidth - 20; const watermarkY = canvasHeight - 30; ``` --- #### 三、完整示例代码 ```javascript export default { data() { return { canvasWidth: 0, canvasHeight: 0, watermarkedImg: '' } }, methods: { async addWatermark() { // 获取图片信息 const imgInfo = await uni.getImageInfo({ src: 'your-image-path' }); // 设置画布尺寸 this.canvasWidth = imgInfo.width; this.canvasHeight = imgInfo.height; // 等待画布渲染 this.$nextTick(() => { const ctx = uni.createCanvasContext('watermarkCanvas', this); // 绘制原始图片 ctx.drawImage(imgInfo.path, 0, 0, this.canvasWidth, this.canvasHeight); // 添水印 ctx.setFontSize(20); ctx.setFillStyle('rgba(255,255,255,0.7)'); ctx.fillText('Watermark © 2023', this.canvasWidth - 180, this.canvasHeight - 20); // 导出图片 ctx.draw(false, () => { uni.canvasToTempFilePath({ canvasId: 'watermarkCanvas', success: (res) => { this.watermarkedImg = res.tempFilePath; uni.previewImage({ urls: [this.watermarkedImg] }); } }); }); }); } } } ``` --- #### 四、注意事项 1. **性能优化** -图片处理前先压缩:使用 `uni.compressImage` - 使用 `canvasToTempFilePath` 的 `fileType` 参数控制输出格式(建议 `jpg`) 2. **真机兼容性** - iOS 需设置画布尺寸为整数 - Android 注意最大尺寸限制(4096px) 3. **水印样式增强** ```javascript // 添旋转和水印背景 ctx.rotate(-30 * Math.PI / 180); ctx.fillRect(x, y, textWidth + 10, 30); ``` --- #### 五、替代方案(无需 Canvas) 如果不需要复杂水印,可使用 CSS 实现: ```html <view class="image-container"> <image :src="imgSrc" mode="widthFix"/> <view class="watermark">你的水印</view> </view> <style> .image-container { position: relative; } .watermark { position: absolute; right: 10px; bottom: 10px; opacity: 0.7; } </style> ``` > ⚠️ 注意:CSS 方案在图片保存时水印会丢失,仅适用于展示场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值