460 lines
14 KiB
HTML
460 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta
|
|
name="viewport"
|
|
content="initial-scale=1.0, user-scalable=no, width=device-width"
|
|
/>
|
|
<title>热力图</title>
|
|
|
|
<script src="./static/tailwind.min.js"></script>
|
|
<link href="./static/remixicon/remixicon.css" rel="stylesheet" />
|
|
|
|
<style>
|
|
html,
|
|
body,
|
|
#container {
|
|
margin: 0;
|
|
padding: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="container"></div>
|
|
|
|
<button
|
|
id="toggle-chart-btn"
|
|
class="h-7 w-7 rounded-full border shadow-xl transition-all hover:bg-slate-200 mb-6 mx-1 fixed right-2 top-2 bg-white"
|
|
onclick="toggleChart()"
|
|
>
|
|
<i class="ri-bar-chart-line"></i>
|
|
</button>
|
|
<div
|
|
id="chart-box"
|
|
class="rounded-2xl shadow-2xl transition-all border fixed top-10 right-2 p-4 backdrop-blur-xl bg-white bg-opacity-70"
|
|
>
|
|
<div id="linegraph" class="w-96 h-64"></div>
|
|
</div>
|
|
|
|
<div
|
|
id="control-box"
|
|
class="fixed border rounded-2xl shadow-xl bottom-4 left-4 right-4 backdrop-blur-xl bg-white bg-opacity-70"
|
|
>
|
|
<span id="hint">双击区域即可编辑,或点击 New 创建新区域</span>
|
|
<div class="flex flex-row flex-nowrap items-center p-4">
|
|
<button
|
|
class="rounded-xl transition-all hover:bg-slate-200 p-2 mb-6 mx-1"
|
|
onclick="createPolygon()"
|
|
>
|
|
New
|
|
</button>
|
|
<!-- <button
|
|
class="rounded-xl transition-all hover:bg-slate-200 p-2 mb-6 mx-1"
|
|
onclick="startEdit()"
|
|
>
|
|
Edit
|
|
</button> -->
|
|
<button
|
|
class="rounded-xl transition-all hover:bg-slate-200 p-2 mb-6 mx-1"
|
|
onclick="stopEdit()"
|
|
>
|
|
Stop
|
|
</button>
|
|
|
|
<button
|
|
class="h-7 w-7 rounded-full transition-all hover:bg-slate-200 mb-6 mx-1"
|
|
id="toggle-play-btn"
|
|
onclick="togglePlay()"
|
|
>
|
|
<i class="ri-play-line"></i>
|
|
</button>
|
|
<div class="grow relative mb-6 mx-1">
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="23"
|
|
value="0"
|
|
id="control-bar"
|
|
class="h-2 w-full cursor-pointer appearance-none rounded-lg bg-gray-200"
|
|
oninput="updateData(this.value)"
|
|
/>
|
|
<div
|
|
class="-bottom-6 flex w-full flex-nowrap justify-between px-2 text-sm text-gray-500"
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">0</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">1</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">2</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">3</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">4</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">5</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">6</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">7</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">8</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">9</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">10</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">11</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">12</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">13</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">14</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">15</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">16</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">17</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">18</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">19</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">20</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">21</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">22</span></span
|
|
>
|
|
<span class="relative">
|
|
<span class="absolute left-1/2 -translate-x-1/2">23</span></span
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="text/javascript" src="./static/echarts.min.js"></script>
|
|
<script type="text/javascript" src="./heatmapData.js"></script>
|
|
<script type="text/javascript" src="./data.js"></script>
|
|
|
|
<script type="text/javascript">
|
|
window._AMapSecurityConfig = {
|
|
securityJsCode: data.gaode.securityJsCode,
|
|
};
|
|
</script>
|
|
<script src="https://webapi.amap.com/maps?v=2.0&key=13471667a960ce7a08b3dfdd9a4fb193&plugin=AMap.PolygonEditor"></script>
|
|
<script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
|
|
|
|
<script>
|
|
var chartEle = document.getElementById("linegraph");
|
|
var chart = echarts.init(chartEle, null, {
|
|
renderer: "canvas",
|
|
useDirtyRect: false,
|
|
});
|
|
var app = {};
|
|
var option = {
|
|
title: {
|
|
text: "Distribution of Water",
|
|
},
|
|
tooltip: {
|
|
trigger: "axis",
|
|
axisPointer: {
|
|
type: "cross",
|
|
},
|
|
},
|
|
xAxis: {
|
|
type: "category",
|
|
boundaryGap: false,
|
|
data: data.chart.xAxis,
|
|
},
|
|
yAxis: {
|
|
type: "value",
|
|
axisLabel: {
|
|
formatter: "{value} T",
|
|
},
|
|
axisPointer: {
|
|
snap: true,
|
|
},
|
|
},
|
|
visualMap: {
|
|
show: false,
|
|
dimension: 0,
|
|
pieces: [{ gt: 0, lte: 24, color: "green" }],
|
|
padding: 0,
|
|
},
|
|
series: [
|
|
{
|
|
name: "Water",
|
|
type: "line",
|
|
smooth: true,
|
|
data: data.chart.series,
|
|
markArea: {
|
|
itemStyle: { color: "rgba(255, 173, 177, 0.4)" },
|
|
data: [[{ name: "Now", xAxis: "0" }, { xAxis: "1" }]],
|
|
},
|
|
},
|
|
],
|
|
grid: {
|
|
left: "15%",
|
|
right: 10,
|
|
bottom: "10%",
|
|
},
|
|
};
|
|
chart.setOption(option);
|
|
|
|
var map = new AMap.Map("container", {
|
|
resizeEnable: true,
|
|
center: data.center,
|
|
zoom: data.zoom,
|
|
});
|
|
|
|
// heatmap.js document:
|
|
// http://www.patrick-wied.at/static/heatmapjs/docs.html
|
|
var heatmap;
|
|
var playing = false;
|
|
map.plugin(["AMap.HeatMap"], function () {
|
|
heatmap = new AMap.HeatMap(map, {
|
|
radius: 25, // 每个点的半径大小
|
|
opacity: [0, 0.8],
|
|
gradient: {
|
|
0.1: "rgb(255, 255, 255)",
|
|
0.2: "rgb(225, 225, 255)",
|
|
0.3: "rgb(195, 195, 255)",
|
|
0.4: "rgb(175, 175, 255)",
|
|
0.5: "rgb(155, 155, 255)",
|
|
0.6: "rgb(135, 135, 255)",
|
|
0.7: "rgb(115, 115, 255)",
|
|
0.8: "rgb( 95, 95, 255)",
|
|
0.9: "rgb( 75, 75, 255)",
|
|
1.0: "rgb( 55, 55, 255)",
|
|
},
|
|
});
|
|
heatmap.setDataSet({
|
|
max: 1000,
|
|
data: heatmapData[0],
|
|
});
|
|
});
|
|
|
|
function showHeatmap() {
|
|
heatmap.show();
|
|
}
|
|
|
|
function hideHeatmap() {
|
|
heatmap.hide();
|
|
}
|
|
|
|
function updateData(value) {
|
|
option.series[0].markArea.data = [
|
|
[
|
|
{
|
|
name: "Now",
|
|
xAxis: value.toString(),
|
|
},
|
|
{
|
|
xAxis: (parseInt(value) + 1).toString(),
|
|
},
|
|
],
|
|
];
|
|
chart.setOption(option);
|
|
|
|
heatmap.setDataSet({
|
|
data: heatmapData[value],
|
|
max: 1000,
|
|
});
|
|
}
|
|
|
|
function togglePlay() {
|
|
let btn = document.getElementById("toggle-play-btn");
|
|
if (playing) {
|
|
playing = false;
|
|
btn.innerHTML = '<i class="ri-play-line"></i>';
|
|
stopPlay();
|
|
} else {
|
|
playing = true;
|
|
btn.innerHTML = '<i class="ri-pause-line"></i>';
|
|
startPlay();
|
|
}
|
|
}
|
|
|
|
function startPlay() {
|
|
let slider = document.getElementById("control-bar");
|
|
intervalID = setInterval(function () {
|
|
if (slider.value < 23) {
|
|
slider.value++;
|
|
} else {
|
|
slider.value = 0;
|
|
}
|
|
updateData(slider.value);
|
|
}, 100); // Do every 100ms
|
|
}
|
|
|
|
function stopPlay() {
|
|
clearInterval(intervalID);
|
|
}
|
|
|
|
var temp;
|
|
function toggleChart() {
|
|
let chartBox = document.getElementById("chart-box");
|
|
if (chartBox.style.display !== "none") {
|
|
temp = chartBox.style.display;
|
|
chartBox.style.display = "none";
|
|
} else {
|
|
chartBox.style.display = temp;
|
|
}
|
|
}
|
|
|
|
// var path1 = [
|
|
// [112.964433, 28.22664],
|
|
// [112.956805, 28.191032],
|
|
// [112.950826, 28.118326],
|
|
// [112.941137, 28.103233],
|
|
// [112.93098, 28.109704],
|
|
// [112.899239, 28.11641],
|
|
// [112.879673, 28.149904],
|
|
// [112.886771, 28.170875],
|
|
// [112.862953, 28.188488],
|
|
// [112.85079, 28.223915],
|
|
// [112.852851, 28.234087],
|
|
// [112.88032, 28.225005],
|
|
// ];
|
|
// var path2 = [
|
|
// [112.975993, 28.226261],
|
|
// [112.969743, 28.205509],
|
|
// [112.967603, 28.184652],
|
|
// [112.960208, 28.139103],
|
|
// [113.014548, 28.151931],
|
|
// [113.019324, 28.195638],
|
|
// [113.018336, 28.23149],
|
|
// ];
|
|
// var polygon1 = new AMap.Polygon({
|
|
// path: path1,
|
|
// });
|
|
// var polygon2 = new AMap.Polygon({
|
|
// path: path2,
|
|
// });
|
|
|
|
// map.add([polygon1, polygon2]);
|
|
// map.setFitView();
|
|
var polyEditor = new AMap.PolygonEditor(map);
|
|
|
|
// polyEditor.addAdsorbPolygons([polygon1, polygon2]);
|
|
polyEditor.on("add", function (data) {
|
|
console.log(data);
|
|
var polygon = data.target;
|
|
polyEditor.addAdsorbPolygons(polygon);
|
|
|
|
polygon.on("dblclick", () => {
|
|
polyEditor.setTarget(polygon);
|
|
polyEditor.open();
|
|
hint.innerText = "正在编辑区域,点击 Stop 退出编辑";
|
|
});
|
|
|
|
polygon.on("mouseover", () => {
|
|
var counts = [];
|
|
var seriesData = [];
|
|
for (var i = 0; i < heatmapData.length; i++) {
|
|
var heatmapPoints = heatmapData[i];
|
|
var totalCount = 0;
|
|
|
|
for (var j = 0; j < heatmapPoints.length; j++) {
|
|
var point = heatmapPoints[j];
|
|
if (pointInPolygon(point, polygon.getPath())) {
|
|
totalCount += point.count;
|
|
}
|
|
}
|
|
|
|
counts.push({
|
|
hour: i,
|
|
totalcount: totalCount,
|
|
});
|
|
seriesData.push(totalCount);
|
|
}
|
|
|
|
let slider = document.getElementById("control-bar");
|
|
var currentHour = slider.value;
|
|
var currentTotalCount = counts[currentHour].totalcount;
|
|
console.log(
|
|
"Total Count at Hour " + currentHour + ": " + currentTotalCount
|
|
);
|
|
option.series[0].data = seriesData;
|
|
chart.setOption(option);
|
|
});
|
|
});
|
|
|
|
function pointInPolygon(point, polygon) {
|
|
var x = point.lng,
|
|
y = point.lat;
|
|
var n = polygon.length;
|
|
var inside = false;
|
|
|
|
for (var i = 0, j = n - 1; i < n; j = i++) {
|
|
var xi = polygon[i].lng,
|
|
yi = polygon[i].lat;
|
|
var xj = polygon[j].lng,
|
|
yj = polygon[j].lat;
|
|
|
|
if (yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) {
|
|
inside = !inside;
|
|
}
|
|
}
|
|
return inside;
|
|
}
|
|
|
|
// polygon1.on("dblclick", () => {
|
|
// polyEditor.setTarget(polygon1);
|
|
// polyEditor.open();
|
|
// hint.innerText = "正在编辑区域,点击 Stop 退出编辑";
|
|
// });
|
|
// polygon2.on("dblclick", () => {
|
|
// polyEditor.setTarget(polygon2);
|
|
// polyEditor.open();
|
|
// hint.innerText = "正在编辑区域,点击 Stop 退出编辑";
|
|
// });
|
|
|
|
function createPolygon() {
|
|
polyEditor.close();
|
|
polyEditor.setTarget();
|
|
polyEditor.open();
|
|
|
|
var hint = document.getElementById("hint");
|
|
hint.innerText = "正在创建一个新区域,右键完成,点击 Stop 退出编辑";
|
|
}
|
|
|
|
function stopEdit() {
|
|
polyEditor.close();
|
|
hint.innerText = "双击区域即可编辑,或点击 New 创建新区域";
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|