天天看點

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

在去年的時候也實作過合成海報的功能,不過當時時間倉促,實作的比較簡單。

就一個旋轉功能,圖檔也不能拖動放大,也不能裁剪。

這次有時間就實作一個功能稍微多點的海報。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作
用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作
用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

第一屏

第二屏

第三屏

總共有三屏,第一屏是選擇圖檔,第二屏是合成圖檔,第三屏是顯示結果圖,可儲存分享朋友圈。

頁面内容不是很多,分析起來也比較簡單。

1)每一屏的左右邊距相同,上邊距各不相同。

2)螢幕内的元素,大部分是居中,有些特殊邊距的可用絕對定位,例如第一屏中父親圖與智語圖,兩張圖有重疊部分。

3)第2和3屏中的按鈕布局可以用Flex中的兩端對齊。

4)4種按鈕,可将背景制作成Sprite 圖,友善重用。1種彈出框,1種Loading。

5)有3種動畫,放大、脈沖以及旋轉360°。

6)這次實作的難點是拖動、裁剪和旋轉,需要經過邏輯計算高寬、坐标等。

1)Sprite圖

在移動端的話,位置就是用百分比來計算。從上面的總覽圖中可以看到多種按鈕背景,有幾個就是字不一樣,可以重複使用。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

2)PrimusUI

有多個子產品可以使用,此次就用了三個子產品normalize、layout與loading。

3)High DPI Canvas

在demo代碼中有一張hidpi.html頁面,就是在比較引入此插件後表現的差別,下圖是在iphone6中展現的樣子。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

下面是一段插件中的代碼,就是計算devicePixelRatio(裝置像素比)與webkitBackingStorePixelRatio(Canvas緩沖區的像素比),做個除法。

然後将Canvas的width和height根據這個比來放大,而CSS中的width和height再縮小回原來的,以此達到1像素的對應。

4)touch.js

5)FileReader

在執行上傳插件的“change”中,就是通過此對象擷取圖檔的data:URL。

1)音頻控制

為了營造父親節氣氛,特地選了首接地氣的歌曲配合頁面。

播放器就使用了HTML5标簽“audio”。

這裡注意下,IOS是禁止自動播放音頻的,解決辦法就是不要自動播放,或者就是第一次點選頁面觸發播放。

剩下的就是音頻标簽綁定播放和停止,在觸發的時候添加旋轉或脈沖動畫。

2)上傳圖檔

上傳就是綁定file标簽的“change”事件,除了前面說到的用FileReader擷取圖檔的data:URL外,還将原圖做了一次壓縮。

壓縮其實就是将圖檔放到Canvas中,然後用Canvas輸出“jpeg圖檔”,并且品質是“0.7”,可以将一張800多KB的png圖檔壓縮到50多KB。

還發現一個現象,如果用Canvas輸出“png”的data:URL,會比原圖還要大。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作
用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

在“reader.onload”事件中除了壓縮圖檔,還會儲存此圖的真實際寬度和高度,下面的旋轉會用到尺寸,還儲存了一條旋轉資訊的緩存。

3)拖拽、放大、縮小

此功能是需要與上面的touch.js手勢庫結合。

拖拽使用了CSS3的“translate3d”屬性,而放大縮小使用了CSS3的“scale”屬性。

原先旋轉也想用CSS3的“rotate”屬性實作,不過後面實作後,裁剪圖檔變得非常棘手,不能下手,最後是否決了這個實作方式。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

4)旋轉

為了解決裁剪的問題,每次旋轉都會生成一張新的圖檔,并将這個圖檔資訊緩存起來。

由于是新的圖檔,是以就可以直接按照原先的方式來裁剪了,也不用考慮旋轉角度的問題。

旋轉的邏輯放在“filterImage”中,當時在編寫旋轉的時候,碰到旋轉後的圖形變形的問題,後面用圖檔的實際寬高就解決了變形。

之是以變形是因為寬高用了CSS計算後的值,下圖中的兩個尺寸就是計算後的值。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

下圖介紹了操作過程:

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

為了提升性能,每個方向的圖檔資訊都會被緩存起來。

5)裁剪

比較複雜的一部分,計算圖檔相對于畫框的left和top邊距。

而right和bottom與以往的定義不同,這裡是高度與寬度分别和top與left相加後的值。

再根據不同邏輯,分别計算畫框與圖檔的X、Y、width和height的值。

最後計算實際圖檔的寬度與CSS計算後的圖檔寬度比,将這個值與圖檔的X、Y、width和height相乘,得出最終值。

這裡注意下,在iphone5S中,如果圖檔的實際高度 < 計算後的高度,就會出現不顯示。具體的邏輯在“intersect”方法中。

下圖是某一種情況下的各個坐标值:

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

6)合成

合成其實就是将兩張Canvas合并到一起。下面代碼中的“drawImage”是自定義的一個方法,最終還是會調用Canvas的“drawImage”。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

sx、sy對應的是圖檔的x、y坐标,而dx、dy對應的是畫布的x、y坐标。

用H5中的Canvas等技術制作海報一、概要二、涉及的知識點三、實作

demo下載下傳:

<a href="https://github.com/pwstrick/father" target="_blank">https://github.com/pwstrick/father</a>

參考資料:

<a href="https://github.com/jondavidjohn/hidpi-canvas-polyfill" target="_blank">hidpi canvas</a>

<a href="http://touch.code.baidu.com/" target="_blank">touch.js</a>

<a href="http://jiaolonghuang.github.io/2015/11/16/bug-canvas/" target="_blank">一次關于canvas hidpi的2個bug解決過程</a>

<a href="http://www.html5rocks.com/en/tutorials/canvas/hidpi/?redirect_from_locale=zh" target="_blank">High DPI Canvas</a>

<a href="http://www.jianshu.com/p/2cd5143cf9aa" target="_blank">High DPI Canvas中文版</a>

<a href="http://www.straysh.info/article/9" target="_blank">結合HTML5的純js圖檔上傳</a>

<a href="http://stackoverflow.com/questions/6974684/how-to-send-formdata-objects-with-ajax-requests-in-jquery" target="_blank">how-to-send-formdata-objects-with-ajax-requests-in-jquery</a>

<a href="http://stackoverflow.com/questions/16968945/convert-base64-png-data-to-javascript-file-objects" target="_blank">convert-base64-png-data-to-javascript-file-objects</a>

<a href="http://ca.lagou.com/posters/index?from=singlemessage&amp;isappinstalled=0" target="_blank">那些年,我們曾一起走過</a>

<a href="https://happycoder.net/hidpi-canvas-polyfill/" target="_blank">canvas 在高清屏下繪制圖檔變模糊的解決方法</a>

    本文轉自 咖啡機(K.F.J)   部落格園部落格,原文連結:http://www.cnblogs.com/strick/p/5593166.html,如需轉載請自行聯系原作者