Restore smooth touch map dragging

This commit is contained in:
liu weikai
2026-06-12 16:01:11 +08:00
parent a98111dfef
commit 3c796ea873
3 changed files with 86 additions and 5 deletions
@@ -117,6 +117,7 @@ class Runtime
friend const Widgets& widgets(const Runtime& runtime);
friend void set_size(Runtime& runtime, lv_coord_t width, lv_coord_t height);
friend void apply_model(Runtime& runtime, const Model& model);
friend void apply_model_lightweight(Runtime& runtime, const Model& model);
friend void apply_overlay(Runtime& runtime, const ui::map::MapOverlaySnapshot& overlay);
friend void clear(Runtime& runtime);
friend bool project_point(const Runtime& runtime, const GeoPoint& point, lv_point_t& out_screen_point);
@@ -132,6 +133,7 @@ void destroy(Runtime& runtime);
const Widgets& widgets(const Runtime& runtime);
void set_size(Runtime& runtime, lv_coord_t width, lv_coord_t height);
void apply_model(Runtime& runtime, const Model& model);
void apply_model_lightweight(Runtime& runtime, const Model& model);
void apply_overlay(Runtime& runtime, const ui::map::MapOverlaySnapshot& overlay);
void clear(Runtime& runtime);
bool project_point(const Runtime& runtime, const GeoPoint& point, lv_point_t& out_screen_point);
@@ -85,6 +85,7 @@ constexpr std::uint32_t kLvglFunctionKeyF1 = 0x110001U;
constexpr std::uint32_t kInvalidMemberId = 0xFFFFFFFFU;
constexpr std::size_t kMaxTrackOverlayPoints = 48;
constexpr int kDefaultTrackerZoom = 16;
constexpr std::uint32_t kMapDragPreviewIntervalMs = 16;
struct TrackOverlayPoint
{
@@ -146,6 +147,7 @@ char s_map_notice_text[64]{};
uint32_t s_map_notice_until_ms = 0;
int s_map_drag_start_pan_x = 0;
int s_map_drag_start_pan_y = 0;
std::uint32_t s_map_drag_last_preview_ms = 0;
std::vector<TrackOverlayPoint> s_track_points;
std::vector<std::string> s_track_modal_names;
std::string s_track_file;
@@ -166,6 +168,7 @@ void request_refresh_view();
void consume_key_event(lv_event_t* e);
bool load_map_track_file_impl(const char* path, bool show_fail_toast);
::ui::presentation_sources::TeamMapOverlaySource& team_map_overlay_source();
void apply_map_drag_preview();
lv_obj_t* create_map_control_button(lv_obj_t* parent,
lv_coord_t width,
const char* text,
@@ -412,6 +415,7 @@ void clear_map_controls()
s_member_button_ids.clear();
s_member_list_hash = 0;
s_member_panel_last_ms = 0;
s_map_drag_last_preview_ms = 0;
}
void set_hidden(lv_obj_t* obj, bool hidden)
@@ -1237,6 +1241,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*)
case ::ui::widgets::map::GesturePhase::Pressed:
s_map_drag_start_pan_x = s_map_pan_x;
s_map_drag_start_pan_y = s_map_pan_y;
s_map_drag_last_preview_ms = 0;
s_map_drag_active = false;
break;
case ::ui::widgets::map::GesturePhase::DragBegin:
@@ -1246,7 +1251,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*)
s_map_drag_active = true;
s_map_pan_x = s_map_drag_start_pan_x + event.total_dx;
s_map_pan_y = s_map_drag_start_pan_y + event.total_dy;
request_refresh_view();
apply_map_drag_preview();
break;
case ::ui::widgets::map::GesturePhase::DragEnd:
case ::ui::widgets::map::GesturePhase::Cancel:
@@ -1256,6 +1261,7 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*)
s_map_pan_x = 0;
s_map_pan_y = 0;
sync_workspace_viewport_from_renderer();
s_map_drag_last_preview_ms = 0;
request_refresh_view();
}
s_map_drag_active = false;
@@ -1263,6 +1269,32 @@ void map_gesture_callback(const ::ui::widgets::map::GestureEvent& event, void*)
}
}
void apply_map_drag_preview()
{
if (!s_root)
{
return;
}
const std::uint32_t now_ms = sys::millis_now();
if (s_map_drag_last_preview_ms != 0 &&
now_ms - s_map_drag_last_preview_ms < kMapDragPreviewIntervalMs)
{
return;
}
s_map_drag_last_preview_ms = now_ms;
const auto snapshot = map_workspace_model().snapshot();
if (!snapshot.header.valid)
{
return;
}
::ui::widgets::map::apply_model_lightweight(
s_map_runtime,
build_map_model(snapshot));
}
void refresh_view()
{
if (!s_root)
@@ -1280,7 +1312,16 @@ void refresh_view()
if (snapshot.header.valid)
{
::ui::widgets::map::apply_model(s_map_runtime, build_map_model(snapshot));
if (s_map_drag_active)
{
::ui::widgets::map::apply_model_lightweight(
s_map_runtime,
build_map_model(snapshot));
}
else
{
::ui::widgets::map::apply_model(s_map_runtime, build_map_model(snapshot));
}
if (!s_map_drag_active && commit_pending_map_pan_from_screen())
{
snapshot = map_workspace_model().snapshot();
@@ -46,7 +46,18 @@ struct RuntimeImpl
namespace
{
#ifndef MAP_VIEWPORT_DEBUG
#define MAP_VIEWPORT_DEBUG 0
#endif
#if MAP_VIEWPORT_DEBUG
#define MAP_VIEWPORT_LOG(...) std::printf("[MapViewport] " __VA_ARGS__)
#else
#define MAP_VIEWPORT_LOG(...) \
do \
{ \
} while (0)
#endif
constexpr double kCoordPi = 3.14159265358979323846;
constexpr double kCoordA = 6378245.0;
@@ -343,7 +354,7 @@ GeoPoint transformed_focus(const Model& model)
return out;
}
void refresh_tiles(RuntimeImpl& impl, const char* reason)
void refresh_tiles(RuntimeImpl& impl, const char* reason, bool prime_visible)
{
if (!is_runtime_alive(impl))
{
@@ -383,7 +394,10 @@ void refresh_tiles(RuntimeImpl& impl, const char* reason)
impl.model.pan_x,
impl.model.pan_y,
true);
prime_visible_tiles(impl, reason);
if (prime_visible)
{
prime_visible_tiles(impl, reason);
}
MAP_VIEWPORT_LOG("refresh_tiles reason=%s zoom=%d pan=%d,%d src=%u contour=%d anchor=%d size=%dx%d map_data=%d visible_map=%d\n",
reason ? reason : "<none>",
impl.model.zoom,
@@ -718,7 +732,31 @@ void apply_model(Runtime& runtime, const Model& model)
static_cast<unsigned>(impl->model.map_source),
impl->model.contour_enabled ? 1 : 0,
static_cast<unsigned>(impl->model.coord_system));
refresh_tiles(*impl, "apply_model");
refresh_tiles(*impl, "apply_model", true);
render_overlay(*impl);
}
void apply_model_lightweight(Runtime& runtime, const Model& model)
{
if (!runtime.impl_)
{
runtime.impl_ = new RuntimeImpl();
runtime.impl_->tiles.reserve(TILE_RECORD_LIMIT);
}
RuntimeImpl* impl = runtime.impl_;
impl->model = model;
impl->model.map_source = sanitize_map_source(impl->model.map_source);
MAP_VIEWPORT_LOG("apply_model_lightweight focus_valid=%d lat=%.7f lon=%.7f zoom=%d pan=%d,%d src=%u contour=%d coord=%u\n",
impl->model.focus_point.valid ? 1 : 0,
impl->model.focus_point.lat,
impl->model.focus_point.lon,
impl->model.zoom,
impl->model.pan_x,
impl->model.pan_y,
static_cast<unsigned>(impl->model.map_source),
impl->model.contour_enabled ? 1 : 0,
static_cast<unsigned>(impl->model.coord_system));
refresh_tiles(*impl, "apply_model_lightweight", false);
render_overlay(*impl);
}