gpt4 book ai didi

javascript - 如何在 SVG/D3 中围绕其质心旋转文本(垂直翻转)?

转载 作者:行者123 更新时间:2023-11-30 15:11:04 31 4
gpt4 key购买 nike

我有文本对象标记围绕圆均匀分布的点。感谢this article ,我能够正确定位点和文本对象,但圆圈左半球上的标签需要旋转 180 度(垂直翻转)才能更清晰。

enter image description here

我想我可以先围绕它自己的原点旋转文本对象,然后再将它旋转到圆圈周围的适当位置,但无法确定如何定位每个文本对象的中心位置。

对于位于圆圈左半球( Angular >= PI/2 && Angular <=PI*1.5)的文本对象,我如何围绕它们的中心旋转?或者是否有更好的技术使用?

<style type="text/css">
* {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 13px;
}
circle {
fill: steelblue;
fill-opacity: .8;
}

circle:hover {
fill: orange;
fill-opacity: .8;
}
</style>

<div id="canvas"></div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.min.js"></script>
<script type="text/javascript">
(function () {
var paddding = 250;

var createNodes = function () {

var nodeData = [
{ id: 0, label: 'AAA' },
{ id: 1, label: 'BBB' },
{ id: 2, label: 'CCC' },
{ id: 3, label: 'DDD' },
{ id: 4, label: 'EEE' },
{ id: 5, label: 'FFF' },
{ id: 6, label: 'GGG' },
{ id: 7, label: 'HHH' }
];

var radius = 100;
var nodes = [],
width = (radius * 2) + paddding,
height = (radius * 2) + paddding,
angle,
x,
y,
i;

var numNodes = nodeData.length;

for (i = 0; i < numNodes; i++) {
angle = (i / (numNodes / 2)) * Math.PI;
x = (radius * Math.cos(angle)) + (width / 2);
y = (radius * Math.sin(angle)) + (width / 2);
nodes.push({ 'id': i, 'x': x, 'y': y, 'label': nodeData[i].label, 'angle': angle });
}
return nodes;
}

var createSvg = function (radius, callback) {
d3.selectAll('svg').remove();
var svg = d3.select('#canvas').append('svg:svg')
.attr('width', (radius * 2) + paddding)
.attr('height', (radius * 2) + paddding);
callback(svg);
}

var createElements = function (svg, nodes, elementRadius) {
element = svg.selectAll('circle')
.data(nodes)
.enter().append('svg:circle')
.attr('r', elementRadius)
.attr('cx', function (d, i) { return d.x; })
.attr('cy', function (d, i) { return d.y; });

element = svg.selectAll('text')
.data(nodes)
.enter().append('svg:text')
.text(function (d, i) { return d.label + " - " + d.angle.toFixed(2) + ", " + (d.angle*180/Math.PI); })
.attr('x', function (d, i) { return nodes[0].x + 15; }) // add 15 for spacing off point
.attr('y', function (d, i) { return nodes[0].y; })
.attr("dy", ".35em")
.style("alignment-baseline","middle")
.style("text-anchor", "start")
.attr("transform", function(d,i) {
return "rotate(" + (d.angle * 180) / Math.PI + ", 225, 225)";})
;
}

var draw = function () {
var radius = 100;
var nodes = createNodes();

createSvg(radius, function (svg) {
createElements(svg, nodes, 10);
});
}

$(document).ready(function () {
draw();
});
})();
</script>

最佳答案

如果你想反转圆圈左侧的标签。您可以通过不同的方式实现。一种方法是在附加文本时修改文本的三个属性:

.attr('x', function (d, i) { return nodes[0].x + 15; })  
.style("text-anchor", "start")
.attr("transform", function(d,i) {
return "rotate(" + (d.angle * 180) / Math.PI + ", 225, 225)"
})

如果您只修改其中的一部分,您可能得不到想要的结果。

修改text-end

这是必需的,因为您的文本将从您定义的点开始,并且由于文本可能具有可变长度,因此定义起点将比必要的更复杂。对于需要翻转的点,您需要使用:

.style("text-anchor", "end")

修改transformx

文本需要旋转 180 度以使其正确向上;但是,如果您修改此功能以将任何文本添加 180 度,则该文本将出现在显示屏的错误一侧。因此,您还需要将 x 设置为一个新值,以便它显示在显示器的正确一侧:

.attr('x', function (d, i) { return nodes[0].x - 215; }) // radius * 2, add 15 for spacing off point

.attr("transform", function(d,i) {
return "rotate(" + ((d.angle * 180) / Math.PI - 180) + ", 225, 225)"
})

放在一起,看起来像:

(function () {
var paddding = 250;

var createNodes = function () {

var nodeData = [
{ id: 0, label: 'AAA' },
{ id: 1, label: 'BBB' },
{ id: 2, label: 'CCC' },
{ id: 3, label: 'DDD' },
{ id: 4, label: 'EEE' },
{ id: 5, label: 'FFF' },
{ id: 6, label: 'GGG' },
{ id: 7, label: 'HHH' }
];

var radius = 100;
var nodes = [],
width = (radius * 2) + paddding,
height = (radius * 2) + paddding,
angle,
x,
y,
i;

var numNodes = nodeData.length;

for (i = 0; i < numNodes; i++) {
angle = (i / (numNodes / 2)) * Math.PI;
x = (radius * Math.cos(angle)) + (width / 2);
y = (radius * Math.sin(angle)) + (width / 2);
nodes.push({ 'id': i, 'x': x, 'y': y, 'label': nodeData[i].label, 'angle': angle });
}
return nodes;
}

var createSvg = function (radius, callback) {
d3.selectAll('svg').remove();
var svg = d3.select('#canvas').append('svg:svg')
.attr('width', (radius * 2) + paddding)
.attr('height', (radius * 2) + paddding);
callback(svg);
}

var createElements = function (svg, nodes, elementRadius) {
element = svg.selectAll('circle')
.data(nodes)
.enter().append('svg:circle')
.attr('r', elementRadius)
.attr('cx', function (d, i) { return d.x; })
.attr('cy', function (d, i) { return d.y; });

element = svg.selectAll('text')
.data(nodes)
.enter().append('svg:text')
.text(function (d, i) { return d.label + " - " + d.angle.toFixed(2) + ", " + (d.angle*180/Math.PI); })
.attr('x', function (d, i) { return nodes[0].x - 215; }) // radius * 2, add 15 for spacing off point
.attr('y', function (d, i) { return nodes[0].y; })
.attr("dy", ".35em")
.style("alignment-baseline","middle")
.style("text-anchor", "end")
.attr("transform", function(d,i) {
return "rotate(" + ((d.angle * 180) / Math.PI - 180) + ", 225, 225)";})
;
}

var draw = function () {
var radius = 100;
var nodes = createNodes();

createSvg(radius, function (svg) {
createElements(svg, nodes, 10);
});
}

$(document).ready(function () {
draw();
});
})();
* {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 13px;
}
circle {
fill: steelblue;
fill-opacity: .8;
}

circle:hover {
fill: orange;
fill-opacity: .8;
}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.min.js"></script>
<div id="canvas"></div>

但是,现在右边的标签是颠倒的。剩下的就是确定标签是落在右半边还是左半边,并据此分配适当的属性。

零度指向右边,它不是图的顶部。因此,您需要确定d.angle是否小于90度(右下)或大于270度(右上),如果是,则可以应用您的原始代码。如果没有,那么你需要使用上面的代码翻转标签:

(function () {
var paddding = 250;

var createNodes = function () {

var nodeData = [
{ id: 0, label: 'AAA' },
{ id: 1, label: 'BBB' },
{ id: 2, label: 'CCC' },
{ id: 3, label: 'DDD' },
{ id: 4, label: 'EEE' },
{ id: 5, label: 'FFF' },
{ id: 6, label: 'GGG' },
{ id: 7, label: 'HHH' }
];

var radius = 100;
var nodes = [],
width = (radius * 2) + paddding,
height = (radius * 2) + paddding,
angle,
x,
y,
i;

var numNodes = nodeData.length;

for (i = 0; i < numNodes; i++) {
angle = (i / (numNodes / 2)) * Math.PI;
x = (radius * Math.cos(angle)) + (width / 2);
y = (radius * Math.sin(angle)) + (width / 2);
nodes.push({ 'id': i, 'x': x, 'y': y, 'label': nodeData[i].label, 'angle': angle });
}
return nodes;
}

var createSvg = function (radius, callback) {
d3.selectAll('svg').remove();
var svg = d3.select('#canvas').append('svg:svg')
.attr('width', (radius * 2) + paddding)
.attr('height', (radius * 2) + paddding);
callback(svg);
}

var createElements = function (svg, nodes, elementRadius) {
element = svg.selectAll('circle')
.data(nodes)
.enter().append('svg:circle')
.attr('r', elementRadius)
.attr('cx', function (d, i) { return d.x; })
.attr('cy', function (d, i) { return d.y; });

element = svg.selectAll('text')
.data(nodes)
.enter().append('svg:text')
.text(function (d, i) { return d.label + " - " + d.angle.toFixed(2) + ", " + (d.angle*180/Math.PI); })
.attr('x', function (d, i) {
if (d.angle > Math.PI/2 && d.angle < 1.5 * Math.PI) {
return nodes[0].x - 215 }
else {
return nodes[0].x + 15;
}
})
.attr('y', function (d, i) { return nodes[0].y; })
.attr("dy", ".35em")
.style("alignment-baseline","middle")
.style("text-anchor", function(d) {
if (d.angle > Math.PI/2 && d.angle < 1.5 * Math.PI) {
return "end"
}
else {
return "start";
}
})
.attr("transform", function(d,i) {
if (d.angle > Math.PI/2 && d.angle < 1.5 * Math.PI) {
return "rotate(" + ((d.angle * 180) / Math.PI - 180) + ", 225, 225)";
}
else {
return "rotate(" + ((d.angle * 180) / Math.PI) + ", 225, 225)"
}
})
;
}

var draw = function () {
var radius = 100;
var nodes = createNodes();

createSvg(radius, function (svg) {
createElements(svg, nodes, 10);
});
}

$(document).ready(function () {
draw();
});
})();
* {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 13px;
}
circle {
fill: steelblue;
fill-opacity: .8;
}

circle:hover {
fill: orange;
fill-opacity: .8;
}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.min.js"></script>
<div id="canvas"></div>

关于javascript - 如何在 SVG/D3 中围绕其质心旋转文本(垂直翻转)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45105203/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com