2017-09-15 2 views
1

Lars Kothof hat eine gute Erklärung here wie SVG-Elemente zu erstellen, die der Größe des Textes entsprechen. Ich versuche jedoch, dies dynamisch mit Daten aus JSON oder CSV zu tun.Mit d3 zu rect, die Textgröße entspricht

JS Fiddle here.

svg.selectAll('rect') 
     .data(states.features) 
     .enter() 
     .append('rect') 
      .attrs({ 
      x: function(d) { return path.centroid(d)[0] - 50; }, 
      y: function(d) { return path.centroid(d)[1] - 13; }, 
      'text-anchor': 'middle', 
      'width': 100, 
      'height': 18, 
      'fill': 'rgba(232, 232, 232, 0.8)', 
      'opacity': 1, 
      'rx': 7, 
      'ry': 7 
     }); 

    svg.selectAll('text') 
     .data(states.features) 
     .enter() 
     .append('text') 
      .text(function(d) { return d.properties.name; }) 
      .attrs({ 
      x: function(d) { return path.centroid(d)[0]; }, 
      y: function(d) { return path.centroid(d)[1]; }, 
      'text-anchor': 'middle', 
      'font-size': '7pt', 
      'fill': 'rgb(25,25,25)', 
      'opacity': 1 
     }); 

Das Konzept Ich bin nicht begreifen ist, wie ich eine Funktion, ähnlich wie Lars schreiben kann, die sowohl die <rect> und die <text> und verwendet die Dimensionen des Textes, die Abmessungen des Rechtecks ​​zu bestimmen, erzeugt.

+0

Warum sich damit beschäftigen? Warum nicht so? https://StackOverflow.com/a/31013492/1038015 keine Messung erforderlich. –

+0

Es ist eine gute Idee, aber das 'filter' Attribut scheint Probleme mit Anti-Aliasing zu verursachen. –

+0

Ich denke, es gibt eine andere Antwort, die Sie auf die gleiche Frage versuchen können, wenn Sie Antialiasing-Probleme bekommen. –

Antwort

2

Hier ist eine Lösung und zugehörige JS Fiddle. Was ich gemacht habe, wird jedem rect und Text entsprechende IDs zugewiesen, und nachdem die Texte erzeugt wurden, wurde die reelle Größe basierend auf dem Text angepasst. Außerdem musste die x-Position des Textes entsprechend angepasst werden.

svg.selectAll('rect') 
    .data(states.features) 
    .enter() 
    .append('rect') 
     .attrs({ 
     y: function(d) { return path.centroid(d)[1] - 13; }, 
     'text-anchor': 'middle', 
     'width': 100, 
     'height': 18, 
     'fill': 'rgba(232, 232, 232, 0.8)', 
     'opacity': 1, 
     'rx': 7, 
     'ry': 7 
    }); 

svg.selectAll('text') 
    .data(states.features) 
    .enter() 
    .append('text') 
     .text(function(d) { return d.properties.name; }) 
     .attrs({ 
     x: function(d) { return path.centroid(d)[0]; }, 
     y: function(d) { return path.centroid(d)[1]; }, 
     'text-anchor': 'middle', 
     'font-size': '7pt', 
     'fill': 'rgb(25,25,25)', 
     'opacity': 1, 
     id: function(d) { return 'text' + d.id } 
    }); 

svg.selectAll('rect') 
    .attr('width', function(d) { return document.getElementById('text'+d.id).getBBox().width; }) 
    .attr('x', function(d) { return path.centroid(d)[0] - document.getElementById('text'+d.id).getBBox().width/2; }); 
+0

Danke! Dies ist eine gute Lösung für meine Frage, da ich mit der "Filter" -Lösung die Antialiasing-Probleme bekommen habe. Ich bin gespannt, welche Auswirkung dies auf die Ladezeit hat, aber die Methode wird mir helfen, neue Probleme anzugehen. –