react-native-skia icon indicating copy to clipboard operation
react-native-skia copied to clipboard

[ iOS 18 Simulator regression] Scrolling Freezes When Canvas is offscreen

Open wcandillon opened this issue 8 months ago • 5 comments

Description

This issue only happens on Simulator v18 and above.

We're hitting the same issue as https://github.com/rive-app/rive-react-native/issues/294 When on simulator, invoking CAMetalLayer::nextDrawable can take up to 1 second if the canvas is offscreen (e.g., presenting the surface doesn't change any pixels on screen).

Doing gesture events while still having the canvas offscreen will result in having the correct framerate.

React Native Skia Version

latest

React Native Version

confirmed on 0.78 and 0.79

Using New Architecture

  • [x] Enabled

Steps to Reproduce

use the example below

Snack, Code Example, Screenshot, or Link to Repository

import React, { useEffect } from "react";
import {
  Canvas,
  LinearGradient,
  Fill,
  // Use this function instead of interpolateColor from Reanimated
  interpolateColors,
  vec,
} from "@shopify/react-native-skia";
import {
  useDerivedValue,
  useSharedValue,
  withRepeat,
  withTiming,
} from "react-native-reanimated";
import { Text, useWindowDimensions, View } from "react-native";
import { ScrollView } from "react-native-gesture-handler";

const startColors = [
  "rgba(34, 193, 195, 0.4)",
  "rgba(34,193,195,0.4)",
  "rgba(63,94,251,1)",
  "rgba(253,29,29,0.4)",
];
const endColors = [
  "rgba(0,212,255,0.4)",
  "rgba(253,187,45,0.4)",
  "rgba(252,70,107,1)",
  "rgba(252,176,69,0.4)",
];

const AnimatedGradient = () => {
  const { width, height } = useWindowDimensions();
  const colorsIndex = useSharedValue(0);
  useEffect(() => {
    colorsIndex.value = withRepeat(
      withTiming(startColors.length - 1, {
        duration: 4000,
      }),
      -1,
      true
    );
  }, [colorsIndex]);
  const gradientColors = useDerivedValue(() => {
    return [
      interpolateColors(colorsIndex.value, [0, 1, 2, 3], startColors),
      interpolateColors(colorsIndex.value, [0, 1, 2, 3], endColors),
    ];
  });
  console.log("Rendering");
  return (
    <Canvas style={{ width: 300, height: 300, backgroundColor: "white" }}>
      <Fill>
        <LinearGradient
          start={vec(0, 0)}
          end={vec(width, height)}
          colors={gradientColors}
        />
      </Fill>
    </Canvas>
  );
};

export const Breathe = () => {
  return (
    <ScrollView contentContainerStyle={{ flexGrow: 1, gap: 20, padding: 20 }}>
      <AnimatedGradient />
      <Text>
        Start scrolling until the Animated Skia Component is off-screen
      </Text>
      <View style={{ height: 1000 }} />
    </ScrollView>
  );
};

wcandillon avatar Apr 26 '25 19:04 wcandillon

+1

Yurii-Lutsyk avatar May 16 '25 08:05 Yurii-Lutsyk

And i guess it's not only ios problem, android has the same problem

Yurii-Lutsyk avatar May 16 '25 08:05 Yurii-Lutsyk

it's an interesting comment because on a older iOS simulator (same React/React Native version), the bug doesn't appear.

On Fri, May 16, 2025 at 10:11 AM Yurii Lutsyk @.***> wrote:

And i guess it's not only ios problem, android has the same problem

— Reply to this email directly, view it on GitHub or unsubscribe. You are receiving this email because you authored the thread.

Triage notifications on the go with GitHub Mobile for iOS or Android.

wcandillon avatar May 16 '25 08:05 wcandillon

+1 Same, the screen is unusable when the canvas is offscreen, scroll and whole ui thread freezes. Good thing it's only effecting the simulator

Elmosh avatar May 17 '25 19:05 Elmosh

I'm not sure if this issue is related at all, but I experienced some freezes on real Android and iOS devices. The freezing happens only on some devices (e.g., only iPhone, never had it on an iPad). Also, the scrolling remains intact; instead, everything else is frozen (the app is completely unresponsive to any input, like buttons or input fields, except the scrolling).

mbpictures avatar Oct 10 '25 21:10 mbpictures