您好,登錄后才能下訂單哦!
本篇內容主要講解“怎么使用SVG實現提示框功能”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么使用SVG實現提示框功能”吧!
NO.1
前言
Tooltips常被稱為提示框(或信息提示框),提示框能夠以較強的交互性、自由度為用戶提供相應的提示信息。今天我們要聊的不是如何實現強大的交互行為,而是來看看如何以最好的方式來還原他們的視覺效果,并且能適用于不同的場景。
NO.2
背景
上圖是從平時工作場景碰到的UI效果截圖過來的。上圖中展示的Tooltips框基本上覆蓋了常見的UI風格。簡單的來歸納一下:
帶邊框的提示框
純色(或帶透明度純色)的提示框
帶內陰影(或外陰影)的提示框
帶邊框+漸變的提示框
帶邊框+透明度背景的提示框
提示框三角帶圓角和陰影的提示框
可能還有我未碰到的提示框UI風格。面對這么多的UI風格,對于前端實現上來說是具有一定的挑戰性,特別是多種效果組合在一起的。比如說,帶有邊框+內外陰影+漸變(或透明度)+圓角三角等。基本上組合了上圖所提到的各種UI風格。
NO.3
clip-path方案
通常上圖的實現是使用CSS畫個尖角來拼接上去,比較優秀的方案
我們簡單介紹下clip-path
方案:
把提示框分成兩個部分,一個是四方形,一個是三角形,然后兩個拼接在一起組合成一個提示框。
假設提示框的尺寸是w x h
,邊框厚度是h2
,那么繪制帶有缺口的時需要以下幾個坐標點:
d1
坐標(0, 0)
d2
坐標((50% - b), 0)
或((w / 2 - b), 0)
其中b
是三角形對角邊長度的一半,后面會介紹到
d3
坐標((50% - b - h2), h2)
或((w / 2 - b - h2), h2)
d4
坐標((50% + b + h2), h2)
或((w / 2 + b + h2), h2)
d5
坐標((50% + b), 0)
或((w / 2 + b), 0)
d6
坐標(100%, 0)
或(w, 0)
d7
坐標(100%, 100%)
或(w, h)
d8
坐標(0, 100%)
或(0, h)
坐標點放置到clip-path
的polygon()
函數中,最終剪切之后的圖形看上去像下圖
clip-path: polygon(
0 0,
calc(50% - 4px) 0,
calc(50% - 7px) 2px,
calc(50% + 7px) 2px,
calc(50% + 4px) 0,
100% 0,
100% 100%,
0 100%,
0 0);
另外就是三角形的部分,如果我們的三角形是一個10px x 10px
旋轉45deg
得到。根據一些三角函數的公式和已知的正方形邊長就可以計算出正方形斜對角的長度:
NO.4
clip-path方案碰到問題
這個效果整體看起來還是不錯的,但是細看就會發現在接縫處或許會存在有空隙、有重疊的問題
采用vw
方案后這類像素對不齊的問題也算是司空見慣了,同時第一個Tooltips由于是背景需要從左到右漸變的,此時尖角的漸變過度要和下方的漸變匹配上就更需要費力氣了。
由于先前就遇到過此類ToolTip樣式問題,告知視覺同學后,體貼的視覺同學修改了一版不帶透明度的純色提示框,然而視覺效果大打折扣。
其實我們對于原先采用CSSclip-path
的方案其實也存在很多的缺陷,它在面對帶有陰影、背景透明或者漸變、帶邊框同時出現時就顯出了實現成本高和效果一般的缺點。
NO.5
SVG 方案
在討論中我們想到 SVG的path
和這個提示框的樣式天然的匹配(建議先了解下path
的相關文檔),查閱了相關的文檔和資料后我們大致得到了使用SVG來實現的如下幾個優點:
能輕松滿足陰影、背景透明或者漸變、帶邊框的效果,甚至更為復雜多變的場景
SVG的path
實現簡單,并且代碼量極小
可擴展性,可維護性
使用Demo工具,我們會得到path
的數據大致如下:
M 0,0 L -15,-15 H -79 Q -84,-15 -84,-20 V -85 Q -84,-90-79,-90
H 61 Q 66,-90 66,-85 V -20 Q 66,-15 61,-15 H 15 z
通常使用SVG畫path
時用到命令如下表:
命令 | 名稱 | 參數 |
M | moveto(移動到) | (x y)+ |
Z | closepath(關閉路徑) | (none) |
L | lineto(畫線到) | (x y)+ |
H | horizontal lineto(水平線到) | x+ |
V | vertical lineto (垂直線到) | y+ |
C | curveto(三次貝塞爾曲線到) | (x1 y1 x2 y2 x y)+ |
S | smooth curveto(光滑三次貝塞爾曲線到) | (x2 y2 x y)+ |
Q | quadratic Bézier curveto(二次貝塞爾曲線到) | (x1 y1 x y)+ |
T | smooth quadratic Bézier curveto(光滑二次貝塞爾曲線到) | (x y)+ |
A | elliptical arc (橢圓弧) | (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
R | Catmull-Rom curveto* (Catmull-Rom曲線) | x1 y1 (x y)+ |
貝塞爾曲線
在SVGpath
命令中我個人認為最精髓的部分是貝塞爾曲線,貝塞爾能畫出各種令人愉悅的曲線。
貝塞爾曲線完全由其控制點決定其形狀,n個控制點對應著n-1階的貝塞爾曲線,并且可以通過遞歸的方式來繪制。我們先看下一次和二次貝塞爾曲線如何來繪制的:
一次曲線:
一條直線上,隨著時間t的變化,紅色線段的那個點的坐標公式應該如下:
二次貝塞爾曲線:
p0、p1、p2
是3個不共線的點,依次用線段連接,此時隨意取線段p0p1
上的一個點p0'
, 如上圖: 我們的p0'
點在p0p1
線段的0.26處(t=0.26),此刻p1p2
線段相同比列取p1'
點,此時p0'
和p1'
連接后形成線段p0'p1'
, 在按照如上比列進行取值p0''
, 這時候就確定了二次貝塞爾曲線的一個點。
通過一番巴拉巴拉牛逼的推導后,二次貝塞爾曲線公式為:
N次貝塞爾可以認為是如上取值方式的迭代過程,可以通過下圖直觀的感受到1~4次曲線隨著時間t的變化過程
SVG中的Q命令
回到我們的ToolTips
話題, 其中的圓角是可以通過二次貝塞爾曲線來實現,SVG中Q
命令就是來實現二次貝塞爾曲線的
對應的指令,其中x1,y1就是我們上面提到的p1
點:
Q x1 y1, x y
二次貝塞爾曲線Q
示例如下:
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
</svg>
通過設置起始點和調整控制點p1
我們能得到我們想要的圓角,如下圖所示,小圓點為我們的p1
控制點
NO.6
樣式設置
實現了上方的SVG后接下來的透明、背景漸變、陰影、邊框的設置就都不成問題了。
背景透明:
path {
fill: rgba(0,0,0, .3);
storke: #ffffff;
storke-width: 1px
}
陰影:
svg {
filter:drop-shadow(2px 4px 6px black)
}
關于為何使用drop-shadow
來實現陰影,可以看下圖使用了box-shadow
和drop-shadow
效果區別,
使用box-shadow
的時候我們的尖角部分沒有陰影,氣泡框部分是有陰影的,就會出現下圖所示的情況,而使用drop-shadow
就能符合我們尖角和氣泡框都有陰影的要求。
背景漸變
SVG不僅支持簡單的填充,還支持線性漸變和徑向漸變以及圖形紋理等。為了讓漸變能被重復使用,漸變內容需要定義在標簽內部。
如下圖是徑向漸變的演示:
<svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="black" stop-opacity="0"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
<rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/>
</svg>
將這個漸變作用到我們提示框后可以看到如下圖的效果,終于不用辛辛苦苦的處理尖角的漸變銜接問題了。
NO.7
需求還沒完
上面方案落地到項目中后,可能是我們不經意感動了設計師,最近的需求視覺稿中我們發現其中涉及到的Tooltips樣式已經越發令人驚艷。簡單列舉如下兩個樣式:
第一版方案我們基于Demo工具演示我們已經產出了ToolTips的SDK, 我們使用的單個參數arrowHeight
傳入來生成尖角。在應付上方兩個樣式是不可能的,尖角樣式多變,如何來擴展性和易用性成為了一個問題,不可能多變的尖角樣式都開發一個SDK。
NO.8
方案改進
要應付多變的氣泡尖角一定要想辦法把尖角抽離出原先的氣泡外層路徑,生成尖角路徑后在整合到氣泡上形成一個完整的閉合路徑。
為了簡單處理數值,我將原先的尖角(0,0)
坐標定義更換到下方圖示點:
所以接下來尖角可以自由設計了,只要保證從(0,0)
出發最后回到(-arrowWidth,0)
就行了,如下是一個尖角的路徑:(M 0 0 C -10 0 -8 5 -12 5 S -14 0 -24 0
)
通過設計不同的尖角路徑我們就能組合成不同的氣泡樣式:
上方右側的尖角氣泡最終給出的路徑字符串如下,其中Q -2 7 -9 10 Q -6 5 -7 0
這一段即為我們的尖角路徑:
M 0 0
Q -2 7 -9 10 Q -6 5 -7 0
H -110
Q -116,0 -116,-6
V -56
Q -116,-62 -110,-62
H 101
Q 107,-62 107,-56
V -6
Q 107,0 101,0
H 0 z
從上方簡短的路徑能看出,我們的尖角路徑是完整的整合在整個SVG氣泡路徑中的,所以就不會擔心會出現CSS的 clip-path 方案的問題。
NO.9
可視化工具
方案看起來好像已經搞定了需求中的尖角樣式,然而你可能會說這尖角路徑是如何產生,難道需要通過強大的數學能力推導出來?如下三次貝塞爾曲線就已經不敢直視了,更何況四次、五次...
所以想配合的我們一定要產出可視化工具來實現這路徑生成過程,得益于D3.js工具庫操作SVG方面的強大功能,我們開發完的 生成工具地址
對于熟悉SVG的path
命令的同學來說這個操作不難,如果不熟悉的推薦看下下方的參考文章,了解了曲線命令后就能畫出圓滑的曲線。
到此,相信大家對“怎么使用SVG實現提示框功能”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。