Skip to content

Commit 3e6909e

Browse files
authored
xilem_web: Extend svgdraw example to be an infinite zoomable canvas (#734)
This allows zooming with the mousewheel and panning with the mid/right mouse button. I think it would be nice to add touch support with a pinch gesture handler as well. It also replaces the random color with a color selector. And makes the stroke width range logarithmic. And adds `type_` and `name` attributes to `HtmlInputElement`. It was also optimized by using an `Rc<AnyDomView>` to memoize all previously drawn lines. This way I think the bottleneck now certainly is the browser.
1 parent 0e9d2ec commit 3e6909e

File tree

6 files changed

+219
-67
lines changed

6 files changed

+219
-67
lines changed

xilem_web/src/interfaces.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,13 +822,43 @@ pub trait HtmlInputElement<State, Action = ()>:
822822
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
823823
///
824824
/// # fn component() -> impl HtmlInputElement<()> {
825-
/// input(()).attr("type", "checkbox").checked(true) // results in <input type="checkbox" checked></input>
825+
/// input(()).type_("checkbox").checked(true) // results in <input type="checkbox" checked></input>
826826
/// # }
827827
/// ```
828828
fn checked(self, checked: bool) -> html_input_element::view::Checked<Self, State, Action> {
829829
html_input_element::view::Checked::new(self, checked)
830830
}
831831

832+
/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/type> for more details.
833+
///
834+
/// # Examples
835+
///
836+
/// ```
837+
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
838+
///
839+
/// # fn component() -> impl HtmlInputElement<()> {
840+
/// input(()).type_("radio") // results in <input type="radio"></input>
841+
/// # }
842+
/// ```
843+
fn type_(self, value: impl Into<Cow<'static, str>>) -> Attr<Self, State, Action> {
844+
Attr::new(self, "type".into(), value.into().into_attr_value())
845+
}
846+
847+
/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/name> for more details.
848+
///
849+
/// # Examples
850+
///
851+
/// ```
852+
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
853+
///
854+
/// # fn component() -> impl HtmlInputElement<()> {
855+
/// input(()).name("color") // results in <input name="color"></input>
856+
/// # }
857+
/// ```
858+
fn name(self, value: impl Into<Cow<'static, str>>) -> Attr<Self, State, Action> {
859+
Attr::new(self, "name".into(), value.into().into_attr_value())
860+
}
861+
832862
/// See <https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/checked> for more details.
833863
///
834864
/// # Examples
@@ -837,7 +867,7 @@ pub trait HtmlInputElement<State, Action = ()>:
837867
/// use xilem_web::{interfaces::{Element, HtmlInputElement}, elements::html::input};
838868
///
839869
/// # fn component() -> impl HtmlInputElement<()> {
840-
/// input(()).attr("type", "radio").default_checked(true) // results in <input type="radio" checked></input>
870+
/// input(()).type_("radio").default_checked(true) // results in <input type="radio" checked></input>
841871
/// # }
842872
/// ```
843873
fn default_checked(

xilem_web/web_examples/fetch/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ fn cat_fetch_controls(state: &AppState) -> impl Element<AppState> {
175175
td(label("How many cats would you like?").for_("cat-count")),
176176
td(input(())
177177
.id("cat-count")
178-
.attr("type", "number")
178+
.type_("number")
179179
.attr("min", 0)
180180
.attr("value", state.cats_to_fetch)
181181
.on_input(|state: &mut AppState, ev: web_sys::Event| {
@@ -193,7 +193,7 @@ fn cat_fetch_controls(state: &AppState) -> impl Element<AppState> {
193193
),
194194
td(input(())
195195
.id("reset-debounce-update")
196-
.attr("type", "checkbox")
196+
.type_("checkbox")
197197
.checked(state.reset_debounce_on_update)
198198
.on_input(|state: &mut AppState, event: web_sys::Event| {
199199
state.reset_debounce_on_update = input_target(&event).checked();
@@ -203,7 +203,7 @@ fn cat_fetch_controls(state: &AppState) -> impl Element<AppState> {
203203
td(label("Debounce timeout in ms:").for_("debounce-timeout-duration")),
204204
td(input(())
205205
.id("debounce-timeout-duration")
206-
.attr("type", "number")
206+
.type_("number")
207207
.attr("min", 0)
208208
.attr("value", state.debounce_in_ms)
209209
.on_input(|state: &mut AppState, ev: web_sys::Event| {

xilem_web/web_examples/mathml_svg/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn slider(
4848
cb: fn(&mut Triangle, web_sys::Event),
4949
) -> impl HtmlInputElement<Triangle> {
5050
html::input(())
51-
.attr("type", "range")
51+
.type_("range")
5252
.attr("min", 1)
5353
.attr("max", max)
5454
.attr("value", value)

xilem_web/web_examples/svgdraw/index.html

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,48 @@
1414
touch-action: none;
1515
}
1616

17-
.controls {
17+
input[type=radio] {
18+
display: none;
19+
}
20+
21+
.color>input[type=radio]:checked+div {
22+
transform: scale(1.25);
23+
}
24+
25+
.color>input[type=radio]+div {
26+
transition: transform 0.3s ease-in-out;
27+
border-radius: 50%;
28+
border-color: black;
29+
border-width: 1px;
30+
border-style: solid;
31+
width: 23px;
32+
height: 23px;
33+
margin: 2.2px;
34+
background-color: red;
1835
display: block;
36+
}
37+
38+
.color {
39+
display: inline-block
40+
}
41+
42+
.controls {
43+
position: absolute;
1944
left: 0;
20-
right: 0;
21-
margin-inline: auto;
2245
width: fit-content;
2346
height: 1.5rem;
24-
padding-top: 0.25rem;
25-
padding-bottom: 0.25rem;
47+
padding: 1.0rem;
48+
font-family: Arial, Helvetica, sans-serif, monospace;
2649
}
2750

28-
.controls>span {
29-
vertical-align: top;
51+
.controls>div {
52+
margin-bottom: 10px;
3053
}
3154

3255
.value-range {
33-
display: inline-block;
34-
position: relative;
56+
position: absolute;
3557
height: 1.5rem;
3658
width: 20rem;
37-
3859
}
3960

4061
.value-range::before,
@@ -53,12 +74,12 @@
5374
.value-range::before {
5475
text-align: left;
5576
/* hardcoded values aren't optimal here, but this example is not about styling/layouting */
56-
content: "1";
77+
content: "0.1";
5778
}
5879

5980
.value-range::after {
6081
text-align: right;
61-
content: "30";
82+
content: "1000";
6283
}
6384

6485
input[type=range] {
@@ -95,7 +116,6 @@
95116

96117
label {
97118
line-height: 1.5rem;
98-
position: absolute;
99119
}
100120
</style>
101121
</head>

0 commit comments

Comments
 (0)