-
Notifications
You must be signed in to change notification settings - Fork 6
Knowledge: In Upload
kimyoungyin edited this page Jun 24, 2022
·
5 revisions
stackoverflow: How to get the theme outside styled-components?
- 채울 svg 속성을 svg 파일에서 "current"로 변경
// cut.svg -> CutIcon
<svg
aria-label="자르기 선택"
fill="current" // 이렇게!
height="16"
role="img"
viewBox="0 0 24 24"
width="16"
>
<path
d="M10 20H4v-6a1 1 0 00-2 0v7a1 1 0 001 1h7a1 1 0 000-2zM20.999 2H14a1 1 0 000 2h5.999v6a1 1 0 002 0V3a1 1 0 00-1-1z"
></path>
</svg>
-
styled-component
가 주는useTheme()
hook을 이용하여styled-component
밖에서도 theme 객체를 읽어내어 svg ReactComponent에 적용
import styled, { useTheme } from "styled-components";
const Cut = ({ currentWidth }: CutProps) => {
const theme = useTheme();
// return문 일부에서(svg ReactComponent)
<button>
<CutIcon
fill={
handlingMode === "ratio"
? theme.font.default_black
: theme.color.bg_white
}
/>
</button>
// ... 생략
}
커스텀으로 input range 스타일을 바꾸고 싶을 때 사용합니다.
- 기존 스타일 초기화(배경 퍼센트 색 제거 포함)
& > input[type="range"] {
-webkit-appearance: none;
width: 100%;
background: transparent;
}
& > input[type="range"]:focus {
// blue border 제거
outline: none;
}
& > input[type="range"]::-ms-track {
width: 100%;
// 투명
background: transparent;
border-color: transparent;
color: transparent;
}
& > input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none; // 동그란 원 기본 속성 제거
}
-
각각 커스텀 스타일(생략)
-
react two way binding
value={scale}
onChange={scaleChangeHandler}
- linear-gradient로 value값 배경색으로 나타내줌
주의: linear-gradient의 첫 번째 퍼센트가 작으면 그라데이션 처리되므로, 50%를 기준으로 to right, to left로 나눠줌
style={{
background:
scale >= 50
? `linear-gradient(to right, white ${scale}%, black ${
100 - scale
}%)`
: `linear-gradient(to left, black ${
100 - scale
}%, white ${scale}%)`,
}}
![스크린샷 2022-02-22 오후 7 15 26](https://user-images.githubusercontent.com/78777345/155111473-3eebc010-b425-45c5-b5ba-bb0188c6b5f0.png)
Canvas의 사용 용도: 복잡한 그래픽 애니메이션 및 이미지 조작(화질 개선, 필터 적용 등)을 위해 사용됩니다.
.canvas {
width:400px;
height:200px;
}
<canvas width={400} height={200}></canvas>
캔버스에 css로 width, height ≠ canvas 태그 내부 속성 width, height
- css로 적용한 width, height: html 좌표계 -> 현재 브라우저에 보이는 픽셀을 기준으로 설정된 값으로, 우리가 기존에 사용하던 개념과 동일합니다.
- canvas 태그 내부 속성 width, height: 캔버스 내부 좌표계 -> 캔버스 내부를 몇 개의 픽셀로 구성할 것인가에 대한 값입니다. 자바스크립트로 그려질 캔버스 크기관련 픽셀값은 모두 이 width, height를 기준으로 그려집니다.
응용(고해상도 표현): 기존보다 2배 더 고해상도로 보여주고 싶다면, canvas의 width와 height를 2배로 키우고 그린 다음에 css로 1/2로 줄여줍니다. 해상도가 2배가 됩니다.
<canvas>보여줄 요소</canvas>
- 렌더링 컨텍스트(CanvasRenderingContext2D): Canvas 태그에서 가져온 객체임과 동시에, canvas에 그릴 여러 프로퍼티를 갖고 있는 객체
// js
const canvas = document.getElementById('tutorial');
const ctx = canvas.getContext('2d');
// react, ts: useRef()와 옵셔널 처리
const canvasRef = useRef<HTMLCanvasElement>(null);
if (!canvasRef.current) return;
const canvas = canvasRef.current;
const context = canvas.getContext("2d");
if (context) {
// ...
}
Canvas에 이미지 그리기: CanvasRenderingContext2D.drawImage()
- parameters: 3개 혹은 5개 혹은 9개가 가능합니다. 저는 5개를 사용하였습니다.
drawImage의 첫번째 파라미터는 이미지 src가 아니라 '이미지 관련 객체'를 사용하며, 보통 다음과 같이 생성자 함수로 객체를 생성한 후 사용합니다.
// 제 코드의 일부분입니다.
const img = new Image(currentImageWidth, currentImageHeight); // url만으로 canvas에 이미지를 그릴 수 없습니다. 생성자 함수를 통해 새로운 img 객체를 만들어줍니다.
img.src = currentFile.url;
// img 객체가 load될 때까지 기다린 후에 img 객체를 사용할 수 있으므로, 약간의 딜레이가 발생할 수 있습니다.
img.onload = () => {
// 캔버스에 넣기 등 img 객체를 사용한 작업
}
- 이미지의 일부분만 그리려면?: (1)sx, sy로 원본 이미지의 일부를 잘라 canvas에 그리거나, (2)dx, dy를 음수로 조정하여 캔버스 밖에서 그리기 시작하는 방법
저는 (2)를 선택했습니다.
// drawImage 코드
context.drawImage(
img,
-(
currentImageWidth / 2 -
currentCanvasWidth / 2 -
currentFile.translateX
),
-(
currentImageHeight / 2 -
currentCanvasHeight / 2 -
currentFile.translateY
),
img.width,
img.height,
);
- 이미지 필터 적용: CanvasRenderingContext2D.filter
꼭 그리기 '전'에 context의 필터를 적용해야 합니다. Canvas API가 기본적으로 제공하는 api를 적용했습니다.
// useEffect에서 구현
if (!canvasRef.current) return;
const canvas = canvasRef.current;
const context = canvas.getContext("2d");
if (context) {
const img = new Image(currentImageWidth, currentImageHeight); // url만으로 canvas에 이미지를 그릴 수 없습니다. 생성자 함수를 통해 새로운 img 객체를 만들어줍니다.
img.src = currentFile.url;
img.onload = () => {
context.clearRect(
0,
0,
currentCanvasWidth,
currentCanvasHeight,
);
// 이미지 로드가 완료되었을 떄 함수가 실행됩니다.
// 이미지 자체의 시작지점(sx,sy)를 조작하면 이미지 크기가 초기화되버리므로,
// canvas에 그리기 시작하는 좌표(dx,dy)를 조작하여 간접적으로 translate를 구현합니다.
context.filter = `brightness(${
currentFile.brightness / 3 + 100
}%) contrast(${currentFile.contrast / 3 + 100}%) saturate(${
currentFile.saturate + 100
}%)
blur(${currentFile.blur / 50}px)
`;
context.drawImage(
img,
-(
currentImageWidth / 2 -
currentCanvasWidth / 2 -
currentFile.translateX
),
-(
currentImageHeight / 2 -
currentCanvasHeight / 2 -
currentFile.translateY
),
img.width,
img.height,
);
};
}
이미지 클릭 이벤트라면
const changeSearchBarPosition = (
event: React.MouseEvent<HTMLImageElement>,
) => {
const { clientX, clientY, currentTarget } = event; // clientX, clientY는 브라우저 왼쪽, 위로부터 마우스까지 거리
const {
x: left, // 브라우저 왼쪽으로부터 클릭한 요소까지 거리
y: top, // 브라우저 위쪽으로부터 클릭한 요소까지 거리
width, // 클릭한 요소의 너비
height, // 클릭한 요소의 높이
} = currentTarget.getBoundingClientRect(); // getBoundingCientRect()는 클릭된 요소 관련 좌표를 얻을 수 있다
const x = ((clientX - left) / width) * 100; // %(비율) 즉, 상대값으로 계산하면 브라우저 resize event에도 대응할 수 있다.
const y = ((clientY - top) / height) * 100;
setSearchBarPosition({ x, y }); // 상대적인 마우스 위치에 뭔가 띄우고 싶다면 setState를 통해 스타일에 적용(인라인 등등)
};