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

时间:2019-03-01 04:17:10

标签: javascript php arrays json leaflet

我有一个带有多个多边形的传单地图,用于显示状态下的停电情况。每个镇都可以悬停或单击,从而触发信息在角落的窗格中更新或显示在弹出窗口中。

当用户单击城镇或将鼠标悬停在城镇上时,显示的数据应符合以下条件: 城镇,受影响的城镇百分比和受影响的会员人数

问题 是,我没有任何数据值显示在我的popUpClick函数中(其中包括镇名,该镇名是弹出窗​​口的,因为它是数组的属性) 。如您从此screenshot所看到的,数据正在为我的表和info.update函数(infobox)工作,但弹出窗口中没有值。

该多边形还可以用作choropleth(完全起作用,不是问题)。

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>

1 个答案:

答案 0 :(得分:0)

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

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

feature.properties

这意味着您希望onEachFeature(feature, layer) -> popUpClick(layer, feature) -> popUpClick(layer, props) -> props.townMC 具有feature属性,但实际上它有一个townMC对象,其中包含properties —将townMC参数重命名为{ {1}},然后使用props 3. feature方法似乎是从事件到侦听器函数的映射,但是您已经将let town = feature.properties.townMC映射到调用结果 on。这对我来说很奇怪,我不确定为什么它可以工作。它可以解释为什么要素属性为空/未定义的原因,因为它被调用太早了。否则可能是红色鲱鱼。

其他建议:

  • 保持参数的排序和命名一致(即重新排列/重命名click的参数)
  • popupClick内使用popupClick来存储所有变量;它们现在已经全球化了,可能会有不良的副作用
  • 合并let中的两个popupClick语句
  • 为各个函数编写一些unit tests和/或断言,以缩小可能出现错误的地方