我們有許多眾所周知的圖表類型:酒吧,甜甜圈,線,派,您可以命名。所有流行的圖表庫支持這些。然後有圖表類型甚至沒有名稱。使用堆疊的(嵌套)正方形查看此DreamT-Up圖表,可以幫助可視化相對大小,或者不同的值相互比較:
沒有任何互動,創建此設計非常簡單。一種方法是堆疊元素(例如SVG
但是,一旦我們引入了一些互動性,事情就會變得棘手。應該這樣做:當我們將鼠標移到其中一種形狀上時,我們希望其他人逐漸消失並移開。
我們將使用矩形和掩碼創建這些不規則的形狀 - 具有
現在,在我們開始之前,您可能會想知道是否是使用自定義形狀的更好的SVG替代品。絕對是可能的!但是用繪製形狀可能令人生畏,甚至會變得凌亂。因此,我們正在使用“更容易”的元素來獲得相同的形狀和效果。
例如,這是我們必須使用
<svg viewbox="“" width="“" height="“"> </svg>
如果0H0V56…對您沒有任何意義,請查看“ SVG路徑語法:插圖指南”,以詳細說明語法。
給定這樣的數據集:
鍵入datasetEntry = { 標籤:字符串; 值:數字; }; 鍵入dataset = datasetEntry []; const rawdataset:dataset = [ {label:'bad',值:1231}, {label:'begint',value:6321}, {label:'開發',值:10028}, {label:'已完成',值:12123},, {label:'示例',值:2120} ];
…我們想以這樣的SVG結束:
<svg viewbox="“" width="“" height="“"> <rect width="“" height="“" y="“" fill="“" ...> </rect> <rect width="“" height="“" y="“" fill="“" ...> </rect> <rect width="“" y="“" fill="“" ...> </rect> <rect width="“" y="“" fill="“" ...> </rect> <rect width="“" height="“" y="“" fill="“" ...> </rect> </svg>
在瞬間,我們需要最高價值會變得很明顯。我們可以使用Math.max()獲取它。它接受任何數量的參數,並返回集合中的最高值。
const dataseThighestValue:number = math.max( ... RAWDATASET.MAP((輸入:DataSetEntry)=> entry.value) );
由於我們有一個小數據集,因此我們可以說我們將獲得12123。
如果我們看設計,則代表最高值(12123)的矩形覆蓋了圖表的整個區域。
我們任意選擇320個SVG尺寸。由於我們的矩形是正方形,因此寬度和高度相等。我們如何使12123等於320?較少的“特殊”值怎麼樣? 6321矩形有多大?
換句話說,我們如何將一個數字從一個範圍([0,12123])映射到另一個範圍([0,320])?或者,用更多的數學術語,我們如何將變量擴展到[a,b]的間隔?
出於我們的目的,我們將實現這樣的功能:
const remapvalue =( 價值:數字, Frommin:數字, Frommax:數字, Tomin:數字, tomax:數字 ):數字=> { 返回((value -frommin) /(frommax -frommin)) *(tomax -tomin)tomin; }; 重新值(1231,0,12123,0,320); // 32 重新值(6321,0,12123,0,320); // 167 重新值(12123,0,12123,0,320); // 320
由於我們將值映射到代碼中的相同範圍,而不是一遍又一遍地傳遞最小值和最大值,因此我們可以創建一個包裝函數:
const valuerMapper =( Frommin:數字, Frommax:數字, Tomin:數字, tomax:數字 )=> { 返回(值:數字):number => { 返回重新值(Value,Frommin,Frommax,Tomin,Tomax); }; }; const remapdatasetValuetosvgdimension = valueremapper( 0, DataseThighestValue, 0, svgdimension );
我們可以這樣使用:
RemapdatasetValuetosvgdimension(1231); // 32 RemapdatasetValuetosvgdimension(6321); // 167 RemapdatasetValuetosvgdimension(12123); // 320
剩下的與DOM操縱有關。我們必須創建
請注意,我們使用的是CreateElementn,而不是更常見的Createlement。這是因為我們正在使用SVG。 HTML和SVG元素具有不同的規格,因此它們屬於不同的名稱空間URI。碰巧的是,CreateElement便利地使用HTML名稱空間!因此,要創建一個SVG,我們必須是這個冗長:
document.createelementns('http://www.w3.org/2000/svg','svg')as svgsvgelement;
當然,我們可以創建另一個輔助功能:
const createsvgnSelement =(element:string):svgelement => { 返回document.createelementns('http://www.w3.org/2000/svg',element); };
當我們將矩形附加到DOM時,我們必須注意它們的命令。否則,我們必須明確指定z索引。第一個矩形必須是最大的,最後一個矩形必須是最小的。最好在循環之前對數據進行分類。
const data = rawdataset.sort( (a:datasetEntry,b:datasetEntry)=> b.value -a.value ); data.foreach((D:DATASETENTRY,index:number)=> { const rect:svgrectelement = keresvgnSelement('rect')作為svgrectelement; const rectdimension:number = remapdatasetValuetosvgdimension(d.Value); rect.setAttribute('width',`$ {rectDimension}`); rect.setAttribute('height',`$ {rectDimension}`); rect.setAttribute('y',`$ {svgdimension -rectDimension}`); svg.appendchild(rect); });
坐標係從左上角開始;那就是[0,0]在哪裡。我們總是要從左側繪製矩形。控制水平位置的X屬性默認為0,因此我們不必設置它。 Y屬性控制垂直位置。
為了給人以視覺印象:所有矩形都源於觸摸其左下角的同一點,我們必須將矩形向下推下。多少錢?矩形不填充的確切量。該值是圖表的維度和特定矩形之間的差異。如果我們將所有位放在一起,我們最終都會得到這樣做:
我們已經使用CSS添加了該動畫的代碼。
我們必須將矩形變成不規則的形狀,看起來像是第七名,或者字母L旋轉180度。
如果我們專注於“丟失的零件”,那麼我們可以看到它們切入了我們已經與之合作的相同矩形。
我們想隱藏那些切口。這就是我們最終要獲得想要的L形狀的方式。
掩模是您定義的東西,然後應用於元素。通常,掩碼在其屬於的
<svg> <mask> </mask> </svg>
在
<svg> <mask> </mask> <rect mask="“" url> </rect> </svg>
這不是定義或塗上口罩的唯一方法,但這是該演示的最直接方法。讓我們在編寫任何代碼以生成口罩之前進行一些實驗。
我們說,我們想覆蓋與現有矩形大小相匹配的切口區域。如果我們採用最大的元素,並且將先前的矩形應用於掩模,我們最終以此代碼:
<svg viewbox="“" width="“" height="“"> <mask> <rect width="“" height="“" y="“" fill="“”"> </rect> </mask> <rect width="“" height="“" y="“" fill="“#264653”" mask="“" url> </rect> </svg>
蒙版內的元素需要一個填充值。那應該是什麼?我們會根據選擇的填充值(顏色)看到完全不同的結果。
如果我們為填充使用白色值,那麼我們就會得到:
現在,我們的大矩形與掩蔽矩形相同。不完全是我們想要的。
如果我們使用黑色值,則看起來像這樣:
我們什麼都沒有。那是因為充滿黑色的東西變得不可見。我們使用白色和黑色填充物控制面具的可見性。虛線作為視覺輔助,以引用無形區域的尺寸。
現在,讓我們使用白色和黑色之間的東西,說格雷:
它既不是完全不透明的也不是堅固的;這是透明的。因此,現在我們知道我們可以使用與白色和黑色值不同的東西來控制這裡的“可見度”,這是一個很好的技巧,可以保留在我們的後口袋中。
到目前為止,這是我們涵蓋和了解的有關面具的知識:
我們只為掩模使用了一種形狀,但是與任何通用HTML標籤一樣,我們可以根據需要在其中嵌套盡可能多的子元素。實際上,實現我們想要的目標的訣竅是使用兩個SVG
<svg viewbox="“" width="“" height="“"> <mask> <rect width="“" height="“" y="“" fill="“"> </rect> <rect width="“" height="“" y="“" fill="“"> </rect> </mask> <rect width="“" height="“" y="“" fill="“#264653”" mask="“" url> </rect> </svg>
我們的掩蔽矩形之一充滿了白色。另一個充滿黑色。即使我們知道規則,也要嘗試一下可能性。
<mask> <rect width="“" height="“" y="“" fill="“" black> </rect> <rect width="“" height="“" y="“" fill="“" white> </rect> </mask>
現在讓我們對黑色矩形頂部的東西進行翻轉:
<mask> <rect width="“" height="“" y="“" fill="“" white> </rect> <rect width="“" height="“" y="“" fill="“" black> </rect> </mask>
這就是我們想要的!
最大的白色矩形下的所有內容都是可見的,但是較小的黑色矩形在其頂部(在Z軸上更靠近我們),掩蓋了這一部分。
現在我們知道了我們必須做什麼,我們可以相對輕鬆地創建口罩。這類似於我們首先生成彩色矩形的方式 - 我們創建了一個輔助環,在其中創建掩碼和兩個矩形。
這次,我們沒有將矩形直接附加到SVG上,而是將其附加到蒙版:
data.foreach((D:DATASETENTRY,index:number)=> { constmask:svgMaskElement = svgmaskelement; createSvgnSelement('mask'); const rectdimension:number = remapdatasetValuetosvgdimension(d.Value); const rect:svgrectelement = keresvgnSelement('rect')作為svgrectelement; rect.setAttribute('width',`$ {rectDimension}`); // ...設置其餘屬性... mask.setAttribute('id',`maskw $ {rectDimension.tofixed()}`); mask.appendchild(rect); // ...創建和設置較小矩形的屬性... svg.appendchild(蒙版); }); data.foreach((D:DATASETENTRY,index:number)=> { // ...我們的代碼生成彩色矩形... });
我們可以將索引用作面具的ID,但這似乎是一個更可讀的選擇,至少對我而言:
mask.setAttribute('id',`maskw $ {rectDimension.tofixed()}`); // MaskW320,MASW240,...
至於在面罩中添加較小的矩形,我們可以輕鬆訪問所需的值,因為我們以前訂購了從最高到最低的矩形值。這意味著循環中的下一個元素是較小的矩形,我們應該引用一個元素。我們可以通過其索引來做到這一點。
// ...上一部分我們創建了蒙版和矩形... const smalleRectIndex =索引1; //當我們處於最小時,沒有下一個 if(data [smalleRectIndex]!== undefined){ const smalleRectDimension:number = remapdatasetValuetosvgdimension( 數據[SmalleRectIndex] ); const smallErcret:svgrectelement = createSvgnSelement( 'rect' )作為svgrectement; // ...設置矩形屬性... mask.AppendChild(SmallerRect); } svg.appendchild(蒙版);
剩下的就是將蒙版屬性添加到我們原始循環中的彩色矩形中。它應該匹配我們選擇的格式:
rect.setAttribute('mask',`url(#baskw $ {rectdimension.tofixed()})`); // maskW320,maskW240,...
我們完成了!我們已經成功製作了一個由嵌套正方形製成的圖表。它甚至在鼠標懸停上分開。而所需的只是使用
以上是如何使用口罩創建嵌套正方形的動畫圖表的詳細內容。更多資訊請關注PHP中文網其他相關文章!