javascript - 如何在 d3.js 中定位特定区域的圆圈
问题描述
我在 d3 中创建了一个图形,它读取一个数组并在鼠标光标经过一个圆圈时显示数据。
我的图形有 3 个实体:
- 位于页面中心的主圆圈。
- 进入主圈的彩色饼图。
- 对应于代码中定义的数组的每条记录的小圆圈。
我希望能够找到主圆边缘的小圆圈,如下图所示。
知道怎么做吗?我将不胜感激任何建议或帮助。
我留下了我创建的图形的完整代码。非常感谢
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script src="//d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<style>
.underline {
text-decoration: underline;
}
</style>
</head>
<body style="background-color: rgb(233, 236, 239)">
<br><legend align="center">D3 Test</legend><hr>
<div class="container">
<div class="jumbotron">
<script type="text/javascript">
var w = 1200;
var h = 550;
var padding = 20;
var radius = Math.min(w, h);
var dataset = [
[ 600, 150]
];
var data = [
[5, 20, "1.- Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto."],
[480, 90, "2.- Lorem Ipsum ha sido el texto de relleno estándar de las industrias desde el año 1500"],
[750, 50, "3.- cuando un impresor (N. del T. persona que se dedica a la imprenta) desconocido usó una galería de textos"],
[100, 33, "4.- Es un hecho establecido hace demasiado tiempo que un"],
[330, 95, "5.- Parecerlo un español que se puede leer. Muchos paquetes de autoedición y editores de páginas web usan el Lorem Ipsum como su te"],
[410, 12, "6- Ingresó como texto de relleno en documentos electrónicos, quedan"],
[475, 44, "7.- Esencialmente igual al original. Fue popularizado en los 60s "],
[25, 67, " 8.- Más recientemente con software de autoedición, como por ejemplo Al"],
[85, 21, "9.- Normal de las letras, al contrario de usar textos como por ejemplo "],
[220, 88, "10.- Muchas variaciones de los pasajes de Lorem Ipsum disponibles, pero la mayoría sufrió alteraciones en al"]
];
var data_colors = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25, 15, 20, 18, 17, 16, 18, 23, 25 ];
var data_2 = [
[122, 72]
];
var xScale_data = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale_data = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d[1]; })])
.range([h - padding, padding * 4]);
var rScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([2, 5]);
var rScale_data = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d[1]; })])
.range([2, 5]);
//Crear un elemento SVG
var svg = d3.select("div.jumbotron")
.append("svg")
.attr("width", w)
.attr("height", h)
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", w / 2)
.attr("cy", h / 2)
.attr("r", function(d) {
return rScale(d[1]) * 25;
})
.attr("stroke", "rgb(255, 255, 255)")
.attr("stroke-width", "8")
.attr("fill", function(d) {
return "rgb(233, 236, 239)";
});
svg.on("click", function() {
document.getElementById("msg").setAttribute("style", "display:none;");
document.getElementById("msg").innerHTML = '';
d3.event.stopPropagation();
});
var dataCircle = d3.select("svg")
.append("svg")
.attr("width", w)
.attr("height", h)
dataCircle.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale_data(d[0]);
})
.attr("cy", function(d) {
return yScale_data(d[1]);
})
.attr("id", function(d){
return "circle-" + d[1]
})
.on("mouseover", function(d) {
document.getElementById("msg").removeAttribute("style");
document.getElementById("circle-" + d[1]).setAttribute("stroke", "rgb(140, 233, 255)");
document.getElementById("circle-" + d[1]).setAttribute("stroke-width", "5");
document.getElementById("msg").innerHTML = d[2];
d3.event.stopPropagation();
})
.on("mouseout", function(d) {
document.getElementById("msg").setAttribute("style", "display:none;");
document.getElementById("circle-" + d[1]).removeAttribute("stroke");
document.getElementById("circle-" + d[1]).removeAttribute("stroke-width");
document.getElementById("msg").innerHTML = '';
d3.event.stopPropagation();
})
.on("click", function(d) {
document.getElementById("msg").removeAttribute("style");
document.getElementById("msg").innerHTML = d[2];
d3.event.stopPropagation();
})
.attr("style", "cursor:pointer;")
.attr("r", function(d) {
return rScale_data(d[1]) * 8;
})
.attr("fill", function(d) {
return "rgba(" + Math.floor((Math.random() * 255) + 0) + "," + Math.floor((Math.random() * 255) + 0) + "," + Math.floor((Math.random() * 255) + 0) + ", 0.30)";
})
var color = d3.scale.category20();
var pie = d3.layout.pie()
.value(function(d) { return 5; })
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 508)
.outerRadius(radius - 480);
var svg = d3.select("svg")
.append("svg")
.attr("width", w )
.attr("height", h )
.append("g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
svg.datum(data_colors).selectAll("path")
.data(pie)
.enter()
.append("path")
.attr("cx", w / 2)
.attr("cy", h / 2)
.attr("r", 125)
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc);
</script>
<div class="row">
<div class="col-lg-12">
<div id="msg" style="display:none;" class="underline alert alert-warning" align="center"></div>
</div>
</div>
</div>
</div>
</body>
</html>
解决方案
如果您不需要太明确小圆圈在主圆圈周围的位置,您可以使用 d3.forceRadial ( https://github.com/d3/d3-force#forceRadial )。
如果您想更精确地了解小圆出现在主圆的圆周上的位置,您可以编写一个函数,根据所需的半径和角度指定 x 和 y 坐标(相对于圆心),例如
function xyCoordinates(angle, radius) {
let radians = 0.0174532925
let x = radius * Math.sin(a * radians)
let y = radius * Math.cos(a * radians)
return [x,y]
}
推荐阅读
- php - 没有从 Laravel 的原始查询中得到任何结果
- json - 如何使用 Jackson 创建无名 Json 数组
- html - 无法在 ::before div 中居中段落
- sql - Oracle 数据库列定义不明确/标识符无效
- reactjs - 类型错误:作者未定义
- angular - 仅使用 X 标记删除 Modal
- material-ui - 如何修复此警告“useLayoutEffect”相关警告?
- swift - 未调用完成处理程序 - Alamofire / stripe
- java - Hibernate UserType:存储在数据库中的 LocalDate 无效
- unity3d - 在多个游戏对象上使用一个网络摄像头纹理