svg 可視化操作
本文是兩篇系列文章中的第一篇,該系列文章示範了可視化技術,這些技術可以幫助您從資料中提取業務價值資訊。 您将看到如何使用可伸縮矢量圖形(SVG)和開放源代碼的D3 JavaScript庫來建立可在浏覽器中檢視的可視化效果,以通過形狀和顔色傳達資訊。 我将通過示例來展示這些技術,這些示例可以可視化與社交媒體使用相關的浏覽名額。 在第1部分中,我概述了SVG和D3如何協同工作以及一些基本示例。 第2部分将更深入地研究這種開放标準技術的強大組合的可視化功能。
分析社交媒體名額
社交媒體大資料挑戰
諸如Twitter,Facebook和YouTube之類的社交媒體網站提供了全面的Web服務界面,以展示其功能。 例如,YouTube Data API使應用程式可以将視訊上傳到YouTube或在網站上播放現有的YouTube視訊。 現在,這些站點也在開發分析API。 例如,YouTube Analytics(分析)API向程式設計用戶端提供統計資訊,例如觀看次數和喜歡次數。 結果是更多的業務應用程式可以通過視覺和程式界面與社交媒體進行互動。 對于各種規模的公司而言,自然而然的挑戰是通過大資料分析充分利用大社交資料量的業務。 資料可視化是整個分析領域的組成部分,是本系列文章的重點。 了解有關IBM大資料平台的IBM InfoSphere Streams和IBM InfoSphere BigInsights産品的綜合分析功能。
公司了解客戶行為的一種創新方式是通過社交媒體提出想法,并與潛在客戶進行互動讨論。 社交媒體上的互動反映了雙向的人類互動:要了解人們的好惡,您必須傾聽他們的意見,就像您與任何想以積極方式與之互動的人所做的一樣。
以一家家居裝飾公司的假設場景為例,該公司以部落格,視訊,Facebook頁面和讨論論壇的形式釋出開放内容。 此内容通過社交媒體資源展示了公司的想法,并試圖引發讨論和其他形式的使用者互動。 内容迎合了各個客戶的口味和喜好,是以可以幫助他們從一種社交資源導航到另一種社交資源。 為了判斷不斷變化的客戶趨勢并提出新的方法和新的設計,該公司希望從三個方面分析浏覽資料:
- 受歡迎程度,以每種社交資源的觀看次數表示
- 參與資源互動的使用者數
- 使用者從一種資源導航到另一種資源的方向
表1 , 2和3顯示樣品的資料顯示的使用者分别視圖,使用者互動和導航,數量,即發生在三個星期。 請注意,表使用顔色名稱表示公司使用的社交媒體資源(例如部落格和Facebook頁面)的類型。
表1顯示了每種資源的使用者視圖數量:
表1.每種社交資源的使用者視圖數
社會資源 | 藍色 | 金 | 綠色 | 紅 | 栗色 |
---|---|---|---|---|---|
第一周 | 7057 | 7483 | 3749 | 3846 | 4598 |
第二周 | 2371 | 7397 | 4589 | 2861 | 8249 |
第三周 | 5972 | 5672 | 9152 | 9725 | 8983 |
您可以在表1中看到,在第1周中藍色資源被檢視了7,057次,而黃金資源是該周中檢視次數最多的資源。
表2顯示了使用者互動資料:
表2.在每種社交資源上進行互動的使用者數
社會資源 | 藍色 | 金 | 綠色 | 紅 | 栗色 |
---|---|---|---|---|---|
第一周 | 2052年 | 2089 | 1586 | 1426 | 2632 |
第二周 | 2071 | 2190 | 7214 | 3782 | 2721 |
第三周 | 3076 | 3190 | 4532 | 3825 | 4831 |
從表2中可以看到,第一周有2052個使用者在藍色資源上進行了互動,并且在第一周内,褐紅色資源上的使用者互動度最高。
表3顯示了從藍色資源導航到其他資源的使用者數量:
表3.藍色社交資源的導航資料
社會資源 | 藍金 | 藍綠色 | 藍到紅 | 藍色到栗色 |
---|---|---|---|---|
第一周 | 3057 | 3483 | 8749 | 8456 |
第二周 | 2371 | 7397 | 4589 | 2861 |
第三周 | 5972 | 5672 | 9152 | 9725 |
從表3中可以看到,第1周有3057位使用者通路了藍色資源後,他們導航到黃金資源,紅色資源從藍色資源中獲得了最多的閱聽人。
可視化浏覽資料
與數字表相比,視覺表示提供了一種更輕松,更快捷的方式來解釋大資料量。 表1 ,表2和表3中的資料可以通過多種方式以圖形方式表示。 例如,圖1是顯示表1中第1周資料的簡單方法:
圖1.每個社交資源第1周的觀看次數,以圓圈表示

圖1将每個資源的視圖數表示為一個圓圈。 圓的相對大小與它們表示的數字成比例,是以,觀看最多的資源(金)由最大的圓表示。 每個圓圈還顯示了第1周每種資源獲得的實際觀看次數。
圖2是圖1的略微變體,它使用不同的圓圈布局:
圖2.第1周視圖以不同的圓圈布局顯示
每種資源的普及程度隻是公司要分析的資料的一個次元。 圖3顯示了第1周中每種資源的視圖數和在資源上進行互動的使用者數,以一種直覺的表示形式顯示了二維:
圖3.圓圈内的圓圈顯示了第一周的使用者視圖數量和進行互動的使用者數量
在圖3中 ,外圈代表資源視圖的總數,内圈代表在資源上進行互動的使用者數。 我還在每個圓圈中加了數字,以顯示實際的觀看和互動資料。
圖1 , 2和3層示出了簡單的方法來組合顔色,形狀,和實際的數字來表示資料。 通過檢視圖3 ,您可以看到在第1周中,黃金資源吸引了最多的使用者觀看,栗色資源吸引了最多的互動。
使用開放技術進行資料可視化
動态生成JavaScript以實作可視化
D3,DVG和JavaScript共同構成了一個完整的基于浏覽器的資料可視化套件。 為了示範它們在本系列中的結合使用,我在示例代碼中對示例資料進行了寫死。 實際項目中的大多數JavaScript代碼都是由伺服器端元件動态組合在一起的。 在大資料分析應用程式中,此類元件可能包括基于Apache Hadoop的叢集,托管各種伺服器端子產品的Web和應用程式伺服器以及資料庫伺服器。 使用D3和來自此類來源JavaScript來生成SVG代碼非常适合支援JavaScript的現代業務應用程式,例如IBM Business Process Manager(請參閱參考資料 )。
目前的開放标準和開放源代碼工具功能強大,足以支援資料的圖形表示。 SVG是一種開放的網際網路聯盟(W3C)标準,它定義了一種用于繪制二維圖形對象的基于XML的格式。 (請參閱相關資訊的連結,約SVG的介紹性文章。)SVG是由幾個浏覽器支援。 我在Google Chrome上測試了本文所有的SVG和JavaScript代碼。
如果您正在使用資料和SVG,則D3庫提供了一些魔術。 它會帶走您的資料以及繪圖說明,将資料與所需的SVG标簽相關聯,并立即生成SVG代碼,您可以在浏覽器中檢視它。 當D3繪制複雜的圖形對象時,它使您可以友善地使用資料,是以您可以一次又一步地深入到您的圖形中,并僅處理繪制圖形的每個小部分所需的少量資料。
對于本文和第2部分中的示例,我将從簡單的工程圖過渡到複雜的工程圖,探索D3的功能,并為每個工程圖提供SVG和JavaScript代碼。 我從最簡單的情況開始:SVG代碼生成如圖1所示的圓圈。
SVG資料表示
清單1是用于繪制圖1中的圓圈的SVG代碼:
清單1.繪制圖1中圓圈的SVG代碼
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="1000" height="1000">
<g transform="translate(70,143)">
<circle r="70.57" style="fill: #000fff;"></circle>
<text x="-10" fill="grey">7057</text>
</g>
<g transform="translate(216,143)">
<circle r="74.83" style="fill: #fff555;"></circle>
<text x="-10" fill="grey">7483</text>
</g>
<g transform="translate(329,143)">
<circle r="37.49" style="fill: #aaf000;">
</circle>
<text x="-10" fill="grey">3749</text>
</g>
<g transform="translate(404,143)">
<circle r="38.46" style="fill: #cc0000;"></circle>
<text x="-10" fill="grey">3846</text>
</g>
<g transform="translate(489,143)">
<circle r="45.98" style="fill: #993344;"></circle>
<text x="-10" fill="grey">4598</text>
</g>
</svg>
您可以看到清單1中的根标簽是
<svg>
。
<svg>
标記建立畫布,在該畫布上您可以使用其他SVG标記進行繪制,還可以用作這些标記的包裝。
<svg>
标簽的
width
和
height
屬性指定SVG畫布的尺寸。 我在清單1中設定的畫布是1,000 x 1,000機關。
根
<svg>
标記有五個
<g>
子标記, 圖1中每個圓圈一個。
<g>
标記用作完成每個圓及其随附文本的圖形的包裝。 每個
<g>
标記都有一個名為
transform
屬性,其值是
translate (X, Y)
。
translate (X, Y)
值确定繪制圓的點。 例如, 清單1中第一個
<g>
标記的
transform
屬性将第一個圓的中心置于位置70、143。
五個
<g>
标記中的每個标記對于
transform
屬性均具有不同的
X
值,并且它們均具有相同的
Y
值。 結果,五個圓沿水準線排列。
<g>
标記的不同
X
值會導緻每個圓畫在前一個圓的旁邊,并且中間沒有可見的空格。 稍後,我将向您展示用于生成這些值的簡單JavaScript。
進一步進入清單1 ,請注意,每個
<g>
标記都有兩個子代-一個
<circle>
标記和一個
<text>
标記-分别繪制了圓圈和其随附的文本。 每個
<circle>
标記都有一個
r
屬性,該屬性定義圓的半徑。 請注意,每個
<circle>
标記的
r
屬性的值是按比例縮小100的視圖數。每個
<circle>
标記還具有
style
屬性,該屬性指定填充圓圈的顔色。 我使用六位數的十六進制格式來表示顔色的RGB(紅色,綠色,藍色)代碼。 (參見相關主題上使用顔色的更多細節。)的
<text>
标簽包裝每個圓圈内要被顯示的文本。 我在每個
<text>
标記中包含的
x="-10"
屬性使文本稍微移位以更好地定位。
<text>
标記的
fill
屬性指定文本顔色。
您可以下載下傳本文的所有代碼示例,然後在浏覽器視窗中打開每個代碼示例。 嘗試在清單1中的SVG代碼中添加更多的圓圈或文本,然後檢視浏覽器如何顯示SVG。
使用JavaScript和D3生成SVG
清單2中JavaScript代碼使用D3生成清單1中的SVG代碼:
清單2.使用D3生成圖1的SVG
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
//Step 1:
var views = [
[7057, 7483, 3749, 3846, 4598],
[ 2371, 7397, 4589, 2861, 8249],
[ 5972, 5672, 9152, 9725, 8983],
];
var width = 1000, height = 1000;
var colors = [ "blue",
"yellow",
"green",
"red",
"maroon"
];
var week = 0;
//Step 2:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
//Step 3:
.selectAll("g")
.data(views[week])
.enter();
//Step 4:
var g = svg.append("g")
//Step 5:
.attr("transform", function(d,i){
var x = 0;
for (var count=0;
count<i;
count++ )
x+=views[week][count];
for (var count=0;
count<=i;
count++ )
x+=views[week][count];
return "translate(" + x/100 + "," + height / 7 + ")" }
);
//Step 6:
g.append("circle")
.attr("r", function(d){return d/100})
.style("fill", function(d, i){return colors[i];});
g.append("text")
.attr("x", -10)
.attr("fill", "grey")
.text(function(d){return d});
</script>
</body>
我添加了注釋以訓示清單2中的步驟:
步驟1 :第一步是将使用者視圖資料存儲在數組中。 我還設定了一些變量來存儲畫布的尺寸和要在SVG繪圖中使用的顔色。
步驟2:我開始将D3與
d3.select("body").append("svg")
,這會将
<svg>
标記添加到HTML頁面的主體中。 在這裡,我還通過調用
.attr()
函數來設定SVG畫布的寬度和高度。
步驟3 :這三個函數調用
.selectAll().data().enter()
一起形成了D3帶來的強度和易用性:
-
調用選擇根SVG标記的所有.selectAll("g")
子标記。 盡管它現在無法選擇任何内容(因為不存在),但它知道我要查找的内容。<g>
-
調用将所有五種社交資源的一周使用者浏覽資料提供給D3。.data(views[week])
-
調用将各個.enter()
标記與各個使用者視圖資料記錄相關聯。<g>
步驟4 :
.append("g")
調用告訴D3 添加足夠的
<g>
标簽,以便為資料中的每個記錄提供一個
<g>
标簽 。 因為開始時不存在
<g>
标簽,并且資料數組中的每個星期都有五條記錄(每個社交資源一個),是以D3将五個
<g>
标簽添加到根
<svg>
标簽中。 第一個
<g>
标記在内部與第一個資料記錄(即views-data數組中的7057)關聯,第二個
<g>
标記與第二個記錄在内部關聯,依此類推。 D3在内部将資料與SVG标簽相關聯,是以我在創作時隻需要傳遞一次資料數組,而不必擔心将正确的資料與每個單獨的SVG标簽相關聯。
步驟5 :我還必須為五個
<g>
标簽的每一個添加一個
transform
屬性,是以我調用
.attr()
函數。 我隻需要調用一次,D3在内部處理循環,以確定将
transform
屬性添加到五個
<g>
标簽的每個标簽中。
.attr()
函數将要編寫的屬性的名稱(在本例中為
transform
)作為其第一個參數。 回想一下清單1的讨論,
transform
屬性決定了圓的位置,是以必須在函數中計算其值。 是以,
.attr()
函數的第二個參數是另一個函數調用,該函數本身具有兩個參數:
d
和
i
。
D3為您提供了進行函數調用的機會,因為在編寫屬性值時可能需要與
<g>
标記關聯的資料。
d
參數儲存您正在為其為其編寫
transform
屬性值的特定
<g>
标記的資料(例如,對于與表示藍色使用者視圖的記錄相關聯的第一個
<g>
标記為7057)社會資源)。 D3的神奇之處在于,它内部處理與單個标簽相關的正确資料關聯,是以您不必擔心選擇正确的資料。 D3的神奇之處在于,它内部處理與單個标簽相關的正确資料關聯,是以您不必擔心選擇正确的資料。 在創作SVG時,您可以專注于資料處理。
i
參數是資料的從零開始的索引(例如,對于與第一條記錄相關聯的第一個
<g>
标記,
i
= 0)。 您可以在此步驟中看到,我使用
i
參數計算
<g>
标簽的适當位置,進而在最左側繪制了第一個(藍色)社交資源的圓圈,然後繪制了與第一個圓圈相鄰的第二個圓圈, 等等。
如果僅嘗試運作步驟1-5的代碼,則會看到五個
<g>
子标記以及
transform
屬性,如清單3的SVG代碼所示。(這些
<g>
标記不會在浏覽器中顯示圖形)視窗呢。)
清單3.僅帶有五個 <g>
标簽的SVG代碼
<g>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="1000" height="1000">
<g transform="translate(70,143)">
</g>
<g transform="translate(216,143)">
</g>
<g transform="translate(329,143)">
</g>
<g transform="translate(404,143)">
</g>
<g transform="translate(489,143)">
</g>
</svg>
步驟6 :剩下的任務是向五個
<g>
标簽的每一個添加
<circle>
标簽和
<text>
<g>
标簽。 為此,您需要兩次調用
.append()
函數(對于
<circle>
一次,對于
<text>
标簽一次)。
請注意,我使用
.attr("r", function(d){return d/100})
來建立圓的
r
屬性(半徑)。 在這種情況下,我必須隻知道特定資源的視圖數才能繪制成比例的圓。 這就是為什麼我隻需要
d
參數而不需要
i
參數的原因,是以我省略了
i
。
d
參數自動包含正确的資料(視圖數),是以我将d的值除以100以縮放圓的大小。
基于D3JavaScript代碼已準備就緒,可以繪制圖1的圓圈。 如果從浏覽器視窗中的示例代碼下載下傳中打開Listing2.html,您會看到它生成了清單1的SVG并顯示了圖1的圓圈。
圓的布局略有不同
您可以稍微修改清單2中的代碼以繪制如圖2所示的圓的布局。 清單4顯示了修改後JavaScript:
清單4.用于繪制圖2布局的修改後的代碼
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var views = [
[7057, 7483, 3749, 3846, 4598],
[ 2371, 7397, 4589, 2861, 8249],
[ 5972, 5672, 9152, 9725, 8983],
[ 9763, 8462, 9782, 1953, 5182],
[ 9567, 1571, 2895, 2783, 1874],
[ 2371, 7397, 4589, 2861, 8249]
];
var width = 1000, height = 1000;
var colors = [ "#0000ff", //blue
"#ffd700", //gold
"#008000", //green
"#ff0000", //red
"#800000" //maroon
];
var week = 0, scale = 100;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.selectAll("g").data(views[week]).enter();
var g = svg.append("g")
.attr("transform", function(d,i){
var x = 10000, y = 10000;
if (!(i%2)){
for (var count=0;
count<i;
count++)
x+=views[week][count];
for (var count=0;
count<=i;
count++)
y+=views[week][count];
} else {
for (var count=0;
count<i;
count++)
y+=views[week][count];
for (var count=0;
count<=i;
count++)
x+=views[week][count];
}
return "translate(" + x/scale + "," + y/scale + ")"}
);
g.append("circle")
.attr("r", function(d){return d/scale})
.style("fill", function(d, i){return colors[i];});
g.append("text")
.attr("x", -10)
.attr("fill", "grey")
.text(function(d){return d});
</script>
</body>
通過将清單2與清單4進行比較,您可以看到修改在于
transform
屬性值的計算, 清單4中以粗體突出顯示了該屬性。
圍成一圈
現在看清單5,它是用于繪制圖3的圓的SVG代碼(圓内的圓同時表示視圖和互動資料):
清單5.圖3的SVG代碼
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="1000" height="1000">
<g transform="translate(100,170.57)">
<circle r="70.57" style="fill: #0000ff;">
</circle>
<circle r="20.52" style="fill: #add8e6;">
</circle>
<text x="-15" y="35.52" fill="white">7057</text>
<text x="-15" y="5">2052</text>
</g>
<g transform="translate(245.4,170.57)">
<circle r="74.83" style="fill: #ffd700;">
</circle>
<circle r="20.89" style="fill: #ffff00;">
</circle>
<text x="-15" y="35.89" fill="white">7483</text>
<text x="-15" y="5">2089</text>
</g>
<g transform="translate(245.4,282.89)">
<circle r="37.49" style="fill: #008000;"></circle>
<circle r="15.86" style="fill: #90ee90;"></circle>
<text x="-15" y="30.86" fill="white">3749</text>
<text x="-15" y="5">1586</text>
</g>
<g transform="translate(321.35,282.89)">
<circle r="38.46" style="fill: #ff0000;"></circle>
<circle r="14.26" style="fill: #f08080;"></circle>
<text x="-15" y="29.26" fill="white">3846</text>
<text x="-15" y="5">1426</text>
</g>
<g transform="translate(321.35,367.33)">
<circle r="45.98" style="fill: #800000;"></circle>
<circle r="26.32" style="fill: #cd5c5c;"></circle>
<text x="-15" y="41.32" fill="white">4598</text>
<text x="-15" y="5">2632</text>
</g>
</svg>
您可以看到清單5在每個
<g>
标記内有兩個
<circle>
和兩個
<text>
标記,而清單1僅具有一對
<circle>
和
<text>
标記。 這很容易了解,因為圖3必須繪制兩個具有相同中心的圓以給出一個圓内的圓的視圖,并且兩個圓中的每個圓都有一個與之關聯的數字。
清單6顯示了用于生成圖3的基于D3JavaScript代碼:
清單6.用于繪制圖3JavaScript
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var viewsAndInteraction = [
[ [7057, 2052], [7483, 2089], [3749, 1586],
[3846, 1426], [4598, 2632] ],
[ [5972, 2071], [5672, 2190], [9152, 7214],
[9725, 3782], [8983, 2721] ],
[ [8749, 3076], [4768, 3190], [6738, 4532],
[9546, 3825], [6983, 4831] ]
];
var width = 1000, height = 1000;
var viewColors = [ "blue",
"gold",
"green",
"red",
"maroon"
];
var interactionColors = [ "lightblue",
"yellow",
"lightgreen",
"lightcoral",
"indianred"
];
var week = 0, scale = 100;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.selectAll("g")
.data(viewsAndInteraction[week])
.enter();
var g = svg.append("g")
.attr("transform", function(d,i){
var x = 10000, y = 10000;
if (!(i%2)){
for (var count=0;
count<i;
count++)
x+=viewsAndInteraction[week][count][0];
for (var count=0;
count<=i;
count++)
y+=viewsAndInteraction[week][count][0];
} else {
for (var count=0;
count<i;
count++)
y+=viewsAndInteraction[week][count][0];
for (var count=0;
count<=i;
count++)
x+=viewsAndInteraction[week][count][0];
}
return "translate(" + x/scale + "," + y/scale + ")"}
);
g.append("circle")
.attr("r", function(d){return d[0]/scale})
.style("fill", function(d, i){return viewColors[i];});
g.append("circle")
.attr("r", function(d){return d[1]/scale})
.style("fill", function(d, i){return interactionColors[i];});
g.append("text")
.attr("x", -15)
.attr("y", function(d){return (15 + d[1]/scale);})
.attr("fill", "white")
.text(function(d){return d[0]});
g.append("text")
.attr("x", -15)
.attr("y", 5)
.text(function(d){return d[1]});
</script>
</body>
如果将清單2中JavaScript與清單6中的代碼進行比較,您會發現幾乎所有内容都是相同的。 差別在于清單6 :
- 您必須使用視圖和互動資料,是以
數組同時包含視圖和互動資料。viewsAndInteraction
- 有兩對
和g.append("circle")
函數調用可繪制兩個圓,每個圓都與文本位于同一中心。g.append("text")
現在,您已經看到了所有三個圖的SVG和JavaScript。 下一個示例将導航資料可視化。
可視化導航資料表示
圖4使用不同顔色的圓弧和弦顯示了第一周的一些導航資料:從藍色資源導航到其他資源的使用者數量:
圖4.彩色圓弧和弦顯示導航資料
圖4中的彩色弧線代表不同的社會資源。 藍色資源通過和弦連接配接到所有其他資源。 每個和弦代表導航。
藍色和弦在藍色資源處開始和結束,代表開始在藍色資源處浏覽并且不進一步浏覽的使用者數量。 從藍色資源開始到黃金資源結束的金和弦代表從藍色資源導航到金資源的使用者數量。 同樣, 圖4描述了從藍色資源到其餘資源的導航。
請注意,和弦(從藍色開始)按升序排列,首先由較小的和弦代表較少的使用者。 是以,您無需數字即可檢視哪些資源吸引了更多使用者。
使用SVG繪制弧線和弦
清單7顯示了繪制圖4的部分SVG代碼:
清單7.用于繪制圖4的部分SVG代碼
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="500" height="500">
<g transform="translate(250,250)">
<path style="fill: #0000ff;"
d="M1.1633760361312584e-14,-190A190,190 0 0,1
177.80498922385382,-66.97302298019123L140.372
3599135688,-52.873439194887816A150,150 0 0,0
9.18454765366783e-15,-150Z"></path>
<path style="fill: #ffd700;"
d="M177.80498922385382,-66.97302298019123A190,190 0 0,1
141.9432774826573,126.30164677264251L112.06048222315049,99
.71182639945462A150,150 0 0,0 140.3723599135688,-
52.873439194887816Z"></path>
<path style="fill: #008000;"
d="M141.9432774826573,126.30164677264251A190,190 0 0,1 -
141.87314929322426,126.38041584684909L-
112.00511786307179,99.77401251067033A150,150 0 0,0
112.06048222315049,99.71182639945462Z"></path>
<path style="fill: #ff0000;"
d="M-141.87314929322426,126.38041584684909A190,190 0
0,1 -136.03537960886078,-132.64379176830383L-
107.39635232278484,-104.7187829749767A150,150 0 0,0 -
112.00511786307179,99.77401251067033Z"></path>
<path style="fill: #800000;"
d="M-136.03537960886078,-132.64379176830383A190,190 0 0,1 -
3.7240908056998534e-13,-190L-2.9400716887104106e-13,-
150A150,150 0 0,0 -107.39635232278484,-
104.7187829749767Z"></path>
<g>
<!--Drawing SVG code for chords goes here. -->
</g>
</g>
</svg>
您可以看到清單7中的根
<svg>
标記有一個
<g>
子标記,而子标記又有五個
<path>
标記和另一個内部
<g>
子标記。 五個
<path>
标記繪制五個彩色弧。 内部的
<g>
标記包裝用于繪制和弦的SVG代碼,我将在稍後解釋。 首先,我解釋
<path>
标記如何繪制五個弧。
繪制一組彩色弧
使用SVG
<path>
标簽可以很容易地繪制一組具有适當顔色的弧,其目的是定義繪制路徑,就像用筆在紙上繪制一樣。 路徑可以是封閉的(例如,三角形)或開放的(例如,一組互連的線)。 您需要一條閉合的路徑來繪制圓弧,如圖5所示:
圖5.用 <path>
标簽繪制弧
<path>
在圖5中 ,圓弧的封閉路徑的周長用黑色繪制,封閉路徑用黃色填充。 如果用筆繪制此弧,則将繪制兩條彎曲的曲線和兩條黑色的直線,然後用黃色填充内部。
圖4中的五個弧形中的每一個均使用相同的顔色作為其外圍并填充其閉合路徑。 是以,您需要五個
<path>
标簽,每個圓弧對應一個。
在清單7中 ,您可以看到五個
<path>
标記中的每個标記都有兩個屬性:
style
和
d
。
style
屬性定義用于繪制的顔色,
d
屬性定義繪制路徑。
d
屬性的值(例如
M8.572244476756641e-15,-140A140,140 0 0,1 93.95877067680189,103.78703875197591L67.11340762628707,74.13359910855422A100,100 0 0,0 6.123031769111886e-15,-100Z
看起來很長并且複雜。 官方SVG規範要求使用此格式來定義該值,以定義确切的繪制路徑。
格式包括
M
後跟兩個逗号分隔的數字,然後是
A
然後是數個數字,然後是
L
然後是兩個逗号分隔的數字,然後是另一個
A
然後是數個數字,最後是
Z
此序列的裝置:M OVE由後的數字定義的點
M
,然後繪制由數字定義的A RC之後
A
,然後繪制A L INE到由号碼之後定義的點
L
,然後繪制另一個甲 RC(第二圓弧)。 末端裝置中的
Z
傳回初始位置 ,進而形成閉合路徑。
好消息是,您無需了解有關此序列如何精确繪制所需圓弧的更多詳細資訊-因為所有這些值都是使用D3庫計算的,該庫包含用于繪制複雜圖形的易于使用的功能。 稍後,我将向您展示D3 JavaScript代碼,該代碼執行所有繪圖計算并動态生成圖4的完整SVG代碼。
每個圓的五個
<path>
标記都是繪制弧所需要的。 在浏覽器中打開Listing7.svg檔案(請參閱下載下傳 ),檢視沒有任何弦的彩色弧,如圖6所示:
圖6.彩色弧
現在,我将展示如何繪制和弦來表示導航。
繪制和弦
像弧一樣,用一個
<g>
标記繪制和弦,該标記是五個
<path>
标記的包裝,每個和弦一個,如清單8所示:
清單8.用于繪制五個和弦的SVG代碼
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="500" height="500">
<g transform="translate(250,250)">
<!--Drawing SVG code for arcs goes here. -->
<g>
<path d="M9.18454765366783e-15,-150A150,150 0 0,1
19.52349842170555,-148.72401624948697Q 0,0
9.18454765366783e-15,-150Z"
style="fill: #0000ff;">
</path>
<path d="M19.52349842170555,- 148.72401624948697A150,150
0 0,1 41.344235247425466,-144.18964668729006Q 0,0
140.3723599135688,-52.873439194887816A150,150 0 0,1
144.99722485611238,-38.41620470616511Q 0,0
19.52349842170555,-148.72401624948697Z"
style="fill: #ffd700;">
</path>
<path d="M111.39598065576133,-100.4536484839712A150,150
0 0,1 140.3723599135688,-52.873439194887816Q 0,0
84.8772338498757,123.67641316756206A150,150 0 0,1
50.93706344958661,141.08655345968583Q 0,0
111.39598065576133,-100.4536484839712Z"
style="fill: #008000;">
</path>
<path d="M-149.71409635840777,9.256854302914952A150,150
0 0,1 -140.64142529945457,-52.15351847898602Q 0,0
68.6764412000974,-133.35496400243062A150,150 0 0,1
111.39598065576133,-100.4536484839712Q 0,0 -
149.71409635840777,9.256854302914952Z"
style="fill: #ff0000;">
</path>
<path d="M-59.58349836433014,-137.65829696268898A150,150
0 0,1 -1.6078040591602227e-13,-150Q 0,0
41.344235247425466,-144.18964668729006A150,150 0 0,1
68.6764412000974,-133.35496400243062Q 0,0 -
59.58349836433014,-137.65829696268898Z"
style="fill: #800000;">
</path>
</g>
</g>
</svg>
您可以看到清單8中所有和弦的
<path>
标記(如清單7中的标記)對于要由D3計算的
d
屬性具有一個長而複雜的值。
清單8省略了弧的
<path>
标記。 如果在浏覽器中檢視清單8中的SVG代碼,您将看到沒有弧的和弦(是以也沒有圓的周長),如圖7所示:
圖7.五組不帶圓弧的和弦
現在,我将向您展示用于生成圖4的SVG代碼的基于D3JavaScript代碼。
使用D3繪制帶有和弦的圓圈
您可以在清單9JavaScript代碼中看到五個步驟,該步驟使用D3編寫圖4的SVG:
清單9.生成圖4中的SVG代碼的五個步驟
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
//Step 1:
var navigation = [
[3057, 3483, 8749, 8465, 4598],
[ 2371, 7397, 4589, 2861, 8249],
[ 5972, 5672, 9152, 9725, 8983],
[ 9763, 8462, 9782, 1953, 5182],
[ 9567, 1571, 2895, 2783, 1874]
];
var navigationChord = d3.layout.chord()
.matrix(navigation);
var chordCalculations = navigationChord.chords;
var colors = [ "blue",
"gold",
"green",
"red",
"maroon"
];
var width = 500, height = 500, radius = 150, arcStroke = 40;
//Step 2:
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
//Step 3:
.append("g")
.attr("transform", function(d,i){
return "translate(" + width/2 + "," + height / 2 + ")"
});
//Step 4:
svg.selectAll("path")
.data(navigationChord.groups())
.enter()
.append("path")
.style("fill", function(d, i) { return colors[i]; })
.attr("d", d3.svg.arc().innerRadius(radius)
.outerRadius(radius+arcStroke));
//Step 5:
navigationChord.sortSubgroups(d3.ascending);
svg.append("g")
.selectAll("path")
.data(chordCalculations)
.enter()
.append("path")
.attr("d", d3.svg.chord().radius(radius))
.style("fill", function(d, i) {
if (i < colors.length) return colors[i]})
.style("opacity", function(d, i){
if (!(i < colors.length)) return 0 });
</script>
</body>
步驟1存儲資料并設定變量。 我将導航資料存儲在一個名為
navigation
的數組中,然後将其傳遞給内部處理布局的
d3.layout
。 我将
d3.layout
完成的計算存儲在名為
chordCalculations
的變量中,該變量在第5步中用于繪制和弦。
步驟2是編寫
<svg>
包裝器并設定其尺寸。
步驟3是添加
<g>
标記,用作所有圖形标記的包裝。
步驟4為您在清單7中看到的SVG代碼的弧線建立了五個
<path>
标記。 使用
d3.svg.arc()
,它在内部進行所有計算,以為彩色弧的所有五個
<path>
标簽建立
d
屬性的值。
步驟5編寫和弦的
<path>
标記。 我首先将和弦按升序排列,然後将和弦計算傳遞到D3的四個神奇步驟:
.selectAll().data().enter().append()
。 最後,
d3.svg.chord()
繪制五個和弦的
<path>
标記的
d
屬性的值。
下次
在本文中,我為發現SVG和D3協同工作的全部圖形功能奠定了基礎。 第2部分展示了D3布局的優勢,它可以執行圖形計算以在單個SVG畫布上繪制形狀的多個副本。 它還顯示了如何繪制流行度,使用者互動和導航資料的圖表表示形式。 最後,我向您展示如何在單個SVG工程圖中将圓,弧,和弦,圖表和布局放在一起。
翻譯自: https://www.ibm.com/developerworks/opensource/library/os-dataviz1/index.html
svg 可視化操作