<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>할 일 목록</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
line-height: 1.6;
}
h1 {
text-align: center;
margin-bottom: 20px;
}
.input-container {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
input[type="text"] {
padding: 10px;
font-size: 1rem;
border: 1px solid #ccc;
border-radius: 5px;
width: 300px;
}
button {
padding: 10px 20px;
font-size: 1rem;
background-color: #007aff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-left: 10px;
}
button:hover {
background-color: #005ecb;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
li {
display: flex;
align-items: center;
background-color: #f5f5f5;
margin: 5px 0;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
justify-content: space-between;
}
.task-text {
flex-grow: 1;
margin-left: 10px;
}
.completed {
text-decoration: line-through;
color: #ccc;
}
.check-btn {
background-color: #4caf50;
color: white;
border: none;
border-radius: 50%;
cursor: pointer;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
line-height: 1;
}
.check-btn:hover {
background-color: #45a049;
}
.particle {
position: absolute;
border-radius: 50%; /* 원형 */
opacity: 1;
animation: explode 1s ease-out forwards, fade-out 1.5s ease-out forwards;
}
@keyframes explode {
0% {
transform: translate(0, 0) scale(1);
}
50% {
transform: scale(1.5); /* 크기 확장 */
}
100% {
transform: translate(var(--x), var(--y)) scale(0.5); /* 최종 위치 */
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>
</head>
<body>
<h1>할 일 목록</h1>
<div class="input-container">
<input type="text" id="todoInput" placeholder="할 일을 입력하세요">
<button onclick="addTask()">할 일 추가</button>
</div>
<ul id="todoList"></ul>
<script>
function addTask() {
const input = document.getElementById("todoInput");
const task = input.value.trim();
if (task === "") {
alert("할 일을 입력하세요!");
return;
}
// 새로운 할 일 생성
const listItem = document.createElement("li");
// 체크 버튼
const checkButton = document.createElement("button");
checkButton.textContent = "✔";
checkButton.className = "check-btn";
checkButton.onclick = function () {
completeTask(listItem, taskSpan);
};
// 할 일 텍스트
const taskSpan = document.createElement("span");
taskSpan.textContent = task;
taskSpan.className = "task-text";
// 구성
listItem.appendChild(checkButton);
listItem.appendChild(taskSpan);
document.getElementById("todoList").appendChild(listItem);
// 입력 필드 초기화
input.value = "";
}
function completeTask(listItem, taskSpan) {
taskSpan.classList.add("completed");
// 파티클 애니메이션 생성
const particleCount = 50; // 파티클 수
const rect = listItem.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement("div");
particle.className = "particle";
// 초기 위치 설정
particle.style.left = `${centerX}px`;
particle.style.top = `${centerY}px`;
// 무작위 크기, 색상 설정
const size = Math.random() * 8 + 4; // 크기 (4~12px)
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
particle.style.backgroundColor = getRandomColor();
// 애니메이션 속성 설정
const angle = Math.random() * 2 * Math.PI; // 방향 (라디안)
const distance = Math.random() * 120 + 50; // 거리
particle.style.setProperty("--x", `${distance * Math.cos(angle)}px`);
particle.style.setProperty("--y", `${distance * Math.sin(angle)}px`);
// 파티클 제거
setTimeout(() => {
particle.remove();
}, 1500);
document.body.appendChild(particle);
}
}
function getRandomColor() {
const colors = ["#FF5722", "#FF9800", "#FFC107", "#4CAF50", "#03A9F4", "#9C27B0", "#E91E63"];
return colors[Math.floor(Math.random() * colors.length)];
}
document.getElementById("todoInput").addEventListener("keypress", function (e) {
if (e.key === "Enter") {
addTask();
}
});
</script>
</body>
</html>