[NEXT] 비율에 따라 변하는 외접하는 두 원

김승환·2022년 7월 17일
0
post-thumbnail

일을 하던 중에 두 모집군의 비율에 따라 크기가 변하는 외접하는 두 원의 코드를 짜달라는 요청을 받았다.

50:50 일때 0:100 일때
  • 요구사항
    1. 원의 크기는 두 모집군의 비율에 따라 변한다.
    2. 원은 시계 방향으로만 돌고 최대 45도까지만 회전한다.
    3. 일정 크기 이상 혹은 이하는 원의 크기는 변하지 않고 회전만한다.

처음에는 어려울 줄 알았지만 갑자기 아이디어 하나가 떠올라서 쉽게 구현할 수 있었다.
하나의 큰 원만 회전시키고, 그 내부의 원들은 큰 원의 지름상에 위치하여 서로의 크기만을 변화시키는 것이다.
비율에 따라 container div를 rotate시키면서 내부 원의 지름을 변경하는 방식으로 구현했다.

Circle.tsx

import * as S from "./Circle.style";
import { useEffect, useState } from "react";
import { MAX_DIAMETER } from "./Circle.style";

export default function CircleTemplate() {
  const [ratio, setRatio] = useState(50);
  const [deg, setDeg] = useState(0);
  const [diameter, setDiameter] = useState(MAX_DIAMETER / 2);

  useEffect(() => {
    setDeg(0.9 * Math.abs(ratio - 50));
  }, [ratio]);

  const onChangeHandler = (e) => {
    const target = e.target.value;
    setRatio(target);
    setDiameter(2 * target);
  };
  return (
    <S.Container>
      <S.RatioInput onChange={onChangeHandler} />
      <S.CircleContainer deg={deg}>
        <S.InnerCircle width={diameter} height={diameter} isLeft={true} />
        <S.InnerCircle
          width={MAX_DIAMETER - diameter}
          height={MAX_DIAMETER - diameter}
          isLeft={false}
        />
      </S.CircleContainer>
    </S.Container>
  );
}

Circle.style.ts

import styled from "styled-components";

export const MAX_DIAMETER = 200;
export const QUARTER = MAX_DIAMETER / 4;

export const Container = styled.div`
  padding: 100px 20px;
`;

export const RatioInput = styled.input`
  width: 240px;
  height: 40px;
  margin: 20px 0;
`;

export const CircleContainer = styled.div<{ deg }>`
  width: ${MAX_DIAMETER}px;
  height: ${MAX_DIAMETER}px;
  display: flex;
  align-items: center; // 내부 두 원을 외부 원의 지름상에 위치하기 위한 가운데 정렬
  transition-duration: 1s;
  transition-timing-function: cubic-bezier(0, 0, 0.1, 1);
  transform: rotate(${({ deg }) => deg}deg);
`;
export const InnerCircle = styled.div<{ width; height; isLeft }>`
  width: ${({ width }) => width}px;
  height: ${({ height }) => height}px;
  border-radius: 50%;
  min-width: ${QUARTER}px;
  min-height: ${QUARTER}px;
  max-width: ${MAX_DIAMETER - QUARTER}px;
  max-height: ${MAX_DIAMETER - QUARTER}px;
  background-color: ${({ isLeft }) => (isLeft ? "#dadee0" : "#ea0b25")};
  transition-duration: 1s;
  transition-timing-function: cubic-bezier(0, 0, 0.1, 1);
`;

input에 입력하는 숫자게 따라 원이 변하게 된다. 0~100을 넘어가는 숫자에 대해 딱히 제한하는 코드는 딱히 작성하지 않았다

profile
팀스파르타에서 IT 직군 채용 플랫폼 '인텔리픽'을 개발하고 있습니다.

0개의 댓글