nest介绍之音乐地图

nest(https://github.com/vindurriel/nest)是一个视觉组件,它用图(graph)来展示元素之间的关系。一个节点(node)表示一个元素或者元素的某个属性,节点之间的连线(link)表示元素之间的关系。 元素和关系的类型、属性都可以是任意定制的。使用者可以和图进行交互, 允许的操作包括拖拽、添加、删除、聚焦、平移和放缩。 节点的颜色由数据实体的type属性决定,不同type即颜色之间的节点,使用一种特殊type的节点连接,这种节点的type是relationship(关系)。 为什么要做 传统的展示元素和关系的视觉组件有列表、树等,但是所能展示的拓扑关系必须是有向无环图(DAG),通俗的比喻,张三的儿子的儿子不可能是他爹。现实生活中很多元素间的关系满足DAG, 但是不满足例子也很多,比如朋友关系,张三的朋友的朋友可能也是张三的朋友,这在关系上就形成了一个环,不满足DAG。而图可以表示非DAG的拓扑关系,也就是所谓的网络。 nest是为了展示图而生的视觉组件,它能在二维平面展示复杂的元素关系,并且用户可以实时地修改图的布局、增删节点。 nest可以作为脑图使用,也可以作为更一般意义上的关系展示图,参见下面的例子。 例子 音乐地图(http://nest.ap01.aws.af.cm/model/python?theme=light)是一个探索音乐元素之间关系的动态地图,展示歌曲、艺术家、专辑和精选集之间的关系。数据抓取自虾米网。 使用方法如下: 搜索框中可搜索音乐。 点击see all可查看其他用户已经探索过的音乐地图。 保存按钮可以上传当前音乐地图。 ?按钮中可显示图例。 左键单击节点: 选中该节点,可能会弹出可供扩展的关系节点(如选中歌曲节点,弹出歌曲所在的专辑和歌手) 左键拖拽: 空白处平移,节点上调整节点位置。 左键双击节点: 扩展该节点,即添加与该节点有关系的新节点。支持svg动画的浏览器上(chrome、firefox、IE)该节点会振动,并弹出同类型的新节点。 ctrl+左键单击节点: 同左键双击节点。 shift+左键单击节点: 删除该节点,同时一并删除只与该节点有连线的所有节点 alt+左键单击节点: 将该节点设为根节点。图本身无所谓根节点,根节点的唯一目的在于以该节点的id来存储图。 地址栏中可修改theme参数,支持light和dark。 技术 nest在前台采用了d3.js,而d3.js采用了svg。 后台是web.py。 前后台通信采用了ajax和json。 源代码在github https://github.com/vindurriel/nest。 开发计划 将nest组件化, 允许嵌入到任意的html网页中 固化二次开发的接口, 提供SDK

2013年9月4日

forced graph

下图是用d3中的forced graph画出的post和tag的关联关系。为了区别post和tag,使用了两种颜色, 并且施加了两个力场,把post向左推,tag向右推。 参考了下面两个例子: Custom Forces Labeled Force Layout

2013年7月26日

用d3.js来呈现post-tag的多对多关系

最近想用更好的方式呈现blog和tag之间的关系,也就是重写本博客的标签页面。 blog和tag之间是多对多的关系,就是说一篇blog可以有多个tag,一个tag可以包含多篇blog。适合表现这种映射关系的图表叫做平行集(Parallel Set)。 平行集是反应两组或以上数据集之间映射关系的图表。 d3是一个用javascript的库,主要用途是用svg做数据可视化。 d3非常强大,基本上能想到的图表都可以实现。而对于平行集,d3有一个插件d3.parsets。 需要添加如下css和js: d3.parsets.css d3.v3.min.js d3.parsets.js 然后在tags.html里写一些javascript。 先构造出所有post和tag的对应数据。d3.parsets使用csv格式,所以要先生成一个csv格式的字符串。在这里,列名就是post,tag。 比如本篇blog对应两个tag:d3和visualization,那么要在csv里添加两行: {{ page.title }},d3 {{ page.title }},visualization 相关代码如下: var csv="post,tag"; {% for post in site.posts %} {% for tag in post.tags %} csv+="\n{{post.title}},{{tag}}"; {% endfor %} {% endfor %} 接着实例化一个chart,再把数据给它: var chart = d3.parsets() .tension(0.8) .width("800") .height("480") .dimensions(["tag","post"]); var vis = d3.select("#vis").append("svg") .attr("width", chart.width()) .attr("height", chart.height()); var parsed_csv=d3.csv.parse(csv); vis.datum(parsed_csv).call(chart); 我还想实现这样一个功能:点击图中的博客时可以跳转到博客页面。 var posts={}; {% for post in site.posts %} posts["{{post.title}}"]={ "url":"{{post.url}}", }; {% endfor %} vis.selectAll(".category text").on("click",function(d){ if(!(d.name in posts)) return; window.open(posts[d.name].url); }); d3虽然可以看到很多jQuery的影子, 但在data和view的生成方式上很独特,非常地描述化。 这篇文章是作者自己总结的d3处理数据上的一种模式,也就是所谓的join。

2013年7月22日