斜線を含む SVG のコンポーネントを作成する
まとめ
- strokeはpathの中心に線を引くので、図形によっては欠けることがある
- pathで2つの線を時計まわりと反時計まわりとそれぞれ異なる方向にひき、fillすることで線を引くこともできる
斜線に stroke を使う
上のような三角形を作成するために stroke
を使ってコンポーネントを作ってみます。
import React, { useMemo } from "react";
type Props = {
width: number;
height: number;
strokeWidth?: number;
};
export const Triangle: React.FC<Props> = (props) => {
const { width, height, strokeWidth = 2 } = props;
const d = useMemo(() => {
const x = width;
const y = height;
return `M ${x} 0 H ${width} V ${height} H 0 L 0 ${y} L ${x} 0 Z`;
}, [height, width]);
return (
<svg
viewBox={`0 0 ${width} ${height}`}
role="img"
width={width}
height={height}
strokeWidth={strokeWidth}
stroke="#000"
fill="transparent"
>
<path d={d} />
</svg>
);
};
このコンポーネントを表示させると、次のような斜線部分の太い三角形になってしまいます。
これは斜線が太くなったわけではなく、直線部分がviewBoxからはみ出てしまったため欠けている状態になっていることが原因です。viewBoxを少し大きくしてみると、期待する図形が表示されることを確認できます。
これはSVGのpathのstrokeがpathの中心から描かれることが原因です。strokeはpathの内側や外側を通るような指定をすることが今のところできません。つまり線の欠けない正しいpathにするためには、次のようなコードにする必要があります。
const d = useMemo(() => {
const x = width - strokeWidth / 2;
const y = height - strokeWidth / 2;
return `M ${x} 0 H ${x} V ${y} H 0 L 0 ${y} L ${x} 0 Z`;
}, [height, width, strokeWidth]);
線を path で描く
strokeを使用せず、2本の線を引いてfillしてみます。
import React, { useMemo } from "react";
type Props = {
width: number;
height: number;
strokeWidth?: number;
};
export const Triangle: React.FC<Props> = (props) => {
const { width, height, strokeWidth = 2 } = props;
const d = useMemo(() => {
const x = width;
const y = height;
const innerX = x + strokeWidth / 2;
const innerY = y + strokeWidth / 2;
const innerWidth = width - strokeWidth;
const innerHeight = height - strokeWidth;
return `
M ${x} 0 H ${width} V ${height} H 0 L 0 ${y} L ${x} 0 Z
M ${innerX} ${strokeWidth} L ${strokeWidth} ${innerY} H ${strokeWidth} V ${innerHeight} H ${innerWidth} V ${strokeWidth} L ${innerX} ${strokeWidth} Z
`;
}, [height, width, strokeWidth]);
return (
<svg
viewBox={`0 0 ${width} ${height}`}
role="img"
width={width}
height={height}
fill="#000"
>
<path d={d} />
</svg>
);
};
この方法でも三角形を描くことができます。