SVG解決方案
SVG做圖形化任務(wù)變得簡單,餅圖自然也是可以的,各種復(fù)雜的效果都是可以做出來,這里主要是分享一些技巧。
讓我們從一個(gè)簡單的圓開始:
<svg?width="100"?height="100"> <circle?r="30"?cx="50"?cy="50"?/> </svg>
然后給這個(gè)圓附上一些簡單的樣式:
circle?{ ??fill:?yellowgreen; ??stroke:?#655; ??stroke-width:?30; }
注:你可能已經(jīng)知道,CSS屬性同樣適用于SVG元素,考慮到可移植性,這將是會(huì)很方便的。
圖九:我們的起點(diǎn):一個(gè)綠色的SVG圓,填充色為#655
圖九顯示,SVG strokes不僅僅包含stroke和stroke-width屬性。它還包含一些不是很常用的屬性來微調(diào)strokes。stroke-dasharray就是其中之一。它是為了創(chuàng)建虛的strokes。例如,我們可以這樣用:
stroke-dasharray:?20?10;
圖十:一個(gè)簡單的dashed stroke,由stroke-dasharray所創(chuàng)建
上面的CSS代碼表示我們要虛實(shí)相間的圓(實(shí)線部分寬度為20,間隔部分寬度為10)。到現(xiàn)在為止,你可能想知道這個(gè)SVG與餅圖究竟有啥關(guān)系?當(dāng)我們把實(shí)線部分的寬度設(shè)置為0,間隔部分寬度設(shè)置為大于或等于圓的周長,這樣就變得清晰了。(C = 2πr, so in our case C = 2π × 30 ≈ 189):
stroke-dasharray:?0?189;
圖十一:多個(gè)不同stroke-dasharray值的效果圖;從左到右依次為:0 189;40 149; 95 189; 150 189;
正如你所看到的,圖十一的第一個(gè)SVG把所有的stroke部分移除了,我們只能看到綠色的圓。然而,好玩的是當(dāng)我們開始逐漸增加stroke-dasharray屬性的第一個(gè)值時(shí),stroke部分慢慢回來了。由于間隙(gap)部分太大了,我們無法看到更多的實(shí)線部分筆畫(stroke),僅僅只有一個(gè)stroke覆蓋在圓上,看起來就像是我們所指定的圓的周長的百分比。
你可能已經(jīng)開始試圖去弄清楚究竟發(fā)生了什么:如果我們減小圓的半徑到足夠小,以至于完全被筆畫(stroke)所覆蓋,我們最終會(huì)得到類似于餅圖的東西。例如,圖十二,如果你將半徑設(shè)置為25,并且將筆觸的寬度設(shè)置為50會(huì)發(fā)生什么?下面的代碼所呈現(xiàn)出來的圖形如下:
圖十二:我們的SVG慢慢的有點(diǎn)像餅圖了
記住:SVG筆觸總是一半在所對(duì)應(yīng)的元素內(nèi),一半在元素外。將來我們將控制這一行為。
<svg?width="100"?height="100"> ??<circle?r="25"?cx="50"?cy="50"?/> </svg>
circle?{ ??fill:?yellowgreen; ??stroke:?#655; ??stroke-width:?50; ??stroke-dasharray:?60?158;?/*?2π?×?25?≈?158?*/ }
現(xiàn)在,把它變成一個(gè)我們?cè)谥暗慕鉀Q方案中所呈現(xiàn)的餅圖就變得更簡單了:我們只要在筆觸的下一層畫一個(gè)大的綠色的圓,然后順時(shí)針旋轉(zhuǎn)90°,這樣,是他看起來像是從12點(diǎn)鐘方向開始。由于<svg>元素也是一個(gè)HTML元素,我們同樣可以給它寫樣式:
svg?{ ??transform:?rotate(-90deg); ??background:?yellowgreen; ??border-radius:?50%;}
圖十三:最終的SVG餅圖
你可以看到最終的效果圖(圖十三)。這種技術(shù)使得餅圖從0到100%的動(dòng)畫效果更加簡單。我們僅僅需要?jiǎng)?chuàng)建一個(gè)CSS動(dòng)畫,使得屬性stroke-dasharray的值從0 158到158 158;
@keyframes?fillup?{ ??to?{?stroke-dasharray:?158?158;?} } circle?{ ??fill:?yellowgreen; ??stroke:?#655; ??stroke-width:?50; ??stroke-dasharray:?0?158; ??animation:?fillup?5s?linear?infinite; }
作為額外的改進(jìn),我們可以指定圓的半徑以使得它的周長為(無限接近于)100,這樣我們就能方便的指定stroke-dasharray的長為百分比,而不需要去做額外的計(jì)算。由于周長=2πr,所以,半徑r=100÷2π≈15.915494309,我們可以大約的認(rèn)為是16。我們還將在viewBox屬性中設(shè)置SVG的尺寸而不是直接設(shè)置它的width和height,以使其適應(yīng)期容器的大小。
經(jīng)過這些修改,圖十三餅圖將變成:
<svg?viewBox="0?0?32?32"> ??<circle?r="16"?cx="16"?cy="16"?/> </svg>
svg?{ ??width:?100px;?height:?100px; ??transform:?rotate(-90deg); ??background:?yellowgreen; ??border-radius:?50%; } circle?{ ??fill:?yellowgreen; ??stroke:?#655; ??stroke-width:?32; ??stroke-dasharray:?38?100;?/*?for?38%?*/ }
注意到了沒有?現(xiàn)在設(shè)置百分比將變得非常簡單。當(dāng)然,即使已經(jīng)變得如此簡單了,我們?nèi)匀徊辉敢馊ブ貜?fù)設(shè)置每一個(gè)SVG餅圖。是時(shí)候讓JavaScript為我們提供一點(diǎn)點(diǎn)自動(dòng)化的幫助的時(shí)候了。我們將寫一小段腳本來接管如下的簡單的HTML標(biāo)記:
<div?class="pie">20%</div> <div?class="pie">60%</div>
并且在每個(gè).pie元素中添加內(nèi)聯(lián)SVG,并附帶所有的必要元素和屬性。它還將添加一個(gè)<title>元素,以幫助讀屏器用戶也能知道餅圖的百分比的值。最終的腳本如下:
$$('.pie').forEach(function(pie)?{ ??var?p?=?parseFloat(pie.textContent); ??var?NS?=?"http://www.w3.org/2000/svg"; ??var?svg?=?document.createElementNS(NS,?"svg"); ??var?circle?=?document.createElementNS(NS,?"circle"); ??var?title?=?document.createElementNS(NS,?"title"); ??circle.setAttribute("r",?16); ??circle.setAttribute("cx",?16); ??circle.setAttribute("cy",?16); ??circle.setAttribute("stroke-dasharray",?p?+?"?100"); ??svg.setAttribute("viewBox",?"0?0?32?32"); ??title.textContent?=?pie.textContent; ??pie.textContent?=?''; ??svg.appendChild(title); ??svg.appendChild(circle); ??pie.appendChild(svg);});
這就是SVG的餅圖。你可能會(huì)認(rèn)為CSS的方法更好,因?yàn)樗拇a更簡單并且也更少的外來元素。然而,相對(duì)于純CSS來說,SVG的方法也有一定的長處:
它非常容易添加第三種顏色:只要添加另外一種筆觸,并用stroke-dashoffset設(shè)置筆觸的偏移量。或者,將stroked長度添加到之前的圓的長度。你如何能夠?qū)⒌谌N顏色添加到第一張解決方案做的餅圖里呢?
我們不需要額外擔(dān)心打印問題,因?yàn)镾VG元素被認(rèn)為是內(nèi)容并打印,就像<img>元素一樣。第一種方案取決于背景,因此不會(huì)打印。
我們能夠通過內(nèi)聯(lián)樣式來改變顏色,這意味著我們能夠很方便的通過JavaScript腳本來改變(e.g.,取決于用戶輸入)。第一張方案依賴于偽元素,除了繼承之外,它不支持內(nèi)聯(lián)樣式,這并不總是方便的。
未來的餅圖
錐形梯度在這里也將非常有幫助。餅圖所需要的是一個(gè)圓形元素,具有兩個(gè)顏色停止點(diǎn)的錐形漸變。 例如,圖5中的40%餅圖將簡單如下:
.pie?{ ??width:?100px;?height:?100px; ??border-radius:?50%; ??background:?conic-gradient(#655?40%,?yellowgreen?0); }
此外,一旦CSS Values Level 3中定義的更新的attr()函數(shù)被廣泛實(shí)現(xiàn),您將能夠使用簡單的HTML屬性來控制百分比:
background:?conic-gradient(#655?attr(data-value?%),?yellowgreen?0);
這也使得它非常容易添加第三種顏色。 例如,對(duì)于像上面上顯示的餅圖,我們只需添加兩個(gè)顏色:
background:?conic-gradient(deeppink?20%,?#fb3?0,?#fb3?30%,?yellowgreen?0);
錐形梯度在這里也將非常有幫助。
這個(gè)餅圖就基本做出來了,大家有問題嗎? 同時(shí)大家學(xué)習(xí)可以加入我們的學(xué)習(xí)群 497187010 一起學(xué)習(xí)和交流哦 另有學(xué)習(xí)資料和 學(xué)習(xí)交流 解答大家的學(xué)習(xí)問題