Vue 圖片剪裁元件設計思考

前言

當初接觸到 rxjs 這套以流的方式處理事件及資料的庫時,以爲很是新奇,便嘗試本身從頭寫了一個 rxjs + vuerx + vue 支援觸控端、響應式的圖片剪裁元件,取名叫 vuejs-clipper 併發布至 npm。前端

算是一個簡單的元件,這篇主要介紹下當初的一些有趣的思考方向,而非程式方面如何實做。vue

完整的程式碼、使用範例都在連結裏,有興趣、喜歡的話可使用看看或給個星當作鼓勵 :)git

vuejs-clipper 展現

結構

前端使用Vue,要在Vue Component中使用rxjs的話,vuerx這個Vue的插件(Plugin)提供二者很好的結合,讓Vue component多了個subscriptions選項可定義 rxjs 的 subject 和 Observable 等。github

以及提供v-stream,和v-on同樣監聽Dom事件,可是以rxjs Observable流式來處理。npm

元件使用Vue SFC方式開發,最後用@vue/cli 打包成umd擋案可用script引入。canvas

構想

(如下圖多注意)併發

其實已經有許多圖片剪裁元件的庫了,像是這個cropper.js,功能應該很是強大齊全(沒有使用過...汗顏),還有結合cropper.js和Vue component的vue-cropperjs等等......優化

這邊打個岔,先來定義一些名詞以方便我後面繼續講下去。。。插件

這張圖以vuejs-clipper爲例設計

若是剛剛有玩一下cropper.js的話能夠發現,他的剪裁匡和圖片都是能夠縮放移動的。

不過當初個人想法是,其中一個往左移動,不就相對於另外一個元素往右移動了;其中一個元素縮小,就相對於另外一個元素放大了啊。因此我認爲圖片或剪裁匡,選擇其中一個進行縮放和移動就好。

基於這個原則我作了兩種不一樣的元件,取名叫 clipper-basic(示例) 和 clipper-fixed(示例)。

clipper-basic

手指/滑鼠在剪裁元件上只能縮放移動剪裁匡,但能夠另外綁定屬性來控制圖片旋轉和放大。

clipper-fixed

手指/滑鼠在剪裁元件上只能縮放移動圖片,但能夠另外綁定屬性來控制圖片旋轉。

元件設計

接下來介紹一些設計、優化的重點。

位置、大小使用百分比

剪裁匡、圖片都是剪裁元件的子元素,長寬(width, height)、位置(top/bottom, left/right),須要用相對外匡的百分比來表示,不然熒幕大小一變就會跑版。

若是能使用 transform: translate 來替代layout: top/bottom, left/right 的話效能會更好,但當初開始寫的時後我剪裁匡的位置和長寬並不是一塊兒計算,render的順序不一致致使我用 translate 的話經常會跑版,後來就乾脆用 top/bottom, left/right 來表示位置了。。。

拖弋剪裁匡

如何實做拖弋剪裁匡相信你們都會的:

紅點是一開始點擊的位置(基準點,跟着藍色匡移動)

按着滑鼠/手指從P1移動到P2

移動匡(藍色匡)移動後位置(以top, left表示的話):top 便是 y2 - y1,left 則是 x2 - x1

固然咱們還要判斷藍色匡不能超出黑色外匡, 計算出來的 top/left 須要介於 min top/left 和 max top/left 之間。

上圖演示一個例子,當鼠標移動到 藍點1 時藍色匡並不會移動由於已經抵達邊界,但若是使用者依然按着滑鼠/手指並移回 藍點2,會發現藍色匡仍是沒有移動,這是由於基準點 紅點 並無改變,形成在灰色斜線的區域移動滑鼠,藍色匡都不會移動,是一個不太好的體驗。

解決方法:當藍色匡抵達邊界,但滑鼠/手指仍在移動時,基準點跟着改變且不超出邊界,這樣就不會有滑鼠白白移動的感受。

如下示範滑鼠從P1點擊移動到P2,P3,P4,紅色基準點跟着改變,這樣當鼠標一往回移動藍色匡就能夠跟着移動。

拖弋圖片的話就比較沒有這個問題,由於圖片是能夠超出邊界的。

縮放剪裁匡

縮放剪裁匡其實就是判斷一開始滑鼠點在匡上的哪一個方位,就使用對秤點看成基準點,剪裁匡以該點不動來縮放。

能夠發現Cropper.js是有八個基準點能夠縮放的:

但當初的 clipper-basic 設計成剪裁匡是能夠縮放成任意比例的,所以邊上的基準點就不須要了,只作了四個基準點:

其實在任意比例 (長寬比例不限 ) 下這樣設計是沒問題的,但後來想要加上限制比例的設定就比較尷尬了,能夠去展現把 ratio 選項打勾並縮放剪裁匡試試,由於少了邊上的基準點,在水平或垂直縮放時用起來有些奇怪,可是對角縮放就不會。

剪裁元件長寬

正常來講圖片剪裁元件能夠設定外觀長寬,但一開始 clipper-basic 並無要作圖片縮放,並想把這個元件作成像一個 <img> 元素,根據圖片自動調整比例,可是隻作了根據寬度調整高度,而沒有設定高度來調整寬度的選項。。。

這就形成一個問題,假設圖片剪裁元件設定 width: 500px,當上傳一個很長的圖片時,網頁的佈置會被拉的很長。

算是設計上的疏失,可能的解決辦法寫在這裏

clipper-fixed 的話是有設定剪裁比例的,長寬比則是看剪裁比例相同。

縮放圖片

clipper-fixed 縮放圖片,綁定滾輪/兩指觸控事件,會發現若是使用固定比例縮放(假設每次縮放0.1倍好了),在圖片較小時會以爲縮放的很快,圖片很大時縮放則感受很是緩慢。

所以須要用線性方式來調整縮放比例: (下圖只是示例,非真正的比例)

縮放率要隨着圖片的大小增長,公式的話…一元、二元應該都是能夠的,調整到本身感受最溫馨的參數。

輸入和輸出

想要表現的像一個<img>,所以有src屬性,接受一個圖片的 URL。 輸出則是一個canvas element,使用者可將canvas繪製到其餘地方,或者轉成image元素、Blob、URL等,這些操做是比較消耗效能和時間的。

設計這個元件(而非函式庫)就是想要間單一點,單純控制UI,不介入一些上傳、轉換圖片的處理。

結語

總結一下此次做這個元件能夠改善的地方,之後(應該是不會有之後.w.)能夠改進:

  • 剪裁元件的長寬設定方式不佳
  • 剪裁匡縮放基準點能夠設爲八個
  • 剪裁元件的初始狀態沒法設定 (一開始剪裁匡的位置、大小等)。

我的認爲 clipper-fixed 這種操做方式是最通用也最沒毛病的,但我也不懂一些UI/UX啥的,不知道怎樣使用者操做比較順手。。。

雖說是用 vue + vuerx + rxjs 但本文幾乎沒有講到這三者的時做和程式碼,因本人也算是剛接觸的生手,尚在摸索,就沒有對這幾個庫做講解。

就先介紹到這,但願你們會喜歡。

相關文章
相關標籤/搜索