2013-09-03 6 views
2

J'ai donc un rectangle SVG qui contient du texte SVG. Le texte SVG qui est placé dans la zone de texte inclut des éléments provenant du profil d'un utilisateur. Ces informations sont envoyées à partir du serveur et je veux qu'il y ait un positionnement spécifique comme ceci:SVG Texte sensible au positionnement

enter image description here

Jusqu'à présent, j'ai réussi à le faire assez facilement ... mais la chose est parfois les gens ne » t remplir complètement leur profil (c'est-à-dire laisser leur date de naissance ou leur lieu de résidence) afin de créer un texte SVG vierge.

<g display="default"> 
    <text x="10" y="30">Alexander the Great</text> 
    <text x="10" y="40"></text> 
    <text x="10" y="50">Greece </text> 
</g> 

Je peux supposer qu'ils ont toujours leur nom, mais si la date de naissance ne sont pas fournies, je le veux pour que ma zone de texte est assez intelligent qu'il se déplace emplacement juste sous le nom.

Pour le moment, je saisis des attributs x et y spécifiques à mon nœud de texte, ce qui explique pourquoi cela s'avère un peu difficile. Y a-t-il un moyen de faire en sorte que le positionnement soit plus réactif? Par CSS ou par des attributs SVG? Je génère les éléments SVG via D3.js, donc si j'en ai besoin, je pourrais simplement mettre des instructions à vérifier, mais je veux éviter cela. Merci.

+4

Il semble que vous souhaitiez utiliser du HTML et un ensemble de 'div's. Ils vont repositionner automatiquement. –

+1

Notez que vous pouvez intégrer XHTML dans SVG via ''. – Phrogz

+0

J'étais au courant de '' et envisageait de faire un div afin qu'il puisse se repositionner automatiquement mais je n'étais pas tout à fait sûr si c'était une bonne pratique. Je vais essayer quelques trucs et vous laisser savoir. Si l'un de vous pouvait afficher une réponse pour que d'autres personnes voient un exemple, ce serait formidable. – aug

Répondre

1

En supposant que vous receviez des données JSON pour les entrées de profil, vous pouvez insérer un tableau avec des entrées non vides, puis générer les nœuds de texte à partir du tableau.

record = { 
    "name": "Alex G.", 
    "dob": "", 
    "location": "Greece" 
}; 

// This provides and array of objects with both key names and values. 
var props = d3.entries(record).filter(function(d) { 
    return d.value.length > 0; 
}).map(function(d) { 
    return d.key + ": " + d.value; 
}); 

Ensuite, vous pouvez ajouter les données au DOM avec d3:

d3.select('g[display="default"]') 
    .data(props) 
    .enter().append('text') 
    .attr('x', 10) 
    .attr('y', function(d, i) {return (i+1) * 10;}) 
    .text(function(d) { return d; }); 

EDIT: La suggestion de Adam Pearce Incorporated pour une méthode plus idiomatiques de construction du tableau des accessoires.

+0

Façon plus idiomatique de créer le tableau props - var props = d3.entries (enregistrement) .filter (fonction (d) {return d.value.length> 0;}). Map (fonction (d) {return d. touche + ":" + d.valeur; }); –

+0

Merci, j'ai fait une modification qui attire l'attention sur cette méthode. –

+0

Je pense qu'un div suffirait pour ma situation mais j'accepte cette réponse car il semble que c'est la façon D3 de le faire. J'aime aussi beaucoup la réponse de Scott Cameron, mais celle-ci me semble un peu plus hachée, car elle utilise une échelle qui peut ou non être utilisée. – aug

3

Vous pouvez potentiellement utiliser une échelle ordinal Y et une liaison de données pour contrôler le nombre et la position des éléments <text>.

Parce que vous vous souciez le nombre d'éléments et pas nécessairement le contenu, votre échelle pourrait être basée sur l'indice de tableau:

var yScale = d3.scale.ordinal() 
    .domain([0, 1, 2]) 
    .range([30, 40, 50]); 

Si vous mettez vos données dans un tableau (ou un tableau de tableaux pour plusieurs utilisateurs), vous pouvez faire quelque chose comme ça (supposé un seul utilisateur):

d3.selectAll("text") 
    .data(profile) 
    .enter().append("text") 
     .attr("x", 10) 
     .attr("y", function(d, i) { return yScale(i); }) 
     .text(function(d) { return d; }); 

Si est ["Alexander the Great", "Greece"] vous obtiendrez juste Nom et emplacement ensemble votre tableau « profil ». Si vous incluez un élément pour Data of Birth, vous obtiendrez les trois champs.

1

Utilisez tspan dans l'élément de texte. Cela résout parfaitement votre problème.

<text y="30"> 
    <tspan x="200">Alexander the Great</tspan> 
    <tspan x="200" dy="1em"></tspan> 
    <tspan x="200" dy="1em">Greece </tspan> 
</text>