Skip to content
React Native Skia ガイドブック
Esc
navigateopen⌘Jpreview
On this page

多角形とパス

矩形・線・点といった多角形(Polygon)系の図形と、任意の形状を描けるPathの基本を、トリム(部分描画)デモとあわせて解説します。

制御点からパスを作り、塗りと線を適用し、開始位置と終了位置で部分描画する流れ

制御点で輪郭を作り、塗り・ストローク・トリムを同じPathへ重ねていきます。

前章の円・楕円・Boxに続いて、矩形や線分といった多角形(Polygon)系の図形と、より自由な形状を描ける<Path>を見ていきます。

Rect: 矩形を描く

Name Type Description
x number x座標
y number y座標
width number
height number 高さ
import { Canvas, Rect } from "@shopify/react-native-skia";

const RectDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Rect x={0} y={0} width={256} height={256} color="lightblue" />
    </Canvas>
  );
};

RoundedRect: 角丸矩形を描く

Name Type Description
x number x座標
y number y座標
width number
height number 高さ
r? number または Vector 角丸の半径。省略時は0
import { Canvas, RoundedRect } from "@shopify/react-native-skia";

const RoundedRectDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <RoundedRect x={0} y={0} width={256} height={256} r={25} color="lightblue" />
    </Canvas>
  );
};

4つの角それぞれに異なる半径を指定したい場合は、rの代わりにrectpropに角ごとの座標を持つオブジェクトを渡します。

const size = 256;
const r = size * 0.2;
const rrct = {
  rect: { x: 0, y: 0, width: size, height: size },
  topLeft: { x: 0, y: 0 },
  topRight: { x: r, y: r },
  bottomRight: { x: 0, y: 0 },
  bottomLeft: { x: r, y: r },
};

<RoundedRect rect={rrct} color="lightblue" />;

以下のデモでshapeを切り替えると、この章で扱うRectRoundedRectDiffRectLinePointsをまとめて確認できます。RoundedRectDiffRectradiusで角の丸みを、Pointsmodeで点のつなぎ方を調整できます。

Skiaを読み込み中…

DiffRect: 2つの矩形の差分を描く

外側の矩形から内側の矩形をくり抜いた形を描きます。ドーナツ状の枠線や、額縁のような表現に使えます。

Name Type Description
outer RectOrRRect 外側の矩形
inner RectOrRRect 内側の矩形(くり抜く部分)
import { Canvas, DiffRect, rect, rrect } from "@shopify/react-native-skia";

const DiffRectDemo = () => {
  const outer = rrect(rect(0, 0, 256, 256), 25, 25);
  const inner = rrect(rect(50, 50, 156, 156), 50, 50);
  return (
    <Canvas style={{ flex: 1 }}>
      <DiffRect inner={inner} outer={outer} color="lightblue" />
    </Canvas>
  );
};

上のRoundedRect: 角丸矩形を描く節にあるデモのshapediffRectに切り替えると確認できます。

Line: 線分を描く

Name Type Description
p1 Point 始点
p2 Point 終点
import { Canvas, Line, vec } from "@shopify/react-native-skia";

const LineDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Line p1={vec(0, 0)} p2={vec(256, 256)} color="lightblue" style="stroke" strokeWidth={4} />
    </Canvas>
  );
};

上のRoundedRect: 角丸矩形を描く節にあるデモのshapelineに切り替えると確認できます。

Points: 複数の点を描く

複数の点を描画し、modeで点同士のつなぎ方を指定できます。

Name Type Description
points Point[] 描画する点の配列
mode PointMode points(接続なし)・lines(2点ずつ接続)・polygon(全体を接続)。デフォルトはpoints
import { Canvas, Points, vec } from "@shopify/react-native-skia";

const points = [
  vec(128, 0), vec(168, 80), vec(256, 93), vec(192, 155), vec(207, 244),
  vec(128, 202), vec(49, 244), vec(64, 155), vec(0, 93), vec(88, 80), vec(128, 0),
];

const PointsDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Points points={points} mode="polygon" color="lightblue" style="stroke" strokeWidth={4} />
    </Canvas>
  );
};

mode="polygon"で星形の頂点を順につなぐと、そのまま星のアウトラインになります。上のRoundedRect: 角丸矩形を描く節にあるデモのshapepointsに切り替えると、modeによる違いも確認できます。

Path: 任意の形状を描く

<Path>はSkiaの中で最も柔軟な図形コンポーネントです。パスの記法はSVG Pathと意味的に同じです。

Name Type Description
path SkPath または string 描画するパス。SVG Path記法の文字列、またはSkia.PathBuilderで作ったオブジェクト
start number パスの開始位置をトリムする(01、デフォルト0)
end number パスの終了位置をトリムする(01、デフォルト1)
stroke StrokeOptions パスをストローク済みの塗りつぶし形状に変換する。widthstrokeMiterLimitprecisionを持つ

SVG記法で書く

import { Canvas, Path } from "@shopify/react-native-skia";

const SVGPathDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Path
        path="M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z"
        color="lightblue"
      />
    </Canvas>
  );
};

PathBuilderで組み立てる

プログラムで動的にパスを組み立てたいときはSkia.PathBuilderを使います。メソッドチェーンで座標を積み上げ、最後に.build()でイミュータブルなSkPathを得ます。

import { Canvas, Path, Skia } from "@shopify/react-native-skia";

const path = Skia.PathBuilder.Make()
  .moveTo(128, 0)
  .lineTo(168, 80)
  .lineTo(256, 93)
  .lineTo(192, 155)
  .lineTo(207, 244)
  .lineTo(128, 202)
  .lineTo(49, 244)
  .lineTo(64, 155)
  .lineTo(0, 93)
  .lineTo(88, 80)
  .lineTo(128, 0)
  .close()
  .build();

const PathBuilderDemo = () => {
  return (
    <Canvas style={{ flex: 1 }}>
      <Path path={path} color="lightblue" />
    </Canvas>
  );
};

先ほどSVG記法で書いた星と同じ形になります。細かい座標をコードで生成したい場合や、後からSkia.Path.Stroke()のような静的操作を適用したい場合はこちらが向いています。

以下のデモはpoints(頂点数)を変えるたびにSkia.PathBuilderでパスを組み立て直しています。SVG文字列では表現しづらい、頂点数が動的に変わる形状を作れるのがPathBuilderの強みです。

Skiaを読み込み中…

start/endでパスを部分的に描く(トリム)

startendを使うと、パスの一部分だけを描画できます。アニメーションでパスを少しずつ描き足す表現でよく使われます。

<Path
  path="M 128 0 L 168 80 L 256 93 L 192 155 L 207 244 L 128 202 L 49 244 L 64 155 L 0 93 L 88 80 L 128 0 Z"
  color="lightblue"
  style="stroke"
  strokeJoin="round"
  strokeWidth={5}
  // 最初と最後の1/4ずつをトリムする
  start={0.25}
  end={0.75}
/>

以下のデモでstart・end・strokeWidth・色相(hue)を動かして、トリムされる範囲を確認できます。

Skiaを読み込み中…

fillType: 内側の判定方法

fillTypeは図形の「内側」をどう判定するかを決めるプロパティです。winding(デフォルト)・evenOddinverseWindinginverseEvenOddが指定できます。星形のように自己交差するパスでは、この設定によって塗られる範囲が変わります。

<Path path={starPath} color="lightblue" fillType="evenOdd" />

windingでは交差した内側の五角形部分まで塗りつぶされますが、evenOddでは交差のたびに内外が反転するため、星の角だけが塗られた中抜きの見た目になります。

以下のデモは、隣り合わない頂点を結んで自己交差させたペンタグラム(五芒星)に4種類のfillTypeを切り替えて適用します。windingevenOddで中央の塗られ方がどう変わるか確認してください。

Skiaを読み込み中…

補足: Path APIのマイグレーション

React Native Skiaは、可変(mutable)なPath APIから、PathBuilderによる不変(immutable)なPath APIへの移行を進めています。既存コードを新しいAPIに書き換える際は、Path API Migration Guideに新旧APIの対応表がまとまっているので参照してください。