我写了一个基础的图片预览画笔涂改局部区域形成蒙版的组件,蒙版图片尺寸与原图一致,效果如下:


实现的uniapp组件代码如下:
点击查看代码
<template>
<view class="image-mask-editor">
<view v-if="!imagePath" class="upload-container">
<button @tap="chooseImage">上传图片</button>
</view>
<view v-else class="canvas-container"
style="position: fixed; top: 0;bottom: 0;left:0;right:0; width: 100%;z-index:3;background-color: black;">
<view style="position: relative;">
<!-- <canvas style="display: none;" canvas-id="myCanvas" :style="canvasStyleexport" ></canvas> -->
<image :src="imagePath" mode="widthFix" class="background-image" :style="imgStyle"></image>
<canvas canvas-id="maskCanvas" class="maskCanvas" :style="canvasStyle" @touchstart="touchstartmask"
@touchmove="touchmovemask" @touchend="touchendmask"></canvas>
<view class="controls">
<button @tap="clearMask">清除遮罩</button>
<button @tap="getMaskImage">预览遮罩图</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
ctx: null,
scaleratio: 0,
imgrealWidth: 0,
imgrealHeight: 0,
screenWidth: 0,
screenHeight: 0,
canvasStyle: '',
soureimgPath: "", //原图压缩后与蒙版图尺寸一致
imgStyle: '',
imagePath: '',
points: [], //路径点集合
isDrawing: false,
lastX: 0,
lastY: 0,
}
},
onReady() {
// 获取屏幕宽度
uni.getSystemInfo({
success: (res) => {
this.screenWidth = res.windowWidth
this.screenHeight = res.windowHeight
}
})
},
methods: {
chooseImage() {
uni.chooseImage({
count: 1,
success: (res) => {
this.soureimgPath = res.tempFilePaths[0]
this.imagePath = res.tempFilePaths[0]
this.$nextTick(() => {
this.initCanvas()
})
}
})
},
initCanvas() {
// 获取图片尺寸以设置画布大小
uni.getImageInfo({
src: this.imagePath,
success: (imageInfo) => {
// 设置 canvas 的实际尺寸为图片尺寸
this.imgrealWidth = imageInfo.width;
this.imgrealHeight = imageInfo.height;
//this.setCanvasStyle();
// 创建 canvas 上下文
this.ctx = uni.createCanvasContext('maskCanvas', this);
const scale = this.screenWidth / this.imgrealWidth;
this.scaleratio = scale;
// 根据原始宽高比计算正确的高度
const height = this.imgrealHeight * scale;
const top = (this.screenHeight / 2) - (height / 2);
this.imgStyle = `top:${top}px;`;
this.canvasStyle =
`width: ${this.screenWidth}px; height: ${height}px;top:${top}px; `
// this.canvasStyleexport =
// `width: ${this.imgrealWidth}px; height: ${this.imgrealHeight}px; `
// // 设置 canvas 的绘图尺寸
this.ctx.width = this.screenWidth;
this.ctx.height = height;
// 将图片绘制到画布上作为尺寸压缩后的原图
// this.ctx.drawImage(this.imagePath, 0, 0, this.screenWidth, height);
// this.ctx.draw();
// this.$nextTick(() => {
// uni.canvasToTempFilePath({
// canvasId: 'maskCanvas',
// success: (res) => {
// console.log('原图压缩后图片路径:', res.tempFilePath);
// this.soureimgPath = res.tempFilePath;
// this.clearMask();
// // uni.previewImage({
// // urls: [res.tempFilePath]
// // })
// // uni.saveFile({
// // tempFilePath: res.tempFilePath,
// // success: function(res) {
// // var savedFilePath = res.savedFilePath;
// // }
// //})
// // 这里可以进行后续操作,比如上传或显示遮罩图
// },
// fail: (err) => {
// console.error('获取遮罩图片失败:', err);
// }
// });
// })
},
});
},
setCanvasStyle() {
// 计算缩放比例
const scale = this.screenWidth / this.imgrealWidth;
this.scaleratio = scale;
// 根据原始宽高比计算正确的高度
const height = this.canvasHeight * scale;
this.canvasStyle =
`width: ${this.screenWidth}px; height: ${height}px; transform: scale(1); transform-origin: left top;`
},
touchstartmask(e) {
this.isDrawing = true;
this.lastX = e.changedTouches[0].x;
this.lastY = e.changedTouches[0].y;
this.drawCircle(this.lastX, this.lastY);
},
touchmovemask(e) {
if (!this.isDrawing) return;
const currentX = e.changedTouches[0].x;
const currentY = e.changedTouches[0].y;
this.drawCircle(currentX, currentY);
this.lastX = currentX;
this.lastY = currentY;
},
touchendmask() {
this.isDrawing = false;
},
drawCircle(x, y) {
const scaledX = x;
const scaledY = y;
const radius =30;
this.ctx.beginPath();
this.ctx.arc(scaledX, scaledY, radius, 0, Math.PI * 2);
this.ctx.fillStyle = 'rgba(255, 255,255, 1)';
this.ctx.fill();
this.ctx.draw(true);
},
clearMask() {
this.ctx.clearRect(0, 0, this.screenWidth, this.screenWidth * this.scaleratio);
this.ctx.draw();
},
getMaskImage() {
uni.canvasToTempFilePath({
canvasId: 'maskCanvas',
destWidth: this.imgrealWidth,
destHeight: this.imgrealHeight,
success: (res) => {
console.log('遮罩图片路径:', res.tempFilePath);
uni.previewImage({
urls: [res.tempFilePath]
})
// uni.saveFile({
// tempFilePath: res.tempFilePath,
// success: function(res) {
// var savedFilePath = res.savedFilePath;
// }
//})
// 这里可以进行后续操作,比如上传或显示遮罩图
},
fail: (err) => {
console.error('获取遮罩图片失败:', err);
}
});
}
}
}
</script>
<style>
.maskCanvas {
position: absolute;
opacity: 0.4;
z-index: 2;
left: 0;
top: 0;
}
.controls {
display: flex;
padding-top: 20px;
}
.background-image {
position: absolute;
left: 0;
z-index: 1;
width: 100%;
right: 0;
}
</style> 网友回复
如何让ai帮我自动在小红书或抖音上自动根据需求截流与潜在客户聊天拉客?
如果用go编写一个在virtualbox中启动的简单操作系统?
go如何搭建一个零信任网络?
如何用python实现一个公网代理访问软件?
如何用go实现一个公网代理访问软件?
如何用python实现一个内网穿透打洞程序,实现内网的80端口暴露到公网上可以访问?
如何用go实现一个内网穿透打洞程序,实现内网的80端口暴露到公网上可以访问?
何为Shadowsocks 代理?
python如何实现类似php的opendir目录相互隔离的fastcgi多租户虚拟空间?
nodejs如何实现类似php的opendir目录相互隔离的fastcgi多租户虚拟空间?


