Skip to main content
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>
);

Build docs developers (and LLMs) love