【Canvas】图片裁剪

上传时要注意的配置(运行环境:node服务器)

1.app.js中post请求模块的设置:

		app.use(bodyParser.urlencoded({limit:"50mb",extended: true}))   <!--为true是允许传任何数据类型-->

		app.use(bodyParser.json({limit:"50mb"}))  <!--limit:"50mb"设置post上传文件允许的大小-->


2.控制层文件中用到fs文件读写模块:
								npm i fs -D

效果

从服务器打开html,点击上传图片,在画布中显示,鼠标点击移动红框选择需要裁切的像素信息范围,点击保存

在这里插入图片描述

请求成功,将裁切后的图片保存到服务器

在这里插入图片描述

裁切后的图片信息(imgName,imgSrc)存入数据库

在这里插入图片描述

控制层文件

//文件读写操作的模块
const fs=require("fs")

const canvasController={

	upload(req,resp){
		let imgData=req.body.imgData;
		// console.log(imgData) 图片数据只是后面那串码,不需要这部分(data:image/png;base64,)
		let base64Data=imgData.replace("data:image/png;base64,","")

		//数据放Buffer缓冲区把文件读出来
		let dataBuffer=Buffer.from(base64Data,"base64")

		//文件名
		let fileName=new Date().getTime()+"_cutImg.png";

		//文件写入
		fs.writeFile("public/images/"+fileName,dataBuffer,function (err) {
			if(err){
				//如果写的过程出错
				resp.send(err)
			}else{
				resp.send("保存成功")
			}
		})

		//存入数据库
		canvasModel.uploadDao([null,fileName,"images/"+fileName])
			.then((data)=>{
				console.log(data); //writeFile也在向客户端响应,在同一接口下同时向客户端发送了两次信息,这里要嘛不写或者resp.end()
			})
	}


}

页面代码

<style>
		*{
			margin: 0;
			padding: 0;
		}
		canvas{
			border: 1px solid yellowgreen;
		}
		#cutBox{
			width: 270px;
			height: 270px;
			border: 2px solid red;
			position: absolute;
			top: 50px;
			left: 50px;
			z-index: 1;
			cursor: grab;
		}
		#imageBox,#imgShow{
			float: left;
		}
		.clear{
			clear: both;
		}
	</style>
</head>
<body>
	
	<div id="imageBox"><!--装所有内容-->
			<canvas id="myCanvas" width="500" height="500"></canvas><!--完整图片-->
			<div id="cutBox" class="regular"></div><!--裁剪框-->
	</div>

	<div id="imgShow"><!--装所有预览的内容:h1预览提示文字、一个小的画布canvas-->

	</div>
	<p class="clear"></p><!--此处存在的作用:清除浮动对后续元素的影响-->

	<p>
		<input type="file" id="uploadImag"><!--上传需要被裁剪的图片-->
		<button id="btnSave">保存图片</button>
	</p>


</body>
<script src="js/jquery.3.6.js"></script>
<script>
	let bigCanvas=document.getElementById("myCanvas").getContext("2d", { willReadFrequently: true });
	let newCanvas;


	//当(文件)输入框发生变化时绘制被选中的图片
	$("#uploadImag").change(function () {
		//重新选择后,先删除旧节点、清空旧画布、清空上次的预览框画布内容,不然会导致添加很多img节点、画布内容叠加显示、残留上次预览画面
		$("#myImg").remove()
		bigCanvas.clearRect(0,0,500,500)
		newCanvas.clearRect(0,0,270,270)

		// console.log($("#uploadImag")[0].value)  拿到绝对路径,浏览器为了安全不允许从本地上传文件

		console.log($("#uploadImag")[0].files)
		//拿到input选择的文件信息
		let imgFile=$("#uploadImag")[0].files[0];

		//FileReader可以直接从本地读取文件,把文件直接转成编码的形式
		let reader=new FileReader(); //创建文件读取对象
		reader.readAsDataURL(imgFile); //调用对象的读取方法,传入需要读取的文件,将图片文件解析成base64编码格式
		reader.onload=function () { //读取完毕后执行
			$("#imageBox").before("<img src='"+this.result+"' id='myImg'/>")

			//图片节点加载完后
			$("#myImg")[0].onload=function () {
				//画
				bigCanvas.drawImage($("#myImg")[0],0,0,500,500,0,0,500,500)
			}
			$("#myImg").css("display","none")
		}
	})


	//裁剪框
	$("#cutBox").on("mousedown",function (e) {
		let clickE=e;

		//鼠标在框中按下的时候,框移动到鼠标移动的位置(有图片的时候才可以移动)
		if($("#uploadImag")[0].files.length==0){
			alert("请选择图片!!!")
		}else{
			//已经选好了要裁剪的图片
			$(this).on("mousemove",function (e) {
				let currentE=e;
				//框跟着鼠标移动
				$(this).css({
					left:currentE.clientX-clickE.offsetX+"px", //clientX相对于屏幕左上角的位置
					top:currentE.clientY-clickE.offsetY+"px",
				})

				//超出边界(左边、上边:left<=0,右边、下边:left>=500-270-2)
				if(parseInt($(this).css("left"))<=0){
					$(this).css("left","0px")
				}
				if(parseInt($(this).css("left"))>=228){
					$(this).css("left","228px")
				}
				if(parseInt($(this).css("top"))<=0){
					$(this).css("top","0px")
				}
				if(parseInt($(this).css("top"))>=228){
					$(this).css("top","228px")
				}
			})
		}
	})


	//鼠标弹起:获取裁剪框内的内容,用小canvas画出
	$(document).on("mouseup",function () {
		$("#cutBox").off("mousemove"); // 解除mousemove的绑定

		//预览
		$("#imgShow").html($("<h1>预览</h1><canvas id='newCanvas' width='270' height='270'></canvas>"))
		newCanvas=$("#newCanvas")[0].getContext("2d")


		//画布提供了一个方法:getImageData(要获取的图片的起始x坐标,要获取的图片的起始y坐标,要获取的像素宽度,要获取的像素高度),可以获取指定区域所有的像素信息
		//获取裁剪框左上角的坐标点
		let cutBoxLeft=$("#cutBox").position().left; //jquery对象的position()相对于父元素,offset()相对于文档
		let cutBoxTop=$("#cutBox").position().top;

		let imgData=bigCanvas.getImageData(cutBoxLeft,cutBoxTop,270,270)
		// console.log(imgData)
		//将获取的信息放入小画布:putImageData(imgData,在此画布中放的x坐标,放的y坐标)
		newCanvas.putImageData(imgData,0,0)
	})



	//保存
	$("#btnSave").click(function () {
		//有图片时才能保存
		if($("#uploadImag")[0].files.length==0){
			alert("未上传图片!!!")

		}else{
			//将小canvas的内容传到服务器,canvas的内容服务器无法识别,需要转为base64编码格式
			let imgDataUrl=$("#newCanvas")[0].toDataURL(); //转成base64
			// console.log(imgDataUrl)

			$.ajax({
				type:"post",
				url:"upload.do",
				data:{
					imgData:imgDataUrl
				},
				success:function (data) {
					console.log(data)
				}
			})
		}
	})

</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值