1. 概要
前回はError Handlingの使い方についてでした。今回はCanvasの使い方についてです。
対象としては開発を1年程やってて自分で最初から開発してみたい方になります。そのため細かい用語などの説明はしません。
- こちらのFlutterの例と同様のものです。
2. nodeのインストール
こちらを参考
3. プロジェクトを作成
こちらを参考
4. 必要なライブラリをインストール
こちらを参考
5. ソースコード
※前回より差分のみを記載
5-1-1. src/app/components/component05/canvas.tsx
"use client";
import { useCallback, useEffect, useRef } from "react";
type CanvasProps = {
canvasWidth: number;
canvasHeight: number;
axisX: number;
axisY: number;
rectWidth: number;
rectHeight: number;
data: number;
};
const Canvas = (props: CanvasProps) => {
const {
canvasWidth,
canvasHeight,
axisX,
axisY,
rectWidth,
rectHeight,
data,
} = props;
const canvasRef = useRef<HTMLCanvasElement>(null);
const startAxis = 30;
const endAxis = 270;
const distance = 40;
const getCtx = (): CanvasRenderingContext2D => {
const canvas: any = canvasRef.current;
if (!canvas || !canvas.getContext) throw new Error("Something may happen.");
return canvas.getContext("2d");
};
const drawOutline = useCallback(
(ctx: CanvasRenderingContext2D, fgColor: string) => {
const rect = new Path2D();
rect.rect(0, 0, canvasWidth, canvasHeight);
ctx.beginPath();
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.fillStyle = fgColor;
ctx.stroke(rect);
},
[canvasWidth, canvasHeight]
);
const drawRect = useCallback(
(ctx: CanvasRenderingContext2D, fgColor: string) => {
const rect = new Path2D();
rect.rect(axisX, axisY, rectWidth, rectHeight);
ctx.beginPath();
ctx.fillStyle = fgColor;
ctx.fill(rect);
},
[axisX, axisY, rectWidth, rectHeight]
);
const drawLine = useCallback(
(ctx: CanvasRenderingContext2D, fgColor: string) => {
ctx.beginPath();
ctx.strokeStyle = fgColor;
ctx.lineWidth = 2;
for (let i = 0; i < 7; i++) {
const y = startAxis + i * distance;
const x = startAxis + i * distance;
ctx.moveTo(startAxis, y);
ctx.lineTo(endAxis, y);
ctx.moveTo(x, startAxis);
ctx.lineTo(x, endAxis);
}
ctx.stroke();
},
[]
);
const drawArc = useCallback(
(ctx: CanvasRenderingContext2D, fgColor: string) => {
const radius = 5;
const startAngle = 0;
const endAngle = Math.PI * 2;
ctx.beginPath();
ctx.fillStyle = fgColor;
for (let i = 0; i < data; i++) {
const pointAxis = startAxis + distance * i;
ctx.moveTo(pointAxis, pointAxis);
ctx.arc(pointAxis, pointAxis, radius, startAngle, endAngle, true);
}
ctx.fill();
},
[data]
);
const drawAll = useCallback(() => {
const ctx: CanvasRenderingContext2D = getCtx();
drawRect(ctx, "green");
drawLine(ctx, "white");
drawArc(ctx, "red");
}, [drawRect, drawLine, drawArc]);
useEffect(() => drawAll(), [drawAll]);
return <canvas ref={canvasRef} width={canvasWidth} height={canvasHeight} />;
};
export default Canvas;
5-1-2. src/app/components/component05/page.module.scss
.component {
color: blue;
& ul {
margin-left: 20px;
& li {
list-style: disc;
}
}
canvas {
border: 1px solid black;
}
}
5-1-3. src/app/components/component05/page.tsx
"use client";
import React, { useState } from "react";
import { Button } from "@mui/material";
import GoBack from "@/lib/components/go-back";
import scss from "./page.module.scss";
import Canvas from "./canvas";
const Component05 = () => {
const [point, setPoint] = useState(0);
const drawPoint = () => {
point == 7 ? setPoint(0) : setPoint(point + 1);
};
return (
<div className={scss.component}>
<GoBack />
<br />
<br />
<ul>
<li>Drawing</li>
</ul>
<Canvas
canvasWidth={300}
canvasHeight={300}
axisX={0}
axisY={0}
rectWidth={300}
rectHeight={300}
data={point}
/>
<br />
<Button
variant="contained"
size="medium"
color="primary"
onClick={() => drawPoint()}
>
Click
</Button>
</div>
);
};
export default Component05;
5-1-4. src/app/component/page.tsx
"use client";
import React from "react";
import { Link } from "@mui/material";
import scss from "./page.module.scss";
const Components = () => {
return (
<div className={scss.components}>
<ul>
<li>
<Link href="/components/component01" underline="hover">
Component01
</Link>
</li>
<li>
<Link href="/components/component02" underline="hover">
Component02
</Link>
</li>
<li>
<Link href="/components/component03" underline="hover">
Component03
</Link>
</li>
<li>
<Link href="/components/component04" underline="hover">
Component04
</Link>
</li>
<li>
<Link href="/components/component05" underline="hover">
Component05
</Link>
</li>
</ul>
</div>
);
};
export default Components;
6. サーバーを起動
npm run dev
7. ブラウザで確認
- http://localhost:3000

8. ディレクトリの構造
.
├── README.md
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ ├── js
│ │ └── script.js
│ ├── next.svg
│ └── vercel.svg
├── src
│ ├── app
│ │ ├── components
│ │ │ ├── component01
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── component02
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── component03
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── component04
│ │ │ │ ├── checkbox-demo.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ ├── page.tsx
│ │ │ │ ├── radio-demo.tsx
│ │ │ │ └── select-demo.tsx
│ │ │ ├── component05
│ │ │ │ ├── canvas.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── page.module.scss
│ │ │ └── page.tsx
│ │ ├── events
│ │ │ ├── event01
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── page.module.scss
│ │ │ └── page.tsx
│ │ ├── favicon.ico
│ │ ├── globals.css
│ │ ├── globals.scss
│ │ ├── hooks
│ │ │ ├── hook01
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── hook02
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── hook03
│ │ │ │ ├── child.tsx
│ │ │ │ ├── counter-provider.tsx
│ │ │ │ ├── grandchild.tsx
│ │ │ │ ├── myself.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── hook04
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── hook05
│ │ │ │ ├── child.tsx
│ │ │ │ ├── counter-provider.tsx
│ │ │ │ ├── grandchild.tsx
│ │ │ │ ├── myself.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── hook06
│ │ │ │ ├── child.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ ├── page.tsx
│ │ │ │ ├── play-provider.tsx
│ │ │ │ ├── text-box.tsx
│ │ │ │ └── video-player.tsx
│ │ │ ├── page.module.scss
│ │ │ └── page.tsx
│ │ ├── layout.module.scss
│ │ ├── layout.tsx
│ │ ├── nextjs
│ │ │ ├── nextjs01
│ │ │ │ ├── child
│ │ │ │ │ ├── client-page.tsx
│ │ │ │ │ ├── metadata.ts
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── nextjs02
│ │ │ │ ├── [...slug]
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ ├── page.tsx
│ │ │ │ └── shop
│ │ │ │ └── [id]
│ │ │ │ └── page.tsx
│ │ │ ├── nextjs03
│ │ │ │ ├── fetch-image.tsx
│ │ │ │ ├── get-image.tsx
│ │ │ │ ├── loading.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── nextjs04
│ │ │ │ ├── actions.ts
│ │ │ │ ├── list.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ ├── page.tsx
│ │ │ │ └── register-form.tsx
│ │ │ ├── nextjs05
│ │ │ │ ├── locale-switcher.tsx
│ │ │ │ ├── metadata.ts
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── nextjs06
│ │ │ │ ├── error.tsx
│ │ │ │ ├── fetch-check.tsx
│ │ │ │ ├── page.module.scss
│ │ │ │ └── page.tsx
│ │ │ ├── page.module.scss
│ │ │ └── page.tsx
│ │ ├── page.module.scss
│ │ ├── page.tsx
│ │ └── redux
│ │ ├── page.module.scss
│ │ ├── page.tsx
│ │ ├── redux01
│ │ │ ├── child.tsx
│ │ │ ├── counter-slice.ts
│ │ │ ├── grandchild.tsx
│ │ │ ├── hooks.ts
│ │ │ ├── myself.tsx
│ │ │ ├── page.module.scss
│ │ │ ├── page.tsx
│ │ │ └── store.ts
│ │ └── redux02
│ │ ├── child.tsx
│ │ ├── hooks.ts
│ │ ├── image-box.tsx
│ │ ├── image-slice.ts
│ │ ├── page.module.scss
│ │ ├── page.tsx
│ │ ├── store.ts
│ │ ├── text-box.tsx
│ │ └── text-slice.ts
│ ├── lib
│ │ ├── common
│ │ │ ├── db
│ │ │ │ ├── pool-config.ts
│ │ │ │ └── pool.ts
│ │ │ ├── definitions.ts
│ │ │ ├── i18n
│ │ │ │ ├── dictionaries
│ │ │ │ │ ├── cn.json
│ │ │ │ │ ├── en.json
│ │ │ │ │ ├── ja.json
│ │ │ │ │ └── ko.json
│ │ │ │ ├── dictionaries.ts
│ │ │ │ └── i18n-config.ts
│ │ │ └── sidebar-links.tsx
│ │ ├── components
│ │ │ ├── alert-snackbar.tsx
│ │ │ ├── go-back.tsx
│ │ │ └── spacer.tsx
│ │ ├── footer.tsx
│ │ ├── header.tsx
│ │ ├── sidebar.tsx
│ │ └── utils
│ │ └── util.ts
│ └── scss
│ └── common
│ ├── _index.scss
│ ├── _mixin.scss
│ ├── _mq.scss
│ └── _variables.scss
├── tailwind.config.ts
└── tsconfig.json
42 directories, 133 files
9. 備考
今回はCanvasの使い方についてでした。
10. 参考
- Docs | Next.js (nextjs.org)
- Quick Start – React
- Getting Started with Redux | Redux
- Getting Started with React Redux | React Redux (react-redux.js.org)
- Material UI: React components based on Material Design (mui.com)
投稿者プロフィール

-
開発好きなシステムエンジニアです。
卓球にハマってます。
最新の投稿
【Next.js】2025年3月8日【NextJS】Cropping a portion of an image with React Cropper
【Next.js】2025年2月9日【NextJS】View and Download PDF
【AWS】2025年2月1日【AWS】Github ActionsやAWS SAMを使ってAWS S3・CloudFrontにウェブコンテンツをデプロイし、サブドメインにアクセスできるようにする
【AWS】2025年1月25日【AWS】Deploy Serverless NextJS app with AWS Lambda Web Adapter using AWS SAM