手机端移动端的前端原生js裁剪图片上传

手机端移动端的前端原生js裁剪图片上传,第1张

手机端移动端的html" class="superseo">前端原生js裁剪图片上传 选择头像时裁剪上传,确保图片是个正方形,不会出现压扁拉伸的现象

效果图

原理很简单,其实就是用canvas截图出来而已,只是要对比例做一下处理。


<input onchange="iconChange()" type="file" id="imageFile" accept="image/*" style="display:none">
<canvas id="captureCanvas" style="display: none;">canvas>
//定义几个会用到的变量
let captureImage,c,ctx,orginImgRate,x,y;
function iconChange(){
     let file =  document.getElementById("imageFile").files && document.getElementById("imageFile").files[0];
     handleImage(file,async (f)=>{
         choose(f)
     });
 }
//对文件处理,转成可预览的base64,顺便封装个formData
async function handleImage(file,fn){
	if(file.size>5*1024*1024){
	      layer.msg("图片大小不能超过5M!",{type:1});
	      return;
	}
	let orginFile = {};
	var filereader = new FileReader();
	var formData = new FormData();
	filereader.readAsDataURL(file);
	filereader.onload=function (e) {
		formData.append("file",file);
		orginFile = {base64:e.target.result,formData};
		fn(orginFile);
	}
}

//这里调用的layer的d出层,没有用layer的话也可以用别的代替
async function choose(data){
    let  content = `
            
                ${data.base64}"  />
                
                
            
        `
    const layerIndex = layer.open({
        skin:"center-open",
        area:'90%',
        offset:"50%",
        title:'确定使用这张图片作为你的头像吗?',
        content,
        btn: ['确定','取消'],
        //在d出成功之后运行success这个方法
        success(){
	          setTimeout(async ()=>{
	                 c=document.getElementById("captureCanvas");
	                 ctx=c.getContext("2d");
	                 captureImage = document.getElementById("captureImage");
	                 const capture = document.getElementById("capture");
	                 //如果是横着的图片,裁剪框默认撑满图片高度
	                 if(captureImage.width>captureImage.height){
	                     capture.style.height = captureImage.height+"px"
	                     capture.style.width = captureImage.height+"px"
	                 }else{
     	                 //如果是竖着的图片,裁剪框默认撑满图片宽度
	                     capture.style.width = captureImage.width+"px"
	                     capture.style.height = captureImage.width+"px"
	                 }
	                 const imgInfo = await loadImg(data.base64);
	                 //计算画布大小与图片分辨率之间的比例
	                 orginImgRate = imgInfo.h/captureImage.height
	                 c.width = capture.offsetWidth
	                 c.height = capture.offsetHeight
	                 //渲染画布
	                 drawCanvas(captureImage,
	                 ctx,
	                 capture.offsetLeft*orginImgRate,
	                 capture.offsetTop*orginImgRate,
	                 capture.offsetWidth*orginImgRate,
	                 capture.offsetWidth*orginImgRate,0,0,
	                 capture.offsetWidth,
	                 capture.offsetWidth)
	             })
        },
        //当点击确定时触发
        yes: async function(){
	        //将裁剪完的画布转成base64
			const src = c.toDataURL("image/png");
			const blob = base64ToBlob(src);
			const file = blobToFile(blob, data.origin.name);
			const tempFormData = new FormData()
			tempFormData.append("file",file)
			//拿到装好File的tempFormData,该干嘛干嘛
			//todo 上传文件 修改头像
        }
    });
}
//获取图片的宽和高
function loadImg(el){
	return new Promise((resolve)=>{
		var img =new Image();
		img.src = el;
		img.onload = function(){
			resolve({h:img.height,w:img.width});
		}
	})
}
//触屏结束触发,把body变为可滚动状态
function touchCaptureEnd(){
	body.style.overflow="scroll"
}
function drawCanvas(captureImage,ctx,left,top,width,height,tw,th,sw,sh){
	ctx.drawImage(captureImage,left,top,width,height,tw,th,sw,sh);
}
//当手指碰到屏幕那一刻,获取手指碰到的在选择框内的相对横坐标和纵坐标,用来移动裁剪框
function touchCapture(e){
	x = e.changedTouches[0].clientX-e.target.offsetLeft
	y = e.changedTouches[0].clientY-e.target.offsetTop
}
//在手指在屏幕上舞动时,把body变成hidden不给滚动
function touchCaptureMove(e){
	const target = e.changedTouches[0];
	if(!body.style.overflow || body.style.overflow=="scroll"){
		body.style.overflow="hidden"
	}
	//移动x方向和y方向
	e.target.style.left = target.clientX-x+"px";
	e.target.style.top = target.clientY-y+"px";
	if(target.clientX-x<=0){
		e.target.style.left = "0px"
		console.log("到最左边了")
	}else if(e.target.offsetLeft+e.target.offsetWidth>captureImage.width){
		console.log("到最右边边了")
		e.target.style.left = captureImage.width-e.target.offsetWidth+"px"
	}
	if(target.clientY-y<0){
		e.target.style.top = "0px"    
		console.log("到最上了")
	}else if(e.target.offsetTop+e.target.offsetHeight>captureImage.height){
		e.target.style.top = captureImage.height-e.target.offsetHeight+"px"
		console.log("到最下了了")
	}
	//实时更新canvas的图像
	drawCanvas(captureImage,ctx,e.target.offsetLeft*orginImgRate,
		e.target.offsetTop*orginImgRate,
		e.target.offsetWidth*orginImgRate,
		e.target.offsetWidth*orginImgRate,0,0,
		e.target.offsetWidth,
		e.target.offsetWidth
	)
	function drawCanvas(captureImage,ctx,left,top,width,height,tw,th,sw,sh){
		ctx.drawImage(captureImage,left,top,width,height,tw,th,sw,sh);
	}
}

// base64转blob
const base64ToBlob = function(base64Data) {
  let arr = base64Data.split(','),
      fileType = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]),
      l = bstr.length,
      u8Arr = new Uint8Array(l);
      
  while (l--) {
      u8Arr[l] = bstr.charCodeAt(l);
  }
  return new Blob([u8Arr], {
      type: fileType
  });
};
// blob转file
const blobToFile = function(newBlob, fileName) {
  newBlob.lastModifiedDate = new Date();
  newBlob.name = fileName;
  return newBlob;
};

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/925123.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-16
下一篇2022-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存