Skip to content

Commit 550369f

Browse files
author
Jihye Hong
authored
Merge pull request #3755 from jihyerish/improve-distance-function
[css-nav-1] Modify the definition of the distance function
2 parents a91609b + 25efd08 commit 550369f

File tree

3 files changed

+97
-35
lines changed

3 files changed

+97
-35
lines changed

css-nav-1/Overview.bs

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,11 +1041,11 @@ Issue(w3c/csswg-drafts#2324): CSS should have a term for “border box taking in
10411041

10421042
To <dfn lt="find focusable areas | finding focusable areas">find focusable areas</dfn> within a containing element <var>C</var>,
10431043
with an optional <var>visibleOnly</var> argument that defaults to <code>true</code>,
1044-
follow the following steps:
1044+
run the following steps:
10451045

10461046
1. Let <var>focusables</var> be the <a spec=infra for="/">set</a> of all the <a>focusable areas</a> whose [=DOM anchor=] are descendants of <var>C</var>.
10471047
In the case of [=boxes=] with several [=box fragments=], each [=box fragment=] is considered separately.
1048-
2. The UA should <a spec=infra for=set>remove</a> from <var>focusables</var> items that have a [=DOM anchor=] whose <a element-attr spec=html><code>tabindex</code></a> attribute is set to a negative value.
1048+
2. The User Agent should <a spec=infra for=set>remove</a> from <var>focusables</var> items that have a [=DOM anchor=] whose <a element-attr spec=html><code>tabindex</code></a> attribute is set to a negative value.
10491049

10501050
Note: This is a "SHOULD" in order to mirror the exclusion of elements with negative tabindex
10511051
from the <a>sequential focus navigation order</a> as defined in [[HTML#the-tabindex-attribute]].
@@ -1087,7 +1087,7 @@ To <dfn lt="select the best candidate | selecting the best candidate">select the
10871087
within a <a spec=infra for="/">set</a> of <var>candidates</var>
10881088
in a direction <var>dir</var>,
10891089
starting from <var>searchOrigin</var>,
1090-
follow the following steps:
1090+
run the following steps:
10911091

10921092
1. If <var>candidates</var> is <a spec=infra for=set>empty</a>, return <code>null</code>
10931093
2. If <var>candidates</var> contains a single item, return that item
@@ -1098,19 +1098,19 @@ follow the following steps:
10981098
4. Let <var>insiders</var> be the subset of <var>candidates</var> items
10991099
whose [=DOM anchor=] are descendants of <var>searchOrigin</var>
11001100
and whose <a>boundary box</a>'s
1101-
* top edge is below the top edge of <var>insideArea</var> if <var>D</var> is <code>down</code>
1102-
* bottom edge is above the bottom edge of <var>insideArea</var> if <var>D</var> is <code>up</code>
1103-
* right edge is left of the right edge of <var>insideArea</var> if <var>D</var> is <code>left</code>
1104-
* left edge is right of the left edge of <var>insideArea</var> if <var>D</var> is <code>right</code>
1101+
* top edge is below the top edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/down}}
1102+
* bottom edge is above the bottom edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/up}}
1103+
* right edge is left of the right edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/left}}
1104+
* left edge is right of the left edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/right}}
11051105

11061106
Note: this sub-setting is necessary to avoid going in the opposite direction than the one requested.
11071107
5.
11081108
* If <var>insiders</var> is non empty
11091109
1. Let <var>closest subset</var> be the subset of <var>insiders</var> whose <a>boundary box</a>'s
1110-
* top edge is closest to the top edge of <var>insideArea</var> if <var>D</var> is <code>down</code>
1111-
* bottom edge is closest to the bottom edge of <var>insideArea</var> if <var>D</var> is <code>up</code>
1112-
* right edge is closest to the right edge of <var>insideArea</var> if <var>D</var> is <code>left</code>
1113-
* left edge is closest to the left edge of <var>insideArea</var> if <var>D</var> is <code>right</code>
1110+
* top edge is closest to the top edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/down}}
1111+
* bottom edge is closest to the bottom edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/up}}
1112+
* right edge is closest to the right edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/left}}
1113+
* left edge is closest to the left edge of <var>insideArea</var> if <var>dir</var> is {{SpatialNavigationDirection/right}}
11141114
2. If <var>closest subset</var> contains a single item,
11151115
return that item,
11161116
else return the first item of <var>closest subset</var> in document order,
@@ -1123,38 +1123,100 @@ follow the following steps:
11231123
1. Set <var>candidates</var> be the subset of its items
11241124
whose <a>boundary box</a>'s geometric center is within the closed half plane
11251125
whose boundary goes through the geometric center of the <var>searchOrigin</var>
1126-
and is perpendicular to <var>D</var>.
1126+
and is perpendicular to <var>dir</var>.
11271127
2. For each <var>candidate</var> in <var>candidates</var>,
1128-
find the points <var>P1</var> inside the <a>boundary box</a> of <var>searchOrigin</var>
1129-
and <var>P2</var> inside the <a>boundary box</a> of <var>candidate</var>
1130-
that minimize the <var>distance</var> between these two points,
1131-
when <var>distance</var> is defined as follows:
1132-
1133-
<dl>
1134-
<dt><var>distance</var>:
1135-
<dd><var>A</var> + <var>B</var> + <var>C</var> - <var>D</var>
1136-
1137-
<dt><var>A</var>:
1138-
<dd>The euclidian distance between <var>P1</var> and <var>P2</var>
1139-
1140-
<dt><var>B</var>:
1141-
<dd>The absolute distance in the <var>dir</var> direction between <var>P1</var> and <var>P2</var>
1142-
1143-
<dt><var>C</var>:
1144-
<dd>The absolute distance in the direction which is orthogonal to <var>dir</var> between <var>P1</var> and <var>P2</var>
1145-
1146-
<dt><var>D</var>:
1147-
<dd>The square root of the area of intersection between the <a>boundary boxes</a> of <var>candidate</var> and <var>searchOrigin</var>
1148-
</dl>
1149-
3. Return the item of the <var>candidates</var> set that has the smallest <var>distance</var>.
1128+
1. If the <var>searchOrigin</var> is an element, then find the points <var>P1</var> inside the <a>boundary box</a>
1129+
of <var>searchOrigin</var> and P2 inside the boundary box of <var>candidate</var>.
1130+
2. Else if the <var>searchOrigin</var> is a point, then let the point <var>P1</var> be the <var>searchOrigin</var>
1131+
and find the point <var>P2</var> inside the <a>boundary box</a>.
1132+
3. Let <var>intersectRect</var> be an <dfn>intersecting area</dfn> between the search origin and a candidate.
1133+
4. Select the <var>P1</var> and <var>P2</var> that make the smallest <var>distance</var> between those two points by
1134+
<a>calculating the distance</a>.
1135+
5. Return the item of the <var>candidates</var> set that has the smallest <var>distance</var>.
11501136
If several have the same distance,
11511137
return the first one in document order,
11521138
unless its [=boundary box=] overlaps with the [=boundary box=] of an other item at the same distance,
11531139
and that item is higher in the CSS [=painting order=].
11541140
In that case, return that item instead,
1155-
unless it too is overlapped with another higher item at the same distance, recursively.
1141+
unless it too is overlapped with another higher item at the same distance, recursively.
1142+
</div>
1143+
1144+
<div algorithm="to calculate the distance">
1145+
To <dfn lt="calculating the distance | to calculate the distance">calculate the <var>distance</var></dfn>, the function is defined as below:
1146+
1147+
<pre class="prod">
1148+
<var>distance</var> = <var>euclidian</var> + <var>displacement</var> - <var>alignment</var> - <var>sqrt(Overlap)</var>
1149+
</pre>
1150+
1151+
The meaning of each factor in the function is as follows:
1152+
1153+
<dl dfn-type="value" dfn-for="spatial-navigation-distance-function">
1154+
<dt><var>euclidian</var>
1155+
<dd>The euclidian distance between <var>P1</var> and <var>P2</var>
1156+
1157+
<dt><var>displacement</var>
1158+
<dd>The degree of displacement in <var>dir</var> between <var>searchOrigin</var> and <var>candidate</var>
1159+
<dd>Defined as <pre class="prod">(absolute distance on the axis orthogonal to <var>dir</var> + <var>orthogonalBias</var>) * <var>orthogonalWeight</var></pre>
1160+
1161+
* <var>orthogonalBias</var>
1162+
* If the <var>dir</var> is {{SpatialNavigationDirection/left}} or {{SpatialNavigationDirection/right}},
1163+
height of <var>searchOrigin</var> / 2
1164+
* Else if the <var>dir</var> is {{SpatialNavigationDirection/up}} or {{SpatialNavigationDirection/down}},
1165+
width of <var>searchOrigin</var> / 2
1166+
1167+
* <var>orthogonalWeight</var>:
1168+
* If the <var>dir</var> is {{SpatialNavigationDirection/left}} or {{SpatialNavigationDirection/right}}, 30
1169+
* Else if the <var>dir</var> is {{SpatialNavigationDirection/up}} or {{SpatialNavigationDirection/down}}, 2
1170+
1171+
<dt><var>alignment</var>
1172+
<dd>The degree of alignment in <var>dir</var> between <var>searchOrigin</var> and <var>candidate</var>
1173+
<dd>Defined as <pre class="prod"><var>alignBias</var> * <var>alignWeight</var></pre>
11561174

1175+
* <var>alignBias</var>
11571176

1177+
* If the <var>dir</var> is {{SpatialNavigationDirection/left}} or {{SpatialNavigationDirection/right}},
1178+
height of <var>intersectRect</var> / height of <var>candidate</var>
1179+
* Else if the <var>dir</var> is {{SpatialNavigationDirection/up}} or {{SpatialNavigationDirection/down}},
1180+
width of <var>intersectRect</var> / width of <var>candidate</var>
1181+
1182+
* <var>alignWeight</var> is 5
1183+
1184+
<dt><var>sqrt(Overlap)</var>
1185+
<dd>The square root of an <a>overlapping area</a> between the <a>boundary boxes</a> of <var>searchOrigin</var> and <var>candidate</var>
1186+
<dd>Let <var>overlapRect</var> be
1187+
<var>intersectRect</var> if the <a>overlapping area</a> exists,
1188+
and 0 otherwise.
1189+
<dd>Defined as <pre class="prod">sqrt(height of <var>overlapRect</var> * width of <var>overlapRect</var>)</pre>
1190+
</dl>
1191+
1192+
NOTE: The values of <var>alignWeight</var> and <var>orthogonalWeight</var> in the function are decided based on
1193+
the collected <a href="https://wicg.github.io/spatial-navigation/tests/ux/list.html">UX test cases</a>.
1194+
It aims to show the generally expected result in the real pages.
1195+
Everyone is welcome to contribute to the test cases!
1196+
1197+
<div class='example'>
1198+
This example shows how the <a>intersecting area</a>(<var>intersectRect</var>) is defined.
1199+
1200+
<figure>
1201+
<img alt="" src="images/intersecting-area-1.png" style="height: 200px;"/>
1202+
<figcaption>The <a>intersecting area</a> when there is the <a>overlapping area</a>.</figcaption>
1203+
</figure>
1204+
1205+
The figure above is the simplest case to define the <a>intersecting area</a>.
1206+
The <dfn>overlapping area</dfn> is the geometric overlap region between the two elements.
1207+
In this case, the <a>intersecting area</a> is the same as the <a>overlapping area</a> without reference to the direction of the navigation.
1208+
1209+
<figure>
1210+
<img alt="" src="images/intersecting-area-2.png" style="height: 200px;"/>
1211+
<figcaption>The <a>intersecting area</a> when the elements are aligned.</figcaption>
1212+
</figure>
1213+
1214+
In the case above, the search origin element and the candidate element are aligned and the requested direction is {{SpatialNavigationDirection/right}}.
1215+
The <a>intersecting area</a> is created with
1216+
(1) The gap between two elements.
1217+
(2) The parts of the edges from each element which are overlapped
1218+
when the right edge of the search origin element and the left edge of the candidate are projected to each other.
1219+
</div>
11581220
</div>
11591221

11601222
<div class=cssapi>
18.6 KB
Loading
19.4 KB
Loading

0 commit comments

Comments
 (0)