javascript - D3.js - 链接未显示在地图上(传单)
问题描述
所以我在地图上做一个简单的表示,我有节点和链接,一个简单的数据只是为了在我连接到一个 json 文件之前测试它,我正在使用leaflet.js 作为地图。我将展示我的以下 JavaScrip、CSS 和 HTML。
基本上,我可以看到我的节点在地图上创建,但是当涉及到链接时,它们不会在任何地方显示。我确定我在某个地方犯了错误,但我不知道在哪里。我敢打赌,一双新鲜的眼睛可以指出我的基本错误。有人可以帮帮我吗?(注意:在我插入地图并尝试将节点与链接连接之前它工作得很好)
问题我如何在地图中显示节点之间的链接?
$(document).ready(function() {
$("#mapid").height(window.innerHeight);
$('#slide-in').height(window.innerHeight);
$(document).on('click', '#advanced', function() {
if ($('#slide-in').hasClass('in')) {
$('#slide-in').removeClass('in')
} else {
$('#slide-in').addClass('in')
}
});
//A partir daqui
var map = L.map('mapid').setView([41.4079700, -8.5197800], 12)
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v10',
tileSize: 512,
zoomOffset: -1,
}).addTo(map);
//Mover o zoom para o canto inferior direito
map.zoomControl.remove();
L.control.zoom({
position: 'bottomright'
}).addTo(map);
// Até aqui tá certo \\
// Add a svg layer to the map
L.svg().addTo(map);
// dados provisórios
var nodes = [{
lat: 41.4579700,
long: -8.5297800,
private: 2,
numContr: 10
},
{
lat: 41.4379700,
long: -8.5297800,
private: 2,
numContr: 20
},
{
lat: 41.4579700,
long: -8.4897800,
private: 1,
numContr: 40
},
{
lat: 41.4179700,
long: -8.4597800,
private: 1,
numContr: 50
},
{
lat: 41.3879700,
long: -8.5997800,
private: 2,
numContr: 10
},
{
lat: 41.4779700,
long: -8.5097800,
private: 1,
numContr: 30
},
];
var links = [{
source: nodes[0],
target: nodes[1],
fraude: 1
},
{
source: nodes[2],
target: nodes[1],
fraude: 2
},
{
source: nodes[0],
target: nodes[3],
fraude: 1
},
{
source: nodes[0],
target: nodes[4],
fraude: 2
},
{
source: nodes[0],
target: nodes[5],
fraude: 1
},
{
source: nodes[4],
target: nodes[1],
fraude: 1
},
{
source: nodes[4],
target: nodes[5],
fraude: 1
},
{
source: nodes[2],
target: nodes[3],
fraude: 1
}
];
//Adicionar os links
d3.select("#mapid")
.select("svg")
.selectAll("line")
.data(links)
.enter()
.append("line")
.attr("x1", function(d) {
return d.source.x
})
.attr("y1", function(d) {
return d.source.y
})
.attr("x2", function(d) {
return d.target.x
})
.attr("y2", function(d) {
return d.target.y
})
.style("stroke", function(d, i) {
if (d.fraude == 2) {
return "rgb(197,53,53)"
} else {
return "rgb(96,211,62"
}
})
.style("stroke-width", 5)
// Adicionar os nodes
d3.select("#mapid")
.select("svg")
.selectAll("myCircles")
.data(nodes) //onde tão os dados
.enter()
.append("circle")
.attr("cx", function(d) {
return map.latLngToLayerPoint([d.lat, d.long]).x
})
.attr("cy", function(d) {
return map.latLngToLayerPoint([d.lat, d.long]).y
})
.attr("r", function(d, i) {
if (d.numContr >= 50) {
return 20;
} else {
if (d.numContr < 50 && d.numContr > 25) {
return 16;
} else {
if (d.numContr < 25 && d.numContr > 10) {
return 12;
} else {
return 8;
}
}
}
})
.attr("fill", function(d, i) {
if (d.private == 1) {
return "rgb(8,105,114)"
} else {
return "rgb(167,255,131)"
}
})
.attr("stroke", "rgb(7,26,82)")
.attr("stroke-width", 6)
// Function that update circle position if something change
function update() {
d3.selectAll("circle")
.attr("cx", function(d) {
return map.latLngToLayerPoint([d.lat, d.long]).x
})
.attr("cy", function(d) {
return map.latLngToLayerPoint([d.lat, d.long]).y
})
}
// If the user change the map (zoom or drag), it update circle position:
map.on("moveend", update)
})
body {
margin: 0;
padding: 0;
}
#menu-pesquisa {
position: absolute;
z-index: 1000;
width: 324px;
height: 24px;
background: #fff;
left: 0;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 -1px 0px rgba(0, 0, 0, 0.02);
min-height: relative;
border-bottom: 0px solid transparent;
padding: 5px 0px 20px 30px;
text-align: center;
}
#slide-id h2 {
margin: 0;
padding: 0;
margin-bottom: 10px;
}
#slide-in {
padding: 10px;
position: absolute;
width: 250px;
z-index: 1000;
background: white;
margin-left: -270px;
transition: 0.5s;
}
#slide-in.in {
margin-left: 0px;
}
#input-pesquisa {
padding: 10px;
font-size: 15px;
border: 0;
float: left;
width: 65%;
background: transparent;
outline: none;
margin-top: 2px;
}
#input-pesquisa::placeholder {
opacity: 0.6;
font-family: Arial, Helvetica, sans-serif;
}
#Pesquisa {
box-sizing: border-box;
border-style: hidden;
background-color: inherit;
text-align: justify;
padding: 12px;
padding-left: 30px;
padding-right: 30px;
outline: none;
margin-top: -4px;
}
#Pesquisa .icon {
background: url(/images/magnifying-glass.svg) no-repeat;
float: left;
width: 24px;
height: 24px;
color: white;
border-left: none;
cursor: pointer;
border-color: transparent;
position: center;
}
#numero-contrato {
position: absolute;
z-index: 1000;
width: 280px;
height: 80px;
background: #fff;
padding: 5px;
left: 0;
bottom: 15px;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 -1px 0px rgba(0, 0, 0, 0.02);
text-align: initial;
}
#numero-contrato h5 {
padding: 0;
margin-left: 5px;
margin-top: 0px;
font-family: Arial, Helvetica, sans-serif;
}
#tipo-contrato {
position: absolute;
z-index: 1000;
width: 160px;
height: 80px;
background: #fff;
padding: 5px;
right: 230px;
bottom: 15px;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 -1px 0px rgba(0, 0, 0, 0.02);
text-align: initial;
}
#tipo-contrato h5 {
padding: 0;
margin-left: 5px;
margin-top: 0px;
font-family: Arial, Helvetica, sans-serif;
}
#tipo-entidades {
position: absolute;
z-index: 1000;
width: 160px;
height: 80px;
background: #fff;
padding: 5px;
right: 40px;
bottom: 15px;
margin: 10px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 -1px 0px rgba(0, 0, 0, 0.02);
text-align: initial;
}
#tipo-entidades h5 {
padding: 0;
margin-left: 5px;
margin-top: 0px;
font-family: Arial, Helvetica, sans-serif;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://d3js.org/d3.v5.min.js"></script>
<link rel="stylesheet" href="/styles/styles.css">
<link rel="stylesheet" href="/images/magnifying-glass.svg">
<!-- Mapa -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" type="text/javascript"></script>
<title>Fraud Detection</title>
</head>
<body>
<div id="slide-in">
<h2>More info</h2>
</div>
<div id="tipo-entidades">
<h5>Tipos de Entidades:</p>
</div>
<div id="tipo-contrato">
<h5>Tipos de Contratos:</p>
</div>
<div id="numero-contrato">
<h5>Número de contratos realizados:</p>
</div>
<div id="menu-pesquisa">
<input type="text" id="input-pesquisa" placeholder="Pesquisar informações" name="Pesquisa"></input>
<button id="Pesquisa"><span class="icon"></span></button>
</div>
<div>
<!-- <button id="advanced" class="icon">Pesquisa Avançada</button> -->
</div>
<div id="mapid" style="width: 100%;"></div>
</body>
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<script src="/scripts/force_directed_layout.js"></script>
</html>
解决方案
我忘了调整 html 中的坐标和lat
坐标轴,就像我在圆圈中所做的那样。long
x
y
基本上这是我的结果:
d3.select("#mapid")
.select("svg")
.selectAll("line")
.data(links)
.enter()
.append("line")
.attr("x1", function(d) { return map.latLngToLayerPoint([d.source.lat, d.source.long]).x})
.attr("y1", function(d) { return map.latLngToLayerPoint([d.source.lat, d.source.long]).y})
.attr("x2", function(d) { return map.latLngToLayerPoint([d.target.lat, d.target.long]).x})
.attr("y2", function(d) { return map.latLngToLayerPoint([d.target.lat, d.target.long]).y})
.style("stroke", function(d, i)
{
if(d.fraude == 2)
{ return "rgb(197,53,53)"}
else
{ return "rgb(96,211,62"}
})
.style("stroke-width", 5)
而且我还必须更新函数更新,因为如果我不这样做,线条将一直留在框架中:
function update() {
d3.selectAll("circle")
.attr("cx", function(d){ return map.latLngToLayerPoint([d.lat, d.long]).x })
.attr("cy", function(d){ return map.latLngToLayerPoint([d.lat, d.long]).y })
d3.selectAll("line")
.attr("x1", function(d) { return map.latLngToLayerPoint([d.source.lat, d.source.long]).x})
.attr("y1", function(d) { return map.latLngToLayerPoint([d.source.lat, d.source.long]).y})
.attr("x2", function(d) { return map.latLngToLayerPoint([d.target.lat, d.target.long]).x})
.attr("y2", function(d) { return map.latLngToLayerPoint([d.target.lat, d.target.long]).y})
}
推荐阅读
- erlang - 为什么 filelib:is_dir 和 filelib:is_regular 函数不适用于包含空格的文件和文件夹?
- python - 在 Simpy 中建模高峰需求时间
- python - 在 Python 中,为什么不使用不同的 `bind` 方法而不是用于“无短路”输入验证的应用函子呢?
- typescript - TypeScript 的运行时数据验证
- sequence - R quantstrat:是否可以使用 quantstrat 创建复杂的规则?
- python - 如何在 FastAPI 中提取标签名称和描述?
- python - 如果在某些页面上选择器不可用,如何处理错误“没有这样的元素:无法找到元素”
- c# - C# OnDeserializing 与 Mongodb
- python - 完整信号上的相似 FFT 代码或块上的平均之间的差异
- html - 如何在引导卡组中制作方角图像