--- nav: title: 前端 path: /fea group: title: 💊 canvas order: 2 path: /canvas --- ## 基础入门 ### 矩形 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * 绘制矩形 * fillRect(x, y, w, h) 填充矩形 * strokeRect(x, y, w, h) 边框矩形 * clearRect(x, y, w, h) 清除指定区域 */ function fillRect() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); // 实心矩形 ctx.fillStyle = 'red'; ctx.fillRect(25, 25, 50, 50); // 空心矩形 ctx.lineWidth = 1; ctx.fillStyle = 'black'; ctx.strokeRect(75, 75, 50, 50); // 清除区域 ctx.clearRect(50, 50, 50, 50); } useEffect(() => { fillRect(); }, []); return (
); }; ``` ### 三角形 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * 绘制三角形 */ function tri() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); // 实心三角形 ctx.beginPath(); ctx.moveTo(90, 25); ctx.lineTo(25, 90); ctx.lineTo(155, 90); ctx.fill(); ctx.beginPath(); ctx.moveTo(90, 155); ctx.lineTo(25, 90); ctx.lineTo(155, 90); ctx.closePath(); ctx.stroke(); } useEffect(() => { tri(); }, []); return (
); }; ``` ### 绘制圆弧 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); // 绘制圆弧 function drawArc() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); let x = 90, y = 90, r = 30, startAngle = 0, endAngle = (Math.PI / 180) * 180; ctx.beginPath(); ctx.arc(x, y, r, startAngle, endAngle, false); ctx.fill(); ctx.beginPath(); ctx.arc(x, y, r, startAngle, endAngle, true); ctx.stroke(); } useEffect(() => { drawArc(); }, []); return (
); }; ``` ### 绘制贝塞尔曲线 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * quadraticCurveTo(cp1x, cp1y, x, y) cp1 为控制点 * bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) cp1、cp2 为控制点 * x、y 为结束点 */ function bezier() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); // 二次贝塞尔曲线 ctx.beginPath(); ctx.moveTo(30, 90); ctx.quadraticCurveTo(15, 15, 90, 30); ctx.quadraticCurveTo(165, 15, 150, 90); ctx.quadraticCurveTo(148, 130, 70, 120); ctx.quadraticCurveTo(65, 140, 40, 140); ctx.quadraticCurveTo(65, 135, 55, 120); ctx.quadraticCurveTo(30, 115, 30, 90); ctx.stroke(); ctx.font = '18px bold 黑体'; ctx.fillStyle = 'black'; ctx.fillText('聊天框', 120, 160); } useEffect(() => { bezier(); }, []); return (
); }; ``` ### 绘制三次贝塞尔曲线 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * 绘制三次贝塞尔曲线 * */ function beziers() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); // 三次贝塞尔曲线 ctx.beginPath(); ctx.moveTo(90, 40); ctx.bezierCurveTo(90, 36, 70, 25, 50, 25); ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5); ctx.bezierCurveTo(20, 80, 40, 120, 90, 140); ctx.bezierCurveTo(110, 135, 155, 110, 160, 62.5); ctx.bezierCurveTo(160, 22, 140, 25, 130, 25); ctx.bezierCurveTo(120, 25, 110, 30, 90, 40); ctx.fillStyle = 'red'; ctx.fill(); ctx.font = '18px bold 黑体'; ctx.fillStyle = 'black'; ctx.fillText('爱心', 120, 160); } useEffect(() => { beziers(); }, []); return (
); }; ``` ### 绘制笑脸 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * 绘制笑脸 * */ function fillSmile() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(75, 75, 50, 0, Math.PI * 2, true); ctx.moveTo(110, 75); ctx.arc(75, 75, 35, 0, Math.PI, false); ctx.moveTo(65, 65); ctx.arc(60, 65, 5, 0, Math.PI * 2, true); ctx.moveTo(95, 65); ctx.arc(90, 65, 5, 0, Math.PI * 2, true); ctx.stroke(); ctx.font = '18px bold 黑体'; ctx.fillStyle = 'black'; ctx.fillText('笑脸', 120, 160); } useEffect(() => { fillSmile(); }, []); return (
); }; ``` ### 吃豆人 ```jsx import React, { useRef, useEffect } from 'react'; export default () => { const canvasRef = useRef(); /** * 吃豆人 * */ function bean() { let canvas = canvasRef.current; let ctx = canvas.getContext('2d'); // 外墙 _roundedRect(ctx, 12, 12, 160, 160, 15); _roundedRect(ctx, 18, 18, 148, 148, 9); // 内墙 _roundedRect(ctx, 45, 50, 45, 30, 6); _roundedRect(ctx, 115, 50, 45, 30, 6); _roundedRect(ctx, 115, 110, 45, 50, 6); _roundedRect(ctx, 45, 110, 45, 25, 6); // 绘制吃豆人 ctx.beginPath(); ctx.arc(35, 35, 10, Math.PI / 7, -Math.PI / 7, false); ctx.lineTo(31, 37); ctx.fill(); // 绘制魔鬼 ctx.beginPath(); ctx.moveTo(83, 116); ctx.lineTo(83, 102); ctx.bezierCurveTo(83, 94, 89, 88, 97, 88); ctx.bezierCurveTo(105, 88, 111, 94, 111, 102); ctx.lineTo(111, 116); ctx.lineTo(106.3, 111.3); ctx.lineTo(97.3, 111); ctx.lineTo(92, 116); ctx.lineTo(87, 111); ctx.lineTo(83, 116); ctx.fill(); // 绘制小点 for (let i = 0; i < 7; i++) { ctx.fillRect(52 + i * 16, 35, 4, 4); } // 绘制小点 for (let i = 0; i < 7; i++) { ctx.fillRect(28, 52 + i * 16, 4, 4); } // 绘制小点 for (let i = 0; i < 7; i++) { ctx.fillRect(100, 52 + i * 16, 4, 4); } // 绘制小点 for (let i = 0; i < 8; i++) { ctx.fillRect(44 + i * 16, 92, 4, 4); } // 绘制小点 for (let i = 0; i < 3; i++) { ctx.fillRect(44 + i * 16, 148, 4, 4); } ctx.fillStyle = 'white'; ctx.beginPath(); ctx.moveTo(91, 96); ctx.bezierCurveTo(88, 96, 87, 99, 87, 101); ctx.bezierCurveTo(87, 103, 88, 106, 91, 106); ctx.bezierCurveTo(94, 106, 95, 103, 95, 101); ctx.bezierCurveTo(95, 99, 94, 96, 91, 96); ctx.moveTo(103, 96); ctx.bezierCurveTo(100, 96, 99, 99, 99, 101); ctx.bezierCurveTo(99, 103, 100, 106, 103, 106); ctx.bezierCurveTo(106, 106, 107, 103, 107, 101); ctx.bezierCurveTo(107, 99, 106, 96, 103, 96); ctx.fill(); // 右眼 ctx.fillStyle = 'blue'; ctx.beginPath(); ctx.arc(101, 102, 2, 0, Math.PI * 2, true); ctx.fill(); // 左眼 ctx.beginPath(); ctx.arc(89, 102, 2, 0, Math.PI * 2, true); ctx.fill(); ctx.font = '18px bold 黑体'; ctx.fillStyle = 'black'; ctx.fillText('吃豆人', 180, 180); ctx.clearRect(150, 0, 100, 200); /** * 绘制圆角矩形的函数 * * @param {*} ctx 画笔 * @param {*} x x 坐标 * @param {*} y y 坐标 * @param {*} w 宽 * @param {*} h 高 * @param {*} r 半径 */ function _roundedRect(ctx, x, y, w, h, radius) { ctx.beginPath(); ctx.moveTo(x, y + radius); ctx.lineTo(x, y + h - radius); ctx.quadraticCurveTo(x, y + h, x + radius, y + h); ctx.lineTo(x + w - radius, y + h); ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - radius); ctx.lineTo(x + w, y + radius); ctx.quadraticCurveTo(x + w, y, x + w - radius, y); ctx.lineTo(x + radius, y); ctx.quadraticCurveTo(x, y, x, y + radius); ctx.stroke(); } } useEffect(() => { bean(); }, []); return (
); }; ``` ```js ```