티스토리 뷰
반응형
기본 스티커 메모를 아시나요?
헤더 부분을 드래그하면 이동되는 것과 메모 입력하는 기능을 흉내내보았는데요.
제 사이트에는 딱 저 2가지 기능만 필요하여 저 부분만 작업했습니다!
Memo.js
import React, { useCallback, useRef, useState } from 'react';
import styled from 'styled-components';
const Wrap = styled.div`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
background: yellow;
border: 1px solid #c0c0a4;
box-sizing: border-box;
`;
const Header = styled.div`
padding: 5px;
width: 100%;
font-size: 14px;
font-weight: 700;
color: yellow;
background: #c0c0a4;
text-align: center;
`;
const Content = styled.div`
padding: 5%;
max-height: 300px;
overflow-y: auto;
textarea {
padding: 5%;
width: 100%;
min-height: 150px;
box-sizing: border-box;
background: none;
outline: none;
border: none;
}
`;
const Memo = () => {
const [memoText, setMemoText] = useState('');
const wrapRef = useRef(null);
const headerRef = useRef(null);
let lastX = 0;
let lastY = 0;
let startX = 0;
let startY = 0;
const onFocusout = useCallback(({ target }) => {
setMemoText(target.value);
}, [memoText]);
const onMove = useCallback((e) => {
e.preventDefault();
lastX = startX - e.clientX;
lastY = startY - e.clientY;
startX = e.clientX;
startY = e.clientY;
wrapRef.current.style.top = `${wrapRef.current.offsetTop - lastY}px`;
wrapRef.current.style.left = `${wrapRef.current.offsetLeft - lastX}px`;
}, []);
const removeEvent = useCallback(() => {
document.removeEventListener('mouseup', removeEvent);
document.removeEventListener('mousemove', onMove);
}, []);
const onMouseDown = useCallback((e) => {
e.preventDefault();
startX = e.clientX;
startY = e.clientY;
document.addEventListener('mouseup', removeEvent);
document.addEventListener('mousemove', onMove);
}, []);
return (
<Wrap ref={wrapRef}>
<Header
ref={headerRef}
onMouseDown={onMouseDown}
>
Memo
</Header>
<Content>
<textarea
placeholder="메모를 입력해주세요..."
onBlur={onFocusout}
></textarea>
</Content>
</Wrap>
);
};
export default Memo;
포커스가 빠져나갈때 value값을 저장하도록 해두었습니다.
아! 코드는 js에서 사용하던 그대로 사용했으며.. ↓
ref를 통해 style 값을 넣는 부분을 안하고 싶지만..
useState를 사용할 경우 안되더라구요. 비동기여서 그런듯한데....
동기로 잘 사용할 방법을 찾으면 해결 가능할 것 같은데....
velog.io/@aerirang647/32setState-%EB%B9%84%EB%8F%99%EA%B8%B0
[+32]setState -> 비동기
동기와 비동기동기: 코드 한 줄 한 줄 끝날 때까지 기다렸다가 다음줄로 넘어가는 성질.ex. forEach비동기: 코드 한 줄이 하고 있는 일이 끝나지 않았는데 일을 시켜놓고 내려가다가 일이 끝났다는
velog.io
여튼.. 그래서 그냥 ref를 통해 style을 수정해주고있습니다.
더 좋은 방법이 있을 것 같은데 아직 찾지를 못해서...ㅠ
쪼랩에게 좋은 의견이 있으면 말해주심 감사하겠습니다.
완성된 모양과 동작입니다.
반응형