@@ -8,9 +8,12 @@ import androidx.compose.foundation.layout.wrapContentSize
8
8
import androidx.compose.runtime.Composable
9
9
import androidx.compose.ui.Alignment
10
10
import androidx.compose.ui.Modifier
11
+ import androidx.compose.ui.geometry.Offset
12
+ import androidx.compose.ui.graphics.TransformOrigin
11
13
import androidx.compose.ui.graphics.graphicsLayer
12
14
import androidx.compose.ui.input.pointer.PointerEventType
13
15
import androidx.compose.ui.input.pointer.pointerInput
16
+ import androidx.compose.ui.unit.IntSize
14
17
import com.squareup.workflow1.traceviewer.SandboxState
15
18
16
19
/* *
@@ -22,6 +25,7 @@ import com.squareup.workflow1.traceviewer.SandboxState
22
25
*/
23
26
@Composable
24
27
internal fun SandboxBackground (
28
+ appWindowSize : IntSize ,
25
29
sandboxState : SandboxState ,
26
30
modifier : Modifier = Modifier ,
27
31
content : @Composable () -> Unit ,
@@ -41,14 +45,30 @@ internal fun SandboxBackground(
41
45
awaitEachGesture {
42
46
val event = awaitPointerEvent()
43
47
if (event.type == PointerEventType .Scroll ) {
44
- val scrollDelta = event.changes.first().scrollDelta.y
48
+ val pointerInput = event.changes.first()
49
+ val pointerOffsetToCenter = Offset (
50
+ // The x scale seems to be a little different than y, and (3/2) seemed to make zooming
51
+ // smoother easier than just dividing by 2.
52
+ x = pointerInput.position.x - appWindowSize.width / (3 / 2 ),
53
+ y = pointerInput.position.y - appWindowSize.height / 2
54
+ )
55
+ val scrollDelta = pointerInput.scrollDelta.y
45
56
// Applies zoom factor based on the actual delta change rather than just the act of scrolling
46
57
// This helps to normalize mouse scrolling and touchpad scrolling, since touchpad will
47
58
// fire a lot more scroll events.
48
59
val factor = 1f + (- scrollDelta * 0.1f )
49
60
val minWindowSize = 0.1f
50
- val maxWindowSize = 10f
51
- sandboxState.scale = (sandboxState.scale * factor).coerceIn(minWindowSize, maxWindowSize)
61
+ val maxWindowSize = 2f
62
+ val oldScale = sandboxState.scale
63
+ val newScale = (oldScale * factor).coerceIn(minWindowSize, maxWindowSize)
64
+ val scaleRatio = newScale / oldScale
65
+
66
+ val newOrigin = sandboxState.offset - pointerOffsetToCenter
67
+ val scaledView = newOrigin * scaleRatio
68
+ val resetViewOffset = scaledView + pointerOffsetToCenter
69
+ sandboxState.offset = resetViewOffset
70
+ sandboxState.scale = newScale
71
+
52
72
event.changes.forEach { it.consume() }
53
73
}
54
74
}
0 commit comments