如何使用D3和CoffeeScript将网络可视化的节点替换为图像? [英] How do I replace a node with an image using D3 and CoffeeScript for a network visualization?

查看:750
本文介绍了如何使用D3和CoffeeScript将网络可视化的节点替换为图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图解决这个问题几天,我完全被骗了。



我正在使用此网络实施步骤:
,但我不熟悉CoffeeScript足以添加代码在正确的位置...我觉得我试过每一个地方没有运气。



我想要做的是根据节点所包含的数据放置一个特定的图片来代替一个节点。我喜欢在CoffeeScript本身中有一个if语句,以便根据所选的节点插入一个图片(可以是名称或组或任何内容)。我也希望每个节点都有文本标签,说,金额,但我仍然需要研究更多的如何做到这一点。



示例节点:

 nodes:[{
match:1.0,
name:Airplane,
virtualAmount:1000,
artist:Airplane,
amount:999.99,
id:a1234,
playcount:500,
group:airplanePic.jpg
} ,{

谢谢!任何帮助将非常感谢!



(与我的代码)



谢谢Lars,我不知道无法使用图像与SVG。这是我使用的代码:



这是CoffeeScript部分,我相信我需要编辑,以获得我想要的SVG文件来替换当前的一个圆节点。

 #进入/退出显示节点
updateNodes =
node = nodesG.selectAll(circle.node)
.data(curNodesData,(d) - > d.id)

node.enter (circle)
.attr(class,node)
.attr(cx,(d) - > dx)
.attr (d) - > dy)
.attr(r,(d) - > d.radius)
。艺术家))
.style(stroke,(d) - > strokeFor(d))
.style(stroke-width,1.0)



我一直在尝试使用if语句,像这样,但我是CoffeeScript的新手,所以要温柔。

 如果d.group是airplane#comment:或任何组名我正在寻找
.attr(src,tinyWhale .jpg)

但是,我现在知道这不会工作, t将图像导入SVG。我仍然很困惑,如何用SVG替换节点,即使在阅读Lar的注释和链接的问题。



我可以只创建一个if语句,并用googled svg文件替换圆圈?



再次感谢您的帮助。



更新2:
谢谢Lars试图将它添加到vis.coffee文件,但是当我添加任何代码时打破。下面是我如何添加代码:



第四个.attr是添加的代码。

  node.enter()。append(circle)
.attr(class,node )
.attr(cx,(d) - > dx)
.attr(cy,(d) - > dy)
.attr(r (d) - > d.radius)#this是添加的代码
.attr(fill,(d) - >url(#+ d.group +))
.style(fill,(d) - > nodeColors(d.artist))
.style(stroke,(d) - > strokeFor(d))
.style stroke-width,1.0)



我添加了这里,这也打破了代码。

 #网络可视化的起点
#初始化可视化并开始强制layout
network =(selection,data) - >
#格式化我们的数据
allData = setupData(data)

#创建我们的svg和组
vis = d3.select(selection).append(svg )
.attr(width,width)
.attr(height,height)
linksG = vis.append(g)。attr(id,links )
nodesG = vis.append(g)。attr(id,nodes)

defs = svg.append(defs)
b $ b defs.selectAll(pattern)$​​ b $ b .data(curNodesData)
.append(pattern)$​​ b $ b .attr(id,(d) - & group)
.append(image)
.attr(xlink:href,(d) - > d.group)

感谢您的帮助和耐心!



这是我的vis.coffee文件:
https:// dl.dropboxusercontent .com / u / 18496047 / vis.coffee
因为它不会让我在问题中有多个链接。



编辑3:
使用这个开始,我希望能帮助我找出CoffeeScript的节点实现。

 #从原始数据创建节点对象
#将用作每个
#在vis中,然后将每个节点
#添加到要稍后使用的@nodes中
create_nodes:()=>
@ data.forEach(d)=>
node = {
id:d.id
radius:@radius_scale(d.total_amount)
value:d.total_amount
name:d.tweet_rate
org:d.organization
group:d.tweet_amount
top_conv:d.top_conv
x:Math.random()* 900
y:Math.random()* 800
}
@ nodes.push node

@ nodes.sort(a,b) - > b.value - a.value


#在#vis创建svg,然后
#为每个节点创建圆形表示
create_vis:()=>
@vis = d3.select(#vis)。append(svg)
.attr(width,@width)
.attr(height,@height )
.attr(id,svg_vis)

@circles = @ vis.selectAll(circle)
.data(@nodes,(d) > d.id)

#使用,因为我们在
#鼠标回调中需要'this'
that = this

#radius将最初设置为0。
#查看转换
@ circle.enter()。append(circle)
.attr(r,0)
.attr d)=> @fill_color(d.group))
.attr(stroke-width,2)
.attr(stroke,(d)=> d3.rgb
.attr(id,(d) - >bubble _#{d.id})
.on(mouseover ,(d,i) - > that.show_details(d,i,this))
.on(mouseout,

#花费转换以使气泡出现,以
#正确的半径结束
@ circle.transition()。duration(2000).attr(r, ) - > d.radius)

编辑4:



我将CoffeeSctipt转换为JavaScript的可读性和我自己的舒适性。



任何答案都可以通过JS或CoffeeScript提供。



谢谢...这个问题是杀了我。



任何想要帮助的人:
plnkr.co/edit/DeI4a0gjg0p8ypRS2HUn?p=preview

解决方案

为什么不用您的图片替换圆圈:

  node.enter (image)
.attr(class,node)
.attr(href,tinyWhale.jpg)
.attr(x,function d){return dx;})
.attr(y,function(d){return dy;})
.attr(width,function(d){return d.radius; })
.attr(height,function(d){return d.radius;})


$ b b

而不是:

  node.enter()。append('circle')... 


I've been attempting to solve this problem for days, and am completely stumped.

I'm using this network implementation walk-through: http://flowingdata.com/2012/08/02/how-to-make-an-interactive-network-visualization/

I have successfully created my visualization through this walk-through, and now would like to replace a node with a small picture, based on the node's value.

This is a great example of code to work from, where every node was replaced with an image. http: //bl.ocks .org/mbostock/950642

Specifically:

node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);

The only issue is that this code is in JavaScript, and my implementation of the network graph is written in CoffeeScript.

I tried creating my own JavaScript file with the code above and linking to it, however this did not work for me, and quite frankly I don't know if that is the best approach to take anyway.

I tried converting the code from JavaScript into CoffeeScript through this JS to CoffeeScript tool, http://js2coffee.org/, however I am not familiar with CoffeeScript enough to add the code in the correct location... and I feel like I've tried every spot with no luck.

What I'm exactly trying to do is to put a specific picture in place of a node based on the data contained by the node. I would prefer to have an if statement in the CoffeeScript itself to insert a picture based on the node selected, (could be the name or group or whatever.) I would also like to have the text label for each node as well, displaying, say, "amount," however I still need to research more on how to do that one.

Sample node:

"nodes" : [{
"match" : "1.0",
"name" : "Airplane",
"virtualAmount" : "1000",
"artist" : "Airplane",
"amount" : "999.99",
"id" : "a1234",
"playcount" : "500",
"group" : "airplanePic.jpg"
}, {

Thanks! Any help would be very much appreciated!

Edit: (with my code)

Thank you Lars, I was unaware of the inability to use an image with an SVG. Here is the code I am working with:

This is the CoffeeScript section that I believe I need to edit to get my desired SVG file to replace what is currently a circle for a node.

# enter/exit display for nodes
updateNodes = () ->
  node = nodesG.selectAll("circle.node")
    .data(curNodesData, (d) -> d.id)

node.enter().append("circle")
  .attr("class", "node")
  .attr("cx", (d) -> d.x)
  .attr("cy", (d) -> d.y)
  .attr("r", (d) -> d.radius)
  .style("fill", (d) -> nodeColors(d.artist))
  .style("stroke", (d) -> strokeFor(d))
  .style("stroke-width", 1.0)

I have been trying to use an if statement, like this, however I'm new to CoffeeScript so be gentle.

if d.group is "airplane"     #comment: or whatever group name I'm looking for
.attr("src", "tinyWhale.jpg")

However, I'm now aware that this won't work since I can't import an image to an SVG. I'm still very confused as to how to replace the node with an SVG, even after reading Lar's comment and linked question.

Would I be able to just create an if statement and replace the circle with a googled svg file?

Thanks again for the help.

Update 2: Thanks so much Lars, I am trying to add this to the vis.coffee file, however it breaks when I add any of the code. Here is how I am adding the code:

The 4th .attr is the code added.

node.enter().append("circle")
  .attr("class", "node")
  .attr("cx", (d) -> d.x)
  .attr("cy", (d) -> d.y)
  .attr("r", (d) -> d.radius) #this is the code added
  .attr("fill", (d) -> "url(#" + d.group + ")")
  .style("fill", (d) -> nodeColors(d.artist))
  .style("stroke", (d) -> strokeFor(d))
  .style("stroke-width", 1.0)

And I added this here, which also breaks the code. Am I putting this in the entirely wrong spot?

# Starting point for network visualization
# Initializes visualization and starts force layout
network = (selection, data) ->
# format our data
allData = setupData(data)

# create our svg and groups
vis = d3.select(selection).append("svg")
  .attr("width", width)
  .attr("height", height)
linksG = vis.append("g").attr("id", "links")
nodesG = vis.append("g").attr("id", "nodes")

defs = svg.append("defs")

defs.selectAll("pattern")
  .data(curNodesData)
  .append("pattern")
  .attr("id", (d) -> d.group)
  .append("image")
  .attr("xlink:href", (d) -> d.group)

Thanks for your help and patience!

Here is my vis.coffee file: https:// dl.dropboxusercontent .com/u/18496047/vis.coffee Added spaces because it won't let me have more than one link in the question.

Edit 3: Using this to go off of, which I hope will help me figure out the CoffeeScript node implementation.

# create node objects from original data
# that will serve as the data behind each
# bubble in the vis, then add each node
# to @nodes to be used later
create_nodes: () =>
  @data.forEach (d) =>
    node = {
      id: d.id
      radius: @radius_scale(d.total_amount)
      value: d.total_amount
      name: d.tweet_rate
      org: d.organization
      group: d.tweet_amount
      top_conv: d.top_conv
      x: Math.random() * 900
      y: Math.random() * 800
    }
    @nodes.push node

  @nodes.sort (a,b) -> b.value - a.value


# create svg at #vis and then 
# create circle representation for each node
create_vis: () =>
  @vis = d3.select("#vis").append("svg")
    .attr("width", @width)
    .attr("height", @height)
    .attr("id", "svg_vis")

  @circles = @vis.selectAll("circle")
    .data(@nodes, (d) -> d.id)

  # used because we need 'this' in the 
  # mouse callbacks
  that = this

  # radius will be set to 0 initially.
  # see transition below
  @circles.enter().append("circle")
    .attr("r", 0)
    .attr("fill", (d) => @fill_color(d.group))
    .attr("stroke-width", 2)
    .attr("stroke", (d) => d3.rgb(@fill_color(d.group)).brighter(5))
    .attr("id", (d) -> "bubble_#{d.id}")
    .on("mouseover", (d,i) -> that.show_details(d,i,this))
    .on("mouseout", (d,i) -> that.hide_details(d,i,this))

  # Fancy transition to make bubbles appear, ending with the
  # correct radius
  @circles.transition().duration(2000).attr("r", (d) -> d.radius)

Edit 4:

I converted the CoffeeSctipt to JavaScript for readability and my own comfortability.

Any answers can be contributed via JS or CoffeeScript.

Thanks... this problem is killing me.

Anyone who wants to help: plnkr.co/edit/DeI4a0gjg0p8ypRS2HUn?p=preview

解决方案

Why not replacing circles with your image:

node.enter().append("image")
  .attr("class", "node")
  .attr("href", "tinyWhale.jpg")
  .attr("x", function(d) { return d.x;})
  .attr("y", function(d) { return d.y;})
  .attr("width", function(d) { return d.radius;})
  .attr("height", function(d) { return d.radius;})

instead of:

node.enter().append('circle')...

这篇关于如何使用D3和CoffeeScript将网络可视化的节点替换为图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆