How to Create Smooth Transitions for SVG Cutout in a React Native Tab Bar?

I’m working on a custom tab bar in a React Native (Expo) application using react-native-reanimated and react-native-svg. I want to create a circular cutout effect that aligns with the tab items, but I’m struggling to achieve smooth transitions on both sides of the cutout without increasing the depth of the circle.

Current Code

import React, { useState, useEffect, useMemo } from 'react';
import { View, StyleSheet, LayoutChangeEvent, useWindowDimensions } from 'react-native';
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
import Animated, {
    useAnimatedStyle,
    useSharedValue,
    useAnimatedProps,
    Easing,
    withTiming,
} from 'react-native-reanimated';
import Svg, { Path } from 'react-native-svg';
import TabBarAnimation from './TabBarAnimation';
import { SafeAreaView } from 'react-native-safe-area-context';

const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const AnimatedPath = Animated.createAnimatedComponent(Path);

const CIRCLE_VERTICAL_OFFSET = -35;

const TabBar = ({ state, descriptors, navigation }: BottomTabBarProps) => {
    const { width } = useWindowDimensions();
    const [dimensions, setDimensions] = useState({ width: width, height: 60 });

    const tabWidth = dimensions.width / state.routes.length;
    const buttonWidth = dimensions.width / state.routes.length;

    const onTabbarLayout = (e: LayoutChangeEvent) => {
        setDimensions({
            height: e.nativeEvent.layout.height,
            width: e.nativeEvent.layout.width,
        });
    };

    const tabPositionX = useSharedValue(0);
    const circleY = useSharedValue(0);
    const animatedStyle = useAnimatedStyle(() => {
        return {
            transform: [{ translateX: tabPositionX.value + 2 }, { translateY: circleY.value }],
        };
    });

    useEffect(() => {
        tabPositionX.value = withTiming(tabWidth * state.index, { duration: 300 });
    }, [state.index, tabWidth]);

    // This part is responsible for creating SVG
    const animatedPathProps = useAnimatedProps(() => {
        const cutoutCenter = tabPositionX.value + tabWidth / 2 + 2; // Center of the cutout
        const cutoutRadius = 30; // Radius of the cutout
        const smoothingFactor = 10; // Factor for smoothing the edges

        return {
            d: `
            M0 0
            H${cutoutCenter - cutoutRadius - smoothingFactor}
            Q${cutoutCenter - cutoutRadius} 0, ${cutoutCenter - cutoutRadius} ${smoothingFactor}
            A${cutoutRadius} ${cutoutRadius} 0 0 0 ${cutoutCenter + cutoutRadius} ${smoothingFactor}
            Q${cutoutCenter + cutoutRadius} 0, ${cutoutCenter + cutoutRadius + smoothingFactor} 0
            H${dimensions.width}
            V${dimensions.height}
            H0
            V0
            Z
          `,
        };
    });

    const circleSize = Math.min(dimensions.height * 0.8, buttonWidth * 0.8);
    const circleMargin = (buttonWidth - circleSize) / 2;

    return (
        <SafeAreaView style={styles.safeArea} edges={['bottom']}>
            <View style={styles.container}>
                <View onLayout={onTabbarLayout} style={styles.tabbar}>
                    <Animated.View
                        style={[styles.circleContainer, animatedStyle, { width: tabWidth }]}
                    >
                        <View
                            style={[
                                styles.circle,
                                {
                                    width: circleSize,
                                    height: circleSize,
                                    borderRadius: circleSize / 2,
                                    top: `${CIRCLE_VERTICAL_OFFSET}%`,
                                },
                            ]}
                        />
                    </Animated.View>
                    <AnimatedSvg
                        width={dimensions.width}
                        height={dimensions.height}
                        style={StyleSheet.absoluteFill}
                    >
                        <AnimatedPath animatedProps={animatedPathProps} fill="black" />
                    </AnimatedSvg>
                    {state.routes.map((route, index) => {
                        const { options } = descriptors[route.key];
                        const label: string =
                            typeof options.tabBarLabel === 'string'
                                ? options.tabBarLabel
                                : typeof options.title === 'string'
                                  ? options.title
                                  : route.name;

                        const isFocused = state.index === index;

                        const onPress = () => {
                            const event = navigation.emit({
                                type: 'tabPress',
                                target: route.key,
                                canPreventDefault: true,
                            });

                            if (!isFocused && !event.defaultPrevented) {
                                navigation.navigate(route.name, route.params);
                            }
                        };

                        const onLongPress = () => {
                            navigation.emit({
                                type: 'tabLongPress',
                                target: route.key,
                            });
                        };

                        return (
                            <TabBarAnimation
                                key={route.name}
                                onPress={onPress}
                                onLongPress={onLongPress}
                                isFocused={isFocused}
                                routeName={route.name}
                                label={label}
                            />
                        );
                    })}
                </View>
            </View>
        </SafeAreaView>
    );
};

const styles = StyleSheet.create({
    container: {
        position: 'absolute',
        bottom: 0,
        left: 0,
        right: 0,
    },
    tabbar: {
        flexDirection: 'row',
        height: 60,
    },
    safeArea: {
        backgroundColor: 'transparent',
    },
    circleContainer: {
        position: 'absolute',
        top: 0,
        bottom: 0,
        justifyContent: 'center',
        alignItems: 'center',
    },
    circle: {
        backgroundColor: '#000',
        position: 'absolute',
    },
});

export default TabBar;

Issue

When I increase the smoothingFactor for the edges of the tab bar, it also increases the depth of the circular cutout but I want to have smooth transitions on both sides of the cutout without affecting the cutout’s depth or height if you want to call it that.

Question

What should I do to achieve smooth transitions at the edges leading to the circular cutout without changing its depth?

Desired result

This is what I want to achieve

Current State

This is what it currently looks like

Thank you for your help!