Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
'mobile-ui' => [
'name' => 'nativephp/mobile-ui',
'baseline' => '0.3',
'released_versions' => ['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7'],
'released_versions' => ['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9'],
],
],

Expand Down
80 changes: 74 additions & 6 deletions resources/views/docs/mobile/4/edge-components/gesture-area.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ order: 225

## Overview

Captures a vertical pan/drag gesture over its content and writes the translation to a bound
[shared value](../digging-deeper/gestures), so the drag can drive animation on the UI thread with no PHP round-trip.
Children render normally — gesture detection wraps the whole content frame.
Captures drag and pinch gestures over its content and writes them to bound
[shared values](../digging-deeper/gestures), so the gesture can drive animation on the UI thread with no PHP
round-trip. Children render normally — gesture detection wraps the whole content frame.

@verbatim
```blade static
Expand All @@ -27,9 +27,18 @@ screen in your app and drag the card.

## Props

- `pan-y` - A [`SharedValue`](../digging-deeper/gestures) that receives the vertical drag translation (required for
the gesture to do anything). Bind it, then read it from animatable props (`translate-y`, `opacity`, `scale`, …)
on the children.
- `pan-y` - A [`SharedValue`](../digging-deeper/gestures) that receives the vertical drag translation. Bind it, then
read it from animatable props (`translate-y`, `opacity`, `scale`, …) on the children.
- `pan-x` - The same for the horizontal drag translation. Bind one axis or both.
- `pinch` - A `SharedValue` that receives the pinch scale factor, where `1` is the content's own size. Read it from
`scale` on the children.
- `pinch-min` / `pinch-max` - The smallest and largest the pinch scale can go (optional, float). The limit is applied
as the fingers move, so the scale never runs past it and a pinch that changes direction responds straight away.
- `bounded` <x-docs.version-badge since="4.7" /> <x-docs.version-badge package="mobile-ui" since="0.9" /> - Keep zoomed content on screen (optional, boolean). See
[Zoomable images](#zoomable-images).
- `content-ratio` <x-docs.version-badge since="4.7" /> <x-docs.version-badge package="mobile-ui" since="0.9" /> - The content's width over height, for `bounded` (optional, float).
The content is taken to be that shape fitted inside the area, which is where an image with `fit="contain"` draws.
Leave it out when the content fills the area.

<aside>

Expand All @@ -38,3 +47,62 @@ through PHP during the gesture. See [Gestures & Animation](../digging-deeper/ges
interpolation formulas.

</aside>

## Zoomable images

<x-docs.version-badge since="4.7" /> <x-docs.version-badge package="mobile-ui" since="0.9" />

With `bounded`, the gesture area keeps zoomed content inside its own edges, the way a photo viewer does:

- Zoomed in, the content pans until its edges meet the area's edges, and no further.
- On an axis where the zoomed content still fits, such as the height of a wide photo, it stays centered. At its own
size it fits both ways, so it doesn't move at all.
- A drag past an edge moves with resistance, and the content springs back into place when the finger lifts.
- A pinch zooms around the point between the fingers, and two fingers pan as they pinch.

Bind both pan axes and the pinch, bind the content's transforms to the same values, and pass the image's shape as
`content-ratio`:

@verbatim
```blade static
<native:gesture-area
:pinch="$zoom" pinch-min="1" pinch-max="4"
:pan-x="$panX" :pan-y="$panY"
bounded :content-ratio="$width / $height"
class="w-full flex-1">
<native:image
:src="$url"
fit="contain"
:scale="$zoom"
:translate-x="$panX"
:translate-y="$panY"
class="w-full h-full"
/>
</native:gesture-area>
```
@endverbatim

The shared values live on the component. Making fresh ones puts the image back at its own size, in the middle:

```php
use Native\Mobile\Edge\SharedValue;

public ?SharedValue $zoom = null;
public ?SharedValue $panX = null;
public ?SharedValue $panY = null;

public function showImage(): void
{
$this->zoom = SharedValue::make(1.0);
$this->panX = SharedValue::make();
$this->panY = SharedValue::make();
}
```

<aside>

Without `content-ratio` the bounds are the area itself. That's right for content that fills the area, but an image
drawn smaller than the area (with bars above and below, or at the sides) could then be pulled partly off screen.
Pass its width over height so the bounds match the picture.

</aside>
Loading