我正在Rust中构建一个紫杉web应用程序,并试图从CSS选择器中获得一个CanvasRenderingContext2d。我遇到的问题是如何将stdweb::web::Element
转换为stdweb::web::html_element::CanvasElement
。
我的当前代码是:
use stdweb::web::{CanvasRenderingContext2d, document, Element, IParentNode};
use stdweb::web::html_element::CanvasElement;
fn get_canvas_context(selector: &str) -> CanvasRenderingContext2d {
let element: Element = document().query_selector(selector)
.expect(format!("query_selector({selector}) not found").as_str())
.unwrap()
;
// BUG: the trait `From<stdweb::web::Element>` is not implemented for `CanvasElement`
let canvas_element: CanvasElement = element
.try_into()
.expect(format!("query_selector({selector}) not CanvasElement").as_str())
;
let context: CanvasRenderingContext2d = canvas_element.get_context()
.expect(format!("query_selector({selector}) failed to get_context()").as_str())
;
context
}
cargo check
报告以下错误
error[E0277]: the trait bound `CanvasElement: From<stdweb::web::Element>` is not satisfied
--> src/utils.rs:12:10
|
12 | .try_into()
| ^^^^^^^^ the trait `From<stdweb::web::Element>` is not implemented for `CanvasElement`
|
= note: required because of the requirements on the impl of `Into<CanvasElement>` for `stdweb::web::Element`
= note: required because of the requirements on the impl of `std::convert::TryFrom<stdweb::web::Element>` for `CanvasElement`
= note: required because of the requirements on the impl of `std::convert::TryInto<CanvasElement>` for `stdweb::web::Element`
我的最终目标是返回一个我认为需要canvas_element.get_context()
的CanvasRenderingContext2d
正确的做法是什么?
试试dyn_into
:
let canvas = document
.get_element_by_id("my-canvas")
.unwrap()
.dyn_into::<web_sys::HtmlCanvasElement>()?;
更多信息见JsCast
文档。
感谢@ben用你上面的答案激励了我。
该代码在实践中实现比您的代码片段所建议的要复杂一些。然而,你的提示使用.dyn_into()
从JsCast允许我搜索github更多的代码示例。
经过几天的努力,我终于能够编译和呈现以下代码片段:
- 灵感:https://github.com/jessaimaya/rust_wasm/blob/89cea2a7aea240f6bd3ec8722e539aca35cee73c/src/browser.rs
- 来源:https://github.com/JamesMcGuigan/fractals/blob/1c5d8bbf5cee6f02536205cd9036f71597f523f1/src/html/canvas_context.rs
use anyhow::{anyhow, Result};
use wasm_bindgen::JsCast;
use web_sys::{CanvasRenderingContext2d, Document, HtmlCanvasElement, Window};
#[allow(dead_code)]
// DOCS: https://developer.mozilla.org/en-US/docs/Web/API/Window
pub fn window() -> Result<Window> {
web_sys::window()
.ok_or_else(|| anyhow!("No Window Found"))
}
#[allow(dead_code)]
// DOCS: https://developer.mozilla.org/en-US/docs/Web/API/Document
pub fn document() -> Result<Document> {
window()?
.document()
.ok_or_else(|| anyhow!("No Document Found"))
}
#[allow(dead_code)]
// DOCS: https://developer.mozilla.org/en-US/docs/Web/API/HtmlCanvasElement
pub fn canvas(id_selector: &str) -> Result<HtmlCanvasElement> {
document()?
.get_element_by_id(id_selector)
.ok_or_else(|| anyhow!("No Canvas Element found with ID 'canvas'"))?
.dyn_into::<web_sys::HtmlCanvasElement>()
.map_err(|element| anyhow!("Error converting {:#?} to HtmlCanvasElement", element))
}
#[allow(dead_code)]
// DOCS: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2d
pub fn canvas_context_2d(id_selector: &str) -> Result<CanvasRenderingContext2d> {
canvas(id_selector)?
.get_context("2d")
.map_err(|js_value| anyhow!("Error getting 2d context {:#?}", js_value))?
.ok_or_else(|| anyhow!("No 2d context found"))?
.dyn_into::<web_sys::CanvasRenderingContext2d>()
.map_err(|element| {
anyhow!(
"Error converting {:#?} to CanvasRenderingContext2d",
element
)
})
}