D3图表(含链接) [英] D3 graph (with links) over google maps

查看:218
本文介绍了D3图表(含链接)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要修改示例,方法是添加节点之间的链接( relatedated )。

 <!DOCTYPE html> 
< html>
< head>
< meta name =viewportcontent =initial-scale = 1.0,user-scalable = no/>
< script type =text / javascriptsrc =http://maps.google.com/maps/api/js?sensor=true>< / script>
< script type =text / javascriptsrc =http://mbostock.github.com/d3/d3.js?1.29.1>< / script>
< style type =text / css>

html,body,#map {
width:100%;
height:100%;
margin:0;
padding:0;
}

.stations,.stations svg {
position:absolute;
}

.stations链接{
position:absolute;
stroke:black;
stroke-width:2px;
}

.stations svg {
width:60px;
height:20px;
padding-right:100px;
font:10px sans-serif;
}

.stations circle {
fill:brown;
stroke:black;
stroke-width:1.5px;
}

< / style>
< / head>
< body>
< div id =map>< / div>
< script type =text / javascript>

//创建Google Map ...
var map = new google.maps.Map(d3.select(#map)。node(),{
zoom: 7,
center:new google.maps.LatLng(44.331216,23.927536),
mapTypeId:google.maps.MapTypeId.TERRAIN
});

//加载站数据。当数据恢复后,创建一个叠加层。
d3.json(test-graph.json,function(json){
var overlay = new google.maps.OverlayView();

//添加容器当覆盖被添加到地图
overlay.onAdd = function(){
var layer = d3.select(this.getPanes()。overlayLayer).append(div)
.attr(class,stations);

//将每个标记绘制为单独的SVG元素
//我们可以使用单个SVG, have?
overlay.draw = function(){
var projection = this.getProjection(),
padding = 10;


var markerLink = layer.selectAll(link)
.data(json.links)
.each(pathTransform)//更新现有标记
.enter $ b .each(pathTransform)
.attr(class,link);

var marker = layer.selectAll(svg)
.data .nodes)
.each(transform)//更新现有标记
.enter()。append(svg:svg)
.each(transform)
.attr class,marker);



//添加圈子。
mark.append(svg:circle)
.attr(r,5)
.attr(cx,padding)
.attr ,padding);

//添加标签。
mark.append(svg:text)
.attr(x,padding + 7)
.attr(y,padding)
.attr dy,.37em)
.text(function(d){return d.id;});

function pathTransform(d){

dsrc = new google.maps.LatLng(d.source.lat,d.source.lng);
dtrg = new google.maps.LatLng(d.target.lat,d.target.lng);
dsrc = projection.fromLatLngToDivPixel(dsrc);
dtrg = projection.fromLatLngToDivPixel(dtrg);
return d3.select(this)
.attr(x1,dsrc.x - padding)
.attr(y1,dsrc.y - padding)
。 attr(x2,dtrg.x - padding)
.attr(y2,dtrg.y - padding);

}

function transform(d){

d = new google.maps.LatLng(d.lat,d.lng);
d = projection.fromLatLngToDivPixel(d);

return d3.select(this)
.style(left,(dx - padding)+px)
.style(top padding)+px);
}
};
};

//将我们的叠加层绑定到地图...
overlay.setMap(map);
});

< / script>
< / body>
< / html>

和JSON文件:

  {directed:true,graph:[],nodes:[
{lat:44.391643516091975,lng:23.159677682342053,id:1 :a},
{lat:44.315988,lng:23.818359,id:a:a ::},
{lat:44.29844994776969,lng: 24.402314492323608,id:b:b},
{lat:44.351118152120485,lng:23.341791630955303,id:a:c},
{lat 44.889424527442685,lng:23.960970697645276,id:e:d},
{lat:43.46084400349923,lng:23.975774627524885,id:d:6104:1},
{lat:44.64680010013528,lng:23.20292820976948,id:c:6104:2},
{lat:44.40446080879215,lng:23.953536570796015,id: b:6104:3},
{lat:44.18593375168617,lng:23.769879901486856,id:af:6104:4},
{lat:44.09051846584001, lng:24.14130778735744,id:aaaa3bab:3d:7305},
{lat:44.66376251969314,lng:23.77379490100736,id:aaaa3bab:3d:5507},
{lat:44.6240449587762,lng:24.08347249542858,id:aaaa3bab:3d:6f06},
{lat:45.00138334367271,lng:24.092331272179138,id: aaaa3bab:3d:1306},
{lat:44.55033831045195,lng:24.312914121854526,id:aaaa3bab:3c:ef05},
{lat:44.74421652327631, lng:24.728457702115804,id:aaaa3bab:3c:ea03},
{lat:43.79401723931746,lng:23.77846416630604,id:aaaa3bab:3d:7200},
{lat:43.67351687345779,lng:23.00140978137842,id:aaaa3bab:3d:5d07},
{lat:43.87692500855015,lng:24.28543591328852,id: aaaa3bab:3d:550b},
{lat:44.28189405244278,lng:23.972410391551893,id:aaaa3bab:3d:2706},
{lat:43.94916218711252, lng:23.9733463072956,id:aaaa3bab:3d:2704},
{lat:44.61479884874806,lng:24.27581898293906,id:aaaa3bab:3d:2608},
{lat:44.92223011339065,lng:23.505887513934034,id:aaaa3bab:3d:6502},
{lat:44.20117807597118,lng:23.70555450810448,id: aaaa3bab:3d:2603},
{lat:43.547714841247966,lng:24.56985383484244,id:aaaa3bab:3d:2601},
{lat:43.92116991202797, lng:22.82805535024416,id:aaaa3bab:3d:5803},
{lat:44.56587414638437,lng:22.970799697228976,id:aaaa3bab:3d:7406},
{lat:44.10230727065641,lng:23.701204095342597,id:aaaa3bab:3d:7407},
{lat:45.25416535851712,lng:24.434312172789625,id: aaaa3bab:3d:7404},
{lat:44.91647619491961,lng:23.678252259828515,id:aaaa3bab:3d:7405},
{lat:45.03473433359779, lng:24.07596179597473,id:aaaa3bab:3d:7402},
{lat:45.16855171992733,lng:23.435986773864467,id:aaaa3bab:3d:7403},
{lat:44.553669079256146,lng:23.05123326220677,id:aaaa3bab:3d:7400},
{lat:43.32871087231798,lng:23.325707869122013,id: aaaa3bab:3d:5308},
{lat:43.40444516345915,lng:23.485798521785892,id:aaaa3bab:3c:f107},
{lat:43.9435337313432, lng:22.968285824722354,id:aaaa3bab:3d:7401},
{lat:44.74549949495889,lng:22.832034225254052,id:aaaa3bab:3d:7408},
{lat:44.34901730307382,lng:24.33506529636527,id:aaaa3bab:3d:7409},
{lat:43.53125851464172,lng:24.763229039168245,id: aaaa3bab:3d:6602},
{lat:44.155575603194634,lng:23.250881840942217,id:aaaa3bab:3c:e300}],
links:[
{source:1,target:25},
{source:1,target:26},
{source:1,target 27,
{source:1,target:28},
{source:1,target:29} target:30},
{source:1,target:31},
{source:1,target:34},
{source :1,target:35},
{source:1,target:36},
{source:3,target:5} b {source:3,target:6},
{source:4,target:15} ,
{source:5,target:19},
{source:5,target:23},
{source:6,target :18},
{source:6,target:20},
{source:7,target:22},
{source: 8,target:37},
{source:8,target:3},
{source:10,target:11} source:17,target:21},{source:18,target:13},{source:18,target:14} :33},{source:19,target:38},{source:23,target:2},{source:25,target:10} :28,target:4},{source:28,target:17},{source:29,target:32} 25,{source:34,target:24},{source:35,target:8},{source:35,target:16} 37,target:7},{source:37,target:12}],multigraph:false}

编辑:现在我可以访问坐标感谢一个数组。
我还有一个问题:显示链接(SVG)。

 <!DOCTYPE html& 
< html>
< head>
< meta name =viewportcontent =initial-scale = 1.0,user-scalable = no/>
< script type =text / javascriptsrc =http://maps.google.com/maps/api/js?sensor=true>< / script>
< script type =text / javascriptsrc =http://mbostock.github.com/d3/d3.js?1.29.1>< / script>
< style type =text / css>

html,body,#map {
width:100%;
height:100%;
margin:0;
padding:0;
}

.stations,.stations svg {
position:absolute;
}

.stations行{
position:absolute;
stroke:black;
stroke-width:2px;
}

.stations svg {
width:60px;
height:20px;
padding-right:100px;
font:10px sans-serif;
}

.stations circle {
fill:brown;
stroke:black;
stroke-width:1.5px;
}

< / style>
< / head>
< body>
< div id =map>< / div>
< script type =text / javascript>

//创建Google Map ...
var map = new google.maps.Map(d3.select(#map)。node(),{
zoom: 7,
center:new google.maps.LatLng(44.331216,23.927536),
mapTypeId:google.maps.MapTypeId.TERRAIN
});

//加载站数据。当数据恢复后,创建一个叠加层。
d3.json(test-graph.json,function(json){
var overlay = new google.maps.OverlayView();

//添加容器当覆盖被添加到地图
overlay.onAdd = function(){
var layer = d3.select(this.getPanes()。overlayLayer).append(div)
.attr(class,stations);

//将每个标记绘制为单独的SVG元素
//我们可以使用单个SVG, have?
overlay.draw = function(){
var projection = this.getProjection(),
padding = 10;


var node_coord = {};

var marker = layer.selectAll(svg)
.data(json.nodes)
.each(transform)//更新现有标记
.enter()。append(svg:svg)
.each(transform)
.attr(class,marker);
marker.append(svg: circle)
.attr(r,5)
.attr(cx,padding)
.attr(cy,padding);

//添加标签。
mark.append(svg:text)
.attr(x,padding + 7)
.attr(y,padding)
.attr dy,.37em)
.text(function(d){return d.id;});


var markerLink = layer.selectAll(link)
.data(json.links)
.each(pathTransform)//更新现有标记
.enter()。append(svg:svg)
.each(pathTransform)
.attr(class,line)
.append(svg:line )
.style(stroke-width,5);

//添加圈子。

function pathTransform(d){
console.log(node_coord [d.source-1 +,+ 1]);
dsrc = new google.maps.LatLng(node_coord [d.source-1 +,+ 1],node_coord [d.source-1 +,+ 0]);
dtrg = new google.maps.LatLng(node_coord [d.target-1 +,+ 1],node_coord [d.target-1 +,+ 0]);
console.log(dsrc);
console.log(dtrg);
console.log(source+ d.source);
console.log(target+ d.target);
dsrc = projection.fromLatLngToDivPixel(dsrc);
dtrg = projection.fromLatLngToDivPixel(dtrg);
console.log(dsrc);
console.log(dtrg);

return d3.select(this)
.attr(x1,dsrc.x - padding)
.attr(y1,dsrc.y - padding)
.attr(x2,dtrg.x - padding)
.attr(y2,dtrg.y - padding);

}

函数transform(d,i){
node_coord [i +,+ 0] = d.lng;
node_coord [i +,+ 1] = d.lat;

d = new google.maps.LatLng(d.lat,d.lng);
d = projection.fromLatLngToDivPixel(d);

return d3.select(this)
.style(left,(dx - padding)+px)
.style(top padding)+px);
}
};
};

//将我们的叠加层绑定到地图...
overlay.setMap(map);
});

< / script>
< / body>
< / html>


解决方案

  b 
$ b我必须包含jQuery才能删除旧的svg: <!DOCTYPE html>
< html>
< head>
< meta name =viewportcontent =initial-scale = 1.0,user-scalable = no/>
< script type =text / javascriptsrc =http://maps.google.com/maps/api/js?sensor=true>< / script>
< script type =text / javascriptsrc =http://mbostock.github.com/d3/d3.js?1.29.1>< / script>
< script type =text / javascriptsrc =http://code.jquery.com/jquery-1.8.1.min.js>< / script>

添加.links类:

 < style type =text / css> 
html,body,#map {
width:100%;
height:100%;
margin:0;
padding:0;
}

.stations ,.stations svg {
position:absolute;
}


.links {
// width:100%;
// height:100%;

position:absolute;
}

.stations svg {
width:60px;
height:20px;
padding-right:100px;
font:10px sans-serif;
}

.stations circle {
fill:brown;
stroke:black;
stroke-width:1.5px;
}

< / style>
< / head>

创建Google地图...

 < body> 
< div id =map>< / div>
< script type =text / javascript>


var map = new google.maps.Map(d3.select(#map)。node(),{
zoom:7,
center :new google.maps.LatLng(44.331216,23.927536),
mapTypeId:google.maps.MapTypeId.TERRAIN
});

//加载站数据。当数据恢复后,创建一个叠加层。
d3.json(test-graph.json,function(json){
var overlay = new google.maps.OverlayView();

//添加容器当叠加层添加到地图时
overlay.onAdd = function(){

var layer = d3.select(this.getPanes()。overlayLayer)
.append (div)
.attr(height,100%)
.attr(width,100%)
.attr );

将每个标记绘制为单独的SVG元素
我们可以使用单个SVG,但它有什么大小?

  overlay.draw = function(){
var radius = 5;
var projection = this.getProjection(),
padding = 10;


var node_coord = {};

var marker = layer.selectAll(svg)
.data(json.nodes)
.each(transform)//更新现有标记
.enter()。append(svg:svg)
.each(transform)
.attr(class,marker);
marker.append(svg:circle)
.attr(r radius)
.attr(cx,padding)
.attr(cy,padding);

//添加标签。
mark.append(svg:text)
.attr(x,padding + 7)
.attr(y,padding)
.attr dy,.37em)
.text(function(d){return d.id;});


var markerLink = layer.selectAll(。links)
.data(json.links)
.each(pathTransform)//更新现有标记
.enter()。append(svg:svg)
.attr(class,links)
.each(pathTransform);

链接转换功能(感谢他的问题)。

  function pathTransform(d){
var t,b,l,r,w,h,currentSvg;
$(this).empty(); //删除旧的行(不能使用d3 .remove(),因为我不能使用选择器之后...)

dsrc = new google.maps.LatLng(node_coord [d.source-1 +,+ 1],node_coord [d.source-1 +,+ 0]);
dtrg = new google.maps.LatLng(node_coord [d.target-1 +,+ 1],node_coord [d.target-1 +,+ 0]);
d1 = projection.fromLatLngToDivPixel(dsrc);
d2 = projection.fromLatLngToDivPixel(dtrg);
if(d1.y< d2.y){
t = d1.y;
b = d2.y;
} else {
t = d2.y;
b = d1.y;
}
if(d1.x l = d1.x;
r = d2.x;
} else {
l = d2.x;
r = d1.x;
}
currentSvg = d3.select(this)

.style(left,(l + radius)+px)
.style top,(t + radius)+px)
.style(width,(r-l- radius)+px)
.style t - radius)+px);
//绘制svg元素内的对角线。我们可以使用2种情况,而不是为了但也许你需要定向你的图形(所以你可以使用一些箭头)
if((d1.y< d2.y)&&(d1.x< ; d2.x)){
currentSvg.append(svg:line)
.style(stroke-width,1)
.style(stroke )
.attr(y1,0)
.attr(x1,0)
.attr(x2,rl) ,bt);
} else if((d1.x> d2.x)&&(d1.y> d2.y)){
currentSvg.append(svg:line)
.style(stroke-width,1)
.style(stroke,black)
.attr(y1,0)
.attr ,0)
.attr(x2,rl)
.attr(y2,bt);
} else if((d1.y< d2.y)&&(d1.x> d2.x)){
currentSvg.append(svg:line)
.style(stroke-width,1)
.style(stroke,black)
.attr(y1,0)
.attr ,0)
.attr(x1,rl)
.attr(y2,bt);
} else if((d1.x< d2.x)&&(d1.y> d2.y)){
currentSvg.append(svg:line)
.style(stroke-width,1)
.style(stroke,black)
.attr(y1,0)
.attr ,0)
.attr(x1,rl)
.attr(y2,bt);
} else {
console.log(something is wrong !!!);
}


return currentSvg;
}

在transform函数中添加一个数组以获取节点坐标。

 函数transform(d,i){
console.log(i);
node_coord [i +,+ 0] = d.lng;
node_coord [i +,+ 1] = d.lat;

d = new google.maps.LatLng(d.lat,d.lng);
d = projection.fromLatLngToDivPixel(d);

return d3.select(this)
.style(left,(dx - padding)+px)
.style(top padding)+px);
}
layer.append(div)
.attr(class,stations.line);

};

};

//将我们的叠加层绑定到地图...
overlay.setMap(map);
});

< / script>



I am trying to modify this example by adding the links between the nodes (related).

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
    <style type="text/css">

html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.stations, .stations svg {
  position: absolute;
}

.stations link {
  position: absolute;
 stroke: black;
 stroke-width: 2px;
}

.stations svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.stations circle {
  fill: brown;
  stroke: black;
  stroke-width: 1.5px;
}

    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="text/javascript">

// Create the Google Map…
var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 7,
  center: new google.maps.LatLng(44.331216, 23.927536),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

// Load the station data. When the data comes back, create an overlay.
d3.json("test-graph.json", function(json) {
  var overlay = new google.maps.OverlayView();

  // Add the container when the overlay is added to the map.
  overlay.onAdd = function() {
    var layer = d3.select(this.getPanes().overlayLayer).append("div")
        .attr("class", "stations");

    // Draw each marker as a separate SVG element.
    // We could use a single SVG, but what size would it have?
    overlay.draw = function() {
      var projection = this.getProjection(),
          padding = 10;


      var markerLink = layer.selectAll("link")
      .data(json.links)
      .each(pathTransform) // update existing markers
    .enter().append("line")
      .each(pathTransform)
      .attr("class", "link");

      var marker = layer.selectAll("svg")
          .data(json.nodes)
          .each(transform) // update existing markers
        .enter().append("svg:svg")
          .each(transform)
          .attr("class", "marker");



      // Add a circle.
      marker.append("svg:circle")
          .attr("r", 5)
          .attr("cx", padding)
          .attr("cy", padding);

      // Add a label.
      marker.append("svg:text")
          .attr("x", padding + 7)
          .attr("y", padding)
          .attr("dy", ".37em")
          .text(function(d) { return d.id; });

      function pathTransform(d) {

        dsrc = new google.maps.LatLng(d.source.lat, d.source.lng);
        dtrg = new google.maps.LatLng(d.target.lat, d.target.lng);
        dsrc = projection.fromLatLngToDivPixel(dsrc);
        dtrg = projection.fromLatLngToDivPixel(dtrg);
        return d3.select(this)
            .attr("x1", dsrc.x - padding)
            .attr("y1", dsrc.y - padding)
            .attr("x2", dtrg.x - padding)
            .attr("y2", dtrg.y - padding);

        }

      function transform(d) {

        d = new google.maps.LatLng(d.lat, d.lng);
        d = projection.fromLatLngToDivPixel(d);

        return d3.select(this)
            .style("left", (d.x - padding) + "px")
            .style("top", (d.y - padding) + "px");
      }
    };
  };

  // Bind our overlay to the map…
  overlay.setMap(map);
});

    </script>
  </body>
</html>

And the JSON file:

    {"directed": true, "graph": [], "nodes": [
{"lat": 44.391643516091975, "lng": 23.159677682342053, "id": "1:a"}, 
{"lat": 44.315988, "lng": 23.818359, "id": "a:a::"}, 
{"lat": 44.29844994776969, "lng": 24.402314492323608, "id": "b:b"}, 
{"lat": 44.351118152120485, "lng": 23.341791630955303, "id": "a:c"}, 
{"lat": 44.889424527442685, "lng": 23.960970697645276, "id": "e:d"}, 
{"lat": 43.46084400349923, "lng": 23.975774627524885, "id": "d:6104:1"}, 
{"lat": 44.64680010013528, "lng": 23.20292820976948, "id": "c:6104:2"}, 
{"lat": 44.40446080879215, "lng": 23.953536570796015, "id": "b:6104:3"}, 
{"lat": 44.18593375168617, "lng": 23.769879901486856, "id": "af:6104:4"}, 
{"lat": 44.09051846584001, "lng": 24.14130778735744, "id": "aaaa3bab:3d:7305"}, 
{"lat": 44.66376251969314, "lng": 23.77379490100736, "id": "aaaa3bab:3d:5507"}, 
{"lat": 44.6240449587762, "lng": 24.08347249542858, "id": "aaaa3bab:3d:6f06"}, 
{"lat": 45.00138334367271, "lng": 24.092331272179138, "id": "aaaa3bab:3d:1306"}, 
{"lat": 44.55033831045195, "lng": 24.312914121854526, "id": "aaaa3bab:3c:ef05"}, 
{"lat": 44.74421652327631, "lng": 24.728457702115804, "id": "aaaa3bab:3c:ea03"}, 
{"lat": 43.79401723931746, "lng": 23.77846416630604, "id": "aaaa3bab:3d:7200"}, 
{"lat": 43.67351687345779, "lng": 23.00140978137842, "id": "aaaa3bab:3d:5d07"}, 
{"lat": 43.87692500855015, "lng": 24.28543591328852, "id": "aaaa3bab:3d:550b"}, 
{"lat": 44.28189405244278, "lng": 23.972410391551893, "id": "aaaa3bab:3d:2706"}, 
{"lat": 43.94916218711252, "lng": 23.9733463072956, "id": "aaaa3bab:3d:2704"}, 
{"lat": 44.61479884874806, "lng": 24.27581898293906, "id": "aaaa3bab:3d:2608"}, 
{"lat": 44.92223011339065, "lng": 23.505887513934034, "id": "aaaa3bab:3d:6502"}, 
{"lat": 44.20117807597118, "lng": 23.70555450810448, "id": "aaaa3bab:3d:2603"}, 
{"lat": 43.547714841247966, "lng": 24.56985383484244, "id": "aaaa3bab:3d:2601"}, 
{"lat": 43.92116991202797, "lng": 22.82805535024416, "id": "aaaa3bab:3d:5803"}, 
{"lat": 44.56587414638437, "lng": 22.970799697228976, "id": "aaaa3bab:3d:7406"}, 
{"lat": 44.10230727065641, "lng": 23.701204095342597, "id": "aaaa3bab:3d:7407"}, 
{"lat": 45.25416535851712, "lng": 24.434312172789625, "id": "aaaa3bab:3d:7404"}, 
{"lat": 44.91647619491961, "lng": 23.678252259828515, "id": "aaaa3bab:3d:7405"}, 
{"lat": 45.03473433359779, "lng": 24.07596179597473, "id": "aaaa3bab:3d:7402"}, 
{"lat": 45.16855171992733, "lng": 23.435986773864467, "id": "aaaa3bab:3d:7403"}, 
{"lat": 44.553669079256146, "lng": 23.05123326220677, "id": "aaaa3bab:3d:7400"}, 
{"lat": 43.32871087231798, "lng": 23.325707869122013, "id": "aaaa3bab:3d:5308"}, 
{"lat": 43.40444516345915, "lng": 23.485798521785892, "id": "aaaa3bab:3c:f107"}, 
{"lat": 43.9435337313432, "lng": 22.968285824722354, "id": "aaaa3bab:3d:7401"}, 
{"lat": 44.74549949495889, "lng": 22.832034225254052, "id": "aaaa3bab:3d:7408"}, 
{"lat": 44.34901730307382, "lng": 24.33506529636527, "id": "aaaa3bab:3d:7409"}, 
{"lat": 43.53125851464172, "lng": 24.763229039168245, "id": "aaaa3bab:3d:6602"}, 
{"lat": 44.155575603194634, "lng": 23.250881840942217, "id": "aaaa3bab:3c:e300"}], 
"links": [
{"source": 1, "target": 25}, 
{"source": 1, "target": 26}, 
{"source": 1, "target": 27}, 
{"source": 1, "target": 28}, 
{"source": 1, "target": 29}, 
{"source": 1, "target": 30}, 
{"source": 1, "target": 31}, 
{"source": 1, "target": 34}, 
{"source": 1, "target": 35}, 
{"source": 1, "target": 36}, 
{"source": 3, "target": 5}, 
{"source": 3, "target": 6}, 
{"source": 4, "target": 15}, 
{"source": 4, "target": 9}, 
{"source": 5, "target": 19}, 
{"source": 5, "target": 23}, 
{"source": 6, "target": 18}, 
{"source": 6, "target": 20}, 
{"source": 7, "target": 22}, 
{"source": 8, "target": 37}, 
{"source": 8, "target": 3}, 
{"source": 10, "target": 11}, 
{"source": 17, "target": 21}, {"source": 18, "target": 13}, {"source": 18, "target": 14}, {"source": 19, "target": 33}, {"source": 19, "target": 38}, {"source": 23, "target": 2}, {"source": 25, "target": 10}, {"source": 28, "target": 4}, {"source": 28, "target": 17}, {"source": 29, "target": 32}, {"source": 32, "target": 25}, {"source": 34, "target": 24}, {"source": 35, "target": 8}, {"source": 35, "target": 16}, {"source": 37, "target": 7}, {"source": 37, "target": 12}], "multigraph": false}

Edit: Now I can access the coordinates thanks to an array. I'm still having one problem: showing the links (SVGs).

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
    <style type="text/css">

html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.stations, .stations svg {
  position: absolute;
}

.stations line {
  position: absolute;
 stroke: black;
 stroke-width: 2px;
}

.stations svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.stations circle {
  fill: brown;
  stroke: black;
  stroke-width: 1.5px;
}

    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="text/javascript">

// Create the Google Map…
var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 7,
  center: new google.maps.LatLng(44.331216, 23.927536),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

// Load the station data. When the data comes back, create an overlay.
d3.json("test-graph.json", function(json) {
  var overlay = new google.maps.OverlayView();

  // Add the container when the overlay is added to the map.
  overlay.onAdd = function() {
    var layer = d3.select(this.getPanes().overlayLayer).append("div")
        .attr("class", "stations");

    // Draw each marker as a separate SVG element.
    // We could use a single SVG, but what size would it have?
    overlay.draw = function() {
      var projection = this.getProjection(),
          padding = 10;


        var node_coord = {};

      var marker = layer.selectAll("svg")
          .data(json.nodes)
          .each(transform) // update existing markers
        .enter().append("svg:svg")
          .each(transform)
          .attr("class", "marker");
     marker.append("svg:circle")
          .attr("r", 5)
          .attr("cx", padding)
          .attr("cy", padding);

      // Add a label.
      marker.append("svg:text")
          .attr("x", padding + 7)
          .attr("y", padding)
          .attr("dy", ".37em")
          .text(function(d) { return d.id; });


    var markerLink = layer.selectAll("link")
      .data(json.links)
      .each(pathTransform) // update existing markers
    .enter().append("svg:svg")
      .each(pathTransform)
      .attr("class", "line")
     .append("svg:line")
     .style("stroke-width", 5);   

      // Add a circle.

  function pathTransform(d) {
        console.log(node_coord[d.source-1 + "," + 1]);
        dsrc = new google.maps.LatLng(node_coord[d.source-1 + "," + 1], node_coord[d.source-1 + "," + 0]);
        dtrg = new google.maps.LatLng(node_coord[d.target-1 + "," + 1], node_coord[d.target-1 + "," + 0]);
        console.log(dsrc);
        console.log(dtrg);
        console.log("source" + d.source);
        console.log("target" + d.target);
        dsrc = projection.fromLatLngToDivPixel(dsrc);
        dtrg = projection.fromLatLngToDivPixel(dtrg);
        console.log(dsrc);
        console.log(dtrg);

        return d3.select(this)
            .attr("x1", dsrc.x - padding)
            .attr("y1", dsrc.y - padding)
            .attr("x2", dtrg.x - padding)
            .attr("y2", dtrg.y - padding);

        }

      function transform(d,i) {
            node_coord[i + "," + 0] = d.lng;
            node_coord[i + "," + 1] = d.lat;

        d = new google.maps.LatLng(d.lat, d.lng);
        d = projection.fromLatLngToDivPixel(d);

        return d3.select(this)
            .style("left", (d.x - padding) + "px")
            .style("top", (d.y - padding) + "px");
      }
    };
  };

  // Bind our overlay to the map…
  overlay.setMap(map);
});

    </script>
  </body>
</html>

解决方案

Got it somehow working finally.

I had to include jQuery for removing the old svg:line elements on redraw.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.1.min.js"></script>

Added a .links class:

<style type="text/css">
html, body, #map {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

.stations, .stations svg {
  position: absolute;
}


.links {
  //width: 100%;
  //height: 100%;

 position: absolute;
}

.stations svg {
  width: 60px;
  height: 20px;
  padding-right: 100px;
  font: 10px sans-serif;
}

.stations circle {
  fill: brown;
  stroke: black;
  stroke-width: 1.5px;
}

    </style> 
</head>

Create the Google Map…

  <body>
    <div id="map"></div>
    <script type="text/javascript">


var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 7,
  center: new google.maps.LatLng(44.331216, 23.927536),
  mapTypeId: google.maps.MapTypeId.TERRAIN
});

// Load the station data. When the data comes back, create an overlay.
d3.json("test-graph.json", function(json) {
  var overlay = new google.maps.OverlayView();

  // Add the container when the overlay is added to the map.
  overlay.onAdd = function() {

    var layer = d3.select(this.getPanes().overlayLayer)
        .append("div")
        .attr("height", "100%")
        .attr("width", "100%")
        .attr("class", "stations");

Draw each marker as a separate SVG element. We could use a single SVG, but what size would it have?

overlay.draw = function() {
  var radius = 5;
  var projection = this.getProjection(),
      padding = 10;


  var node_coord = {};

      var marker = layer.selectAll("svg")
      .data(json.nodes)
      .each(transform) // update existing markers
    .enter().append("svg:svg")
      .each(transform)
      .attr("class", "marker");
 marker.append("svg:circle")
      .attr("r", radius)
      .attr("cx", padding)
      .attr("cy", padding);

  // Add a label.
  marker.append("svg:text")
      .attr("x", padding + 7)
      .attr("y", padding)
      .attr("dy", ".37em")
      .text(function(d) { return d.id; });


var markerLink = layer.selectAll(".links")
  .data(json.links)
  .each(pathTransform) // update existing markers       
.enter().append("svg:svg")
 .attr("class", "links")
  .each(pathTransform);

The link transform function (thanks to his question).

   function pathTransform(d) {
        var t, b, l, r, w, h, currentSvg;
        $(this).empty(); // get rid of the old lines (cannot use d3 .remove() because i cannot use selectors after ... )

        dsrc = new google.maps.LatLng(node_coord[d.source-1 + "," + 1], node_coord[d.source-1 + "," + 0]);
        dtrg = new google.maps.LatLng(node_coord[d.target-1 + "," + 1], node_coord[d.target-1 + "," + 0]);
        d1 = projection.fromLatLngToDivPixel(dsrc);
        d2 = projection.fromLatLngToDivPixel(dtrg);
        if ( d1.y < d2.y ) {
            t = d1.y;
            b = d2.y;
        } else {
            t = d2.y;
            b = d1.y;
        }
        if ( d1.x < d2.x ) {
            l = d1.x;
            r = d2.x;
        } else {
            l = d2.x;
            r = d1.x; 
        }
        currentSvg = d3.select(this)

            .style("left", (l + radius) + "px")
            .style("top", (t + radius) + "px")
            .style("width", (r - l - radius) + "px")
            .style("height", (b - t - radius) + "px");
    // drawing the diagonal lines inside the svg elements. We could use 2 cases instead of for but maybe you will need to orient your graph (so you can use some arrows)
    if (( d1.y < d2.y) && ( d1.x < d2.x)) {
        currentSvg.append("svg:line")
            .style("stroke-width", 1)
            .style("stroke", "black")
            .attr("y1", 0)
            .attr("x1", 0)
            .attr("x2", r-l)
            .attr("y2", b-t);
        } else if ((d1.x > d2.x) && (d1.y > d2.y)){
        currentSvg.append("svg:line")
            .style("stroke-width", 1)
            .style("stroke", "black")
            .attr("y1", 0)
            .attr("x1", 0)
            .attr("x2", r-l)
            .attr("y2", b-t);
        } else if (( d1.y < d2.y) && ( d1.x > d2.x)){
            currentSvg.append("svg:line")
                .style("stroke-width", 1)
                .style("stroke", "black")
                .attr("y1", 0)
                .attr("x2", 0)
                .attr("x1", r-l)
                .attr("y2", b-t);
            } else if ((d1.x < d2.x) && (d1.y > d2.y)){
            currentSvg.append("svg:line")
                .style("stroke-width", 1)
                .style("stroke", "black")
                .attr("y1", 0)
                .attr("x2", 0)
                .attr("x1", r-l)
                .attr("y2", b-t);
            } else {
            console.log("something is wrong!!!");
            }


        return currentSvg;
  } 

Added an array in the transform function to get the node coordinates.

      function transform(d,i) {
      console.log(i);
            node_coord[i + "," + 0] = d.lng;
            node_coord[i + "," + 1] = d.lat;

        d = new google.maps.LatLng(d.lat, d.lng);
        d = projection.fromLatLngToDivPixel(d);

        return d3.select(this)
            .style("left", (d.x - padding) + "px")
            .style("top", (d.y - padding) + "px");
      }
layer.append("div")
     .attr("class", "stations.line");

    };

  };

  // Bind our overlay to the map…
  overlay.setMap(map);
});

</script>

这篇关于D3图表(含链接)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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