如何通过Dioxus获取定位?求wasm-bindgen实现示例
使用 wasm-bindgen 调用浏览器 GPS 定位的实现方法
要通过 wasm-bindgen 调用浏览器的 GPS 定位 API,核心是借助 web-sys 库封装的浏览器 API 绑定,配合 wasm-bindgen 实现 Rust 与 JS 的交互。下面是具体实现步骤:
1. 配置项目依赖
首先在 Cargo.toml 中添加所需依赖,web-sys 需要显式启用与定位相关的特性:
[package] name = "gps-wasm" version = "0.1.0" edition = "2021" [dependencies] wasm-bindgen = "0.2" web-sys = { version = "0.3", features = ["Geolocation", "Position", "PositionOptions", "Navigator", "PositionError"] } js-sys = "0.3" # 如果用异步/await,需要添加下面的依赖 wasm-bindgen-futures = "0.4"
2. Rust 核心代码实现
这里提供两种实现方式:回调式和异步/await 式,前者兼容更多场景,后者更符合现代 JS 异步编程习惯。
方式一:回调式实现
use wasm_bindgen::prelude::*; use web_sys::{Geolocation, Navigator, Position, PositionError, PositionOptions}; #[wasm_bindgen] pub fn request_location() { // 获取浏览器 navigator 对象 let navigator = match Navigator::from(js_sys::global().unchecked_into::<js_sys::Object>()).geolocation() { Ok(geo) => geo, Err(_) => { web_sys::console::error_1(&"当前浏览器不支持地理定位".into()); return; } }; // 配置定位选项:高精度、10秒超时、不使用缓存 let options = PositionOptions::new(); options.set_enable_high_accuracy(true); options.set_timeout(10000); options.set_maximum_age(0); // 成功回调:处理定位结果 let success_callback = Closure::wrap(Box::new(|position: Position| { let coords = position.coords(); let lat = coords.latitude(); let lon = coords.longitude(); let accuracy = coords.accuracy(); web_sys::console::log_1(&format!("定位成功:纬度{},经度{},精度{}米", lat, lon, accuracy).into()); // 这里可以将位置数据传入 Rust 业务逻辑,或者通过其他方式传递给 JS }) as Box<dyn FnMut(Position)>); // 错误回调:处理定位失败 let error_callback = Closure::wrap(Box::new(|error: PositionError| { let err_msg = match error.code() { 1 => "用户拒绝了定位权限", 2 => "无法获取位置信息", 3 => "定位超时", _ => "未知错误", }; web_sys::console::error_1(&format!("定位失败:{}", err_msg).into()); }) as Box<dyn FnMut(PositionError)>); // 发起定位请求 navigator.get_current_position_with_options_and_success_callback_and_error_callback( &options, &success_callback, &error_callback, ); // 手动泄漏闭包,避免被 Rust 回收(JS 端会持有引用) success_callback.forget(); error_callback.forget(); }
方式二:异步/await 式实现
如果更习惯用异步语法,可以借助 wasm-bindgen-futures 将浏览器的 Promise 转换为 Rust 的 Future:
use wasm_bindgen::prelude::*; use wasm_bindgen_futures::JsFuture; use web_sys::{Geolocation, Navigator, PositionOptions}; use serde::Serialize; // 定义用于序列化位置数据的结构体 #[derive(Serialize)] #[wasm_bindgen] pub struct LocationData { pub latitude: f64, pub longitude: f64, pub accuracy: f64, } #[wasm_bindgen] pub async fn get_location() -> Result<LocationData, JsValue> { // 获取 navigator 和 geolocation 对象 let navigator = Navigator::from(js_sys::global().unchecked_into::<js_sys::Object>()); let geolocation = navigator.geolocation().ok_or("当前浏览器不支持地理定位")?; // 配置定位选项 let options = PositionOptions::new(); options.set_enable_high_accuracy(true); options.set_timeout(10000); options.set_maximum_age(0); // 等待定位结果(将 JS Promise 转为 Rust Future) let position = JsFuture::from(geolocation.get_current_position_with_options(&options)).await?; let position = position.dyn_into::<web_sys::Position>()?; let coords = position.coords(); // 构造位置数据并返回给 JS Ok(LocationData { latitude: coords.latitude(), longitude: coords.longitude(), accuracy: coords.accuracy(), }) }
3. JS 端调用代码
用 wasm-pack 编译项目(wasm-pack build --target web)后,在 JS 中引入并调用:
import init, { request_location, get_location } from './pkg/gps_wasm.js'; async function initApp() { await init(); // 初始化 WASM 模块 // 调用回调式定位函数 request_location(); // 调用异步式定位函数 try { const location = await get_location(); console.log('异步获取位置:', location); // 在这里处理位置数据,比如显示在页面上 } catch (err) { console.error('异步定位失败:', err); } } initApp();
关键注意事项
- 环境要求:浏览器仅在 HTTPS 环境(localhost 除外)下允许访问地理定位 API,本地开发可以用
localhost测试。 - 权限处理:浏览器会弹出权限请求,用户必须允许才能获取位置,代码中要处理用户拒绝的情况。
- 错误处理:务必处理浏览器不支持定位、超时、权限拒绝等异常场景,避免 WASM 模块 panic。
内容的提问来源于stack exchange,提问作者Alper
相关产品推荐
相关产品推荐

