用JQuery仿造QQ头像裁剪功能

原文:用JQuery仿造QQ头像裁剪功能

最近工作真心忙碌,几乎没时间写博客。今天趁周末来仿一个QQ头像裁剪功能插件。效果如下:

所有文件都可在我的Github上下载,从头到尾从简到繁按步骤一共分了9个HTML文件,每个步骤文件里的注释都写的很清楚,故在本博客内不赘述。

原理:

主要是通过css的clip来裁剪图片可视区域,拖动剪裁窗口这里使用了JQ-UI的draggable插件(但是缩放没有,贪方便可以使用Resizable插件,但都用插件的话就没有研究的意义了)。

缩放功能原理其实很简单,不外乎获取剪裁框的offset()或position(),以及各容器宽高、鼠标位置,然后做个大杂侩计算。

只能说咱做前端的必须要认真耐心地去做计算,虽然过程颇为麻烦,但绝对不是“做不出来”。有的朋友在做某些功能前,可能会因为需要涉及较麻烦的计算就放弃,这是不靠谱的做法。

P.S.:像效果图中会存在图片被选中(变蓝色)的情况,是因为本章直接用的img,如果不喜欢这种图片被选中的情况,可以用一个div直接设置背景替换img即可(不过这里得使用background-size:100% 100%,如果不考虑IE8-的话,利用这种方法交互视觉上感觉会更好些)

贴一下最终版的代码,想要从头看起的朋友可以去我上方提供的连接查看。

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>裁剪头像</title>
    <script src="jq.js"></script>
    <script src="draggable.js"></script>
    <style type="text/css">
      body {background-color: #333;}
      .pic_wrap{ position:relative; float:left;margin:100px;  width:320px; height:320px; background:black; }
      .pic_wrap img{position:absolute;width:320px; height:320px;}
      .pic1{opacity:0.5;}
      .pic2{clip:rect(0 150px 150px 0);}
      .clip_box{position:absolute; margin-left:-1px; margin-top:-1px;width:150px; height:150px; border:solid 1px white; cursor:move;}
      .clip_box span{display:block; position:absolute; width:8px; height:9px; background:white; border-radius:4px;}
      #lt{left:-4px; top:-4px; cursor:nw-resize;}
      #rt{right:-4px; top:-4px; cursor:ne-resize}
      #lb{left:-4px; bottom:-4px; cursor:sw-resize}
      #rb{right:-4px; bottom:-4px; cursor:se-resize}
      .preview{ margin-top:100px; position:relative; float:left;width:100px; height:100px; overflow:hidden;}
      .pic3{ position:absolute;}
    </style>
    <script type="text/javascript">
    $(function(){
        var $picWrap = $("#pic_wrap");
        var $rawPic = $picWrap.find("img:eq(0)");
        var $clipPic = $picWrap.find("img:eq(1)");
        var $clipBox = $("#clip_box");
        var $prePic = $("#pic3");    //获取预览图
        var prebox_w = $("#preview").width();    //获取预览图容器宽度/高度
        var $lt = $("#lt");
        var $rt = $("#rt");
        var $lb = $("#lb");
        var $rb = $("#rb");
        var wrap_w = $picWrap.width();
        var isResize = !1;
        var flag = "";
        $lt.mousedown(function(e){
            e.stopPropagation();
            isResize=!0;
            flag = "leftTop";
        })
        $rt.mousedown(function(e){
            e.stopPropagation();
            isResize=!0;
            flag = "rightTop";
        })
        $lb.mousedown(function(e){
            e.stopPropagation();
            isResize=!0;
            flag = "leftDown";
        })
        $rb.mousedown(function(e){
            e.stopPropagation();
            isResize=!0;
            flag = "rightDown";
        })
        $(window).mouseup(function(){
            isResize=!1;
            flag = "";
        })
        $clipBox.find("span").mousemove(function(e){
            e.stopPropagation();
        })
        $clipBox.draggable({
             containment: "#pic_wrap",
             drag: function(){
                 setClip();
             },
             stop: function(){
                 var box_pl = $clipBox.position().left;
                 var box_pt = $clipBox.position().top;
                 var box_w = $clipBox.width();
                 if(box_pl+box_w>wrap_w){
                     var l = wrap_w - box_w;
                     $clipBox.css("left",l);
                 }
                 if(box_pt+box_w>wrap_w){
                     var t = wrap_w - box_w;
                     $clipBox.css("top",t);
                 }
                 setClip();
             }
        });
        $picWrap.mousemove(function(e){
            if(isResize){
                var x = e.pageX;
                var y = e.pageY;
                switch(flag){
                    case "leftTop":leftTop(x);console.log("aa");break;
                    case "rightTop":rightTop(y);break;
                    case "leftDown":leftDown(x);break;
                    case "rightDown":rightDown(y);break;
                    default: break;
                }
            }
        })
        function leftTop(x){
            var box_ol = $clipBox.offset().left;
            var box_pl = $clipBox.position().left;
            var box_pt = $clipBox.position().top;
            var box_w = $clipBox.width();
            var s = x - box_ol;
            var newLeft = box_pl + s;
            var newWidth = box_w - s;
            var newTop = box_pt + s;
            newLeft = newLeft<=0?0:newLeft;
            newTop = newTop<=0?0:newTop;
            if(newTop+newWidth>=wrap_w){
                newWidth = newWidth<8?8:newWidth;
                newLeft = newLeft+newWidth>wrap_w?newLeft-8:newLeft;
                newTop = wrap_w - newWidth;
            }
            if(newLeft+newWidth>=wrap_w-8){
                newWidth = newWidth<8?8:newWidth;
                newLeft = wrap_w - newWidth;
            }
            $clipBox.css({"left":newLeft,"width":newWidth,"height":newWidth,"top":newTop});

            setClip();
        }
        function rightTop(y){
            var box_ot = $clipBox.offset().top;
            var box_pt = $clipBox.position().top;
            var box_pl = $clipBox.position().left;
            var box_h = $clipBox.height();
            var s = y - box_ot;
            var newTop = box_pt + s;
            var newHeight = box_h - s;
            newTop = newTop<=0?0:newTop;
            if(newHeight+box_pl>=wrap_w){
                return false;
            }
            $clipBox.css({"top":newTop,"width":newHeight,"height":newHeight});
            setClip();
        }
        function leftDown(x){
            var box_ol = $clipBox.offset().left;
            var box_pl = $clipBox.position().left;
            var box_pt = $clipBox.position().top;
            var box_w = $clipBox.width();
            var s = x - box_ol;
            var newLeft = box_pl + s;
            var newWidth = box_w - s;
            newLeft = newLeft<=0?0:newLeft;
            if(newWidth+box_pt>=wrap_w){
                return false;
            }
            $clipBox.css({"left":newLeft,"width":newWidth,"height":newWidth});
            setClip();
        }
        function rightDown(y){
            var box_ot = $clipBox.offset().top;
            var box_pl = $clipBox.position().left;
            var newHeight = y - box_ot;
            if(newHeight+box_pl>=wrap_w){
                return false;
            }
            $clipBox.css({"width":newHeight,"height":newHeight});
            setClip();
        }
        function setClip(){
            var t = $clipBox.position().top;
            var r = $clipBox.position().left + $clipBox.width();
            var b = $clipBox.position().top + $clipBox.height();
            var l = $clipBox.position().left;
            var rect = "rect("+t+"px "+r+"px "+b+"px "+l+"px)";
            $clipPic.css("clip",rect);
            //预览图设置
            var w = $clipBox.width();
            var pre_w = prebox_w / w * wrap_w ; //存在比例 prebox_w / pre_w = w / wrap_w
            var pre_t = pre_w / wrap_w *t;  //存在比例 pre_t / t = pre_w / wrap_w
            var pre_r = pre_w / wrap_w *r;  //存在比例 pre_r / r = pre_w / wrap_w
            var pre_b = pre_w / wrap_w *b;  //存在比例 pre_b / b = pre_w / wrap_w
            var pre_l = pre_w / wrap_w *l;  //存在比例 pre_l / l = pre_w / wrap_w
            var prect = "rect("+pre_t+"px "+pre_r+"px "+pre_b+"px "+pre_l+"px)";
            $prePic.css({"width":pre_w,"height":pre_w,"clip":prect,"left":-pre_l,"top":-pre_t});
        }
        setClip();
    })
    </script>
  </head>
  <body>
        <div class="pic_wrap" id="pic_wrap">
            <img class="pic1" src="logo.jpg" />
            <img class="pic2" src="logo.jpg" />
            <div class="clip_box" id="clip_box">
                <span id="lt"></span>
                <span id="rt"></span>
                <span id="lb"></span>
                <span id="rb"></span>
            </div>
        </div>

        <div id="preview" class="preview">
            <img class="pic3" id="pic3" src="logo.jpg" />
        </div>
  </body>
</html>

共勉~

时间: 2024-12-11 02:27:02

用JQuery仿造QQ头像裁剪功能的相关文章

上传头像裁剪功能

我之前做项目的时候有需求是需要实现上传头像裁剪再上传到服务器,所以上网看了一下别人写的案例.方法.文章,浪费了1天的时间,最后才跌跌碰碰的终于写了出来. 现在给大家分享一下吧. 所用到的js文件 cropper.min.js, canvas-to-blob.js(这个是IE上需要用到的,不然会不支持转blob) jquery.min.js, bootstrap.min.js ajaxfileupload.js css文件 cropper.min.css,bootstrap.min.css htm

WPF 自定义控件 CropingImage 防QQ头像 编辑功能

1 <ControlTemplate x:Key="reSizeThumb" TargetType="{x:Type Thumb}"> 2 <Border Background="{DynamicResource BlueBrush}"> 3 </Border> 4 </ControlTemplate> 5 6 <ControlTemplate x:Key="moveThumb&qu

jQuery插件ImgAreaSelect 实例讲解一(头像上传预览和裁剪功能)

上一节随笔中,我们已经知道了关于jQuery插件ImgAreaSelect基本的知识:那么现在看一下实例: 首先,要知道我们应该实现什么功能? (1)图片能够实现上传预览功能 (2)拖拽裁剪图片,使其能够显示裁剪后的区域 (3)显示要裁剪区域的坐标 其次,该如何引用该插件呢? 那就具体看一下吧! 第一步:先将样式和文件包引入(根据你自己的位置引入) <!--引入imgareaselect的css样式--> <link rel="stylesheet" type=&qu

Android实现类似换QQ头像功能(图片裁剪)

现在几乎所有的App都有用户登录模块,需要设置用户头像,而关于用户头像部分无疑也是比较头疼的,目前大部分应用的头像部分会有两种方式:一种是利用系统的裁剪功能去获取用户头像,一种就是获取到图片或者照片的地址后自定义头像裁剪界面.而我这里提供了一种利用系统的裁剪功能来获取头像的写法,当然我写的这个只是实现一个简单地功能,比较简单.如果大家有比较好的写法可以和我交流下. 没图说个JB,先看看效果: 首先是打开系统相册,实现代码: Intent intent = new Intent(Intent.AC

写了个基于Jquery的头像裁剪插件

预览图: 说明: 此插件没有做兼容处理,做的过程中只是做思路逻辑分析,至于IE下,没有兼容开发,可在其他标准浏览器下运行,查看源代码 DOM: <head> <script src="jquery.js"></script> <script src="clip.js"></script> </head> <body> <div class="clip-wrapper&

Android裁剪固定大小头像的功能

转载自: http://www.eoeandroid.com/thread-497277-1-1.html 效果很好,特意转载过来记录一下,加深一下印象. 效果就是 :中间的方框不动,可以拖动图片,选择要裁剪的位置. 源码下载地址:http://download.csdn.net/detail/abc13939746593/7540163 Android裁剪固定大小头像的功能,布布扣,bubuko.com

android 设置头像以及裁剪功能

在android的开发过程中,经常遇到设置用户头像以及裁剪图像大小的功能.昨天我遇到了设置用户头像的功能,开始不知道怎么搞,在技术群里问也没人回 答,就研究了微信用户设置头像的功能,了解到用户设置图像的过程,就是两步点击设置头像,选择头像资源的来源,相册和相机两个来得到.      闲话说的有点多了,来说说技术点吧.其实也比较简单,就是通过Intent来启动相册或者相机就可以了. 看下效果图: 代码如下: package com.xzw.picture; import java.io.File;

Android高仿微信头像裁剪

最近公司的APP很多用户反应无法上传头像,于是打算修改原来头像裁剪的代码.参考微信.QQ.唱吧头像裁剪的操作,决定就仿微信头像裁剪来上传用户头像,在Android大神鸿洋的一篇高仿微信头像的博客(博客地址结尾会贴出来)的基础上加了一些代码,加的代码主要增加如下的功能: 1.增加对大图的处理,缩放到我们裁剪框的大小. 2.裁剪后的图片保存到临时文件里,把临时文件的路径返回到需要处理的界面,因为在三星S4传byte数组返回数据时会闪退,传路径则正常. 3.对有些系统返回旋转过的图片进行处理. 这个功

android之照相、相冊裁剪功能的实现过程

今天无聊做了一些照相.相冊裁剪功能,希望能够帮到大家! 不多说了,贴代码实际一点: 首先是XML: <ImageButton android:id="@+id/imageButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/xiaoma" /> <Butt