2017-02-14 7 views
0

d3.jsの背景としてテキストの背後に長方形を配置しようとするのが困難です。私はそれをするために同じg要素に追加する必要があることを読んだが、私の場合はそれがそのようには機能しない。 は私のコード:plunkerd3.jsのテキストの背後に矩形を配置する方法

var urls = [{ 
    "wor": "Nordmerika", 
    "number": "10.9", 
    "lon": "-100.33", 
    "lat": "47.61" 
}, { 
    "wor": "Latinamerika", 
    "number": "14.2", 
    "lon": "-56.62", 
    "lat": "-8.53" 
}, { 
    "wor": "Afrika", 
    "number": "51.8", 
    "lon": "24.5085", 
    "lat": "8.7832" 
}, { 
    "wor": "Asien", 
    "number": "27.5", 
    "lon": "104.238281", 
    "lat": "34.51561" 
}, { 
    "wor": "GUS | Russland", 
    "number": "3.4", 
    "lon": "62.753906", 
    "lat": "47.923705" 
}, { 
    "wor": "Europa | MSOE", 
    "number": "10.9", 
    "lon": "15.2551", 
    "lat": "54.526" 
}] 

//starting map 
var margin = { 
    top: 10, 
    left: 10, 
    bottom: 10, 
    right: 10 
    }, 
    width = parseInt(d3.select('#map').style('width')), 
    width = width - margin.left - margin.right, 
    mapRatio = .5, 
    height = width * mapRatio; 

//Map projection 
var projection = d3.geo.equirectangular() 
    .scale(width/5.8) 
    .translate([width/2, height/2]) //translate to center the map in view 

//Generate paths based on projection 
var path = d3.geo.path() 
    .projection(projection); 

//Create an SVG 
var svg = d3.select("#map") 
    .append("svg") 
    .attr("viewBox", "0 0 " + width + " " + height) 
    .attr("preserveAspectRatio", "xMinYMin"); 

//Group for the map features 
var features = svg.append("g") 
    .attr("class", "features"); 

var labelWidths = []; 

d3.json("countries.topojson", function(error, geodata) { 
    if (error) return console.log(error); //unknown error, check the console 

    var layerOne = svg.append("g"); 
    var layerTwo = svg.append("g"); 
    var layerThree = svg.append("g"); 

    //Create a path for each map feature in the data 
    features.selectAll("path") 
    .data(topojson.feature(geodata, geodata.objects.subunits).features) //generate features from TopoJSON 
    .enter() 
    .append("path") 
    .attr("d", path) 
    .on("click", clicked) 
    .style('fill', '#cdd5db') 
    .style('stroke', '#ffffff') 
    .style('stroke-width', '0.5px') 
    .on('mouseover', function(d, i) { 
     d3.select(this).style('stroke-width', '2px'); 
    }) 
    .on('mouseout', function(d, i) { 
     d3.select(this).style('stroke-width', '0.5px'); 
    }); 


    var bubbles = layerOne.attr("class", "bubble") 
    .selectAll("circle") 
    .data(urls) 
    .enter() 
    .append("circle") 
    .attr("cx", function(d, i) { 
     return projection([d.lon, d.lat])[0]; 
    }) 
    .attr("cy", function(d, i) { 
     return projection([d.lon, d.lat])[1]; 
    }) 
    .attr("r", function(d) { 
     if (width >= 1000) { 
     return (d.number) 
     } else { 
     return d.number 
     } 

    }) 
    .style('fill', function(d) { 
     if (d.wor == 'Afrika') { 
     return '#dc0f6e' 
     } else { 
     return '#3e3e3e' 
     } 
    }); 



    var text = layerTwo 
    .attr('class', 'text') 
    .selectAll('text') 
    .data(urls) 
    .enter() 
    .append('text') 
    .attr('x', function(d, i) { 
     if (d.number < 10) { 
     return projection([d.lon, d.lat])[0] + 60; 
     } else { 
     return projection([d.lon, d.lat])[0] 
     } 

    }) 
    .attr('y', function(d, i) { 
     return projection([d.lon, d.lat])[1]; 
    }) 
    .text(function(d) { 
     return d.number; 
    }) 
    .attr("dy", function(d) { 
     if (this.getBBox().width > d.number * 3) { 
     return '-2em' 
     } else { 
     return "0.3em" 
     } 
    }) 
    .attr("text-anchor", "middle") 
    .style('fill', '#fff') 
    .style('font-weight', 'bold') 
    .style('font-size', '1em'); 


    var labels = layerThree 
    .attr('class', 'labels') 
    .selectAll('text') 
    .data(urls) 
    .enter() 
    .append('text') 
    .attr('x', function(d, i) { 
     return projection([d.lon, d.lat])[0] + 60; 

    })[plunker][1] 
    .attr('y', function(d, i) { 
     return projection([d.lon, d.lat])[1]; 
    }) 

    .attr("text-anchor", "middle") 
    .text(function(d) { 
     return d.wor; 
    }) 
    .attr('dy', function(d) { 
     labelWidths.push(this.getBBox().width) 
     var radius = d.number * 2 
     if (radius > 10) { 
     return d.number * 4; 
     } else { 
     return '-0.5em' 
     } 
    }) 
    .style('font-size', '1em') 
    .style('font-weight', 'bold'); 

    var rect = layerThree 
    .attr('class', 'rectlabels') 
    .selectAll('rect') 
    .data(urls) 
    .enter() 
    .append('rect') 
    .attr('x', function(d, i) { 
     return projection([d.lon, d.lat])[0] + 60; 
    }) 
    .attr('y', function(d, i) { 
     return projection([d.lon, d.lat])[1]; 
    }) 
    .attr('dy', function(d) { 
     return '1em' 
    }) 

    .style('fill', '#ffffff') 
    .attr('width', function(d, i) { 
     return labelWidths[i]/10 + 'em' 
    }) 
    .attr('height', '1em'); 

    function clicked(d, i) { 

    } 

}); 

答えて

0

矩形はテキストに正しく並ばいないように見え、その理由がいくつかあります:

  • はあなたの<text>は中央に固定されています、 <rects><rect>の左上の点に固定されています。
  • あなたの<text>要素にさまざまな量のdyを設定していますが、テキストをその距離だけ下に移動しますが、すべての<text>要素はdy=1emであるため、同じ量だけ下がっていません。

私はあなたが6つの<g>要素、ラベルごとに1、<rect>要素と<text>要素を含む各を作成することをお勧めします。次に、<g>要素の属性をx & yに設定する必要があります。

私はあなたにもtext-anchor属性を削除しようとし、代わりにそれは、座標上で中心に得るために半分の幅だけ左に<g>要素((labelWidths[i]/10)/2)を移動すべきだと思います。これは、幅がem単位であるために難しくなります。そのため、ピクセルで行い、それに応じて調整する必要があります。

dy要素を使用せずに試してみてください。これが垂直配置に役立つかどうか確認してください。

関連する問題