问题
I'm trying to add labels to the planets around the sun into this example : http://bl.ocks.org/djvanderlaan/4953593. So far, I've managed to add the labels, but the orientation of the labels is rotating with their position, while I want to keep them horizontal for the comfort of the readers. I've been finding a beginning of a solution to my problem here : how to keep text orientation unchanged during rotation in SVG but it's seems very complicated to me (I am a newbie and really not good at trigonometry) and plus, it's not using d3.js. Here is the code that I'am using :
<div id="planetarium">
</div>
<script type="text/javascript">
var w = 800, h = 600;
var t0 = Date.now();
var planets = [
{ R: 300, r: 5, speed: 5, phi0: 90, name : 'Mercure'},
{ R: 150, r: 10, speed: 2, phi0: 190, name : 'Saturne'}
];
var svg = d3.select("#planetarium").insert("svg")
.attr("width", w).attr("height", h);
svg.append("circle").attr("r", 20).attr("cx", w/2)
.attr("cy", h/2).attr("class", "sun")
var container = svg.append("g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")")
container.selectAll("g.planet").data(planets).enter().append("g")
.attr("class", "planet").each(function(d, i) {
var orbit = d3.select(this).append("circle").attr("class", "orbit")
.attr("r", d.R);
var planet = d3.select(this).append("circle").attr("r", d.r).attr("cx",d.R)
.attr("cy", 0).attr("class", "planet");
var text = d3.select(this).append("text")
.attr("x", d.R)
.attr("y", ".31em")
.text(function(d) { return d.name; });
d3.timer(function() {
var delta = (Date.now() - t0);
planet.attr("transform", function(d) {
return "rotate(" + d.phi0 + delta * d.speed/200 + ")";
});
text.attr("transform", function(d) {
return "rotate(" + d.phi0 + delta * d.speed/200 + ")";
});
});
});
</script>
Here is my plunkr : http://plnkr.co/edit/dJEVXIeR7ly536tcMPWt?p=preview Thank you very much for your help !
回答1:
I've finally found a solution inspired by this example : D3.js: rotate group, keep text the same orientation? Instead of making two different variables for planets and text, I've gathered them in a same rotating group, and then added an inverse rotation on the text, but centered on the planet's center rather than the center of the container. Then I set both phi0 (the positions of the planets at the beginning of the animation) to 0, so that the text would be frozen horizontally. Here is my code :
var planets = [
{ R: 300, r: 5, speed: 5, phi0: 0, name : 'Mercure'},
{ R: 150, r: 10, speed: 2, phi0: 0, name : 'Saturne'}
];
//...
var container = svg.append("g")
.attr("transform", "translate(" + w/2 + "," + h/2 + ")")
var orbit = container.selectAll(".orbit")
.data(planets)
.enter()
.append("circle")
.attr("class", "orbit")
.attr("r", function(d) {return d.R;});
var planets = container.selectAll(".planet")
.data(planets)
.enter()
.append("g")
planets.append("circle")
.attr("class", "planet")
.attr("r", function(d) {return d.r;})
.attr("cx", function(d) {return d.R; })
.attr("cy", 0);
planets.append("text")
.attr("dx", function(d) {return d.R;})
.attr("dy", ".35em")
.text(function(d) {return d.name});
d3.timer(function() {
var delta = (Date.now() - t0);
planets.attr("transform", function(d) {
return "rotate(" + d.phi0 + delta * d.speed/200 + ")";
});
planets.selectAll("text").attr("transform", function(d) {
return "rotate(" + -1*(d.phi0 + delta * d.speed/200) + " " + d.R + " " + 0 + ")";
});
});
Not sure this is a very good solution, but for the moment it works. I will learn trigonometry though, I promise ;)
来源:https://stackoverflow.com/questions/31759946/keeping-text-horizontal-while-its-position-is-rotating-with-d3-js