canvas 插件_基于Angular的Canvas手写签名插件
靈感來源
之前, 在輕流的業(yè)務(wù)中遇到了一個需求, 是能夠讓客戶使用手寫簽名的功能.
簽名演示問題來了, 這...我不會啊! 這得是Canvas了吧. 正所謂, 插件用的好, 下班走的早. 于是我就開始找插件了. 找到了一個ng生態(tài)的插件, 名字不記得了, 只記得他就一個核心文件, 封裝了一個第三方插件. 沒有提供任何原創(chuàng)的方法, 都是直接把第三方簽名插件所提供的方法emit了出來. 以下就是他import的第三方插件.
https://github.com/szimek/signature_pad?github.com那么問題來了, 那我要你干嘛? 我為啥不自己封裝一個呢? 因為業(yè)務(wù)比較緊, 沒有那么多時間去思考如何封裝地更好. 所以直接在輕流中封裝了一個更加適合輕流業(yè)務(wù)的簽名模塊. 比如說, 全屏簽名
全屏簽名在完成業(yè)務(wù)后, 我使用angular library封裝了屬于自己的第三方插件.
https://github.com/eve-sama/ngx-signature-pad?github.com那么我的插件有什么特別之處呢? of course~ 因為第三方插件我認(rèn)為有些地方的設(shè)計不是很合理, 并且沒有一些我想要的API.
注意: 為了方便描述和對比, 在下文中, 第三方插件我將稱之為sp(signature pad的縮寫), 我的插件將稱之為ngx-sp.
一. API風(fēng)格更加ng化
現(xiàn)在讓你來設(shè)計這個簽名組件, 要求實現(xiàn)當(dāng)用戶簽字的時候通知父組件一個簽名事件. 當(dāng)結(jié)束簽字的時候需要通知父組件一個結(jié)束事件. 我們先看看sp是如何處理的
摘自sp README部分sp是通過一個對象的形式傳遞參數(shù), 包括事件也是通過回調(diào)函數(shù)的方法. 如果是我我就不會這么設(shè)計. 我覺得ng社區(qū)的同僚應(yīng)該下意識都是像下面這樣設(shè)計API的
<二. 只有小屏簽名
其實全屏簽名是個非常常見的場景, 但是sp并沒有提供. 其實這個不能說是sp的問題. 因為他提供了一塊兒簽名的canvas, 理論上你就可以在這個基礎(chǔ)上開發(fā)出各種姿勢的簽名. 只是我比較懶, 我希望他能提供類似如下的代碼
sp.fullScreen();遺憾的是他沒有, 在全屏相關(guān)的需求中, Angular CDK是個非常好的工具, 其實可以結(jié)合CDK輕而易舉地實現(xiàn)這樣的需求. 所以, sp沒有, 那ngx-sp就來做.
摘自ngx-signature-pad README部分需要注意一點, 大家想象下, 你比如初始化了一個簽名組件, 尺寸是300*150, 在上面畫了幾筆. 大概這個樣子
小屏簽名當(dāng)調(diào)用fullScrren()的時候, 簽名組件會展示全屏化, 請問, 已經(jīng)簽過的內(nèi)容該如何處理呢? 顯然是要放大的吧. 但是小屏簽名的寬高是由用戶自定義的, 那么全屏的話, 假如ngx-sp真的100%的寬*100%的高, 不一定和用戶設(shè)定的比例相同.
比例不同造成的后果, 就是已簽過的內(nèi)容會被拉寬或者拉高. 所以, 我的設(shè)定就是全屏的寬高比與小屏的寬高比是保持一致的.
全屏簽名順便一提, 之所以我執(zhí)意要把全屏的API封裝進(jìn)ngx-sp, 是因為全屏要做的事兒比較惡心, 我不想在業(yè)務(wù)層做這種事兒. 這幾十行倒也算不上很難, 就是對canvas不熟悉、數(shù)學(xué)又差的一逼的人, 比如我, 比較折騰.
摘自ngx-sp源碼現(xiàn)在好了, 你只需要一個xxx.fullScreen()就可以直接全屏化, 那叫一個美汁兒美汁兒~
三. 只能判斷是否被簽過, 不允許更改狀態(tài)
在sp中, 是這樣判斷是否被簽名過的
// Returns true if canvas is empty, otherwise returns false但是并沒有提供手動更改簽名狀態(tài)的方法. 為什么需要這樣的函數(shù)呢?
比如說前文的全屏簽名, 大家注意看這個操作過程
我的思路, 其實是創(chuàng)建2個canvas實例. 一個用于小屏, 一個用于全屏(使用CDK包裝). 當(dāng)用戶切換模式的時候, 就會把原模式的內(nèi)容copy到新模式的canvas上. 但是因為sp沒有提供手動更改簽名狀態(tài)的方法, 就會導(dǎo)致一個問題.
當(dāng)ngx-sp把小屏簽名的內(nèi)容copy到全屏簽名上, 此時調(diào)用isEmpty()方法, 一定是true(也就是顯示你從未簽名過, 從邏輯上看, 這就是bug了). 因為你全屏簽名的內(nèi)容并不是鼠標(biāo)繪制出來的. 而是通過canvas相關(guān)的方法copy的.
查看sp的源碼, 會發(fā)現(xiàn)相關(guān)屬性是private
摘自sp源碼問題不大, 在輕流的業(yè)務(wù)模塊中, 我就強行把_isEmpty給改了. 反正private在run time時被更改, 瀏覽器也攔不住我.
在ngx-sp中則對外提供了手動更改狀態(tài)的函數(shù)
當(dāng)然了, 在ngx-sp中沒有使用強行更改private這種野路子的方法. 那么我是怎么做的呢? 核心思路其實就是我自己維護(hù)了這個變量.
下面這段代碼, 簡單來說就是在initSmallPad()中會根據(jù)開發(fā)者傳遞的參數(shù)(options), 初始化sp. sp對外提供了一個onBegin的方法, 當(dāng)他觸發(fā)的時候, 我就會手動把_isEmpty標(biāo)記為false. 既然這個變量由我自己來維護(hù), 那么我就可以任意更改了.
摘自ngx-sp源碼所以, 同樣對外暴露了isEmpty()的方法, 但是我的判斷依據(jù)并不是根據(jù)sp源碼里的變量, 也不是直接調(diào)用的sp的isEmpty(), 而是我自己維護(hù)的私有變量.
四. 自由度不夠
sp并沒有對外暴露canvas實例相關(guān)的屬性. 這是一個很麻煩的事兒. 為什么呢, 給不了解canvas的同學(xué)科普一個概念. canvas是允許通過dragImage方法把圖片等資源畫在上面的, 如下圖.
https://eve-sama.github.io/ngx-signature-pad/document (注意是PC模式)我常年寫的字兒自己都不認(rèn)識. 上圖的簽名顯然不是我手畫的. 其實'前夕'那2個字是個圖片.
摘自ngx-sp README在ngx-sp中很容易做到這樣的事兒.
this.signature.getContext().drawImage(this.image, 230, 35, 100, 50, 230, 110, 100, 50); this.signature.setDirty();舉個例子, 假如你的產(chǎn)品經(jīng)理希望你在簽名區(qū)域+個背景圖, 類似下面這樣. 在sp中確實沒法實現(xiàn), 因為sp只允許你設(shè)置背景顏色, 而且是純色.
百度隨便搜的而如果在ngx-sp中, 通過獲取canvas相關(guān)實例, 你可以想怎么畫就怎么畫.
總結(jié)
以上就是對ngx-signature-pad的介紹了, 更多介紹請查看Repo. 我也只是站在巨人的肩膀上做了一點點擴(kuò)展, 希望能幫助到有需要的人~!
Repo地址
https://github.com/eve-sama/ngx-signature-pad?github.comdemo頁, 如果使用瀏覽器的PC模式訪問則側(cè)重文檔, Mobile模式則側(cè)重demo.
NgxSignaturePad?eve-sama.github.io總結(jié)
以上是生活随笔為你收集整理的canvas 插件_基于Angular的Canvas手写签名插件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 灰度调节_网关实现灰度发布
- 下一篇: 动词变名词的变化规则_动词第三人称单数的