我现在正在与D3.js合作,即使我发现非常相似的情况,我也无法将它们放在一起继续前进。
我有类似雷达图的东西,我想附加到我创建的每个斧头(轴的数量不固定可能是4,但也是40)文本,我已经拥有,但是围绕中心旋转文本一旦它们达到180度,就转向它们,实际上是0度。
结果应如下所示:
我现在拥有的是:
我只知道如何在arc
内达到此目标,这也很好地显示here,但我并没有真正理解我的情况。
这是我的代码段,我附加了这些文字标准:
//Write criterias
axis.append("text")
.attr("class","labels")
.attr("font-size","12px")
.attr("font-family","Montserrat")
.attr("text-anchor","middle")
.attr("fill","white")
.attr("x",function (d, i) {
return radius * Math.cos(angleSlice * i - Math.PI/2)*options.circles.labelFactor;
})
.attr("y",function (d, i) {
return radius * Math.sin(angleSlice * i - Math.PI/2)*options.circles.labelFactor;
})
.text(function (d) {
return d;
});
修改
这是我的小提琴:https://jsfiddle.net/fsb47ndf/
感谢您的任何建议
答案 0 :(得分:2)
有些人发现旋转SVG元素很困难,因为rotate
属性的transform
函数会围绕原点(0,0)旋转元素,而不是围绕其中心:
如果未提供可选参数,则旋转大约是当前用户坐标系的原点(source)
因此,一个简单的选项是删除文本的x
和y
属性,并使用transform
定位它们。这样,我们可以轻松计算轮换:
.attr("transform", function(d, i) {
var rotate = angleSlice * i > Math.PI / 2 ?
(angleSlice * i * 180 / Math.PI) - 270 :
(angleSlice * i * 180 / Math.PI) - 90;
return "translate(" + radius * Math.cos(angleSlice * i - Math.PI / 2) * options.circles.labelFactor +
"," + radius * Math.sin(angleSlice * i - Math.PI / 2) * options.circles.labelFactor +
") rotate(" + rotate + ")"
})
这是你的代码:
data = [{
name: 'DATA1',
value: 22,
}, {
name: 'DATA2',
value: 50,
}, {
name: 'DATA3',
value: 0,
}, {
name: 'DATA4',
value: 24,
}, {
name: 'DATA5',
value: 22,
}, {
name: 'DATA6',
value: 30,
}, {
name: 'DATA7',
value: 20,
}, {
name: 'DATA8',
value: 41,
}, {
name: 'DATA9',
value: 31,
}, {
name: 'DATA10',
value: 30,
}, {
name: 'DATA11',
value: 30,
}, {
name: 'DATA12',
value: 30,
}, {
name: 'DATA13',
value: 30,
}, {
name: 'DATA14',
value: 30,
}, ];
var options = {
width: 600,
height: 600,
margins: {
top: 100,
right: 100,
bottom: 100,
left: 100
},
circles: {
levels: 6,
maxValue: 100,
labelFactor: 1.15,
opacity: 0.2,
},
};
var allAxis = (data.map(function(i, j) {
return i.name
})),
total = allAxis.length,
radius = Math.min(options.width / 2, options.height / 2),
angleSlice = Math.PI * 2 / total,
Format = d3.format('');
var rScale = d3.scale.linear()
.domain([0, options.circles.maxValue])
.range([50, radius]);
var svg = d3.select("body").append("svg")
.attr("width", options.width + options.margins.left + options.margins.right)
.attr("height", options.height + options.margins.top + options.margins.bottom);
var g = svg.append("g")
.attr("transform", "translate(" + (options.width / 2 + options.margins.left) + "," + (options.height / 2 + options.margins.top) + ")");
var axisGrid = g.append("g")
.attr("class", "axisWraper");
var axis = axisGrid.selectAll(".axis")
.data(allAxis)
.enter()
.append("g")
.attr("class", "axis")
//append them lines
axis.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", function(d, i) {
var tempX2 = radius * Math.cos(angleSlice * i - Math.PI / 2);
return tempX2;
})
.attr("y2", function(d, i) {
var tempY = radius * Math.sin(angleSlice * i - Math.PI / 2);
return tempY;
})
.attr("class", "line")
.attr("stroke", "black")
.attr("fill", "none");
//Draw background circles
axisGrid.selectAll(".levels")
.data([6, 5, 4, 3, 2, 1])
.enter()
.append("circle")
.attr("class", "gridCircle")
.attr("r", function(d, i) {
return parseInt(radius / options.circles.levels * d, 10);
})
.attr("stroke", "black")
.attr("fill-opacity", options.circles.opacity);
//Write data
axis.append("text")
.attr("class", "labels")
.attr("font-size", "12px")
.attr("font-family", "Montserrat")
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("transform", function(d, i) {
var rotate = angleSlice * i > Math.PI ? (angleSlice * i * 180 / Math.PI) - 270 : (angleSlice * i * 180 / Math.PI) - 90;
return "translate(" + radius * Math.cos(angleSlice * i - Math.PI / 2) * options.circles.labelFactor + "," + radius * Math.sin(angleSlice * i - Math.PI / 2) * options.circles.labelFactor + ") rotate(" + rotate + ")"
})
.text(function(d) {
return d;
});

<script src="https://d3js.org/d3.v3.min.js"></script>
&#13;
答案 1 :(得分:1)
就像Gerardo Furtado已经在他的answer生活中提到的那样,如果你放弃x
和y
属性,转而通过{{1}进行所有定位和轮换,可以变得更轻松}属性。但是,通过让浏览器执行所有三角函数,您可以更进一步。您需要做的就是指定适当的转换定义列表。
transform
如果省略x
和y
属性,它们将默认为.attr("transform", function(d, i) {
var angleI = angleSlice * i * 180 / Math.PI - 90; // the angle to rotate the label
var distance = radius * options.circles.labelFactor; // the distance from the center
var flip = angleI > 90 ? 180 : 0; // 180 if label needs to be flipped
return "rotate(" + angleI + ") translate(" + distance + ")" + "rotate(" + flip + ")");
// ^1.^ ^2.^ ^3.^
})
,这意味着文本将全部从原点开始。从那里开始,只需三次转换即可轻松移动并旋转到最终位置:
0
文本到角度rotate
将旋转的文字向外移至最终位置translate
翻转圆圈左侧的文字。请查看以下代码片段以了解正常工作:
rotate
&#13;
data = [{
name: 'DATA1',
value: 22,
},
{
name: 'DATA2',
value: 50,
},
{
name: 'DATA3',
value: 0,
},
{
name: 'DATA4',
value: 24,
},
{
name: 'DATA5',
value: 22,
},
{
name: 'DATA6',
value: 30,
},
{
name: 'DATA7',
value: 20,
},
{
name: 'DATA8',
value: 41,
},
{
name: 'DATA9',
value: 31,
},
{
name: 'DATA10',
value: 30,
},
{
name: 'DATA11',
value: 30,
},
{
name: 'DATA12',
value: 30,
},
{
name: 'DATA13',
value: 30,
},
{
name: 'DATA14',
value: 30,
},
];
var options = {
width: 600,
height: 600,
margins: {
top: 100,
right: 100,
bottom: 100,
left: 100
},
circles: {
levels: 6,
maxValue: 100,
labelFactor: 1.15,
opacity: 0.2,
},
};
var allAxis = (data.map(function(i, j) {
return i.name
})),
total = allAxis.length,
radius = Math.min(options.width / 2, options.height / 2),
angleSlice = Math.PI * 2 / total,
Format = d3.format('');
var rScale = d3.scale.linear()
.domain([0, options.circles.maxValue])
.range([50, radius]);
var svg = d3.select("body").append("svg")
.attr("width", options.width + options.margins.left + options.margins.right)
.attr("height", options.height + options.margins.top + options.margins.bottom);
var g = svg.append("g")
.attr("transform", "translate(" + (options.width / 2 + options.margins.left) + "," + (options.height / 2 + options.margins.top) + ")");
var axisGrid = g.append("g")
.attr("class", "axisWraper");
var axis = axisGrid.selectAll(".axis")
.data(allAxis)
.enter()
.append("g")
.attr("class", "axis")
//append them lines
axis.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", function(d, i) {
var tempX2 = radius * Math.cos(angleSlice * i - Math.PI / 2);
return tempX2;
})
.attr("y2", function(d, i) {
var tempY = radius * Math.sin(angleSlice * i - Math.PI / 2);
return tempY;
})
.attr("class", "line")
.attr("stroke", "black")
.attr("fill", "none");
//Draw background circles
axisGrid.selectAll(".levels")
.data([6, 5, 4, 3, 2, 1])
.enter()
.append("circle")
.attr("class", "gridCircle")
.attr("r", function(d, i) {
return parseInt(radius / options.circles.levels * d, 10);
})
.attr("stroke", "black")
.attr("fill-opacity", options.circles.opacity);
//Write data
axis.append("text")
.attr("class", "labels")
.attr("font-size", "12px")
.attr("font-family", "Montserrat")
.attr("text-anchor", "middle")
.attr("fill", "black")
.attr("dy", ".35em")
.attr("transform", function(d, i) {
var angleI = angleSlice * i * 180 / Math.PI - 90; // the angle to rotate the label
var distance = radius * options.circles.labelFactor; // the distance from the center
var flip = angleI > 90 ? 180 : 0; // 180 if label needs to be flipped
return "rotate(" + angleI + ") translate(" + distance + ")" + "rotate(" + flip + ")"
})
.text(function(d) {
console.log(d);
return d;
});
&#13;
答案 2 :(得分:0)
您可以使用这样的内容来旋转所有标签。您可能必须根据您的需要调整定位和旋转角度。
var angle = 180;
svg.selectAll(".labels")
.attr("transform", "translate(300,0) rotate("+angle+")");