传单地图更新值显示在悬停但不弹出 - 通过 PHP 来自 sqlDB 的数据



我有一个传单地图,上面有几个多边形,用于显示某个州的停电情况。可以将鼠标悬停在每个城镇上或单击,从而触发信息在角落的窗格中更新或显示在弹出窗口中。

当用户单击或悬停在城镇上时,显示的数据应如下所示: 城镇,受影响城镇百分比和 # 受影响成员

问题是我没有在我的 popUpClick 函数中显示任何数据值(其中包括将成为弹出窗口的城镇名称,因为它是数组的属性)。从此屏幕截图中可以看出,数据适用于我的表和 info.update 函数(信息框),但弹出窗口中没有值。

多边形还用作分区统计(这是完全有效的,而不是问题)。

PHP 将动态数据重新分配给 json 文件,该文件的开头如下所示:

var serviceTowns = {features:[{type:"Feature",properties: 
{percentOut:0, timeOut:"", estRestTime:"", cause:"", metersOut:0, backon:"", 
ShapeSTLength:47738.66356312807, ShapeSTArea:103650697.18991089, CNTY:5, 
FIPS6:5085, townMC:"Wheelock", OBJECTID:52, town:"WHEELOCK"}, geometry: 
{coordinates:[[[-72.066382,44.623496],[-72.073445,44.614341], 
[-72.090108,44.592577],[-72.095247,44.585794],[-72.107467,44.589859], 
[-72.116114,44.592813],[-72.124595,44.595557],[-72.1943,44.62068], 
[-72.202489,44.624105],[-72.207124,44.616742],[-72.228896,44.587984], 
[-72.237341,44.576588],[-72.223447,44.568422],[-72.203096,44.556556], 
[-72.177752,44.541709],[-72.166183,44.535004],[-72.153987,44.527993], 
[-72.137759,44.518585],[-72.131456,44.517563],[-72.124548,44.516587], 
[-72.112684,44.514713],[-72.102359,44.513155],[-72.093739,44.511928], 
[-72.083545,44.51038],[-72.078082,44.529532],[-72.072177,44.549492], 
[-72.066275,44.569281],[-72.060237,44.589858],[-72.057689,44.598425], 
[-72.064812,44.618792],[-72.066382,44.623496]]],type:"Polygon"}},

我包含了整个构建的笔(省略了数据库信誉),但这只允许调查,因为实时数据来自安全数据库。

只是为了兜兜转转。我没有在我的 onclick 弹出窗口中显示任何数据值(其中包括将成为弹出窗口的城镇名称,因为它是数组的属性)。

不用说,非常感谢任何和所有的帮助。 谢谢 杰克

// set initial map view point
const map = L.map('mapid').setView([44.5, -72.6034], 8);
// add map tile layer and set max zoom
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href=”http://osm.org/copyright”>OpenStreetMap</a> contributors',
maxZoom: 11,
}).addTo(map);
// Global Variables ////////
// let metersOut = '0';
// let percentOut = '';
// let town = '';
// add town polygon
L.geoJson(serviceTowns, {
color: '#000',
fillColor: 'grey',
weight: '0.7',
zindex: '2',
}).addTo(map)
// set choropleth params from metersOut in outageValues
function getColor(percentOut) {
return percentOut > 80 ? '#FF0000' :
percentOut > 60 ? '#FFA500' :
percentOut > 40 ? '#FFFF00' :
percentOut > 20 ? '#7CFC00' :
percentOut > 0 ? '#0000FF' :
'grey';
}
// call outage data from php generated object "outageValues" and apply to polygon
function style(feature) {
let percentOut = percentValues[feature.properties.town];
return {
fillColor: getColor(percentOut),
weight: 1,
opacity: 1,
color: 'black',
fillOpacity: 0.3
};
}
L.geoJson(serviceTowns, { style: style }).addTo(map);
// create hover hightlight and townname feature ////////
function highlightFeature(e) {
let layer = e.target;
info.update(layer.feature.properties);
layer.setStyle({
weight: 4,
color: '#666',
fillOpacity: 0.7,
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
}
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
// End highlight //////
//  Onclick gets townname with # of members affected and % of town affected ////////
function popUpClick(layer, props) {
if (props) {
metersOut = (outageValues[props.town] ? outageValues[props.town] : 0);
percentOut = (percentValues[props.town] ? percentValues[props.town] : 0);
town = props.townMC;
}
if (props) {
(layer.bindPopup(('<h3>' + town + '</h3><p># of members affected: ' + metersOut + '<br/>' + percentOut + '% of ' + town + ' affected')))
}
}
// Define hover and click events
function onEachFeature(feature, layer) {
let popup = popUpClick(layer, feature);
// Set click params and generate popup for click ///////////
layer.on({
click: popup,
mouseover: highlightFeature,
mouseout: resetHighlight
});
}
//End Mouse functions ///
// Keep json layer fresh ////
geojson = L.geoJson(serviceTowns, {
style: style,
onEachFeature: onEachFeature,
}).addTo(map);
// ////
// Add Info pane to map div ////////
// ///////
var info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
this.update();
return this._div;
};
// call town data from outageValues and display in infopane
info.update = function (props) {
// parse data from php db
if (props) {
metersOut = (outageValues[props.town] ? outageValues[props.town] : 0);
percentOut = (percentValues[props.town] ? percentValues[props.town] : 0);
town = props.townMC;
}
let message = 'Hover over a town';
if (props) {
message = (metersOut + ' Members affected in ' + town + '<br/>' + percentOut + '% of ' + town + ' affected' + '<br/>'
);
}
this._div.innerHTML = '<h4>VEC Service Territory</h4>' + message;
};
info.addTo(map);
// ////////////
// create legend in bottom and call colors from choropleth params set in getColor function
const legend = L.control({ position: 'bottomleft' });
legend.onAdd = function (map) {
let div = L.DomUtil.create('div', 'info legend'),
grades = [1, 20, 40, 60, 80],
labels = [],
from, to;
labels.push('<p>% of Town<br/>Affected</p><br/><i style="background: grey"></i> ' + '0');   // title and trick legend into showing null value for grey
for (let i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
div.innerHTML =
labels.push(
'<i style="background:' + getColor(from + 1) + '"></i> ' + from + (to ? '&ndash;' + to : '+'));
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);
////// features diabled
// map.dragging.disable();
// map.touchZoom.disable();
map.doubleClickZoom.disable();
map.scrollWheelZoom.disable();
<!-- this is the map build with a current outage table to be placed in a frame module -->
<!-- Connect to a local database to access updated data -->
<?php
$host = "localhost";
$user = "xxxx";
$pass = "xxx";
$database = "xxx";
$conn = mysqli_connect($host, $user, $pass, $database);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sortBy = array('town');
$order = 'off';
if (isset($_GET['sortBy']) && in_array($_GET['sortBy'], $sortBy)) {
$order = $_GET['sortBy'];
}
//Select # of live outages
$outageDataSql = "SELECT * FROM oms_by_town_live_percent ORDER BY " . $order;
$outageDataResult = mysqli_query($conn, $outageDataSql);
$numOutageData = mysqli_num_rows($outageDataResult);
$outageData = [];
while ($row = mysqli_fetch_assoc($outageDataResult)) {
$outageData[$row['town']] = $row;
}
$outageValues = [];
foreach ($outageData as $outage) {
$outageValues[$outage['town']] = $outage['out'];
}
$percentValues = [];
foreach ($outageData as $percent) {
$percentValues[$percent['town']] = round($percent['percent'], 2);
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>VEC Outage Center</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="leaflet.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="serviceTowns.js"></script>
<link rel="stylesheet" href="leaflet.css" />
<link rel="stylesheet" href="map.css" />
</head>
<body>
<!----------------- Map area ---------------------->
<div id="mapid"></div>
<script type="text/javascript">
var outageValues = JSON.parse(<?php echo "'" . json_encode($outageValues) . "'"; ?>);
var percentValues = JSON.parse(<?php echo "'" . json_encode($percentValues) . "'"; ?>);
</script>
<!----------------- Current Outages Table ------------------------>
<div id="outTable">
<?php
$resultID = mysqli_query($conn, $outageDataSql);
for ($x = 0; $x < mysqli_num_rows($resultID); $x++) {
$ascdesc = ($_GET['ad']) ? 'asc' : 'desc';
$row = mysqli_fetch_assoc($resultID);
$out = $row['out'];
$percent = round($row['percent'], 2);
$town = $row['town'];
$off = $row['off'];
$off = date("m/d h:ia", strtotime($off));
$etr = $row['etr'];
if ($etr != null) {
$etr = date("m/d h:ia", strtotime($etr));
} else {
$etr = "TBD";
}
$current = $current . "<tr>
<td>$town</td>
<td bgcolor='#f5f5f5'>$out</td>
<td>$off</td>
<td bgcolor='#f5f5f5'>$etr</td>
<td>$percent</td>
</tr>";
}
echo "<table align=center width=90% cellpadding=3>n";
echo "<tr class='cTable'>
<th bgcolor='#1682c8'><a href='?sortBy=town&ad='" . $ascdesc . "'><font color='white'>Town</font></a></th>
<th bgcolor='#1682c8'><font color='white'># of Member<br>Outages</font></th>
<th bgcolor='#1682c8'><font color='white'>Time Off</font></th>
<th bgcolor='#1682c8'><font color='white'>Estimated<br>Restoration Time</font></th>
<th bgcolor='#1682c8'><font color='white'>Percent Out</font></th>
</tr>n";
echo $current;
"n";
echo "</table>";
?>
</div>
<script src="mapScripts.js"?=v18></script>
</body>
</html>

您可能只是没有正确向下钻取到feature对象。输入一些console.log({feature})语句,您将看到数据是否真的存在,但在不同的对象级别。

在 https://leafletjs.com/examples/geojson/的传单文档中,feature有一个名为properties的属性(是的,这是Leaflet/GeoJSON的一个令人困惑的命名决定),但是在您的popupClick函数中,您已将feature重命名props,而不是向下钻取feature.properties。这就是我的猜测。

onEachFeature(feature, layer) -> 
popUpClick(layer, feature) -> 
popUpClick(layer, props) -> 
props.townMC

这意味着您希望feature具有townMC属性,但它实际上具有一个包含townMCproperties对象 — 将props参数重命名为feature,然后使用let town = feature.properties.townMC3.on方法似乎从事件映射到侦听器函数,但您已将click映射到调用popupClick的结果。这对我来说很奇怪,我不确定为什么它会起作用。这可以解释为什么功能属性为空/未定义,因为它被调用得太早了。或者这可能是一条红鲱鱼。

其他建议:

  • 保持参数的排序和命名一致(即重新排列/重命名popupClick参数)
  • popupClick内对所有变量使用let;它们现在是全局的,可能会产生不良副作用
  • 将两个if语句合并到popupClick
  • 为单个函数编写一些单元测试和/或断言,以缩小错误可能的位置

最新更新