手机图片上传+裁切

本文将详细介绍如何实现在手机端进行图片上传及后续的裁切操作,包括使用的技术栈、关键步骤和常见问题解决,帮助开发者打造更优质的移动端图片处理功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*自定义input file*/
.file {
    display: block;
	width: 47.6vw;
	height: 14.2vw;
	background: url('images/input_bg.png') no-repeat center top;
	background-size: 100% 100%;
	overflow: hidden;
	text-decoration: none;
	text-indent: 0;
	text-align: center;
	line-height: 14.2vw;
	font-size: 4.2vw;
	font-weight: 400;
	color: rgba(255,255,255,1);
	margin: 0 auto;
	position: relative;
}
.file input {
    width: 100%;
	height: 100%;
	position: absolute;
	right: 0;
	top: 0;
	left: 0;
	bottom: 0;
	opacity: 0;
}
/*预览*/
.preview-contain{
    display: none;
	position: absolute;
	background: black;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
}
.pic-border{
	position: absolute;
	/*top: 42vw;*/
	top: 40vw;             
	left: 50%; 
	transform: translateX(-50%);
	width: 85.3vw;
	height: 64vw;	   	
}
#pic-border-visible{
    border: 0.5vw solid lightskyblue;
    overflow: hidden;
}
.pic-wrap{
    width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left:0;
	right: 0;
	bottom: 0;
	background: black;
}
.pic{
    position: absolute;
	top: 50%;
	left: 50%;
}
.btn{
    width: 30.2vw;
    height: 13vw;
	background: url(images/btn_bg.png) no-repeat center top;
	background-size: 100% 100%;
	line-height: 13vw;
	text-align: center;
	font-size: 3.8vw;
	font-weight: bold;
	color: rgba(247,246,251,1);
	margin: 0 auto;
}
.btn_cancel{
	position: absolute;
	top: 130vw;
	left: 15.6vw;
}
.btn_confirm{
	position: absolute;
	top: 130vw;
	right: 15.6vw;
}
.preview-shade{
	position: absolute;
	top: 0;
	left:0;
	width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.8);
    /*pointer-events:none ;*/
}
<a href="javascript:;" class="file">图片上传
    <input type="file" id="upload" accept="image/*" onchange="changeImg(this)"/>
</a>

<div class="preview-contain">
    <!--底部图片-->
	<div id="pic-border-none" class="pic-border">
	    <div id ="pic-wrap-none" class="pic-wrap">
	        <img id="pic-down" class="pic"/>
	    </div>
	 </div>
	 <!--遮罩顶部图片-->
	 <div class="preview-shade">
	     <div id="pic-border-visible" class="pic-border">
	         <div id="pic-wrap" class="pic-wrap">
	             <img id="pic-up" class="pic"/>
	         </div>
         </div>
         <div class="btn btn_cancel" onclick="goBack()">取消</div>
         <div class="btn btn_confirm" onclick="upload()">确认</div>
    </div>
</div>
//图片上传
var Orientation = null;
function changeImg(file){
	$(".change-contain").hide()
	$(".preview-contain").show()
    var reader = new FileReader();
    reader.readAsDataURL(file.files[0]);
	var fileObj = file.files[0];  
	EXIF.getData(fileObj, function() {  
        Orientation = EXIF.getTag(this, 'Orientation');
			console.log("Orientation===>",Orientation)
        });
    reader.onload = function(e) {
        compress(e.target.result);
    };
    $(".pic").css("transform","translate3d(0px, 0px, 0px) scale3d(1, 1, 1) rotate3d(0, 0,                                     1, 0deg)")
}
//预览
function compress(res){
	$(".preview-contain").show();
	var img = new Image();
    img.src = res;
    img.onload=function(){
        var imgWidth = this.width,
        imgHeight = this.height,
        canvas = document.createElement("canvas"),
        ctx = canvas.getContext('2d');
        canvas.width = imgWidth;
        canvas.height = imgHeight;
        if(Orientation && Orientation != 1){//input file ios会旋转
            switch(Orientation){   
                case 6:     // 旋转90度
                    canvas.width = imgHeight;    
                    canvas.height = imgWidth;    
                    ctx.rotate(Math.PI / 2);
                    // (0,-imgHeight) 从旋转原理图那里获得的起始点
                    ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight);
                    break;
               case 3:     // 旋转180度
                   ctx.rotate(Math.PI);    
                   ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight);
                   break;
                case 8:     // 旋转-90度
                   canvas.width = imgHeight;    
                   canvas.height = imgWidth;    
                   ctx.rotate(3 * Math.PI / 2);    
                   ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight);
                   break;
          }
      }else{
          ctx.drawImage(this, 0, 0, imgWidth, imgHeight);
      }
      imgSrc = canvas.toDataURL("image/jpeg", 1.0);

      if(img.width/img.height>$("#pic-wrap-none")[0].offsetWidth/$("#pic-wrap-none")[0].offsetHeight){
        
          $(".pic").css({"width":img.width/img.height*$("#pic-wrap-none")[0].offsetHeight+"px","height":"100%","marginTop":$("#pic-wrap-none")[0].offsetHeight/-2+"px","marginLeft":img.width/img.height*$("#pic-wrap-none")[0].offsetHeight/-2+"px"})
     }else if(img.width/img.height<$("#pic-wrap-none")[0].offsetWidth/$("#pic-wrap-none")[0].offsetHeight){
         $(".pic").css({"width":"100%","height":img.height/img.width*$("#pic-wrap-none")[0].offsetWidth+"px","marginTop":img.height/img.width*$("#pic-wrap-none")[0].offsetWidth/-2+"px","marginLeft":$("#pic-wrap-none")[0].offsetWidth/-2+"px"})
     }else{
         $(".pic").css({"width":"auto","height":"auto","max-width":"100%","max-height":(img.height/$("#pic-wrap-none")[0].offsetHeight)*100+"%","marginTop":$("#pic-wrap-none")[0].offsetHeight/-2+"px","marginLeft":img.width/img.height*$("#pic-wrap-none")[0].offsetHeight/-2+"px"})
     }
     $(".pic").attr("src",imgSrc)
    }
}
                
//上传
function upload(){
    var targetDom = $("#pic-wrap");  
    var copyDom = targetDom.clone();  
	copyDom.width(targetDom.width() + "px");  
	copyDom.height(targetDom.height() + "px");   
	$('body').append(copyDom);  
	    html2canvas(copyDom, {  
	        allowTaint: false,  
	        taintTest: false,  
	        useCORS: true,
        	logging: false,
        	letterRendering: true,
			height: targetDom.scrollHeight,
    		width: targetDom.scrollWidth,
	        onrendered : function(canvas) {
	            let imgData = canvas.toDataURL('image/png',1.0);
	            copyDom.hide()
    			$(".preview-contain").hide();
				$(".label-contain").show();
				uploadFun(imgData) //upyun
				getTags()
	         }  
    })
}


//操作事件
function move(pic){
    var pic=document.getElementById(pic);
	var mc=new Hammer.Manager(pic);  
	var pinch=new Hammer.Pinch();
	var rotate=new Hammer.Rotate();  
	var pan=new Hammer.Pan();
	pinch.recognizeWith(rotate);
	mc.add([pinch,rotate,pan]);
	var pan_ex=pan_ey=rota_ex=pex3=pey3=0,pin_sl=1;
    mc.on("panmove", function(ev) {
	    var pan_mx=ev.deltaX+pan_ex,  
	    pan_my=ev.deltaY+pan_ey;
	    //设置元素变形值
	    pic.style.webkitTransform="translate3d("+pan_mx+"px,"+pan_my+"px,0) scale3d("+pin_sl+","+pin_sl+",1) rotate3d(0,0,1,"+rota_ex+"deg)";  
	    document.getElementById("pic-down").style.webkitTransform="translate3d("+pan_mx+"px,"+pan_my+"px,0) scale3d("+pin_sl+","+pin_sl+",1) rotate3d(0,0,1,"+rota_ex+"deg)";
	    mc.on("panend", function(ev) {
	        pan_ex=pan_mx;
	        pan_ey=pan_my;
	    });  
	    ev.preventDefault();
	}); 
	//双指拉伸旋转 
	mc.on("pinchstart rotatestart", function(ev) {
	    var pinch_sa=ev.scale;
	    var rota_sx=ev.rotation;
	    mc.on("pinchmove rotatemove", function(ev) {
	        pin_ml=ev.scale-pinch_sa+pin_sl;  
	        rota_mx=ev.rotation-rota_sx+rota_ex;
	        if(pin_ml<0.5){
	            pin_ml=0.5;
	        }
	    pic.style.webkitTransform="translate3d("+pan_ex+"px,"+pan_ey+"px,0) scale3d("+pin_ml+","+pin_ml+",1) rotate3d(0,0,1,"+rota_mx+"deg)";
	    document.getElementById("pic-down").style.webkitTransform="translate3d("+pan_ex+"px,"+pan_ey+"px,0) scale3d("+pin_ml+","+pin_ml+",1) rotate3d(0,0,1,"+rota_mx+"deg)";
	     mc.on("pinchend rotateend", function(ev) {
	         pin_sl=pin_ml;  
	         rota_ex=rota_mx;  
	         //计算拉伸之后的区间值  
	         if(ev.type=="rotateend"){
	             pex3=pin_ml*pic.offsetWidth-(pic.offsetWidth);  
	             pey3=pin_ml*pic.offsetHeight-(pic.offsetHeight);   
	         }    
	     });  
	     ev.preventDefault();
    });  
	ev.preventDefault();  
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值