Jquery+ASP.NET 实现开心网上传头像剪裁功能

记录一下一个好用的剪裁图像功能。

转载:http://www.cnblogs.com/xuanye/archive/2008/09/25/1299091.html

前几天博客园cnblogs里有个朋友发了一个类似的帖子(你可以点这里查看),刚刚也要做这个功能,但是原来程序稍微有点问题,特别在前台上有几处不合理的地方,所以就着开心网的代码重写一下,效果如下

Step 1 选择上传照片

image 

Step2 ,点击上传一张图片,默认缩放到刚好填充画布,如果图片小于画布就不缩放了,并且将图片集中

image

缩放图片是,以画布中的选取框为中,向四周扩散,缩小

image

点击保存按钮 保存截取后的图片

image 

来看下代码吧

前台:需要引用Jquery的类库和两个Ui的Js

<script type="text/javascript" src="js/jquery1.2.6.pack.js"></script> 
  <script  type="text/javascript" src="js/ui.core.packed.js" ></script> 
  <script type="text/javascript" src="js/ui.draggable.packed.js" ></script>

html太长就不全贴出来了,挑几个重点来说把:

1:这个我们的html片段

image

2:这个是开心网中的html片段

image

开心网中用一个table作为画布的架子,中间的一个td设置样式为选取框,把img移到table下面,就可以看到上图的效果了,但是在设置drap的时候handler设置为table(id=crop),来看下下面开心网的代码就知道了。

image

因为我们点击的时候,因为table在img之上,所以点击只能点到table。但是Jquery的drap handle不能设置源以外的元素,所以上面的方法就行不通了,参考了原文中的做法,用两个图片代替,一个做成蒙层的效果(ImageDragContainer),一个缩小放到中间的位置,变成剪切窗口(IconContainer),只要控制好两个图片的left,top,width,height,那么可以做到看上去像一个图片那样。如前面的效果所示。

其他html就是一些布局,上传控件和几个用于存放值的textbox了,就不介绍了,来看下js把,关键的,都加上注释了。有问题可以留言交流

/// <reference path="JSintellisense/jquery-1.2.6-intellisense.js" /> 

//全局变量定义 
var CANVAS_WIDTH = 284;  //画布的宽 
var CANVAS_HEIGHT = 266;  //画布的高 
var ICON_SIZE = 120;   //截取框的大小,正方形 
var LEFT_EDGE = (CANVAS_WIDTH - ICON_SIZE) / 2;  //82 
var TOP_EDGE = (CANVAS_HEIGHT - ICON_SIZE) / 2;  //73 
var CANVAS_LEFT_MARGIN = 4; 


//用document. ready事件中在上传后第一次转向时无法获取到图片的实际宽度和高度,应该是没有被下载来的缘故 
$(window).load( function() { 
     var $iconElement = $( "#ImageIcon"); 
     var $imagedrag = $( "#ImageDrag"); 

     //获取上传图片的实际高度,宽度 
     var image =  new Image(); 
    image.src = $iconElement.attr( "src"); 
     var realWidth = image.width; 
     var realHeight = image.height;   
    image =  null;        
    
     //计算缩放比例开始 
     var minFactor = ICON_SIZE /  Math.max(realWidth, realHeight); 
     if (ICON_SIZE > realWidth && ICON_SIZE > realHeight) { 
        minFactor = 1; 
    } 
     var factor = minFactor > 0.25 ? 8.0 : 4.0 /  Math.sqrt(minFactor); 

     //图片缩放比例  
     var scaleFactor = 1; 
     if (realWidth > CANVAS_WIDTH && realHeight > CANVAS_HEIGHT) { 
         if (realWidth / CANVAS_WIDTH > realHeight / CANVAS_HEIGHT) { 
            scaleFactor = CANVAS_HEIGHT / realHeight; 
        } 
         else { 
            scaleFactor = CANVAS_WIDTH / realWidth; 
        } 
    } 
     //计算缩放比例结束 

     //设置滑动条的位置,设置滑动条的值的变化来改变缩放率是一个非线性的变化,而是幂函数类型 即类似y=factor(X)--此处x为幂指数 
     //此处100 * (Math.log(scaleFactor * factor) / Math.log(factor)) 为知道y 求解x,scaleFactor 即为y  此处的100为 中间值,滑动条长度为200 
    $( ".child").css( "left", 100 * ( Math.log(scaleFactor * factor) /  Math.log(factor)) +  "px"); 

     //图片实际尺寸,并近似到整数 
     var currentWidth =  Math.round(scaleFactor * realWidth); 
     var currentHeight =  Math.round(scaleFactor * realHeight); 


     //图片相对CANVAS的初始位置,图片相对画布居中 
     var originLeft =  Math.round((CANVAS_WIDTH - currentWidth) / 2) ; 
     var originTop =  Math.round((CANVAS_HEIGHT - currentHeight) / 2); 
     //计算截取框中的图片的位置 
     var dragleft = originLeft - LEFT_EDGE; 
     var dragtop = originTop - TOP_EDGE; 


     //设置图片当前尺寸和位置 
    $iconElement.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: originLeft +  "px", top: originTop +  "px" }); 
    $imagedrag.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: dragleft +  "px", top: dragtop +  "px" }); 

     //初始化默认值 
    $( "#txt_width").val(currentWidth); 
    $( "#txt_height").val(currentHeight); 
    $( "#txt_top").val(0-dragtop); 
    $( "#txt_left").val(0-dragleft); 
    $( "#txt_Zoom").val(scaleFactor); 

     var oldWidth = currentWidth; 
     var oldHeight = currentHeight; 

     //设置图片可拖拽,并且拖拽一张图片时,同时移动另外一张图片 
    $imagedrag.draggable( 
    { 
        cursor:  'move'
        drag:  function(e, ui) { 
             var self = $( this).data( "draggable"); 
             var drop_img = $( "#ImageIcon"); 
             var top = drop_img.css( "top").replace(/px/,  "");  //取出截取框到顶部的距离 
             var left = drop_img.css( "left").replace(/px/,  "");  //取出截取框到左边的距离 
            drop_img.css({ left: (parseInt(self.position.left) + LEFT_EDGE) +  "px", top: (parseInt(self.position.top) + TOP_EDGE) + "px" });  //同时移动内部的图片 
            $( "#txt_left").val(0 - parseInt(self.position.left)); 
            $( "#txt_top").val(0 - parseInt(self.position.top)); 
        } 
    } 
    ); 
     //设置图片可拖拽,并且拖拽一张图片时,同时移动另外一张图片 
    $iconElement.draggable( 
    { 
        cursor:  'move'
        drag:  function(e, ui) { 
             var self = $( this).data( "draggable"); 
             var drop_img = $( "#ImageDrag"); 
             var top = drop_img.css( "top").replace(/px/,  "");  //取出截取框到顶部的距离 
             var left = drop_img.css( "left").replace(/px/,  "");  //取出截取框到左边的距离 
            drop_img.css({ left: (parseInt(self.position.left) - LEFT_EDGE) +  "px", top: (parseInt(self.position.top) - TOP_EDGE) + "px" });  //同时移动内部的图片 
            $( "#txt_left").val(0 - (parseInt(self.position.left) - LEFT_EDGE)); 
            $( "#txt_top").val(0 - (parseInt(self.position.top) - TOP_EDGE)); 
        } 

    } 
    ); 

     //缩放的代码,要缩放以截取框为中心,所以要重新计算图片的left和top 
    $( ".child").draggable( 
  { 
      cursor:  "move", containment: $( "#bar"), 
      drag:  function(e, ui) { 
       var left = parseInt($( this).css( "left")); 
           //前面讲过了y=factor(x),此处是知道x求y的值,即知道滑动条的位置,获取缩放率 
          scaleFactor =  Math.pow(factor, (left / 100 - 1)); 
           if (scaleFactor < minFactor) { 
              scaleFactor = minFactor; 
          } 
           if (scaleFactor > factor) { 
              scaleFactor = factor; 
          } 
           //以下代码同初始化过程,因为用到局部变量所以没有 
           var iconElement = $( "#ImageIcon"); 
           var imagedrag = $( "#ImageDrag"); 

           var image =  new Image(); 
          image.src = iconElement.attr( "src"); 
           var realWidth = image.width; 
           var realHeight = image.height; 
          image =  null

           //图片实际尺寸 
           var currentWidth =  Math.round(scaleFactor * realWidth); 
           var currentHeight =  Math.round(scaleFactor * realHeight); 

           //图片相对CANVAS的初始位置 
           var originLeft = parseInt(iconElement.css( "left")); 
           var originTop = parseInt(iconElement.css( "top")); 

          originLeft -=  Math.round((currentWidth - oldWidth) / 2); 
          originTop -=  Math.round((currentHeight - oldHeight) / 2); 
          dragleft = originLeft - LEFT_EDGE; 
          dragtop = originTop - TOP_EDGE; 

           //图片当前尺寸和位置 
          iconElement.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: originLeft +  "px", top: originTop +  "px"}); 
          imagedrag.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: dragleft +  "px", top: dragtop +  "px" }); 

          $( "#txt_Zoom").val(scaleFactor); 
          $( "#txt_left").val(0 - dragleft); 
          $( "#txt_top").val(0 - dragtop); 
          $( "#txt_width").val(currentWidth); 
          $( "#txt_height").val(currentHeight); 
          oldWidth = currentWidth; 
          oldHeight = currentHeight; 

      } 
  }); 
     var SilderSetValue =  function(i) { 
         var left = parseInt($( ".child").css( "left")); 
        left += i; 

         if (left < 0) { 
            left = 0; 
        } 
         if (left > 200) { 
            left = 200; 
        } 

        scaleFactor =  Math.pow(factor, (left / 100 - 1));  
         if (scaleFactor < minFactor) { 
            scaleFactor = minFactor; 
        } 
         if (scaleFactor > factor) { 
            scaleFactor = factor; 
        } 
         var iconElement = $( "#ImageIcon"); 
         var imagedrag = $( "#ImageDrag"); 

         var image =  new Image(); 
        image.src = iconElement.attr( "src"); 
         var realWidth = image.width; 
         var realHeight = image.height; 
        image =  null

         //图片实际尺寸 
         var currentWidth =  Math.round(scaleFactor * realWidth); 
         var currentHeight =  Math.round(scaleFactor * realHeight); 

         //图片相对CANVAS的初始位置 
         var originLeft = parseInt(iconElement.css( "left")); 
         var originTop = parseInt(iconElement.css( "top")); 

        originLeft -=  Math.round((currentWidth - oldWidth) / 2); 
        originTop -=  Math.round((currentHeight - oldHeight) / 2); 
        dragleft = originLeft - LEFT_EDGE; 
        dragtop = originTop - TOP_EDGE; 

         //图片当前尺寸和位置 
        $( ".child").css( "left", left +  "px"); 
        iconElement.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: originLeft +  "px", top: originTop +  "px" });
        imagedrag.css({ width: currentWidth +  "px", height: currentHeight +  "px", left: dragleft +  "px", top: dragtop +  "px" }); 

        $( "#txt_Zoom").val(scaleFactor); 
        $( "#txt_left").val(0 - dragleft); 
        $( "#txt_top").val(0 - dragtop); 
        $( "#txt_width").val(currentWidth); 
        $( "#txt_height").val(currentHeight); 

        oldWidth = currentWidth; 
        oldHeight = currentHeight; 
    } 
     //点击加减号的事件 ,滑动条一共200px,点击一下+-20px 
    $( "#moresmall").click( function() { 
        SilderSetValue(-20); 
    }); 
    $( "#morebig").click( function() { 
        SilderSetValue(20); 
    }); 

});

 

后台的代码相对简单,上传保存,通过textbox中的参数进行图片切割,也比较简单,来看下分为两个,一个是缩放裁剪,一个原图裁剪,代码参考原文。

  public  static  string SaveCutPic( string pPath,  string pSavedPath,  int pPartStartPointX,  int pPartStartPointY,  int pPartWidth,  intpPartHeight,  int pOrigStartPointX,  int pOrigStartPointY,  int imageWidth,  int imageHeight) 
        { 
              using (Image originalImg = Image.FromFile(pPath)) 
             { 
                  if (originalImg.Width == imageWidth && originalImg.Height == imageHeight) 
                 { 
                      return SaveCutPic(pPath, pSavedPath, pPartStartPointX, pPartStartPointY, pPartWidth, pPartHeight, 
                             pOrigStartPointX, pOrigStartPointY); 
                       
                 } 
                  string filename =  DateTime.Now.ToString( "yyyyMMddHHmmss") +  ".jpg"
                  string filePath = pSavedPath +  "\\" + filename; 

                 Bitmap thumimg =MakeThumbnail(originalImg, imageWidth, imageHeight); 
                
                 Bitmap partImg =  new Bitmap(pPartWidth, pPartHeight); 

                 Graphics graphics = Graphics.FromImage(partImg); 
                 Rectangle destRect =  new Rectangle( new Point(pPartStartPointX, pPartStartPointY),  new Size(pPartWidth, pPartHeight)); //目标位置 
                 Rectangle origRect =  new Rectangle( new Point(pOrigStartPointX, pOrigStartPointY),  new Size(pPartWidth, pPartHeight)); //原图位置(默认从原图中截取的图片大小等于目标图片的大小) 

                  ///文字水印   
                 Graphics G = Graphics.FromImage(partImg); 
                  //Font f = new Font("Lucida Grande", 6); 
                  //Brush b = new SolidBrush(Color.Gray); 
                 G.Clear(Color.White); 
                  // 指定高质量的双三次插值法。执行预筛选以确保高质量的收缩。此模式可产生质量最高的转换图像。  
                 G.InterpolationMode = InterpolationMode.HighQualityBicubic;  
                 // 指定高质量、低速度呈现。  
                 G.SmoothingMode = SmoothingMode.HighQuality; 

                 graphics.DrawImage(thumimg, destRect, origRect, GraphicsUnit.Pixel); 
                  //G.DrawString("Xuanye", f, b, 0, 0); 
                 G.Dispose(); 

                 originalImg.Dispose(); 
                  if (File.Exists(filePath)) 
                 { 
                     File.SetAttributes(filePath, FileAttributes.Normal); 
                     File.Delete(filePath); 
                 } 
                 partImg.Save(filePath, ImageFormat.Jpeg); 

                 partImg.Dispose(); 
                 thumimg.Dispose(); 
                  return filename; 
             } 
        } 

         public  static Bitmap MakeThumbnail(Image fromImg,  int width,  int height) 
        { 
            Bitmap bmp =  new Bitmap(width, height); 
             int ow = fromImg.Width; 
             int oh = fromImg.Height;  

             //新建一个画板 
            Graphics g = Graphics.FromImage(bmp); 
          
             //设置高质量插值法 
            g.InterpolationMode = InterpolationMode.High; 
             //设置高质量,低速度呈现平滑程度 
            g.SmoothingMode =SmoothingMode.HighQuality; 
             //清空画布并以透明背景色填充 
            g.Clear(Color.Transparent); 

            g.DrawImage(fromImg,  new Rectangle(0, 0, width, height), 
                 new Rectangle(0, 0, ow, oh), 
                GraphicsUnit.Pixel); 

             return bmp; 

       } 

         public  static  string SaveCutPic( string pPath,  string pSavedPath,  int pPartStartPointX,  int pPartStartPointY,  int pPartWidth, int pPartHeight,  int pOrigStartPointX,  int pOrigStartPointY) 
        { 
            string filename =  DateTime.Now.ToString( "yyyyMMddHHmmss") +  ".jpg"
            string filePath = pSavedPath +  "\\" + filename; 

             using (Image originalImg = Image.FromFile(pPath)) 
            { 
                Bitmap partImg =  new Bitmap(pPartWidth, pPartHeight); 
                Graphics graphics = Graphics.FromImage(partImg); 
                Rectangle destRect =  new Rectangle( new Point(pPartStartPointX, pPartStartPointY),  new Size(pPartWidth, pPartHeight)); //目标位置 
                Rectangle origRect =  new Rectangle( new Point(pOrigStartPointX, pOrigStartPointY),  new Size(pPartWidth, pPartHeight)); //原图位置(默认从原图中截取的图片大小等于目标图片的大小) 
                 
                 ///注释 文字水印   
                Graphics G = Graphics.FromImage(partImg); 
                 //Font f = new Font("Lucida Grande", 6); 
                 //Brush b = new SolidBrush(Color.Gray); 
                G.Clear(Color.White); 
                 // 指定高质量的双三次插值法。执行预筛选以确保高质量的收缩。此模式可产生质量最高的转换图像。  
                G.InterpolationMode = InterpolationMode.HighQualityBicubic; 
                 // 指定高质量、低速度呈现。  
                G.SmoothingMode = SmoothingMode.HighQuality;  

                graphics.DrawImage(originalImg, destRect, origRect, GraphicsUnit.Pixel); 
                 //G.DrawString("Xuanye", f, b, 0, 0); 
                G.Dispose(); 

                originalImg.Dispose(); 
                 if (File.Exists(filePath)) 
                { 
                    File.SetAttributes(filePath, FileAttributes.Normal); 
                    File.Delete(filePath); 
                } 
                partImg.Save(filePath, ImageFormat.Jpeg); 
                partImg.Dispose(); 
            } 
             return filename; 
        } 
        
    }


如果还需要不是正方形的,需要如下修改:

改几个地方
1:第一是样式, #ImageDragContainer 的width 和 height 改成你实际的

left 设置成 (CANVAS_WIDTH - ICON_WIDTH) / 2 
top 设置成 (CANVAS_HEIGHT - ICON_HEIGHT) / 2;
其中 :var CANVAS_WIDTH = 284; //画布的宽
var CANVAS_HEIGHT = 266; //画布的高
自己算下 就知道了,默认是 
left = (284-120)/2 =82
top = (266-120)/2 = 73
#ImageDragContainer 
{
border: 1px solid #ccc;
width: 120px;
height: 120px;
cursor: pointer;
position: relative;
top: 73px; 
left: 82px ;
overflow: hidden;
z-index:1;


#IconContainer 的top改成你#ImageDragContainer 的-height 
#IconContainer
{
position:relative; 
left:0px;
top:-120px; 



2:脚本修改 
ICON_SIZE 不能用了 ,变成如下 ,那么所有用到它的都要变成两个 
var ICON_WIDTH = 140;
var ICON_HEIGHT = 100;
var LEFT_EDGE = (CANVAS_WIDTH - ICON_WIDTH) / 2; 
var TOP_EDGE = (CANVAS_HEIGHT - ICON_HEIGHT) / 2; 

接着计算最新缩放比例的地方 
var minFactor =Math.max(CON_WIDTH / realWidth, ICON_HEIGHT/realHeight)
if (ICON_WIDTH > realWidth && ICON_HEIGHT > realHeight) {
minFactor = 1;

}
3:TextBox 写死了截图框的宽度和高度,你需要改一下 
截取框的宽: <asp:TextBox ID="txt_DropWidth" runat="server" Text="140"></asp:TextBox><br />
截取框的高: <asp:TextBox ID="txt_DropHeight" runat="server" Text="100"></asp:TextBox><br />


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值