vue项目中使用canvas,设置canvas背景图,叠加图片,实现鼠标拖动 , 截图保存等功能

因为这个是我的项目代码,所以代码复制过去也用不了,只是给各位做个参考。

canvas背景图,鼠标拖动图片,获取图片在canvas的位置,截图保存等功能

<template>
	<div>
		<div class="clearfix">
			<div class="leftdiv">
				<canvas id="mycanvas" width="600" height="820" @mousedown="touchmove" @mousemove="move" @mouseleave="leave" @mouseup="up" ref="canvas"></canvas>
				<img :src="bgimg" id="bgimg" ref="bgimg" />
				<img src="@/assets/images/zang.png" id="img" ref="img" />
				<div id="testdiv"></div>
			</div>
			<div class="rightdiv">
				<p style="color: #00BCD4;font-weight: 700;font-size: 20px;text-align: left;margin-bottom: 20px;">印章签署信息</p>
				<el-form :label-position="labelPosition" label-width="150px" :model="formLabelAlign" :rules="rules">
					<el-form-item label="类型" prop="type">
						<el-radio-group v-model="formLabelAlign.type">
							<el-radio :label="0" value="0">个人</el-radio>
							<el-radio :label="1" value="1">企业</el-radio>
						</el-radio-group>
					</el-form-item>
					<el-form-item label="企业印章ID">
						<el-select v-model="region" @change="changeSelect">
							<el-option v-for="(item,index) in seallist" :key="index" :label="item.name" :value="item.id"></el-option>
						</el-select>
					</el-form-item>
					<el-form-item label="页码信息">
						<el-select v-model="formLabelAlign.pos_page"  @change="changePage">
							<el-option v-for="(item,index) in pagelist" :key="index"  :label="item" :value="index+1"></el-option>
						</el-select>
					</el-form-item>
					<el-form-item label="X轴坐标">
						<el-input v-model="formLabelAlign.pos_x" onkeyup="this.value=this.value.replace(/[^\d.]/g,'');"></el-input>
						<p style="font-size: 12px;text-align: left;"><span style="color: #ccc;">印章宽度 :</span> {{sealwidth}}</p>
					</el-form-item>
					<el-form-item label="Y轴坐标">
						<el-input v-model="formLabelAlign.pos" onkeyup="this.value=this.value.replace(/[^\d.]/g,'');"></el-input>
						<p style="font-size: 12px;text-align: left;"><span style="color: #ccc;">印章高度 :</span> {{sealheight}}</p>
					</el-form-item>
					<el-form-item label="签署区顺序">
						<el-input v-model="formLabelAlign.signSort" onkeyup="this.value=this.value.replace(/[^\d.]/g,'');"></el-input>
					</el-form-item>
					<el-form-item label="是否添加签署时间戳">
						<el-select v-model="formLabelAlign.add_sign_time">
							<el-option label="是" value="0"></el-option>
							<el-option label="否" value="1"></el-option>
						</el-select>
					</el-form-item>
					<el-form-item label="第三方业务流水号">
						<el-input v-model="formLabelAlign.third_order_no" placeholder="请输入业务流水号"></el-input>
					</el-form-item>
				</el-form>
				<el-button type="primary" @click="onSubmit">编辑印章区域</el-button>
			</div>
		</div>
	</div>
</template>
<script>
	import http from "../../config/http";
	export default {
		data() {
			return {
				region:'',
				ismove: false,
				selectVal:'',
				seallist:[],
				bgimg:require('@/assets/images/1589190467(1).jpg'),
				labelPosition: 'right',
				formLabelAlign: {
					type: 0,
					reigon: '',
					pos_page: '1',
					pos_x: '',
					pos: '',
					signSort: '1',
					add_sign_time: '1',
					third_order_no: '',
					width: '',
					height: ''
				},
				rules: {
					type: [{
						required: true,
						message: '请选择类型',
						trigger: 'blur'
					}],
				},
				// 印章大小
				sealwidth: 120,  //选择印章的时候 获取大小
				sealheight: 120,
				// 印章位置
				OssUrl : JSON.parse(sessionStorage.getItem("state")).OssUrl,
				// 印章列表数据
				res_seal:{},
				//当前左侧canvas要显示的印章数据
				now_seal:{},
				//页码
				pagelist:[],
				//切换左侧背景图的资源
				imgData:[]
			};
		},
		components: {},

		computed: {},
		
		created() {
			http.post({
				url: 'contract_template/read',
				// data: {id:this.$route.query.id},
				data: {id:54},
			}).then(res => {
				console.log('IDres',res)
				let a = res.data[0].images.split(',');
				
				this.imgData = [];
				for(let i in a){
					this.pagelist.push( Number(i)+1)   //获取页码
					this.imgData.push( this.OssUrl + '/' + a[i])
				}
				
				this.bgimg = `${this.OssUrl}/${a[0]}`
				let img = new Image();
				img.src = this.bgimg;
				img.id = 'testimg';
				img.style.display = 'none';
				document.getElementById('testdiv').innerHTML = '';
				document.getElementById('testdiv').append(img);
				let that = this;
				setTimeout(function(){
					that.canvas()
				},300)
			})
			
			if(this.$route.query.template_id != undefined){
				//url上有模版ID ---- 编辑状态
				http.post({
					url: 'contract_template_sign_field/read',
					data: {template_id:this.$route.template_id,id:this.$route.query.id},
				}).then(res => {
					console.log("编辑RES",res)
					this.formLabelAlign = {
						type: 0, //缺少这条数据,峰哥说后台暂时不保存这条
						// reigon: res.data[0].seal_id,
						reigon: "05f96838-04e3-40a5-89b7-d68b178c2d68",
						pos_page: res.data[0].pos_page,
						pos_x:  res.data[0].pos_x,
						pos:  res.data[0].pos,
						signSort: res.data[0].order,
						add_sign_time: res.data[0].add_sign_time,
						third_order_no: res.data[0].third_order_no,
					}
				})
			}
				
			// 获取印章ID
			http.post({
				url: 'contract_seal/read',
				data:{}
			}).then(res2 => {
				console.log('印章',res2)
				this.res_seal = res2.data;
				for(let i in res2.data){
					this.seallist.push({name: res2.data[i].alias, id:res2.data[i].seal_id,width:res2.data[i].width,height:res2.data[i].height})
				}
				this.now_seal = '';
				for(let i in res2.data){
					if(this.formLabelAlign.reigon == res2.data[i].seal_id){
						this.selectVal = this.region = res2.data[i].seal_id
						this.formLabelAlign.width =  res2.data[i].width;
						this.formLabelAlign.height =  res2.data[i].height;
						
						this.now_seal = res2.data[i];
					}
				}
				var that = this;
				setTimeout(function(){
					if(that.$route.query.template_id){
						that.setImg(that.formLabelAlign.pos_x ,that.formLabelAlign.pos)
					}
				},2000)
			})
		},
		mounted() {
			
		},
		methods: {
			onSubmit() {
				this.formLabelAlign.reigon = this.region;
				console.log(this.formLabelAlign)
				
				http.post({
					url: 'contract_template_sign_field/save',
					data: this.formLabelAlign,
				}).then(res => {
					console.log("res",res)
				})
			},
			canvas() {
				//  获取canvas
				var canvas = this.$refs.canvas;
				if (!canvas) {
					return false;
				} else {
					// 设置canvas的背景图
					var context = canvas.getContext("2d");
					var width = canvas.width; //使图片大笑与画布大小一致
					var height = canvas.height; //使图片大笑与画布大小一致
					// var bgimg = this.$refs.bgimg;
					var bgimg = document.getElementById('testimg');
					bgimg.style.width = width;
					bgimg.style.height = height;
					var pattern =  context.createPattern(bgimg,"no-repeat");
					context.fillStyle= pattern;
					context.fillRect(0,0,width,height);
				}

			},
			//控制鼠标拖动,并确保不会出canvas范围
			touchmove(e) {
				this.ismove = true;
			},
			move(e) {
				var canvas = this.$refs.canvas;
				var context = canvas.getContext("2d");
				var width = canvas.width;
				var height = canvas.height;
				if (this.ismove === true && this.selectVal !== '' && e.layerX > this.sealwidth / 2 && e.layerY > this.sealheight / 2 && e.layerX < (width - this.sealwidth/2) && e.layerY < height - this.sealheight/2) {
					context.clearRect(0, 0, width, height);
					this.canvas(); //背景图
					let a = e.layerX - this.sealwidth / 2;
					let b = e.layerY - this.sealheight / 2;
					this.setImg(a,b); //印章
					
					//以印章左下角到整个canvas左下角的距离为标准
					this.formLabelAlign.pos_x = e.layerX ;
					this.formLabelAlign.pos = height - e.layerY;
				}
			},
			leave() {
				this.ismove = false
			},
			up() {
				this.ismove = false;
			},
			
			
			//截图功能
			// 现在我这里的图片是从oss服务器获取的 跨域截图是不被允许的 所以用不了(如果你不需要从oss服务器获取图片,那随便用)
			// 网上有一些解决跨域截图的方式,我就没尝试了,因为这个功能并不在需求里,只是之前做demo弄来玩的
			// getImg(){
			// 	var canvas = this.$refs.canvas;
			// 	var context = canvas.getContext("2d");
			// 	// 截图功能 把整个canvas截图
			// 	var image = new Image();
			// 	image.src = canvas.toDataURL("image/png");							
			// 	var test = document.getElementById("test");
			// 	test.appendChild(image)
			// 	console.log("image",image.src)
			// },
			changePage(val){
				console.log(val);
				let img = document.getElementById('testimg');
				let bgimg = this.imgData[Number(val)-1]
				img.src = bgimg;
				
				var that = this;
				setTimeout(function(){
					// console.log(that.formLabelAlign.pos_x,that.formLabelAlign.pos)
					
					if(that.$route.query.template_id || that.now_seal){
						that.setImg(that.formLabelAlign.pos_x ,that.formLabelAlign.pos)
					}
					that.canvas();
				},1000)
				
			},
			changeSelect(val){
				if(val){
					this.selectVal = val;  //当前选择的这个印章的id
					//选择时加载对应章 显示在canvas
					for(let i in this.res_seal){
						if(val == this.res_seal[i].seal_id){
							this.now_seal = this.res_seal[i]
							console.log('当前印章',this.res_seal[i])
							this.sealwidth = this.res_seal[i].width;
							this.sealheight = this.res_seal[i].height
							
							this.setImg(0,0);
						}
					}
					
				}
			},
			setImg(X,Y){
				var canvas = this.$refs.canvas;
				var context = canvas.getContext("2d");
				this.canvas(); 
				let a = this.sealwidth;
				let b = this.sealheight;
				//  加载图片
				var img = this.$refs.img;
				img.src = this.OssUrl + '/' + this.now_seal.url;
				img.onload = function() {
					// console.log(img)
					//  绘制图片
					context.drawImage(img, X, Y, a, b);
				};
				img.onload();
			}
		}
	};
</script>
<style lang='scss' scoped>
	.leftdiv {
		padding-top: 20px;
		float: left;
		width: 50%;
		height: 880px;
		box-sizing: border-box;
		background-color: #fff;
		/* border-right: 1px solid #ccc; */
	}

	.rightdiv {
		float: left;
		padding: 15px;
		height: 880px;
		width: 50%;
		box-sizing: border-box;
		background-color: #fff;
	}

	.el-select {
		float: left;
		width: 100%;
	}

	#mycanvas {
		border: 1px solid rgb(199, 198, 198);
	}

	#img,
	#bgimg {
		display: none;
	}
</style>

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现canvas图片拖动,可以通过以下步骤完成: 1. 在Vue3使用canvas元素,并在mounted钩子函数获取canvas上下文对象。 2. 加载图片,并在图片加载完成后绘制到canvas上。 3. 监听mousedown、mousemove和mouseup事件,并在事件回调函数实现图片拖动效果。 下面是详细的代码实现: ``` <template> <canvas ref="canvas"></canvas> </template> <script> export default { mounted() { this.canvas = this.$refs.canvas; this.ctx = this.canvas.getContext('2d'); this.img = new Image(); this.img.src = 'your_image_url'; this.img.onload = () => { this.canvas.width = this.img.width; this.canvas.height = this.img.height; this.ctx.drawImage(this.img, 0, 0); }; this.canvas.addEventListener('mousedown', this.onMouseDown); this.canvas.addEventListener('mousemove', this.onMouseMove); this.canvas.addEventListener('mouseup', this.onMouseUp); }, data() { return { isDragging: false, startX: 0, startY: 0, translateX: 0, translateY: 0 }; }, methods: { onMouseDown(event) { this.isDragging = true; this.startX = event.clientX - this.translateX; this.startY = event.clientY - this.translateY; }, onMouseMove(event) { if (this.isDragging) { this.translateX = event.clientX - this.startX; this.translateY = event.clientY - this.startY; this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.translate(this.translateX, this.translateY); this.ctx.drawImage(this.img, 0, 0); this.ctx.translate(-this.translateX, -this.translateY); } }, onMouseUp() { this.isDragging = false; } } } </script> ``` 在这个例子,我们使用canvas元素来显示一张图片,然后监听mousedown、mousemove和mouseup事件来实现图片拖动效果。具体来说,当用户按下鼠标左键时,我们设置isDragging为true,并记录下鼠标当前的位置,当用户移动鼠标时,我们计算出鼠标从按下开始到移动时的偏移量,并将画布的坐标系移动相应的距离,然后重新绘制图片。最后,当用户松开鼠标左键时,我们将isDragging设为false,停止拖动
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值