JavaScript 圖片切割效果

作者: cloudgamer  來源: 博客園  發布時間: 2009-06-18 11:24  閱讀: 2681 次  推薦: 0   原文鏈接   [收藏]  

序一

  很久之前就在一個網站的截取相片的功能中看到這個效果,也叫圖片裁剪、圖片剪切(設置一下也可以做出放大鏡等類似的效果)。
  當時覺得很神奇,礙于水平有限,沒做出來。
  前些日子突然想做一個透鏡效果,就突然想到了這個效果,于是找出當年“珍藏”的代碼決定一嘗所愿。

序二

  自上一個版本的圖片切割效果出來后,雖然也經常看到“框架開發這個如何如何容易”之類的評論,但也受到很多人的肯定,小弟在此感謝大家的支持。
  上一個版本由于是初次接觸這類效果,而且是三個大功能一起開發,能力所限,所以僅僅是實現了效果就完成了。
  后來我知道這個效果叫ImageCropper,找了些這類效果參考,完善了切割的部分。
  近來我把其中的拖放效果縮放效果單獨出來研究,經過整理和完善,再套進切割效果,個人感覺效果已經不錯了。
  要說明的是這個只是一個效果,并不是真正的切割圖片,要獲取真正的切割圖片請參考圖片切割系統

  瀏覽效果請參考:http://www.cnblogs.com/cloudgamer/archive/2008/07/21/ImgCropper.html

  (瀏覽完效果,你一定想知道其中的奧秘吧,那就聽我細細道來吧~)


程序說明

  這個效果主要分三個部分:層的拖放、層的縮放、圖片切割(包括預覽)。
  其中層的拖放層的縮放我已經在其他兩篇文章中有詳細說明,這里就說說圖片切割這部分吧。

【圖片切割】

  關于圖片切割的設計,有三個方法:
  1.定位四個半透明層,遮住要蓋住的部分,沒試過,感覺比較麻煩;
  2.把圖片設為背景圖,通過設置背景圖的位置來實現,但這樣的缺點是只能按圖片的正常比例實現,不夠靈活;
  3.把圖片放到切割對象里面,通過設置圖片的top和left實現,這個方法是可行,但下面有更簡單的方法實現;
  4.通過設置圖片的clip來實現。

  這里介紹方法4的實現方法,這個方法是從當年“珍藏”的代碼中看到的,先說說clip:
  clip的作用是“檢索或設置對象的可視區域。可視區域外的部分是透明的。”
  依據上-右-下-左的順序提供自對象左上角為(0,0)坐標計算的四個偏移數值來剪切。
  例如:

div { position:absolute; width:60px; height:60px; clip:rect(0 20 50 10); }


  注意position:absolute的設置是必須的(詳細看手冊)。

  下面說說具體實現原理:
  首先需要一個容器(_Container),容器里面會插入三個層:
  底圖層(_layBase):那個半透明的圖片;
  切割層(_layCropper):正常顯示的那個部分;
  控制層(_layHandle):就是控制顯示的那個部分。

  其中為了底圖層和切割層是程序自動創建的圖片,控制層是自己定義的層(程序中是一個div)。
  底圖層和切割層必須完全重合,程序中把這兩個層都絕對定位到了左上角:

this._layBase.style.top = this._layBase.style.left = this._layCropper.style.top = this._layCropper.style.left = 0;


  層疊順序也要設置一下保證各層順序。

  下面說說各部分的作用:
  容器:除了容器本身的作用,通過設置其背景色來設置透明的漸變色,由于圖片本身沒有背景色所以要通過容器來設置;
  底圖層:在容器最底部,作用是顯示非選擇區域的圖片,透明效果就是在這層設置;
  切割層:最關鍵的一個層,在底圖層和控制層之間,在這個層通過clip設置其可視區域來實現切割圖片的效果;
  控制層:位于頂部,拖放(_drag)和縮放(_resize)效果就是在這個層實現,根據其拖放和縮放的結果控制切割層的切割效果。

  這里要注意的是控制層的_drag拖放效果的Transparent要設為true(詳細看拖放效果的透明背景bug部分)。
  要使用縮放需要把Resize設為true,并設置各個拖拉對象,程序通過_resize設置縮放的比例和最少范圍(詳細看拖拉縮放效果)。

  下面說說控制層如何控制切割效果:
  控制層的拖放和縮放過程中加入了SetPos設置切割樣式程序,在SetPos程序中根據控制層的樣式設置切割層的可視區域范圍:

var p = this.GetPos();
this._layCropper.style.clip = "rect(" + p.Top + "px " + (p.Left + p.Width) + "px " + (p.Top + p.Height) + "px " + p.Left + "px)";


  其中GetPos程序,它可以把當前控制層的樣式參數作為一個對象返回:

with(this._layHandle){
    
return { Top: offsetTop, Left: offsetLeft, Width: offsetWidth, Height: offsetHeight }
}


  如果理解了的話就會覺得其實原理挺簡單的,不過要想出來還是要一定創意才行,為想出這個方法的人致敬!

【切割預覽】

  預覽效果需要設置Preview屬性為預覽容器對象,程序會自動給容器插入一個預覽對象(圖片)。
  預覽效果的關鍵在于如何根據控制層的數據來給預覽對象定位,這個主要在SetPreview預覽效果程序中處理。
  首先根據控制層的高寬比置預覽對象顯示的寬和高(不是圖片本身的寬高哦),這里可以用GetSize程序獲取:

var p = this.GetPos(), s = this.GetSize(p.Width, p.Height, this.viewWidth, this.viewHeight), scale = s.Height / p.Height;


  其中GetSize獲取尺寸程序可以根據圖片實際大小按比例縮放到要設置的大小:

Code


  可以看出如果后兩個參數(viewWidth和this.viewHeight)都不設置就會按原來大小顯示了,

  然后再按預覽圖跟控制層的比例設置預覽圖的樣式參數:

var pHeight = this._layBase.height * scale, pWidth = this._layBase.width * scale, pTop = o.Top * scale, pLeft = o.Left * scale;


  最后根據參數對預覽對象進行樣式設置和切割:

Code


  這里有點煩亂,但應該不難理解就不詳細說明了。

【圖片大小】

  容器的大小一般是固定的,但圖片的大小就不是固定的,這里又可以使用SetSize程序用來設置圖片大小:

Code


  有了圖片大小就可以用來設置拖放和縮放的范圍限制了:

Code


  ps:程序中的Init程序是用來把個性設置呈現出來,所以一般設置過屬性之后(例如圖片地址、透明度等)就執行一次Init程序就可以顯示效果了。

【ie6渲染bug】

  在拖放效果中說到插入一個div解決ie的透明背景bug,這里就需要修復這個bug。
  跟縮放效果配合使用時,不得不說ie6的一個渲染bug,用下面的代碼測試(ie6):

Code


  可以對比ie7的效果,可以看出里面的div雖然高度設置了100%,但在外面的div修改高度之后,卻不知什么原因沒有填充了(外面的div渲染后,沒有觸發里面的div再渲染)。

  解決這個bug的關鍵是使里面的div能再渲染,這里有幾個方法可以解決:
  1,設置控制層的overflow為hidden,好處是只需要設置一次,但這個樣式會影響其他效果,當然在不影響效果的情況下這個是最好的方法;
  2,在縮放的時候,通過修改控制層的某些樣式,使里面的div再渲染,這樣的樣式包括zoom,display(應該還有其他吧);
  3,在縮放的時候,通過修改插入div的某些樣式,使其再渲染,這樣的樣式包括display(zoom也不行);
  程序中是通過修改_layHandle的zoom解決的:

if(isIE6){ with(this._layHandle.style){ zoom = .9; zoom = 1; }; };


  ps:這個bug的原因貌似跟ie的layout有關,但我查了一下還是沒弄清楚,誰有詳細的介紹或解析務必跟我分享一下啊。


使用說明

  實例化時有三個必要參數:容器對象、控制層、圖片地址:

var ic = new ImgCropper("bgDiv""dragDiv""1.jpg");


  有以下這些可選參數和屬性:
  屬性:默認值//說明
  Opacity: 50,//透明度(0到100)
  Color:  "",//背景色
  Width:  0,//圖片高度
  Height:  0,//圖片高度
  //縮放觸發對象
  Resize:  false,//是否設置縮放
  Right:  "",//右邊縮放對象
  Left:  "",//左邊縮放對象
  Up:   "",//上邊縮放對象
  Down:  "",//下邊縮放對象
  RightDown: "",//右下縮放對象
  LeftDown: "",//左下縮放對象
  RightUp: "",//右上縮放對象
  LeftUp:  "",//左上縮放對象
  Min:  false,//是否最小寬高限制(為true時下面min參數有用)
  minWidth: 50,//最小寬度
  minHeight: 50,//最小高度
  Scale:  false,//是否按比例縮放
  Ratio:  0,//縮放比例(寬/高)
  //預覽對象設置
  Preview: "",//預覽對象
  viewWidth: 0,//預覽寬度
  viewHeight: 0//預覽高度

 

程序代碼

Code

 

完整實例下載

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()