바닐라 JS) 20. APP 꾸미기

송민경's avatar
Sep 03, 2024
바닐라 JS) 20. APP 꾸미기

1. 배경 이미지

  • 전체 화면으로 변경
  • 창 크기에 따라 이미지 조절
  • 젤 뒤에 위치
/* 배경 이미지 설정 */ #bg-img { position: fixed; /* 이미지를 화면에 고정하여 스크롤 시에도 유지 */ top: 0; left: 0; width: 100%; height: 100%; object-fit: fill; object-position: center; z-index: -1; /* 다른 모든 요소의 뒤에 위치 */ }
notion image
 

2. login-form

  • 화면의 가운데 위치
  • 입력, 버튼 수정
  • login-form에 hodden이 추가되었지만 사라지지 않고 텍스트 뒤에 위치해있음 → !important;
    • notion image
.hidden { display: none !important; // 우선 순위 높이기 } /* 로그인 폼의 스타일 */ .login-form { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; align-items: center; /* 수직 중앙 정렬 */ gap: 10px; font-size: 20px; border: none; /* 기본 버튼 테두리 제거 */ } /* 로그인 폼의 입력 필드 스타일 */ .login-form input { padding: 20px; /* 입력 필드 안에 여백 추가 */ font-size: 30px; /* 입력 필드의 텍스트 폰트 크기를 30px로 설정 */ border: 1px solid #ccc; /* 기본 테두리 스타일 */ border-radius: 5px; /* 입력 필드 모서리 둥글게 설정 */ box-sizing: border-box; /* 패딩을 너비 계산에 포함시킴 */ } /* 로그인 폼의 버튼 스타일 */ .login-form button { padding: 20px; font-size: 25px; cursor: pointer; /* 버튼 위에 마우스를 올리면 포인터로 변경 */ background-color: #3c7cc0; color: white; /* 버튼 텍스트 색상 설정 */ border-radius: 5px; } .login-form button:hover { background-color: #0056b3; /* 버튼 호버 시 배경색 변경 */ }
notion image
 

3. 인사말

  • 화면 위쪽에 위치
  • 크기, 테두리 수정
/* 인사말 스타일 */ #greeting { position: fixed; top: 15%; left: 50%; transform: translate(-50%, -50%); font-size: 50px; padding: 20px; text-align: center; /* 텍스트 가운데 정렬 */ border: none; }
notion image
 

4. 명언

  • 아래에 위치
  • 불투명한 배경색 적용
  • 명언과 저자 줄, 크기 변경
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="css/style.css"> </head> <body> <form class="login-form hidden" id="login-form"> <input required maxlength="15" type="text" placeholder="What is your name?" /> <button type="submit">로그인</button> </form> <h2 id="clock">00:00:00</h2> <h1 class="hidden" id="greeting"></h1> <form id="todo-form"> <input type="text" placeholder=" 할일을 쓰고 enter를 누르세요" required/> </form> <ul id="todo-list"></ul> <div id="quote"> <div></div> <div></div> </div> <div id="weather"> <span></span> <span></span> </div> <script src="js/greetings.js"></script> <script src="js/clock.js"></script> <script src="js/quotes.js"></script> <script src="js/background.js"></script> <script src="js/todo.js"></script> <script src="js/weather.js"></script> </body> </html>
const quotes = [ { quote: "The only way to do great work is to love what you do", author: "Steve Jobs" }, { quote: "Life is what happens when you're busy making other plans", author: "John Lennon" }, { quote: "The purpose of our lives is to be happy", author: "Dalai Lama" }, { quote: "Get busy living or get busy dying", author: "Stephen King" }, { quote: "You have within you right now, everything you need to deal with whatever the world can throw at you", author: "Brian Tracy" }, { quote: "Believe you can and you're halfway there", author: "Theodore Roosevelt" }, { quote: "The best way to predict the future is to invent it", author: "Alan Kay" }, { quote: "Your time is limited, don't waste it living someone else's life", author: "Steve Jobs" }, { quote: "If life were predictable it would cease to be life, and be without flavor", author: "Eleanor Roosevelt" }, { quote: "In the end, we will remember not the words of our enemies, but the silence of our friends", author: "Martin Luther King Jr" } ]; const quote = document.querySelector("#quote div:first-child"); const author = document.querySelector("#quote div:last-child"); const todayQuote = quotes[Math.floor(Math.random() * quotes.length)]; quote.innerText = todayQuote.quote; author.innerText = `by ${todayQuote.author}`;
/*명언 스타일*/ #quote { position: fixed; /* 화면에 고정 */ bottom: 5%; /* 바닥에서 20% 위치 */ width: 100%; left: 50%; /* 화면의 가운데 위치 */ transform: translateX(-50%); /* 가운데 정렬 */ text-align: center; /* 텍스트 가운데 정렬 */ color: white; /* 텍스트 색상 (원하는 색상으로 변경 가능) */ padding: 10px; /* 텍스트 주변에 여백 추가 */ background: rgba(0, 0, 0, 0.5); /* 반투명 배경 (선택사항) */ border-radius: 5px; /* 모서리 둥글게 (선택사항) */ }
notion image
 

5. 시계

  • am, pm 추가하고 맨 앞에 오게 하기
  • 왼쪽 여백두기
const clock = document.querySelector("h2#clock"); function getClock() { const date = new Date(); let hours = date.getHours(); const minutes = String(date.getMinutes()).padStart(2, "0"); const seconds = String(date.getSeconds()).padStart(2, "0"); // AM/PM 형식으로 변환 const ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; // 시간 0을 12로 변환 // 두 자리 숫자로 포맷 const formattedHours = String(hours).padStart(2, "0"); clock.innerText = `${ampm} ${formattedHours}:${minutes}:${seconds}`; } getClock(); setInterval(getClock, 1000); // 1초마다 실행
/*시계 스타일*/ #clock { position: fixed; left: 3%; }
notion image
 

6. To Do List

  • todo-form
    • 위쪽과 왼쪽 여백두기
    • placeholder 변경
    • 테두리, 배경 변경
    • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="css/style.css"> </head> <body> <form class="login-form hidden" id="login-form"> <input required maxlength="15" type="text" placeholder="What is your name?" /> <button type="submit">로그인</button> </form> <h2 id="clock">00:00:00</h2> <h1 class="hidden" id="greeting"></h1> <form id="todo-form"> <input type="text" placeholder="✏️ todo 리스트 작성하기!" required/> </form> <ul id="todo-list"></ul> <div id="quote"> <div></div> <div></div> </div> <div id="weather"> <span></span> <span></span> </div> <script src="js/greetings.js"></script> <script src="js/clock.js"></script> <script src="js/quotes.js"></script> <script src="js/background.js"></script> <script src="js/todo.js"></script> <script src="js/weather.js"></script> </body> </html>
      /* todo-form 스타일 설정 */ #todo-form { position: fixed; top: 25%; left: 10%; padding: 20px; text-align: center; border: none; border-radius: 10px; } /* 입력 필드 스타일 설정 */ #todo-form input { padding: 15px; font-size: 20px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; width: 100%; margin-top: 10px; }
      notion image
  • todo-list
    • todo-form 밑에 위치
    • x버튼 배경, 테두리 변경
    • 줄 간격 변경
    • #todo-list{ position: fixed; top: 32%; left: 12%; padding: 15px; }
      notion image
  • 페이지네이션
  • 10개까지가 1개의 페이지
  • 페이지네이션 버튼 추가
  • 이벤트 추가
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="css/style.css"> </head> <body> <form class="login-form hidden" id="login-form"> <input required maxlength="15" type="text" placeholder="What is your name?" /> <button type="submit">로그인</button> </form> <h2 id="clock">00:00:00</h2> <h1 class="hidden" id="greeting"></h1> <form id="todo-form"> <input type="text" placeholder="✏️ todo 리스트 작성하기!" required/> </form> <ul id="todo-list"></ul> <!-- Add this section in your HTML --> <div id="pagination"> <button id="prev-page" disabled>이전</button> <span id="page-info">1</span> <button id="next-page">다음</button> </div> <div id="quote"> <div></div> <div></div> </div> <div id="weather"> <span></span> <span></span> </div> <script src="js/greetings.js"></script> <script src="js/clock.js"></script> <script src="js/quotes.js"></script> <script src="js/background.js"></script> <script src="js/todo.js"></script> <script src="js/weather.js"></script> </body> </html>
// JavaScript (script.js) document.addEventListener("DOMContentLoaded", () => { const toDoForm = document.getElementById("todo-form"); const toDoInput = toDoForm.querySelector("input"); const toDoList = document.getElementById("todo-list"); const prevPageButton = document.getElementById("prev-page"); const nextPageButton = document.getElementById("next-page"); const pageInfo = document.getElementById("page-info"); const TODOS_KEY = "todos"; const ITEMS_PER_PAGE = 10; let toDos = []; let currentPage = 1; function saveToDos() { localStorage.setItem(TODOS_KEY, JSON.stringify(toDos)); } function deleteToDo(event) { const li = event.target.parentElement; li.remove(); toDos = toDos.filter(toDo => toDo.id !== parseInt(li.id)); saveToDos(); updatePagination(); } function paintToDoList() { toDoList.innerHTML = ""; const start = (currentPage - 1) * ITEMS_PER_PAGE; const end = start + ITEMS_PER_PAGE; const toDosToDisplay = toDos.slice(start, end); toDosToDisplay.forEach(paintToDo); prevPageButton.disabled = currentPage === 1; nextPageButton.disabled = end >= toDos.length; pageInfo.innerText = `${currentPage}`; } function paintToDo(newToDo) { const li = document.createElement("li"); li.id = newToDo.id; const span = document.createElement("span"); span.innerText = newToDo.text; const button = document.createElement("button"); button.innerText = "❌"; button.addEventListener("click", deleteToDo); li.appendChild(span); li.appendChild(button); toDoList.appendChild(li); } function handleToDoSubmit(event) { event.preventDefault(); const newToDo = toDoInput.value; toDoInput.value = ""; const newTodoObj = { text: newToDo, id: Date.now(), } toDos.push(newTodoObj); saveToDos(); updatePagination(); } function updatePagination() { const totalPages = Math.ceil(toDos.length / ITEMS_PER_PAGE); if (currentPage > totalPages) { currentPage = totalPages; } paintToDoList(); } function handlePagination(event) { if (event.target.id === "next-page") { currentPage++; } else if (event.target.id === "prev-page") { currentPage--; } updatePagination(); } toDoForm.addEventListener("submit", handleToDoSubmit); prevPageButton.addEventListener("click", handlePagination); nextPageButton.addEventListener("click", handlePagination); const savedToDos = localStorage.getItem(TODOS_KEY); if (savedToDos !== null) { toDos = JSON.parse(savedToDos); updatePagination(); } else { toDos = []; } });
/* 페이지네이션 버튼 스타일 설정 */ #pagination { position: fixed; bottom: 26%; left: 14%; } #pagination button { padding: 10px 10px; margin: 0 10px; font-size: 10px; cursor: pointer; border: none; border-radius: 5px; background-color: #f0f0f0; }
notion image
 

7. 날씨

  • 시간 밑에 표시
  • 소수 첫째자리까지 표시
  • 날씨 이모지 추가
const API_KEY = "46c42ba74d2d22c044c652e13464ef9b"; // 날씨 상태에 따른 이모지 매핑 const weatherEmojis = { "Clear": "☀️", "Clouds": "☁️", "Rain": "🌧️", "Drizzle": "🌦️", "Thunderstorm": "⛈️", "Snow": "❄️", "Mist": "🌫️", "Smoke": "🌫️", "Haze": "🌫️", "Fog": "🌁", "Sand": "🌪️", "Dust": "🌫️", "Ash": "🌋", "Squall": "🌫️", "Tornado": "🌪️" }; function onGeoOk(position) { const lat = position.coords.latitude; const lon = position.coords.longitude; const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`; fetch(url) .then(response => response.json()) .then(data => { const weather = document.querySelector("#weather span:first-child"); const city = document.querySelector("#weather span:last-child"); city.innerText = data.name; // 온도를 소수 첫째 자리까지 표시 const temp = data.main.temp.toFixed(1); // 날씨 상태에 따른 이모지 가져오기 const weatherCondition = data.weather[0].main; const emoji = weatherEmojis[weatherCondition] || "🌥️"; // 기본 이모지 weather.innerText = `${weatherCondition} ${emoji} / ${temp}°C`; }); } function onGeoError() { alert("위치를 찾을 수 없어요. 날씨를 찾을 수 없어요ㅜ"); } navigator.geolocation.getCurrentPosition(onGeoOk, onGeoError);
/*날씨 스타일 설정*/ #weather { position: fixed; /* 화면에 고정 */ top: 7%; left: 3%; font-size: 20px; }
notion image
notion image
Share article
RSSPowered by inblog