react-native-svg: ClipPath appears to be broken

Hello! I’m trying to use ClipPath to cut a circle in a rect in order to highlight what is underneath that circle. Issue #936 covers this and there is a handy answer that says this code should do it:

import React from 'react';
import { View } from 'react-native';
import Svg, { Defs, ClipPath, Circle, Rect } from 'react-native-svg';

export default class App extends React.Component {
  render() {
    return (
      <View
        style={{
          flex: 1,
          alignContent: 'center',
          justifyContent: 'center',
          backgroundColor: '#ecf0f1',
        }}
      >
        <Svg width="100%" height="100%" viewBox="0 0 100 100">
          <Defs>
            <ClipPath id="clip_out" clipRule="evenodd">
              <Rect width={100} height={100}/>
              <Circle cx={50} cy={50} r={25}/>
            </ClipPath>
          </Defs>
          <Rect width={100} height={100} fill="green" clipPath="url(#clip_out)" />
        </Svg>
      </View>
    );
  }
}

Unfortunately the circle does not get cut out. It seems that ClipRule may be failing, but I’m not sure. Here is a snack that shows the behavior.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 23

Commits related to this issue

Most upvoted comments

ClipPath (with Rect) appears to be broken again, on iOS.

  • working fine on Android
"expo": "~41.0.1",
"react-native-svg": "12.1.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",

Another workaround is to use a single Path in the ClipPath: Correction, this is the spec conformant way to get nonzero clip-rule. But, setting it to evenodd on the Path element inside the ClipPath doesn’t affect anything in react-native-svg right now, it needs to be set on the ClipPath element, which isn’t part of the svg spec, as it only allows it to affect anything on elements which are direct descendants of a clip-path element, if I understand it correctly.

import React from 'react';
import { View } from 'react-native';
import Svg, { Defs, ClipPath, Path, Rect } from 'react-native-svg';

export default class App extends React.Component {
  render() {
    return (
      <View
        style={{
          flex: 1,
          alignContent: 'center',
          justifyContent: 'center',
          backgroundColor: '#ecf0f1',
        }}
      >
        <Svg width="100%" height="100%" viewBox="0 0 200 200">
          <Defs>
            <ClipPath id="clip">
              <Path
                d="M0 0 H200 V200 H0 z
                 M 100, 100
                 m -75, 0
                 a 75,75 0 1,0 150,0
                 a 75,75 0 1,0 -150,0"
              />
            </ClipPath>
          </Defs>
          <Rect width={200} height={200} clipPath="url(#clip)" />
        </Svg>
      </View>
    );
  }
}

As you can see in the snack from the beginning of this thread (https://snack.expo.io/SywHux3uE), clipPath is working for android on v9.3.6 which is what expo uses, but it is broken for iOS on that version. The reverse is true for v9.4.0

The latest commit on the dev branch (fde018b) is working beautifully! At least on iOS. I’ll test on android in a bit but I imagine it will be good too. Thank you!!

Noticed a caching bug in android, fixed in latest commit of develop branch: Screenshot_1554138231