文章出處
文章列表
最近工作真心忙碌,幾乎沒時間寫博客。今天趁周末來仿一個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>
共勉~
文章列表
全站熱搜