[知识图谱实战篇] 六.HTML+D3实现点击节点显示相关属性及属性值
前面作者講解了很多知識圖譜原理知識,包括知識圖譜相關技術、Neo4j繪制關系圖譜等,但仍缺少一個系統全面的實例。為了加深自己對知識圖譜構建的認識,為后續創建貴州旅游知識圖譜打下基礎,作者深入學習了張宏倫老師的網易云課程(星球系列電影),并結合自己的理解和技術分享了該系列專欄,從數據采集、數據展示、數據分析到知識圖譜構建,文章后續還會講解中文數據的實體識別、關系抽取、知識計算等。
前文介紹了Python3抓取電影實體知識,Seaborn可視化展示電影信息,D3可視化布局,關系圖譜基本構建。本篇文章將實現點擊節點顯示其相關的屬性及屬性值,通常在知識圖譜中稱之為消息盒(InfoBox)展示,如下圖所示:
<實體,屬性,屬性值>三元組
<實體A,關系,實體B>三元組
代碼下載地址:https://download.csdn.net/download/eastmount/10957228
Github下載地址:https://github.com/eastmountyxz/Knowledge-Graph-Movie
這是一系列基礎性文章,希望對您有所幫助 ,尤其是對知識圖譜感興趣和編程剛入門的同學。同時也因為最近準備博士考試,做題做吐了,寫點新專欄調節下心情,與君共勉,一起加油。
前文:
[知識圖譜實戰篇] 一.數據抓取之Python3抓取JSON格式的電影實體
[知識圖譜實戰篇] 二.Json+Seaborn可視化展示電影實體
[知識圖譜實戰篇] 三.Python提取JSON數據、HTML+D3構建基本可視化布局
[知識圖譜實戰篇] 四.HTML+D3+CSS繪制關系圖譜
[知識圖譜實戰篇] 五.HTML+D3添加鼠標響應事件顯示相關節點及邊
文章目錄
- 一.Python3獲取詳細Json數據
- 二.D3獲取并顯示屬性-屬性值
- 三.CSS設置文本樣式
- 四.HTML完整代碼
推薦作者的知識圖譜前文:
知識圖譜相關會議之觀后感分享與學習總結
中文知識圖譜研討會的學習總結 (上) 圖譜引入、百度知心、搜狗知立方
搜索引擎和知識圖譜那些事 (上).基礎篇
基于VSM的命名實體識別、歧義消解和指代消解
CSDN下載-第一屆全國中文知識圖譜研討會演講PPT 清華大學
CSDN下載-知識圖譜PDF資料 清華大學知識圖譜研討會匯報PPT
[知識圖譜構建] 一.Neo4j圖數據庫安裝初識及藥材供應圖譜實例
[知識圖譜構建] 二.《Neo4j基礎入門》基礎學習之創建圖數據庫節點及關系
[關系圖譜] 一.Gephi通過共線矩陣構建知網作者關系圖譜
[關系圖譜] 二.Gephi導入共線矩陣構建作者關系圖譜
再次強烈推薦大家閱讀張宏倫老師的網易云課程及Github源碼,受益匪淺。
https://github.com/Honlan/starwar-visualization/tree/master/star_war
https://study.163.com/course/courseLearn.htm?courseId=1003528010
一.Python3獲取詳細Json數據
首先定義Python3代碼獲取電影所有完整數據,主要采用字典鍵值對的形式。代碼如下:
# coding:utf8 import json#獲取所有節點的數據 data = {}#讀取電影數據 fr = open('films.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n')) #轉換為字典data[tmp['title']] = tmpprint(tmp['title'], tmp) fr.close()#讀取人物數據 fr = open('film_characters.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n'))data[tmp['name']] = tmp fr.close()#讀取星球數據 fr = open('film_planets.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n'))data[tmp['name']] = tmp fr.close()#讀取飛船數據 fr = open('film_starships.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n'))data[tmp['name']] = tmp fr.close()#讀取裝備數據 fr = open('film_vehicles.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n'))data[tmp['name']] = tmp fr.close()#讀取物種數據 fr = open('film_species.csv', 'r') for line in fr:tmp = json.loads(line.strip('\n'))data[tmp['name']] = tmp fr.close()#寫文件 fw = open("all_data.json", "w") fw.write(json.dumps(data)) fw.close()運行過程中輸出的結果如下所示:
上述代碼將獲取六大實體的所有信息存儲至 all_data.json 文件中,采用 data[tmp[‘name’]]=tmp 賦值變量data。接著將該json文件放入html目錄中,供其調用。
二.D3獲取并顯示屬性-屬性值
接著通過HTML和D3加載數據,調用Python3獲取的 all_data.json 文件。
1.d3.json加載數據
//加載Python獲取的Json信息:六類實體詳細屬性信息 var info;//d3.json獲取數據 d3.json("all_data.json", function(error, data) {if(error) throw error;info = data; });2.HTML設置info布局信息,添加標題 < h4 > < / h4 > 樣式代碼
<!-- 繪制右邊顯示結果 --> <div id="info"><h4></h4> </div>3.然后在鼠標懸浮代碼中增加代碼,實現文字顯示
定位到如下圖所示的位置:
增加相關代碼,它的主要功能包括:
1.設置#info h4樣式,包括顏色及文字,選中節點的name和顏色記為展示的內容。
2.循環遍歷所有info信息,并通過 $(’#info’).append() 函數展示該節點的屬性及屬性值。
代碼如下圖所示:
此時,能夠顯示了選中節點的屬性-屬性值,顯示如下圖所示,但是其顏色和布局均未設置,后續將通過CSS進行設置。
同時,打開瀏覽器的Console也能查看對應節點的信息,通過 console.log(info[name]) 打印。
三.CSS設置文本樣式
接著通過CSS設置Info和標題h4樣式,代碼如下:
- 設置info樣式:絕對定位、距離底部40個像素、距離右邊30個像素、文本右居中、寬度設置。
- 設置info中的p布局字段:顏色、字體、間距。
- 設置span布局和h4布局。
再將HTML文件和JSON文件放置服務器中,作者的本地服務器位于Apache下的路徑 C:\xampp\htdocs\KG 下,最終的運行結果如下所以:
四.HTML完整代碼
完整代碼如下:
<!DOCTYPE html> <html><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>知識圖譜</title><meta name="description" content="" /><meta name="keywords" content="" /><meta name="author" content="" /><link rel="shortcut icon" href=""><script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script><link href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"><script src="http://cdn.bootcss.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> </head> <style type="text/css"> body {background-color: #272b30;padding: 30px 40px;text-align: center;font-family: OpenSans-Light, PingFang SC, Hiragino Sans GB, Microsoft Yahei, Microsoft Jhenghei, sans-serif; }#indicator {position: absolute; left: 60px;bottom: 120px;text-align: left;color: #f2f2f2;font-size: 12px; }#indicator>div {margin-bottom: 4px; }#indicator span {display: inline-block;width: 30px;height: 14px;position: relative;top: 2px;margin-right: 8px; }.links line {stroke: rgb(240, 240, 240); stroke-opactity: 0.2; }.links line.inactive {/*display: none !important;*/stroke-opacity: 0; }.nodes circle {stroke: #fff;stroke-width: 1.5px; }.nodes circle:hover {cursor: pointer; }.nodes circle.inactive {display: none !important; }.texts text {display: none; }.texts text:hover {cursor: pointer; }.texts text.inactive {display: none !important; }#mode {position: absolute;top: 160px;left: 60px; }#mode span {display: inline-block;border: 1px solid #fff;color: #fff;padding: 6px 10px;border-radius: 4px;font-size: 14px;transition: color, background-color .3s;-o-transition: color, background-color .3s;-ms-transition: color, background-color .3s;-moz-transition: color, background-color .3s;-webkit-transition: color, background-color .3s; }#mode span.active, #mode span:hover {background-color: #fff;color: #333;cursor: pointer; }#info {position: absolute;bottom: 40px;right: 30px;text-align: right;width: 270px; }#info p {color: #fff;font-size: 12px;margin-top: 0;margin-bottom: 5px; }#info p span {color: #888;margin-right: 10px; }#info h4 {color: #fff; }</style> <body><!-- 繪制標題樣式 --><h1 style="color:#fff;font-size:32px;margin-bottom:0px;text-align:center;margin-left:40px;">Star Wars</h1><!-- 第一個布局 繪制知識圖譜主圖 --><div style="text-align: center; position:relative;"><svg width="800" height="560" style="margin-right:80px;margin-bottom:-40px;" id="svg1"></svg><!-- 繪制圖例 --><div id="indicator"></div><!-- 繪制模式選擇 --><div id="mode"><span class="active" style="border-top-right-radius:0;border-bottom-right-radius:0;">節點</span><span style="border-top-left-radius:0;border-bottom-left-radius:0;position:relative;left:-5px;">文字</span></div><!-- 繪制搜索框 --><div id="search"></div><!-- 繪制右邊顯示結果 --><div id="info"><h4></h4></div></div><!-- 第二個布局 下部分時間點 文本居中 相對定位--><div style="text-align: center; position:relative;"><svg width="960" height="240" style="margin-right:60px;margin-bottom:-40px;" id="svg1"><g></g></svg></div></body><!-- 增加D3元素庫 --> <script src="https://d3js.org/d3.v4.min.js"></script> <!-- 補充JS代碼 --> <script type="text/javascript">$(document).ready(function() {//定義svg變量將布局svg1選出來 var svg = d3.select("#svg1"), width = svg.attr("width"), height = svg.attr("height");//定義name變量制作圖標var names = ['Films', 'Characters', 'Planets', 'Starships', 'Vehicles', 'Species'];var colors = ['#6ca46c', '#4e88af', '#ca635f', '#d2907c', '#d6744d', '#ded295'];//背景顏色設置 補充CSS樣式設置字體布局for (var i=0; i < names.length; i++) {$('#indicator').append("<div><span style='background-color:" + colors[i] + "'></span>" + names[i] + "</div>");}//利用d3.forceSimulation()定義關系圖 包括設置邊link、排斥電荷charge、關系圖中心點var simulation = d3.forceSimulation().force("link", d3.forceLink().id(function(d) {return d.id;})).force("charge", d3.forceManyBody()).force("center", d3.forceCenter(width / 2, height / 2));//存儲關系圖的數據var graph;//定義d3.json請求python處理好的節點及邊 請求成功返回數據,否則報錯d3.json("starwar_alldata.json", function(error, data) {if(error) throw error;graph = data;console.log(graph);//D3映射數據至HTML中//g用于繪制所有邊,selectALL選中所有的line,并綁定數據data(graph.links),enter().append("line")添加元素//數據驅動文檔,設置邊的粗細//前面定義var svg = d3.select("#svg1")var link = svg.append("g").attr("class","links").selectAll("line").data(graph.links).enter().append("line").attr("stroke-width", function(d) {//return Math.sqrt(d.value);return 1; //所有線寬度均為1});//添加所有的點//selectAll("circle")選中所有的圓并綁定數據,圓的直徑為d.size//再定義圓的填充色,同樣數據驅動樣式,圓沒有描邊,圓的名字為d.id//call()函數:拖動函數,當拖動開始綁定dragstarted函數,拖動進行和拖動結束也綁定函數var node = svg.append("g").attr("class", "nodes").selectAll("circle").data(graph.nodes).enter().append("circle").attr("r", function(d) {return d.size;}).attr("fill", function(d) {return colors[d.group];}).attr("stroke", "none").attr("name", function(d) {return d.id;}).call(d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended));//顯示所有的文本 //設置大小、填充顏色、名字、text()設置文本//attr("text-anchor", "middle")文本居中var text = svg.append("g").attr("class", "texts").selectAll("text").data(graph.nodes).enter().append("text").attr("font-size", function(d) {return d.size;}).attr("fill", function(d) {return colors[d.group];}).attr('name', function(d) {return d.id;}).text(function(d) {return d.id;}).attr('text-anchor', 'middle').call(d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended));//圓增加titlenode.append("title").text(function(d) {return d.id;})//simulation中ticked數據初始化,并生成圖形simulation.nodes(graph.nodes).on("tick", ticked);simulation.force("link").links(graph.links);//ticked()函數確定link線的起始點x、y坐標 node確定中心點 文本通過translate平移變化function ticked() {link.attr("x1", function(d) {return d.source.x;}).attr("y1", function(d) {return d.source.y;}).attr("x2", function(d) {return d.target.x;}).attr("y2", function(d) {return d.target.y;});node.attr("cx", function(d) {return d.x;}).attr("cy", function(d) {return d.y;});text.attr('transform', function(d) {return 'translate(' + d.x + ',' + (d.y + d.size / 2) + ')';});}});// Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension// 本地json數據需要放置服務器中請求 XAMPP//該變量保證拖動鼠標時,不會影響圖形變換,默認為false未選中鼠標var dragging = false;//開始拖動并更新相應的點function dragstarted(d) {if (!d3.event.active) simulation.alphaTarget(0.3).restart();d.fx = d.x;d.fy = d.y;dragging = true;}//拖動進行中function dragged(d) {d.fx = d3.event.x;d.fy = d3.event.y;}//拖動結束function dragended(d) {if (!d3.event.active) simulation.alphaTarget(0);d.fx = null;d.fy = null;dragging = false;}//span點擊事件$('#mode span').click(function(event) {//span都設置為不激活狀態$('#mode span').removeClass('active');//點擊的span被激活$(this).addClass('active');//text隱藏 nodes顯示if ($(this).text() == '節點') {$('.texts text').hide();$('.nodes circle').show();} else {$('.texts text').show();$('.nodes circle').hide();}});//為svg1父元素下的.nodes circle元素綁定鼠標進入事件$('#svg1').on('mouseenter', '.nodes circle', function(event) {//通過變量dragging保證拖動鼠標時,其狀態不受影響,從而改變圖形//鼠標沒有拖動才能處理事件if(!dragging) {//獲取被選中元素的名字var name = $(this).attr("name");//設置#info h4樣式的顏色為該節點的顏色,文本為該節點name//$(this).attr('fill')表示當前懸浮圓的填充色$('#info h4').css('color', $(this).attr('fill')).text(name);//每次點擊添加屬性前把上次顯示的信息去除,否則會不斷疊加$('#info p').remove();//打印懸浮的節點信息console.log(info[name]);//遍歷所有的for (var key in info[name]) {//類型復雜的不進行顯示if (typeof(info[name][key]) == 'object') {continue;}//比較復雜的超鏈接字段不顯示if (key == 'url' || key == 'title' || key == 'name' || key == 'edited' || key == 'created' || key == 'homeworld') {continue;}//顯示值及其字段名字$('#info').append('<p><span>' + key + '</span>' + info[name][key] + '</p>');}//選擇#svg1 .nodes中所有的circle,再增加個classd3.select('#svg1 .nodes').selectAll('circle').attr('class', function(d) {//數據的id是否等于name,返回空if(d.id==name) {return '';} //當前節點返回空,否則其他節點循環判斷是否被隱藏起來(CSS設置隱藏)else {//links鏈接的起始節點進行判斷,如果其id等于name則顯示這類節點//注意: graph=datafor (var i = 0; i < graph.links.length; i++) {//如果links的起點等于name,并且終點等于正在處理的則顯示if (graph.links[i]['source'].id == name && graph.links[i]['target'].id == d.id) {return '';}if (graph.links[i]['target'].id == name && graph.links[i]['source'].id == d.id) {return '';}}return "inactive"; //前面CSS定義 .nodes circle.inactive}});//處理相鄰的邊line是否隱藏 注意 || d3.select("#svg1 .links").selectAll('line').attr('class', function(d) {if (d.source.id == name || d.target.id == name) {return '';} else {return 'inactive';}});}});//鼠標移開還原原圖,顯示所有隱藏的點及邊$('#svg1').on('mouseleave', '.nodes circle', function(event) {//如果dragging為false才處理事件if(!dragging) {d3.select('#svg1 .nodes').selectAll('circle').attr('class', '');d3.select('#svg1 .links').selectAll('line').attr('class', '');} });//鼠標進入文本顯示相鄰節點及邊$('#svg1').on('mouseenter', '.texts text', function(event) {if (!dragging) {var name = $(this).attr('name');//同樣的代碼從選中圓中賦值過來$('#info h4').css('color', $(this).attr('fill')).text(name);$('#info p').remove();for (var key in info[name]) {if (typeof(info[name][key]) == 'object') {continue;}if (key == 'url' || key == 'title' || key == 'name' || key == 'edited' || key == 'created' || key == 'homeworld') {continue;}$('#info').append('<p><span>' + key + '</span>' + info[name][key] + '</p>');}d3.select('#svg1 .texts').selectAll('text').attr('class', function(d) {if (d.id == name) {return '';}for (var i = 0; i < graph.links.length; i++) {if (graph.links[i]['source'].id == name && graph.links[i]['target'].id == d.id) {return '';}if (graph.links[i]['target'].id == name && graph.links[i]['source'].id == d.id) {return '';}}return 'inactive';});d3.select("#svg1 .links").selectAll('line').attr('class', function(d) {if (d.source.id == name || d.target.id == name) {return '';} else {return 'inactive';}});}});//鼠標移除文本還原相應節點及邊$('#svg1').on('mouseleave', '.texts text', function(event) {if (!dragging) {d3.select('#svg1 .texts').selectAll('text').attr('class', '');d3.select('#svg1 .links').selectAll('line').attr('class', '');}});//加載Python獲取的Json信息:六類實體詳細屬性信息var info;//d3.json獲取數據d3.json("all_data.json", function(error, data) {if(error) throw error;info = data;});}); </script> </html>真心希望這篇基礎文章對你有所幫助,最近女神生日到了,準備送個禮物。與君共勉,一起加油~
下載地址:https://download.csdn.net/download/eastmount/10957228
(By:Eastmount 2019-02-13 下午6點 http://blog.csdn.net/eastmount/)
總結
以上是生活随笔為你收集整理的[知识图谱实战篇] 六.HTML+D3实现点击节点显示相关属性及属性值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [知识图谱实战篇] 五.HTML+D3添
- 下一篇: [知识图谱实战篇] 七.HTML+D3实