<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用SVG實(shí)現(xiàn)一個(gè)優(yōu)雅的提示框

          共 5064字,需瀏覽 11分鐘

           ·

          2021-12-01 04:01


          NO.1

          前言

          Tooltips常被稱為提示框(或信息提示框),提示框能夠以較強(qiáng)的交互性、自由度為用戶提供相應(yīng)的提示信息。今天我們要聊的不是如何實(shí)現(xiàn)強(qiáng)大的交互行為,而是來(lái)看看如何以最好的方式來(lái)還原他們的視覺(jué)效果,并且能適用于不同的場(chǎng)景。


          NO.2

          背景



          上圖是從平時(shí)工作場(chǎng)景碰到的UI效果截圖過(guò)來(lái)的。上圖中展示的Tooltips框基本上覆蓋了常見(jiàn)的UI風(fēng)格。簡(jiǎn)單的來(lái)歸納一下:


          • 帶邊框的提示框

          • 純色(或帶透明度純色)的提示框

          • 帶內(nèi)陰影(或外陰影)的提示框

          • 帶邊框+漸變的提示框

          • 帶邊框+透明度背景的提示框

          • 提示框三角帶圓角和陰影的提示框


          可能還有我未碰到的提示框UI風(fēng)格。面對(duì)這么多的UI風(fēng)格,對(duì)于前端實(shí)現(xiàn)上來(lái)說(shuō)是具有一定的挑戰(zhàn)性,特別是多種效果組合在一起的。比如說(shuō),帶有邊框+內(nèi)外陰影+漸變(或透明度)+圓角三角等?;旧辖M合了上圖所提到的各種UI風(fēng)格。


          NO.3

          clip-path方案


          通常上圖的實(shí)現(xiàn)是使用CSS畫(huà)個(gè)尖角來(lái)拼接上去,比較優(yōu)秀的方案如下圖:



          我們簡(jiǎn)單介紹下clip-path方案:


          把提示框分成兩個(gè)部分,一個(gè)是四方形,一個(gè)是三角形,然后兩個(gè)拼接在一起組合成一個(gè)提示框。這樣整個(gè)坐標(biāo)示意圖如下:



          假設(shè)提示框的尺寸是w x h,邊框厚度是h1,那么繪制帶有缺口的時(shí)需要以下幾個(gè)坐標(biāo)點(diǎn):


          • d1坐標(biāo)(0, 0)

          • d2坐標(biāo)((50% - b), 0)((w / 2 - b), 0) 其中b是三角形對(duì)角邊長(zhǎng)度的一半,后面會(huì)介紹到

          • d3坐標(biāo)((50% - b - h1), h1)((w / 2 - b - h1), h1)

          • d4坐標(biāo)((50% + b + h1), h1)((w / 2 + b + h1), h1)

          • d5坐標(biāo)((50% + b), 0)((w / 2 + b), 0)

          • d6坐標(biāo)(100%, 0)(w, 0)

          • d7坐標(biāo)(100%, 100%)(w, h)

          • d8坐標(biāo)(0, 100%)(0, h)


          坐標(biāo)點(diǎn)放置到clip-pathpolygon()函數(shù)中,最終剪切之后的圖形看上去像下圖



          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);


          另外就是三角形的部分,如果我們的三角形是一個(gè) 10px x 10px 旋轉(zhuǎn) 45deg 得到。根據(jù)一些三角函數(shù)的公式和已知的正方形邊長(zhǎng)就可以計(jì)算出正方形斜對(duì)角的長(zhǎng)度:



          NO.4

          clip-path方案碰到問(wèn)題


          這個(gè)效果整體看起來(lái)還是不錯(cuò)的,但是細(xì)看就會(huì)發(fā)現(xiàn)在接縫處或許會(huì)存在有空隙、有重疊的問(wèn)題,如下圖:




          采用vw方案后這類像素對(duì)不齊的問(wèn)題也算是司空見(jiàn)慣了,同時(shí)第一個(gè)Tooltips由于是背景需要從左到右漸變的,此時(shí)尖角的漸變過(guò)度要和下方的漸變匹配上就更需要費(fèi)力氣了。


          由于先前就遇到過(guò)此類ToolTip樣式問(wèn)題,告知視覺(jué)同學(xué)后,體貼的視覺(jué)同學(xué)修改了一版不帶透明度的純色提示框,然而視覺(jué)效果大打折扣。


          其實(shí)我們對(duì)于原先采用CSS clip-path的方案其實(shí)也存在很多的缺陷,它在面對(duì)帶有陰影、背景透明或者漸變、帶邊框同時(shí)出現(xiàn)時(shí)就顯出了實(shí)現(xiàn)成本高和效果一般的缺點(diǎn)。


          NO.5

          SVG 方案


          在討論中我們想到 SVG的path 和這個(gè)提示框的樣式天然的匹配(建議先了解下path的相關(guān)文檔),查閱了相關(guān)的文檔和資料后我們大致得到了使用SVG來(lái)實(shí)現(xiàn)的如下幾個(gè)優(yōu)點(diǎn):


          • 能輕松滿足陰影、背景透明或者漸變、帶邊框的效果,甚至更為復(fù)雜多變的場(chǎng)景

          • SVG的path實(shí)現(xiàn)簡(jiǎn)單,并且代碼量極小

          • 可擴(kuò)展性,可維護(hù)性


          參考相關(guān)文章后,我們完善Demo工具如下:



          使用Demo工具,我們會(huì)得到path的數(shù)據(jù)大致如下:


          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畫(huà)path時(shí)用到命令如下表:


          命令名稱參數(shù)
          M?moveto(移動(dòng)到)(x y)+
          Z?closepath(關(guān)閉路徑)(none)
          L?lineto(畫(huà)線到)(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 (橢圓?。?/td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
          R?Catmull-Rom curveto* (Catmull-Rom曲線)x1 y1 (x y)+


          貝塞爾曲線


          在SVG path 命令中我個(gè)人認(rèn)為最精髓的部分是貝塞爾曲線,貝塞爾能畫(huà)出各種令人愉悅的曲線。


          貝塞爾曲線完全由其控制點(diǎn)決定其形狀,?。顐€(gè)控制點(diǎn)對(duì)應(yīng)著n-1階的貝塞爾曲線,并且可以通過(guò)遞歸的方式來(lái)繪制。我們先看下一次和二次貝塞爾曲線如何來(lái)繪制的:

          一次曲線:

          一條直線上,隨著時(shí)間t的變化,紅色線段的那個(gè)點(diǎn)的坐標(biāo)公式應(yīng)該如下:



          二次貝塞爾曲線:



          p0、p1、p2是3個(gè)不共線的點(diǎn),依次用線段連接,此時(shí)隨意取線段p0p1上的一個(gè)點(diǎn)p0' , 如上圖: 我們的p0'點(diǎn)在p0p1線段的0.26處(t=0.26),此刻p1p2線段相同比列取p1'點(diǎn),此時(shí)p0'p1'連接后形成線段p0'p1', 在按照如上比列進(jìn)行取值 p0'', 這時(shí)候就確定了二次貝塞爾曲線的一個(gè)點(diǎn)。


          通過(guò)一番巴拉巴拉牛逼的推導(dǎo)后,二次貝塞爾曲線公式為:


          N次貝塞爾可以認(rèn)為是如上取值方式的迭代過(guò)程,可以通過(guò)下圖直觀的感受到1~4次曲線隨著時(shí)間t的變化過(guò)程,具體N次貝塞爾曲線的公式可以參考下方關(guān)于曲線的文章




          SVG中的Q命令


          回到我們的ToolTips 話題, 其中的圓角是可以通過(guò)二次貝塞爾曲線來(lái)實(shí)現(xiàn),SVG中 Q 命令就是來(lái)實(shí)現(xiàn)二次貝塞爾曲線的,SVG中 Q 命令的示例圖如下:



          對(duì)應(yīng)的指令,其中x1,y1就是我們上面提到的p1點(diǎn):


          Q?x1?y1,?x?y


          二次貝塞爾曲線 Q 示例如下:


          "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>


          通過(guò)設(shè)置起始點(diǎn)和調(diào)整控制點(diǎn)p1 我們能得到我們想要的圓角,如下圖所示,小圓點(diǎn)為我們的p1控制點(diǎn)



          NO.6

          樣式設(shè)置


          實(shí)現(xiàn)了上方的SVG后接下來(lái)的透明、背景漸變、陰影、邊框的設(shè)置就都不成問(wèn)題了。


          背景透明


          path?{
          ??fill:?rgba(0,0,0,?.3);
          ??storke:?#ffffff;
          ??storke-width:?1px
          }




          陰影


          svg?{
          ? filter:drop-shadow(2px?4px?6px?black)
          }



          關(guān)于為何使用drop-shadow來(lái)實(shí)現(xiàn)陰影,可以看下圖使用了box-shadowdrop-shadow效果區(qū)別,

          使用box-shadow的時(shí)候我們的尖角部分沒(méi)有陰影,氣泡框部分是有陰影的,就會(huì)出現(xiàn)下圖所示的情況,而使用drop-shadow 就能符合我們尖角和氣泡框都有陰影的要求。


          背景漸變


          SVG不僅支持簡(jiǎn)單的填充,還支持線性漸變和徑向漸變以及圖形紋理等。為了讓漸變能被重復(fù)使用,漸變內(nèi)容需要定義在標(biāo)簽內(nèi)部。


          如下圖是徑向漸變的演示:


          "120"?height="240"?version="1.1"?xmlns="http://www.w3.org/2000/svg">
          ??
          ??????
          ????????
          ????????
          ????????
          ??????
          ??

          ????



          將這個(gè)漸變作用到我們提示框后可以看到如下圖的效果,終于不用辛辛苦苦的處理尖角的漸變銜接問(wèn)題了。



          更多


          SVG同時(shí)也支持紋理疊加效果,具體感興趣的可以自行去研究下。


          NO.7

          需求還沒(méi)完


          上面方案落地到項(xiàng)目中后,可能是我們不經(jīng)意感動(dòng)了設(shè)計(jì)師,最近的需求視覺(jué)稿中我們發(fā)現(xiàn)其中涉及到的Tooltips樣式已經(jīng)越發(fā)令人驚艷。簡(jiǎn)單列舉如下兩個(gè)樣式:



          第一版方案我們基于Demo工具演示我們已經(jīng)產(chǎn)出了ToolTips的SDK, 我們使用的單個(gè)參數(shù)arrowHeight傳入來(lái)生成尖角。在應(yīng)付上方兩個(gè)樣式是不可能的,尖角樣式多變,如何來(lái)擴(kuò)展性和易用性成為了一個(gè)問(wèn)題,不可能多變的尖角樣式都開(kāi)發(fā)一個(gè)SDK。


          NO.8

          方案改進(jìn)


          要應(yīng)付多變的氣泡尖角一定要想辦法把尖角抽離出原先的氣泡外層路徑,生成尖角路徑后在整合到氣泡上形成一個(gè)完整的閉合路徑。


          為了簡(jiǎn)單處理數(shù)值,我將原先的尖角 (0,0) 坐標(biāo)定義更換到下方圖示點(diǎn):



          所以接下來(lái)尖角可以自由設(shè)計(jì)了,只要保證從(0,0)出發(fā)最后回到(-arrowWidth,0)就行了,如下是一個(gè)尖角的路徑:(M 0 0 C -10 0 -8 5 -12 5 S -14 0 -24 0



          通過(guò)設(shè)計(jì)不同的尖角路徑我們就能組合成不同的氣泡樣式:



          上方右側(cè)的尖角氣泡最終給出的路徑字符串如下,其中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
          從上方簡(jiǎn)短的路徑能看出,我們的尖角路徑是完整的整合在整個(gè)SVG氣泡路徑中的,所以就不會(huì)擔(dān)心會(huì)出現(xiàn)CSS的 clip-path 方案的問(wèn)題。


          NO.9

          可視化工具


          方案看起來(lái)好像已經(jīng)搞定了需求中的尖角樣式,然而你可能會(huì)說(shuō)這尖角路徑是如何產(chǎn)生,難道需要通過(guò)強(qiáng)大的數(shù)學(xué)能力推導(dǎo)出來(lái)?如下三次貝塞爾曲線就已經(jīng)不敢直視了,更何況四次、五次...



          所以想配合的我們一定要產(chǎn)出可視化工具來(lái)實(shí)現(xiàn)這路徑生成過(guò)程,得益于D3.js工具庫(kù)操作SVG方面的強(qiáng)大功能,我們開(kāi)發(fā)完的?生成工具地址?(https://market.m.taobao.com/app/fdilab/svg-tool-demo/pages/index/index.html) 如下:



          對(duì)于熟悉SVG的 path命令的同學(xué)來(lái)說(shuō)這個(gè)操作不難,如果不熟悉的推薦看下下方的參考文章,了解了曲線命令后就能畫(huà)出圓滑的曲線。


          10

          總結(jié)


          至此在ToolTips這塊基本已經(jīng)滿足了設(shè)計(jì)的需求,同時(shí)也沉淀了SVG路徑生成工具。使用SVG來(lái)實(shí)現(xiàn)ToolTips能覆蓋 CSS clip-path不能完美解決的幾個(gè)場(chǎng)景。在此特別感謝大漠老師的指導(dǎo)。


          11

          參考文章


          • D3官網(wǎng)(https://d3js.org.cn/)

          • 曲線篇: 貝塞爾曲線(https://zhuanlan.zhihu.com/p/136647181)

          • Tooltips using SVG Path(https://medium.com/welldone-software/tooltips-using-svg-path-1bd69cc7becd)

          • SVG漸變(https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Gradients)

          • 深度掌握SVG路徑path的貝塞爾曲線指令(https://www.zhangxinxu.com/wordpress/2014/06/deep-understand-svg-path-bezier-curves-command/)

          • css drop-shadow(https://www.zhangxinxu.com/wordpress/2016/05/css3-filter-drop-shadow-vs-box-shadow/)


          推薦閱讀


          vite —— 一種新的、更快地 web 開(kāi)發(fā)工具


          淘寶是如何縮短首屏?xí)r間、降低服務(wù)器壓力的?邊緣計(jì)算告訴你答案!


          如何使用深度學(xué)習(xí)識(shí)別 UI 界面組件?


          喜歡就點(diǎn)在看哦?

          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天干天天射天天爽 | 免费拍拍拍 | 91久久欧美极品XXXXⅩ | 亚洲人在线视频 | 亚洲社区电影 |