scrolling feels slightly weird on WASM ... normall...
# webassembly
k
scrolling feels slightly weird on WASM ... normally on mac chrome, you have a very different kind of smooth scrolling, compose WASM targets have a weirdly static velocity of a smooth scroll, is this related to OS/platform or Chrome capabilities, or is it about
Canvas
vs
HTML DOM
k
What version of compose do you use?
k
1.11.0
also, https://github.com/sdfgsdfgd/backend/blob/main/dashboard/src/commonMain/kotlin/net/sdfgsdfg/dashboard/DashboardApp.kt#L137-L143 is where I reproduce this, in
LazyColumn
I'm testing if background image I'm displaying could be causing this scroll/fling velocity cap to the scrolling , I'll also test moving scroll to
.body
@Konstantin Tskhovrebov wow, it actually fixes it if you use the snippet I mention below issue seems to be specifically in Compose/Wasm's default wheel/trackpad delta handling for `*LazyColumn*`: small deltas are fine, but higher-velocity trackpad/fling input appears normalized/coalesced/clamped before the list gets useful velocity. The stock composable container was not doing a browser-native-feeling transfer of wheel delta to list scroll distance on Chrome/macOS. workaround:
WheelEvent.deltaY * modeScale * gain -> external Compose state -> LazyListState.scrollBy(delta)
This strongly suggests the fix belongs in the Compose/Wasm scroll input pipeline rather than in app layout/rendering. Heavy content can amplify bad feel, but it was not the root cause of the capped max velocity.
Copy code
// wasm entrypoint
  var wheelScrollPx by remember { mutableStateOf(0f) }

  DisposableEffect(Unit) {
      val target = document.getElementById("dashboard") ?: document
      val listener = { event: Event ->
          val wheel = event as? WheelEvent
          if (wheel != null && !wheel.ctrlKey) {
              event.preventDefault()
              event.stopPropagation()

              val modeScale = when (wheel.deltaMode.toInt()) {
                  1 -> 16.0
                  2 -> window.innerHeight.toDouble()
                  else -> 1.0
              }

              wheelScrollPx += (wheel.deltaY * modeScale * 1.35).toFloat()
          }
      }
      target.addEventListener("wheel", listener, true)
      onDispose { target.removeEventListener("wheel", listener, true) }
  }

  DashboardApp(externalScrollPx = wheelScrollPx)

  // shared dashboard root
  fun DashboardApp(externalScrollPx: Float = 0f) {
      var handledExternalScrollPx by remember { mutableStateOf(externalScrollPx) }
      val listState = rememberLazyListState()

      LaunchedEffect(externalScrollPx) {
          val delta = externalScrollPx - handledExternalScrollPx
          handledExternalScrollPx = externalScrollPx
          if (delta != 0f) listState.scrollBy(delta)
      }

      LazyColumn(state = listState) {
          // dashboard content
      }
  }
k
could you create an issue https://youtrack.jetbrains.com/newissue?project=CMP with a reproducer of the problem and the suggested fix, please 🙏
k
yes, I'm doing that soon 👍
perfect, maybe I'll provide the internal patch too if you guys want me to work on it, lets finish some good work https://youtrack.jetbrains.com/issue/CMP-10297/
PR is ready for review: https://github.com/JetBrains/compose-multiplatform-core/pull/3105 The fix is intentionally small: Web
WheelEvent.DOM_DELTA_PIXEL
events are treated as precise wheel input, so high-resolution Chrome/macOS trackpad deltas bypass the common mouse-wheel smoothing path instead of being capped by the initial
6.dp
threshold. The regression failed before the patch with
Expected <200>, actual <12>
and now passes on both JS and Wasm browser targets.
k
thank you, I will have a look soon
u
+1 same thing for me I'm just trying out wasm in the browser, and was surprised that overall perf is really good but the scroll on MacOS + trackpad feels weird and would put me off using it
also - I'm now trying out chrome on windows with a mouse (scroll wheel) and have 0 issues with that, would never know its wasm