我想在d3.js图表中创建旋转动画。在Gilsha的帮助下,我能够创建如下图表:
现在点击任何一个外圆圈我要旋转所有圆圈并对齐在" hllooo"圈。
我复制了一个旋转圆圈的角度,但问题是该圆圈内的文字也会旋转并创建如下内容:
正如你所看到的那样,文字也是旋转的,我不想要。 transform
函数的代码是:
function angleTween(d, i) {
var angle = 360 - ((i + 1) * 70);
var i = d3.interpolate(0, 90);
return function (t) {
return "rotate(" + i(t) + ")";
};
}
那么如何保持文本不旋转并只旋转形状?
答案 0 :(得分:2)
使用SVGPoint matrixTransform
计算文本元素的x和y属性。
earth.on('click', function() {
texts.style("opacity", 0);
earthLayer
.transition()
.duration(2000)
.attrTween("transform", angleTween)
.each("end", function() {
var svgEl = this.ownerSVGElement;
var angle = d3.select(this).attr("transform").match(/\d+/g)[0];
var matrix = svgEl.createSVGMatrix().rotate(angle);
texts.each(function(d, i) {
var point = this.ownerSVGElement.createSVGPoint();
point.x = +d.cx;
point.y = +d.cy;
point = point.matrixTransform(matrix);
d3.select(this).attr("x", point.x).attr("y", point.y);
});
texts.style("opacity", 1);
});
});
var now = d3.time.year.floor(new Date());
var spacetime = d3.select('body');
var width = 960,
height = 700,
radius = Math.min(width, height);
var radii = {
"sun": radius / 6,
"earthOrbit": radius / 2.5,
"earth": radius / 15,
"moonOrbit": radius / 16,
"moon": radius / 96
};
// Space
var svg = spacetime.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Sun
var sun = svg.append("circle")
.attr("class", "sun")
.attr("r", radii.sun)
//.style("fill", "rgba(255, 204, 0, 1.0)");
.style("stroke", "#f58c2e")
.style("stroke-width", "10")
.style("fill", "none");
// Earth's orbit
var orbit = svg.append("circle")
.attr("class", "earthOrbit")
.attr("r", radii.earthOrbit)
.style("fill", "none")
.style("stroke", "#bababa")
.style("stroke-width", "30");
// Current position of Earth in its orbit
var earthOrbitPosition = d3.svg.arc()
.outerRadius(radii.earthOrbit + 1)
.innerRadius(radii.earthOrbit - 1)
.startAngle(0)
.endAngle(0);
svg.append("path")
.attr("class", "earthOrbitPosition")
.attr("d", earthOrbitPosition)
.style("fill", "rgba(255, 204, 0, 0.75)");
// Time of day
var day = d3.svg.arc()
.outerRadius(radii.earth)
.innerRadius(0)
.startAngle(0)
.endAngle(0);
svg.append("path")
.attr("class", "day")
.attr("d", day)
.attr("transform", "translate(0," + -radii.earthOrbit + ")")
.style("fill", "rgba(53, 110, 195, 1.0)");
// Current position of the Moon in its orbit
var moonOrbitPosition = d3.svg.arc()
.outerRadius(radii.moonOrbit + 1)
.innerRadius(radii.moonOrbit - 1)
.startAngle(0)
.endAngle(0);
svg.append("path")
.attr("class", "moonOrbitPosition")
.attr("d", moonOrbitPosition)
.attr("transform", "translate(0," + -radii.earthOrbit + ")")
.style("fill", "rgba(113, 170, 255, 0.75)");
function getCirclePoints(points, radius, center) {
var circlePositions = [];
var slice = 2 * Math.PI / points;
for (var i = 0; i < points; i++) {
var angle = slice * i;
var newX = (center.X + radius * Math.cos(angle));
var newY = (center.Y + radius * Math.sin(angle));
circlePositions.push({
cx: newX,
cy: newY
});
}
return circlePositions;
}
var circlePositions = getCirclePoints(10, radii.earthOrbit, {
X: 0,
Y: 0
});
var earthLayer = svg.append("g").classed("earthLayer", true);
var textLayer = svg.append("g").classed("textLayer", true);
var earth = earthLayer.selectAll(".earth").data(circlePositions)
.enter()
.append("circle")
.attr("cx", function(d) {
return d.cx;
})
.attr("cy", function(d) {
return d.cy;
})
.attr("class", "earth")
.style("fill", "white")
.attr("r", radii.earth)
.style("stroke", "#bababa")
.style("stroke-width", "10");
texts = textLayer.selectAll("text").data(circlePositions).enter().append("text").attr("x", function(d) {
return d.cx
}).attr("dx", -radii.earth / 2).attr("y", function(d) {
return d.cy
}).text(function(d, i) {
if (i == 0) return "hllooo";
else return "hllooo" + i;
});
earth.on('click', function() {
texts.style("opacity", 0);
earthLayer
.transition()
.duration(2000)
.attrTween("transform", angleTween)
.each("end", function() {
var svgEl = this.ownerSVGElement;
var angle = d3.select(this).attr("transform").match(/\d+/g)[0];
var matrix = svgEl.createSVGMatrix().rotate(angle);
texts.each(function(d, i) {
var point = this.ownerSVGElement.createSVGPoint();
point.x = +d.cx;
point.y = +d.cy;
point = point.matrixTransform(matrix);
d3.select(this).attr("x", point.x).attr("y", point.y);
});
texts.style("opacity", 1);
});
});
function angleTween(d, i) {
var angle = 360 - ((i + 1) * 70);
var i = d3.interpolate(0, angle);
return function(t) {
return "rotate(" + i(t) + ")";
};
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
希望这有帮助。