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>