我需要叶子和烧瓶的帮助。我正在构建一个卫星跟踪 Web 应用程序,它使用 n2yo.com(https://www.n2yo.com/api/) 的 api 来获取其数据。它会询问卫星的 Norad ID 和周期,然后在地图上显示其位置和路径。我试图更新标记,就像每次卫星移动到新位置时在网站上所做的那样。现在这就是我被困住的地方。当我尝试使用 htmx 时,我不喜欢 htmx 使用标记刷新整个地图,我只希望更新 folium 标记对象。请帮助我以下是我的代码。
Python:
from flask import Flask, render_template, redirect, request, render_template_string
import requests
import json
import folium
from folium.plugins import AntPath, Fullscreen
app = Flask(__name__)
LAT = 6.524379
LON = 3.379206
ALT = 10
# SECONDS = 2500
APIKEY = "An_api_key"
@app.route("/", methods = ['GET', 'POST'])
def home():
if request.method == "POST":
id = request.form["id"]
period = request.form["period"]
return redirect(f"/data/{id}/{period}")
return render_template("home.html")
@app.route("/data/<int:id>/<period>")
def data(id, period):
periods = float(period)
periods = periods*60
content = requests.get(f'https://api.n2yo.com/rest/v1/satellite/positions/{id}/{LAT}/{LON}/{ALT}/{periods}/&apiKey={APIKEY}').content
content = content.decode('utf8').replace("'", '"')
path = "static/assets/sat.png"
my_json = json.loads(content)
pos = my_json["positions"]
posi =pos[0]
lat = posi["satlatitude"]
long = posi["satlongitude"]
azimuth = posi["azimuth"]
elevation = posi["elevation"]
altitude = posi["sataltitude"]
name = my_json["info"]["satname"]
# Calculate the custom path
pathlist = [(pos[p]["satlatitude"], pos[p]["satlongitude"]) for p in range(len(pos) - 1)]
satellite_map = folium.Map(location=[LAT,LON], tiles = "cartodb positron", zoom_start=1,world_copy_jump=True, width=600, height=600)
custom_icon = folium.CustomIcon(icon_image=path, icon_size=(30, 30))
folium.Marker(
location=[lat, long], popup='Satellite Position', icon=custom_icon).add_to(satellite_map)
Fullscreen(
title='Expand me',
title_cancel='Exit fullscreen',
force_separate_button=True
).add_to(satellite_map)
AntPath(pathlist, delay=400, weight=3, color = "red", dash_array = [30,15], loop = False).add_to(satellite_map)
satellite_map.get_root().render()
iframe = satellite_map.get_root()._repr_html_()
if 'hx_request' in request.headers:
return render_template("map.html", iframe = iframe, id=id, latitude = lat, longitude=long, azimuth=azimuth, elevation=elevation, altitude=altitude, name=name, period=period)
return render_template("data.html", iframe = iframe, id=id, latitude = lat, longitude=long, azimuth=azimuth, elevation=elevation, altitude=altitude, name=name, period=period)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80,debug=True)
注意:您必须输入 api 密钥才能使其正常工作。别担心,API 是免费的。 :)
另请注意:我使用图像(png)作为标记。所以你可以忽略标记方法中的图标参数。
模板
数据.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Satellite Tracking Map </title>
</head>
<body>
<h1>Satellite Tracking Map ({{id}}) {{name}}</h1>
<div>
<div style="position: relative;">
<div hx-get="/data/{{id}}/{{period}}" hx-trigger="every 5s" hx-target="#update">{{iframe | safe}}</div>
<span id="update">
{%include 'map.html'%}
</span>
</div>
</div>
<script src="https://unpkg.com/[email protected]"
integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO"
crossorigin="anonymous"></script>
</body>
</html>
地图.html
<div id="overlay"
style="position: absolute; top: 10px; right: 10px; background-color: rgba(255, 255, 255, 0.05); padding: 10px; border-radius: 5px;">
<h3>Satellite Data</h3>
<p>Latitude: {{latitude}}</p>
<p>Longitude: {{longitude}}</p>
<p>Altitude: {{altitude}}</p>
<p>Azimuth: {{azimuth}}</p>
<p>Elevation: {{elevation}}</p>
</div>
感谢任何帮助我解决这个问题的人:)
您可以使用
multi-swap
htmx扩展。注册完成后,尝试将maps.html
中的变量放入各自带有ID属性的标签中。
<div id="overlay"
style="position: absolute; top: 10px; right: 10px; background-color: rgba(255, 255, 255, 0.05); padding: 10px; border-radius: 5px;">
<h3>Satellite Data</h3>
<p>Latitude: <span id="latitude">{{latitude}}</span></p>
<p>Longitude: <span id="longitude">{{longitude}}</span></p>
<p>Altitude: <span id="altitude">{{altitude}}</span></p>
<p>Azimuth: <span id="azimuth">{{azimuth}}</span></p>
<p>Elevation: <span id="elevation">{{elevation}}</span</p>
</div>
然后在你的htmx请求中
data.html
,
<div hx-swap="multi:#latitude,#longitude,#altitude,#azimuth,#elevation" hx-get="/data/{{id}}/{{period}}" hx-trigger="every 5s">{{iframe | safe}}</div>