You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:43:15