Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/shopify/react-native-skia/llms.txt

Use this file to discover all available pages before exploring further.

Path effects modify how paths are rendered, allowing you to create dashed lines, rounded corners, discrete segments, and pattern-based effects.

DashPathEffect

Create dashed or dotted lines.
NameTypeDescription
intervalsnumber[]Array of on/off lengths
phasenumberOffset into intervals (default: 0)
childrenReactNodeContent to apply effect to
import { Canvas, Path, DashPathEffect, Skia } from "@shopify/react-native-skia";

const DashDemo = () => {
  const path = Skia.Path.Make();
  path.moveTo(20, 20);
  path.lineTo(236, 236);

  return (
    <Canvas style={{ flex: 1 }}>
      <Path 
        path={path} 
        color="black" 
        style="stroke" 
        strokeWidth={4}
      >
        <DashPathEffect intervals={[10, 10]} />
      </Path>
    </Canvas>
  );
};

Dash Patterns

Simple Dash

// 10px dash, 10px gap
<DashPathEffect intervals={[10, 10]} />

Dot Pattern

// 2px dot, 8px gap
<DashPathEffect intervals={[2, 8]} />

Complex Pattern

// Long dash, short gap, short dash, short gap (repeating)
<DashPathEffect intervals={[20, 5, 5, 5]} />

Animated Dash

Use the phase property to animate dashes:
import { Canvas, Path, DashPathEffect } from "@shopify/react-native-skia";
import { useSharedValue, withRepeat, withTiming } from "react-native-reanimated";
import { useEffect } from "react";

const AnimatedDashDemo = () => {
  const phase = useSharedValue(0);

  useEffect(() => {
    phase.value = withRepeat(withTiming(20, { duration: 1000 }), -1, false);
  }, [phase]);

  return (
    <Canvas style={{ flex: 1 }}>
      <Path path={myPath} color="black" style="stroke" strokeWidth={4}>
        <DashPathEffect intervals={[10, 10]} phase={phase} />
      </Path>
    </Canvas>
  );
};

CornerPathEffect

Round sharp corners in paths.
NameTypeDescription
rnumberCorner radius
childrenReactNodeContent to apply effect to
import { Canvas, Path, CornerPathEffect, Skia } from "@shopify/react-native-skia";

const CornerDemo = () => {
  const path = Skia.Path.Make();
  path.moveTo(50, 50);
  path.lineTo(200, 50);
  path.lineTo(200, 200);
  path.lineTo(50, 200);

  return (
    <Canvas style={{ flex: 1 }}>
      <Path 
        path={path} 
        color="blue" 
        style="stroke" 
        strokeWidth={4}
      >
        <CornerPathEffect r={20} />
      </Path>
    </Canvas>
  );
};

DiscretePathEffect

Break paths into random discrete segments.
NameTypeDescription
lengthnumberSegment length
deviationnumberRandom deviation amount
seednumberRandom seed (default: 0)
childrenReactNodeContent to apply effect to
import { Canvas, Path, DiscretePathEffect, Skia } from "@shopify/react-native-skia";

const DiscreteDemo = () => {
  const path = Skia.Path.Make();
  path.moveTo(20, 128);
  path.lineTo(236, 128);

  return (
    <Canvas style={{ flex: 1 }}>
      <Path 
        path={path} 
        color="red" 
        style="stroke" 
        strokeWidth={2}
      >
        <DiscretePathEffect length={10} deviation={4} seed={42} />
      </Path>
    </Canvas>
  );
};
Great for creating hand-drawn or sketchy effects:
import { Canvas, Circle, DiscretePathEffect } from "@shopify/react-native-skia";

const SketchyCircle = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Circle 
        cx={128} 
        cy={128} 
        r={64} 
        color="black" 
        style="stroke" 
        strokeWidth={2}
      >
        <DiscretePathEffect length={5} deviation={2} />
      </Circle>
    </Canvas>
  );
};

Path1DPathEffect

Stamp a path repeatedly along another path.
NameTypeDescription
pathSkPathPath to stamp
advancenumberDistance between stamps
phasenumberOffset along path
stylePath1DEffectStyleStamping style
childrenReactNodeContent to apply effect to
import { 
  Canvas, 
  Path, 
  Path1DPathEffect, 
  Skia 
} from "@shopify/react-native-skia";

const Path1DDemo = () => {
  // Create the main path
  const mainPath = Skia.Path.Make();
  mainPath.moveTo(20, 128);
  mainPath.quadTo(128, 50, 236, 128);

  // Create the stamp (a small arrow)
  const stamp = Skia.Path.Make();
  stamp.moveTo(0, -5);
  stamp.lineTo(10, 0);
  stamp.lineTo(0, 5);

  return (
    <Canvas style={{ flex: 1 }}>
      <Path 
        path={mainPath} 
        color="blue" 
        style="stroke" 
        strokeWidth={2}
      >
        <Path1DPathEffect 
          path={stamp} 
          advance={30} 
          phase={0} 
          style="rotate" 
        />
      </Path>
    </Canvas>
  );
};

Path1D Styles

  • "translate" - Stamps are only translated
  • "rotate" - Stamps rotate to follow the path
  • "morph" - Stamps morph to follow the path

Path2DPathEffect

Stamp a path in a 2D grid pattern.
NameTypeDescription
matrixSkMatrixTransformation matrix for grid
pathSkPathPath to stamp
childrenReactNodeContent to apply effect to
import { Canvas, Rect, Path2DPathEffect, Skia } from "@shopify/react-native-skia";

const Path2DDemo = () => {
  // Create stamp (a small circle)
  const stamp = Skia.Path.Make();
  stamp.addCircle(0, 0, 3);

  // Create grid matrix (20px spacing)
  const matrix = Skia.Matrix();
  matrix.translate(20, 20);

  return (
    <Canvas style={{ flex: 1 }}>
      <Rect x={0} y={0} width={256} height={256} color="blue">
        <Path2DPathEffect matrix={matrix} path={stamp} />
      </Rect>
    </Canvas>
  );
};

Line2DPathEffect

Create a pattern of lines.
NameTypeDescription
widthnumberLine width
matrixSkMatrixGrid transformation
childrenReactNodeContent to apply effect to
import { Canvas, Rect, Line2DPathEffect, Skia } from "@shopify/react-native-skia";

const Line2DDemo = () => {
  const matrix = Skia.Matrix();
  matrix.translate(10, 10);

  return (
    <Canvas style={{ flex: 1 }}>
      <Rect x={0} y={0} width={256} height={256} color="black">
        <Line2DPathEffect width={2} matrix={matrix} />
      </Rect>
    </Canvas>
  );
};

Combining Path Effects

Path effects can be combined by nesting them. The innermost effect is applied first:
import { 
  Canvas, 
  Path, 
  DashPathEffect, 
  CornerPathEffect,
  DiscretePathEffect 
} from "@shopify/react-native-skia";

const CombinedEffectsDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Path path={myPath} color="blue" style="stroke" strokeWidth={3}>
        {/* Applied first: round corners */}
        <CornerPathEffect r={10}>
          {/* Applied second: make sketchy */}
          <DiscretePathEffect length={5} deviation={2}>
            {/* Applied last: dash the result */}
            <DashPathEffect intervals={[15, 5]} />
          </DiscretePathEffect>
        </CornerPathEffect>
      </Path>
    </Canvas>
  );
};

Sum Path Effect

The Sum component applies multiple path effects in parallel and combines the results:
import { Canvas, Path, Sum, DashPathEffect, DiscretePathEffect } from "@shopify/react-native-skia";

const SumDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Path path={myPath} color="red" style="stroke" strokeWidth={2}>
        <Sum>
          <DashPathEffect intervals={[10, 10]} />
          <DiscretePathEffect length={5} deviation={2} />
        </Sum>
      </Path>
    </Canvas>
  );
};

Imperative API

Create path effects imperatively:
import { Skia, Path1DEffectStyle } from "@shopify/react-native-skia";

// Dash effect
const dashEffect = Skia.PathEffect.MakeDash([10, 10], 0);

// Corner effect
const cornerEffect = Skia.PathEffect.MakeCorner(20);

// Discrete effect
const discreteEffect = Skia.PathEffect.MakeDiscrete(10, 4, 42);

// Compose effects
const composedEffect = Skia.PathEffect.MakeCompose(dashEffect, cornerEffect);

const paint = Skia.Paint();
paint.setPathEffect(composedEffect);

Common Use Cases

Dashed Border

<RoundedRect x={50} y={50} width={156} height={156} r={10} color="blue" style="stroke" strokeWidth={2}>
  <DashPathEffect intervals={[8, 4]} />
</RoundedRect>

Hand-Drawn Effect

<Path path={myPath} color="black" style="stroke" strokeWidth={2}>
  <DiscretePathEffect length={3} deviation={1.5} />
</Path>

Animated Dash Border

const phase = useSharedValue(0);

useEffect(() => {
  phase.value = withRepeat(withTiming(40, { duration: 2000 }), -1, false);
}, []);

return (
  <Rect x={10} y={10} width={236} height={236} color="blue" style="stroke" strokeWidth={3}>
    <DashPathEffect intervals={[20, 20]} phase={phase} />
  </Rect>
);