캔버스 및 2차원 배열을 사용한 반응 연습: 삼각형이 있는 배경
32959 단어 styledcomponentshtmljavascriptreact
shift를 사용하면 오른쪽으로만 기울입니다.
시프트 없음, 오른쪽으로만 기울임:
Shift 키를 사용하여 오른쪽/왼쪽으로 기울이기:
이 연습에서는 다음 방법을 알아봅니다.
useRef, useEffect를 사용할 것입니다.
또한 여기에서 선택 사항인 ts 및 styled-components도 사용합니다.
코드 내부의 주석은 충분한 설명을 제공해야 합니다.
From MDN Web Docs: js에서 함수는 객체이며 다른 객체와 마찬가지로 속성과 메서드를 가질 수 있습니다. 단, 함수를 호출할 수 있습니다.
1단계: React 프로젝트 내에서 "matrix.ts" 파일을 만듭니다.
// ------------------------------------
// This provides a 2 dimensional array.
// Dimensions are x & y.
// Each cell is a string.
// It is implemented as a function object.
// Prototype functions: setValue, getValue.
function Matrix() {
this.getValue = (x: number, y: number): string => this[`${x}:${y}`];
this.setValue = (x: number, y: number, value: string) => {
this[`${x}:${y}`] = value;
};
}
export default Matrix;
2단계: 새 구성 요소 파일 "BackgroundWithTriangles.tsx" 만들기
import React, { useRef, useEffect } from "react";
import styled from "styled-components";
// @ts-ignore
import Matrix from "misc/matrix";
// SETTINGS:
// Canvas contains many squares, each square contains 2 triangles.
// l=logical, w=width, h=height.
const canvas_lw = 1000; // higher for less pixelation
const canvas_lh = 1000; // higher for less pixelation
const square_lw = 30;
const square_lh = 30;
const squareShift_lx = 4; // horizontal
const squareShift_ly = 4; // vertical
const tilt = 0.5; // 0=left, 0.5=equal, 1=right
const drawSquaresOnly = false;
// THESE THREE MUST ADD UP TO 256, FOR RGB:
const grayMinimum = 180; // higher for lighter.
const colourShift = 3; // 0 for full grayscale.
const grayShift = 256 - grayMinimum - colourShift; // 0+
// ------------------------------------
const Canvas = styled.canvas`
position: fixed;
z-index: -1;
top: 0;
left: 0;
width: calc(100vw + 50px); // 50px: compensate for the shifting at the end
height: calc(100vh + 50px); // 50px: compensate for the shifting at the end
`;
// ------------------------------------
// Output range: 0 .. maxIncl.
const getRandomInt = (maxIncl: number) =>
Math.floor(Math.random() * (maxIncl + 1));
// Output range: -x/2 .. x/2
const getShiftPositiveOrNegative = (x: number) => getRandomInt(x) - x / 2;
// ------------------------------------
const getRandomGrayishRgb = () => {
const randomGrayBase = grayMinimum + getRandomInt(grayShift);
const r = randomGrayBase + getRandomInt(colourShift);
const g = randomGrayBase + getRandomInt(colourShift);
const b = randomGrayBase + getRandomInt(colourShift);
return `rgb(${r},${g},${b})`;
};
// ------------------------------------
// "12:34" --> [12, 34]
const stringToArray = (value: string): number[] =>
value.split(":").map((s: string) => Number(s));
// [12, 34] --> "12:34"
const arrayToString = (valueX: number, valueY: number): string =>
`${valueX}:${valueY}`;
// ------------------------------------
const drawTriangle = (
ctx: any,
x1: number, y1: number,
x2: number, y2: number,
x3: number, y3: number,
fillStyle: string
) => {
ctx.beginPath();
ctx.lineWidth = 0;
ctx.fillStyle = fillStyle;
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.fill();
};
// ------------------------------------
const drawSquare = (
ctx: any,
x1: number, y1: number,
x2: number, y2: number,
x3: number, y3: number,
x4: number, y4: number,
fillStyle: string
) => {
ctx.beginPath();
ctx.lineWidth = 0;
ctx.fillStyle = fillStyle;
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x4, y4);
ctx.lineTo(x3, y3);
ctx.closePath();
ctx.fill();
};
// ------------------------------------
// Two triangles forming a square.
const drawSquareOrTriangles = (
ctx: any,
x1: number, y1: number,
x2: number, y2: number,
x3: number, y3: number,
x4: number, y4: number
) => {
if (drawSquaresOnly) {
drawSquare(ctx, x1, y1, x2, y2, x3, y3, x4, y4, getRandomGrayishRgb());
return;
}
// Draw two triangles
if (Math.random() <= tilt) {
// Tilt right, like: /
drawTriangle(ctx, x1, y1, x2, y2, x3, y3, getRandomGrayishRgb());
drawTriangle(ctx, x2, y2, x3, y3, x4, y4, getRandomGrayishRgb());
} else {
// Tilt left, like: \
drawTriangle(ctx, x1, y1, x2, y2, x4, y4, getRandomGrayishRgb());
drawTriangle(ctx, x1, y1, x3, y3, x4, y4, getRandomGrayishRgb());
}
};
// ------------------------------------
// x, y: top left corner of the cell, which contain 1 square or 2 triangles.
const drawCell = (matrix: any, ctx: any, x: number, y: number) => {
// 4 corners of the square
const x1 = x;
const y1 = y;
const x2 = x;
const y2 = y + square_lh;
const x3 = x + square_lw;
const y3 = y;
const x4 = x + square_lw;
const y4 = y + square_lh;
drawSquareOrTriangles(
ctx,
// @ts-ignore
...stringToArray(matrix.getValue(x1, y1)),
...stringToArray(matrix.getValue(x2, y2)),
...stringToArray(matrix.getValue(x3, y3)),
...stringToArray(matrix.getValue(x4, y4))
);
};
// ------------------------------------
const createMatrix = (ctx: any) => {
const matrix = new Matrix();
// Create a matrix of dots for the squares, with shifts
for (let x = 0; x <= canvas_lw; x += square_lw)
for (let y = 0; y <= canvas_lh; y += square_lh) {
const xWithShift = x + getShiftPositiveOrNegative(squareShift_lx);
const yWithShift = y + getShiftPositiveOrNegative(squareShift_ly);
matrix.setValue(x, y, arrayToString(xWithShift, yWithShift));
}
// Draw the squares (we need 4 dots for each square)
for (let x = 0; x <= canvas_lw - square_lw; x += square_lw)
for (let y = 0; y <= canvas_lh - square_lh; y += square_lh) {
drawCell(matrix, ctx, x, y);
}
};
// ------------------------------------
// COMPONENT:
// Draws a window background of squares.
// Each square draws 2 triangles.
// Each triangle has random shifts in: corner positions, and colour.
const BackgroundWithTriangles = () => {
const ref = useRef(null);
// ------------------------------------
useEffect(() => {
if (ref && ref.current) {
const canvas: any = ref.current;
const ctx = canvas.getContext("2d");
createMatrix(ctx);
}
}, [ref?.current]);
// ------------------------------------
// Width and height: logical (int), not physical (px).
return <Canvas ref={ref} width={canvas_lw} height={canvas_lh} />;
};
export default BackgroundWithTriangles;
3단계: 다음 예와 같이 구성 요소(아마도 페이지) 내부에서 새 구성 요소를 사용합니다.
import { BackgroundWithTriangles } from "components";
...
return (
<Page title="Outgoing trend">
<BackgroundWithTriangles />
<TrendChart>
...
질문이나 제안을 환영합니다.
Reference
이 문제에 관하여(캔버스 및 2차원 배열을 사용한 반응 연습: 삼각형이 있는 배경), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/elsyng/react-exercise-with-canvas-2-d-array-background-with-triangles-3nm텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)