728x90
반응형

 

 

 

완성 화면

 

 

 

 

 

 

 

코드 보기 / CSS

.slider__wrap {
        width: 100%;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .slider__img {                /*이미지가 나타나는(보이는) 영역*/
        position: relative;
        width: 800px;
        height: 450px;
        overflow: hidden;
      }
      .slider__inner {              /*이미지가 슬라이드 되는(움직이는) 영역*/
        display: flex;
        flex-wrap: wrap;
        width: 4800px;
        height: 450px;
      }
      .slider {
        position: relative;
        width: 800px;
        height: 450px;
      }
      .slider__btn a{
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        width: 60px;
        height: 60px;
        /* background-color: #fff; */
      }
      .slider__btn a.previous {
        left: 0;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-chevrons-left' width='60' height='60' viewBox='0 0 24 24' stroke-width='2' stroke='%23ffffff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpolyline points='11 7 6 12 11 17' /%3E%3Cpolyline points='17 7 12 12 17 17' /%3E%3C/svg%3E");
        text-indent: -99999px;
    }
      .slider__btn a.next {
        right: 0;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-chevrons-right' width='60' height='60' viewBox='0 0 24 24' stroke-width='2' stroke='%23ffffff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpolyline points='7 7 12 12 7 17' /%3E%3Cpolyline points='13 7 18 12 13 17' /%3E%3C/svg%3E");
        text-indent: -99999px;
    }
      .slider__btn a.previous:hover {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-chevrons-left' width='60' height='60' viewBox='0 0 24 24' stroke-width='2' stroke='%23000000' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpolyline points='11 7 6 12 11 17' /%3E%3Cpolyline points='17 7 12 12 17 17' /%3E%3C/svg%3E");
      }
      .slider__btn a.next:hover {
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-chevrons-right' width='60' height='60' viewBox='0 0 24 24' stroke-width='2' stroke='%23000000' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpolyline points='7 7 12 12 7 17' /%3E%3Cpolyline points='13 7 18 12 13 17' /%3E%3C/svg%3E");
      }
      .slider__dot {
        position: absolute;
        left: 50%;
        bottom: 20px;
        transform: translateX(-50%);
      }
      .slider__dot .dot {
        width: 20px;
        height: 20px;
        background-color: #fff;
        display: inline-block;
        border-radius: 50%;
        text-indent: -9999px;
        transition: all 0.5s;
        margin: 3px;
      }
      .slider__dot .dot.active{
        background-color: rgba(0, 0, 0, 1.5);
      }

 

 

 

 

 

코드 보기 / HTML

<div class="slider__wrap">
            <div class="slider__img">
                <div class="slider__inner">
                    <div class="slider s01"><img src="./img/sliderEffect02-min.jpg" alt="이미지1"></div>
                    <div class="slider s02"><img src="./img/sliderEffect04-min.jpg" alt="이미지2"></div>
                    <div class="slider s03"><img src="./img/sliderEffect06-min.jpg" alt="이미지3"></div>
                    <div class="slider s04"><img src="./img/sliderEffect08-min.jpg" alt="이미지4"></div>
                    <div class="slider s05"><img src="./img/sliderEffect07-min.jpg" alt="이미지5"></div>
                </div>
            </div>
            <div class="slider__btn">
                <a href="#" class="previous">previous (이전)</a>
                <a href="#" class="next">next (다음)</a>
            </div>
            <div class="slider__dot">
                <!-- <a href="#" class="dot active">1</a>
                <a href="#" class="dot">2</a>
                <a href="#" class="dot">3</a>
                <a href="#" class="dot">4</a>
                <a href="#" class="dot">5</a> -->
            </div>
        </div>

 

 

 

 

 

코드 보기  / JAVASCRIPT

 const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const sliderInner = sliderWrap.querySelector(".slider__inner");
        const slider = sliderWrap.querySelectorAll(".slider");
        const sliderDot = sliderWrap.querySelector(".slider__dot");
        const sliderBtn = sliderWrap.querySelectorAll(".slider__btn a");

        let currentIndex = 0;                   //현재 보이는 (가장 위에 있는) 이미지
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderWidth = sliderWrap.querySelector(".slider__img").offsetWidth;            //이미지 width 값
        let dotIndex = "";
        
        function init() {
            //슬라이드 될 이미지만큼 도트 메뉴 생성
            slider.forEach(()=>dotIndex += "<a href='#' class='dot'></a>");
            sliderDot.innerHTML = dotIndex;
            
            //도트 메뉴 활성화 (첫 번째)
            sliderDot.firstChild.classList.add("active");
        }
        init();

        //슬라이드 이미지의 위치 변경
        function moveSlider(num){
            sliderInner.style.transition = "all 400ms";
            sliderInner.style.transform = `translateX(-${sliderWidth * num}px)`;
            currentIndex = num;


            //버튼 활성화
            let DotActive = document.querySelectorAll(".slider__dot .dot");
            DotActive.forEach((active)=>active.classList.remove("active"));
            DotActive[num].classList.add("active");
        }

        // 도트 메뉴 클릭 시 이동
        sliderDot.querySelectorAll(".dot").forEach((dot, index) => {
            dot.addEventListener("click", () => {
                moveSlider(index);
            });
        });

        //슬라이드 버튼 클릭 시
        sliderBtn.forEach((btn, index)=>{
            btn.addEventListener("click",()=>{
                let previousIndex = (currentIndex + (sliderCount - 1)) % sliderCount;
                let nextIndex = (currentIndex + 1) % sliderCount;

                if(btn.classList.contains("previous")){
                    moveSlider(previousIndex);
                } else {
                    moveSlider(nextIndex);
                }
            });
        });

 

 

 

sliderWrap : 슬라이드 이미지를 감싸는 부모 요소
sliderImg : 슬라이드 이미지들을 감싸고 있는 요소
sliderInner : 슬라이드 이미지들을 실제로 이동시키는 요소
slider : 각 슬라이드 이미지를 나타내는 요소들의 배열
sliderDot : 슬라이드 도트 메뉴를 감싸는 요소
sliderBtn : 슬라이드 이전/다음 버튼을 나타내는 요소들의 배열
currentIndex : 현재 보이는 (가장 위에 있는) 이미지의 인덱스
sliderInterval : 다음 이미지로 넘어가는 간격의 시간 (밀리초 단위)
sliderCount : 전체 이미지의 총 개수
sliderWidth : 이미지의 너비 값
dotIndex : 도트 메뉴를 생성하기 위해 사용되는 문자열 변수


init() 함수 :  각 슬라이드 이미지 수만큼 도트 메뉴를 생성하고, 첫 번째 도트 메뉴를 활성화하는 역할을 한다.


moveSlider() 함수 : 슬라이드 이미지의 위치를 변경하고, 현재 보이는 이미지의 인덱스를 업데이트한다.

이 때, 도트 메뉴에서도 현재 보이는 이미지의 인덱스에 해당하는 도트 메뉴를 활성화합니다.

 

sliderDot.querySelectorAll(".dot").forEach : sliderDot 요소 내부의 .dot 요소들에 대해 forEach()를 사용하여 클릭 이벤트를 등록한다. 도트 메뉴를 클릭하면 해당 인덱스에 해당하는 슬라이드 이미지를 보여준다.

 

 sliderBtn.forEach((btn, index) : sliderBtn 요소들에 대해서도 forEach()를 사용하여 클릭 이벤트를 등록한다.

이전/다음 버튼을 클릭하면 이전/다음 슬라이드 이미지를 보여준다.

previousIndex와 nextIndex는 이전/다음 슬라이드 이미지의 인덱스를 계산하는데 사용된다.

이 때, % 연산자를 사용하여 인덱스의 범위가 슬라이드 이미지 수 내에 유지되도록 한다.

 

 

 

 

init()

 

slider.forEach(()=>dotIndex += "<a href='#' class='dot'></a>");

: slider 변수에 할당된 이미지들의 개수만큼 dotIndex 변수에 문자열을 추가한다.

이 문자열은 각 이미지에 해당하는 도트 메뉴를 생성하는 HTML 코드가 된다.


sliderDot.innerHTML = dotIndex;

: sliderDot 변수에 할당된 도트 메뉴를 가지고 있는 HTML 요소에 dotIndex 문자열을 할당하여 도트 메뉴를 생성한다.

sliderDot.firstChild.classList.add("active");

: 첫 번째 도트 메뉴를 활성화합니다.

이를 위해 sliderDot 요소의 첫 번째 자식 요소에 active 클래스를 추가합니다.

 

 

 

 

 

moveSlider

 

sliderInner.style.transition = "all 400ms";

: 슬라이드 이미지가 이동할 때 애니메이션 효과를 추가한다.

all은 모든 속성에 대해 애니메이션을 적용하며, 400ms는 애니메이션 시간을 0.4초로 지정한다.

sliderInner.style.transform = translateX(-${sliderWidth * num}px);

: 슬라이드 이미지를 이동시킨다.

translateX는 요소를 수평 방향으로 이동시키는 CSS 함수이며, - ${sliderWidth * num}px는 이동 거리를 나타낸다. sliderWidth는 슬라이드 이미지의 가로 크기를 나타내며, num은 이동할 이미지의 인덱스이다.

currentIndex = num;

: 현재 보여지는 이미지의 인덱스를 num으로 업데이트 한다.

let DotActive = document.querySelectorAll(".slider__dot .dot");

: 도트 메뉴를 나타내는 HTML 요소를 선택한다.

DotActive.forEach((active)=>active.classList.remove("active"));

:도트 메뉴의 활성화 클래스 active를 모두 제거한다.

DotActive[num].classList.add("active");

: num에 해당하는 이미지에 해당하는 도트 메뉴에 active 클래스를 추가하여 해당 도트 메뉴를 활성화한다.

 

 

 

 

 

sliderDot.querySelectorAll(".dot").forEach((dot, index)

 

 

sliderDot.querySelectorAll(".dot")

: 도트 메뉴 요소를 모두 선택한다.

forEach((dot, index) => {...})

: 선택된 도트 메뉴 요소마다 콜백 함수를 실행한다.

이때, dot은 각 도트 메뉴 요소를 나타내며, index는 해당 요소의 인덱스를 나타낸다.

dot.addEventListener("click", () => {...})

:  각 도트 메뉴 요소에 클릭 이벤트 핸들러를 등록한다.

moveSlider(index)

: 클릭한 도트 메뉴에 해당하는 이미지를 화면에 보여주도록 moveSlider() 함수를 호출한다.

index는 클릭한 도트 메뉴 요소의 인덱스이며, 이를 moveSlider() 함수의 인자로 전달하여 해당 이미지를 화면에 보여주게 된다.

 

 

 

 

 

 sliderBtn.forEach((btn, index)

: 이전/다음 버튼을 클릭할 때 실행되는 이벤트 핸들러를 등록한다.


sliderBtn.forEach((btn, index) => {...})

:  이전/다음 버튼 요소를 모두 선택한다.

btn.addEventListener("click", () => {...})

: 각 버튼 요소에 클릭 이벤트 핸들러를 등록한다.

let previousIndex = (currentIndex + (sliderCount - 1)) % sliderCount;

: 이전 버튼을 클릭했을 때 보여줄 이미지의 인덱스를 계산한다.

currentIndex는 현재 화면에 보이는 이미지의 인덱스이며, (sliderCount - 1)은 이미지 배열의 마지막 인덱스를 의미한다.

% sliderCount는 계산 결과가 이미지 배열의 범위를 벗어나지 않도록 인덱스를 조정한다.

let nextIndex = (currentIndex + 1) % sliderCount;

: 다음 버튼을 클릭했을 때 보여줄 이미지의 인덱스를 계산한다.

currentIndex는 현재 화면에 보이는 이미지의 인덱스이며, + 1은 다음 인덱스를 나타낸다

% sliderCount는 계산 결과가 이미지 배열의 범위를 벗어나지 않도록 인덱스를 조정한다.

if(btn.classList.contains("previous")) {...}

: 클릭한 버튼이 이전 버튼인지 다음 버튼인지 판별한다.

이전 버튼을 클릭한 경우 previousIndex에 해당하는 이미지를 보여주도록 moveSlider(previousIndex) 함수를 호출하며, 다음 버튼을 클릭한 경우 nextIndex에 해당하는 이미지를 보여주도록 moveSlider(nextIndex) 함수를 호출한다.

 

 

 

 

 

 

728x90
반응형

 

 

 

완성 화면

 

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

	const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const sliderInner = sliderWrap.querySelector(".slider__inner");
        const slider = sliderWrap.querySelectorAll(".slider");

        let currentIndex = 0;                   //현재 보이는 (가장 위에 있는) 이미지
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderWidth = sliderWrap.querySelector(".slider__img").offsetWidth;            //이미지 width 값
        let sliderHeight = sliderWrap.querySelector(".slider__img").offsetHeight;            //이미지 height 값
        let sliderClone = sliderInner.firstElementChild.cloneNode(true);        //슬라이드 이미지 중 첫번째 요소(이미지)를 복사

        
        //sliderClone을 슬라이드 될 이미지의 마지막에 추가(붙여넣기)
        sliderInner.appendChild(sliderClone);

        function sliderEffect() {
            currentIndex++;

            sliderInner.style.transition = "all 0.5s";
            sliderInner.style.transform = `translateY(-${sliderHeight*currentIndex}px)`;

            //마지막 슬라이드일 때
            if(currentIndex == sliderCount){
                setTimeout(()=>{
                    sliderInner.style.transition = "0s";
                    sliderInner.style.transform = "translateY(0px)"
                },500);
                currentIndex = 0;
            }
        }
    
        setInterval(sliderEffect, sliderInterval);

 


querySelector() 메서드를 사용하여 HTML 문서에서 이미지 슬라이드 쇼의 요소들을 가져온다.

querySelector() 메서드는 CSS 선택자를 사용하여 문서에서 요소를 선택할 수 있다.

그리고 let 키워드를 사용하여 몇 가지 변수를 정의한다. 

currentIndex 변수는 현재 보이는 이미지의 인덱스를 저장하며, sliderInterval 변수는 이미지가 전환되는 간격을 나타낸다. 

sliderCount 변수는 전체 이미지의 수를 저장하고, sliderHeight 변수는 이미지의 높이를 저장한다.

cloneNode() 메서드를 사용하여 첫 번째 이미지를 복제한 sliderClone 요소를 만들고, appendChild() 메서드를 사용하여 sliderClone 요소를 sliderInner 요소의 마지막 자식으로 추가한다. 

이렇게 하면 슬라이드가 무한으로 반복되는 효과를 구현할 수 있다.

그리고 sliderEffect() 함수를 만든다. 

이 함수는 setInterval() 메서드를 사용하여 일정한 간격으로 호출되며, currentIndex 변수를 증가시킨다. 

그리고 style 속성을 사용하여 sliderInner 요소를 이동시키는 애니메이션 효과를 적용한다. 

마지막 슬라이드일 경우 setTimeout() 메서드를 사용하여 일정 시간 후에 sliderInner 요소를 초기화시킨다.

마지막으로 setInterval() 메서드를 사용하여 sliderEffect() 함수를 일정한 간격으로 호출한다.

 

 

 

코드 보기 / GSAP

 sliderInner.appendChild(sliderClone);

        function sliderEffect() {
            currentIndex++;
            gsap.to(sliderInner, {
                duration: 0.5,
                y: -sliderHeight * currentIndex,
                ease: "power2.inOut",
                onComplete: () => {
                    if (currentIndex == sliderCount) {
                        gsap.set(sliderInner, { y: 0 });
                        currentIndex = 0;
                    }
                },
            });
        }
        setInterval(sliderEffect, sliderInterval);

 

이 코드에서는 sliderHeight 변수를 사용하여 이미지의 높이를 계산하여 이동합니다.


gsap.to() 메소드를 사용하여 sliderInner 요소를 이동시키고, duration 옵션을 사용하여 애니메이션 시간을 설정한다.

y 옵션을 사용하여 sliderInner 요소를 y축 방향으로 이동시키고, ease 옵션을 사용하여 이동 효과를 설정합니다.

onComplete 콜백 함수는 애니메이션이 끝난 후 실행되며, 현재 이미지가 마지막 이미지인 경우 슬라이더를 초기 상태로 되돌리고, currentIndex 변수를 0으로 설정한다.
setInterval() 메소드를 사용하여 sliderEffect() 함수를 주기적으로 실행하여 이미지 슬라이더를 자동으로 이동시킨다.

 

 

 

코드 보기 / Jquery

 setInterval(() => {
            const sliderClone = $(".slider__inner .slider:first-child").clone(true);
            $(".slider__inner").append(sliderClone);
            currentIndex++;
            let sliderHeight = -currentIndex * $(".slider__img").height();
            $(".slider__inner").css("transition", "all 0.5s").css("transform", `translateY(${sliderHeight}px)`);
            if (currentIndex == sliderCount) {
                setTimeout(() => {
                $(".slider__inner").css("transition", "0s").css("transform", "translateY(0px)");
                }, 500);
                currentIndex = 0;
            }
        }, sliderInterval);

 

 

setInterval(() => { ... })

: setInterval( ) 함수는 일정한 간격으로 함수를 반복 실행한다.

 

 

const sliderClone = $(".slider__inner .slider:first-child").clone(true);
: 첫번째 슬라이드를 복제하여 sliderClone 변수에 할당한다.

이 때, true를 인자로 넘겨서 하위 요소들까지 모두 복제하도록 한다.

 

 

 

$(".slider__inner").append(sliderClone);
: 복제된 슬라이드를 슬라이더 내부에 추가한다.

 

 

currentIndex++;
: 현재 슬라이드의 인덱스 값을 1 증가시킵니다.

 

 

let sliderHeight = -currentIndex * $(".slider__img").height();
: sliderHeight 변수에는 현재 슬라이드의 인덱스를 이용하여 슬라이더가 이동해야 할 거리를 계산한다.

이 값은 현재 슬라이드의 인덱스와 슬라이드 이미지의 높이를 곱한 것의 음수값으로 설정된다.

음수값을 사용하는 이유는 슬라이드가 이동해야 할 거리가 슬라이더의 방향과 반대이기 때문이다.

 

 

$(".slider__inner").css("transition", "all 0.5s").css("transform", `translateY(${sliderHeight}px)`);
: CSS transition 속성과 transform 속성을 이용하여 슬라이더가 이동하도록 한다.

transition 속성은 0.5초 동안 모든 속성에 대한 전환 효과를 설정하고, transform 속성은 translateY 함수를 사용하여 sliderHeight 값만큼 슬라이더를 이동시킨다.

 

 

if (currentIndex == sliderCount) {
: 현재 슬라이드 인덱스가 전체 슬라이드 개수와 같아졌을 때, 모든 슬라이드를 보여준 것이므로 다시 처음부터 시작해야 한다.

 

 

$(".slider__inner").css("transition", "0s").css("transform", "translateY(0px)");
: 슬라이더를 초기화하여 다시 처음부터 시작하도록 한다.

transition 속성을 0초로 설정하여 애니메이션 효과가 없도록 한다.

 

 

currentIndex = 0;
: 현재 슬라이드 인덱스 값을 0으로 초기화합니다.

 

}, sliderInterval);
: setInterval() 함수의 두번째 인자로 전달된 sliderInterval 변수는 슬라이드 전환 간격을 지정하는 값이다.

이 값은 일정한 간격으로 실행되는 함수를 정의하는 람다 함수의 실행 주기를 지정한다.

 

 

 

 

 

 

 

728x90
반응형

 

완성 화면

 

 

 

 

 

 

 

 

코드 보기 / CSS

.slider__wrap {
        width: 100%;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .slider__img {                /*이미지가 나타나는(보이는) 영역*/
        position: relative;
        width: 800px;
        height: 450px;
        overflow: hidden;
      }
      .slider__inner {              /*이미지가 슬라이드 되는(움직이는) 영역*/
        display: flex;
        flex-wrap: wrap;
        width: 4800px;
        height: 450px;
      }
      .slider {
        position: relative;
        width: 800px;
        height: 450px;
      }

 

 

코드 보기 / HTML

 <div class="slider__wrap">
            <div class="slider__img">
                <div class="slider__inner">
                    <div class="slider s01"><img src="./img/sliderEffect01-min.jpg" alt="이미지1"></div>
                    <div class="slider s02"><img src="./img/sliderEffect03-min.jpg" alt="이미지2"></div>
                    <div class="slider s03"><img src="./img/sliderEffect05-min.jpg" alt="이미지3"></div>
                    <div class="slider s04"><img src="./img/sliderEffect07-min.jpg" alt="이미지4"></div>
                    <div class="slider s05"><img src="./img/sliderEffect09-min.jpg" alt="이미지5"></div>
                </div>
            </div>
        </div>

 

 

 

 

코드 보기 / JAVASCRIPT

const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const sliderInner = sliderWrap.querySelector(".slider__inner");
        const slider = sliderWrap.querySelectorAll(".slider");

        let currentIndex = 0;                   //현재 보이는 (가장 위에 있는) 이미지
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderWidth = sliderWrap.querySelector(".slider__img").offsetWidth;            //이미지 width 값
        let sliderClone = sliderInner.firstElementChild.cloneNode(true);        //슬라이드 이미지 중 첫번째 요소(이미지)를 복사

        
        //sliderClone을 슬라이드 될 이미지의 마지막에 추가(붙여넣기)
        sliderInner.appendChild(sliderClone);

        function sliderEffect() {
            currentIndex++;

            sliderInner.style.transition = "all 0.5s";
            sliderInner.style.transform = `translateX(-${sliderWidth*currentIndex}px)`;

            //마지막 슬라이드일 때
            if(currentIndex == sliderCount){
                setTimeout(()=>{
                    sliderInner.style.transition = "0s";
                    sliderInner.style.transform = "translateX(0px)"
                },500);
                currentIndex = 0;
            }
        }
    
        setInterval(sliderEffect, sliderInterval);

 

querySelector() 메서드를 사용하여 HTML 문서에서 이미지 슬라이드 쇼의 요소들을 가져온다.

querySelector() 메서드는 CSS 선택자를 사용하여 문서에서 요소를 선택할 수 있다.

그리고 let 키워드를 사용하여 몇 가지 변수를 정의한다. 

currentIndex 변수는 현재 보이는 이미지의 인덱스를 저장하며, sliderInterval 변수는 이미지가 전환되는 간격을 나타낸다. 

sliderCount 변수는 전체 이미지의 수를 저장하고, sliderWidth 변수는 이미지의 너비를 저장한다.

cloneNode() 메서드를 사용하여 첫 번째 이미지를 복제한 sliderClone 요소를 만들고, appendChild() 메서드를 사용하여 sliderClone 요소를 sliderInner 요소의 마지막 자식으로 추가한다. 

이렇게 하면 슬라이드가 무한으로 반복되는 효과를 구현할 수 있다.

그리고 sliderEffect() 함수를 만든다. 

이 함수는 setInterval() 메서드를 사용하여 일정한 간격으로 호출되며, currentIndex 변수를 증가시킨다. 

그리고 style 속성을 사용하여 sliderInner 요소를 이동시키는 애니메이션 효과를 적용한다. 

마지막 슬라이드일 경우 setTimeout() 메서드를 사용하여 일정 시간 후에 sliderInner 요소를 초기화시킨다.

마지막으로 setInterval() 메서드를 사용하여 sliderEffect() 함수를 일정한 간격으로 호출한다.

 

 

 

 

 

코드 보기 / GSAP

<!-- GSAP -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script>
        sliderInner.appendChild(sliderClone);

        function sliderEffect() {
            currentIndex++;
            gsap.to(sliderInner, {
                duration: 0.5,
                x: -sliderWidth * currentIndex,
                ease: "power2.inOut",
                onComplete: () => {
                    if (currentIndex == sliderCount) {
                        gsap.set(sliderInner, { x: 0 });
                        currentIndex = 0;
                    }
                },
            });
        }
        setInterval(sliderEffect, sliderInterval);
    </script>

 

이전 코드와 거의 비슷하지만, 이 코드는 GreenSock Animation Platform (GSAP) 라이브러리를 사용하여 이미지 슬라이드 쇼를 구현하는 코드이다.

먼저 HTML 문서에서 GSAP 라이브러리를 가져오기 위해 script 요소를 추가한다. 

그리고 sliderClone 요소를 sliderInner 요소의 마지막 자식으로 추가하는 코드는 이전(위의 JAVASCRIPT)과 동일하다.

sliderEffect() 함수도 이전과 매우 유사하다.

하지만 이번에는 gsap.to() 메서드를 사용하여 sliderInner 요소를 이동시키는 애니메이션을 적용한다. 

이 메서드는 GSAP 라이브러리에서 제공하는 TweenMax 클래스의 메서드 중 하나이다.

gsap.to() 메서드는 첫 번째 매개변수로 애니메이션을 적용할 대상 요소를 받으며, 두 번째 매개변수로 애니메이션 옵션 객체를 받는데, 이 객체에는 애니메이션의 속성들을 설정할 수 있다.

여기서는 duration 속성을 사용하여 애니메이션의 지속시간을 설정하고, x 속성을 사용하여 요소를 이동시키는 값을 설정한다. 

그리고 ease 속성을 사용하여 애니메이션의 이징(easing) 방법을 설정한다. 

마지막으로 onComplete 속성을 사용하여 애니메이션이 끝난 후에 실행할 함수를 정의한다.

onComplete 속성에서는 현재 인덱스가 마지막 이미지를 가리킬 때 gsap.set() 메서드를 사용하여 sliderInner 요소의 위치를 초기하고, currentIndex 변수를 0으로 설정합니다.
마지막으로 setInterval() 메서드를 사용하여 sliderEffect() 함수를 일정한 간격으로 호출한다.

 

 

 

 

코드 보기 / Jqurey

<!-- Jquery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
    <script>
        setInterval(() => {
            const sliderClone = $(".slider__inner .slider:first-child").clone(true);
            $(".slider__inner").append(sliderClone);
            currentIndex++;
            let sliderWidth = -currentIndex * $(".slider__img").width();
            $(".slider__inner").css("transition", "all 0.5s").css("transform", `translateX(${sliderWidth}px)`);
            if (currentIndex == sliderCount) {
                setTimeout(() => {
                $(".slider__inner").css("transition", "0s").css("transform", "translateX(0px)");
                }, 500);
                currentIndex = 0;
            }
        }, sliderInterval);
    </script>

 

setInterval() 함수를 사용하여 이미지가 일정한 간격으로 슬라이드되도록 한다. 

각 슬라이드 이동 시마다, 첫 번째 이미지 요소를 복사하여 마지막 이미지 뒤에 추가한다.

그리고 currentIndex 변수를 증가시키고, 이동할 거리를 계산하여 $(".slider__inner") 요소에 CSS transform 속성을 적용하여 이동한다. 

이 때, sliderWidth 변수에 -currentIndex * $(".slider__img").width()를 할당하여 슬라이드할 거리를 계산한다.

이후, if 조건문에서 현재 이미지가 마지막 이미지인지 확인하고, 마지막 이미지에 도달하면 다시 첫 번째 이미지로 이동시키기 위해 CSS transform 속성을 초기화 시킨다.

이 방법은 간단한 jQuery 코드를 사용하여 이미지 슬라이드 쇼를 구현하며, setInterval()과 CSS transform 속성을 사용하여 이미지를 슬라이드한다.

 

 

 

 

 

 

 

 

 

728x90
반응형

 

완성 화면 (Effect01)

 

 

 

 

코드 보기 / CSS

.slider__wrap {
        width: 100%;
        height: 100vh;
        align-items: center;
        justify-content: center;
        display: flex;
       }
       .slider__img {
        position: relative;
        width: 800px;
        height: 450px;
        overflow: hidden;
       }
       .slider {
        position: absolute;
        left: 0;
        top: 0;
        opacity: 0;
        transition: all 0.5s;
       }
       .slider::before {
        position: absolute;
        left: 5px;
        top: 5px;
        background: rgba(0, 0, 0, 0.5);
        color: #fff;
        padding: 5px 10px;
       }
       .slider:nth-child(1)::before {content: '이미지1';}
       .slider:nth-child(2)::before {content: '이미지2';}
       .slider:nth-child(3)::before {content: '이미지3';}
       .slider:nth-child(4)::before {content: '이미지4';}
       .slider:nth-child(5)::before {content: '이미지5';}
       .slider:nth-child(1) {z-index: 5;}
       .slider:nth-child(2) {z-index: 4;}
       .slider:nth-child(3) {z-index: 3;}
       .slider:nth-child(4) {z-index: 2;}
       .slider:nth-child(5) {z-index: 1;}

 

 

 

코드 보기 / HTML

<body class="img01 bg01 font01">
    <header id="header">
        <h1>Javascript Slider Effect 01</h1>
        <p>슬라이드 이펙트 </p>
        <ul>
            <li class="active"><a href="sliderEffect01.html">1</a></li>
            <li><a href="sliderEffect02.html">2</a></li>
            <li><a href="sliderEffect03.html">3</a></li>
            <li><a href="sliderEffect04.html">4</a></li>
            <li><a href="sliderEffect05.html">5</a></li>
            <li><a href="sliderEffect06.html">6</a></li>
        </ul>
    </header> 
    <!-- header -->

    <main id="main">
        <div class="slider__wrap">
            <div class="slider__img">
                <div class="slider"><img src="./img/sliderEffect01-min.jpg" alt="이미지1"></div>
                <div class="slider"><img src="./img/sliderEffect02-min.jpg" alt="이미지2"></div>
                <div class="slider"><img src="./img/sliderEffect03-min.jpg" alt="이미지3"></div>
                <div class="slider"><img src="./img/sliderEffect04-min.jpg" alt="이미지4"></div>
                <div class="slider"><img src="./img/sliderEffect05-min.jpg" alt="이미지5"></div>
            </div>
        </div>
    </main>
    <!-- main -->

    <footer id="footer">
        <a href="mailto:goed0522@gmail.com">goed0522@gmail.com</a>
    </footer>
    <!-- footer -->

 

 

 

코드 보기  / JAVASCRIPT  - 기본

       const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const slider = sliderWrap.querySelectorAll(".slider");

        let currentIndex = 0;       //현재 보이는 (가장 위에 있는) 이미지
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간

        setInterval (()=>{
            let nextIndex = (currentIndex+1) % sliderCount;

            slider[currentIndex].style.opacity = "0";      //가장 위에 있는 이미지 숨김
            slider[nextIndex].style.opacity = "1";      //그 다음 이미지를 나타냄

            currentIndex = nextIndex;
            console.log(currentIndex);
        },sliderInterval);

 

const sliderWrap = document.querySelector(".slider__wrap"); 

: HTML에서 .slider__wrap 클래스를 가진 요소를 찾아서 sliderWrap 변수에 할당한다.


const sliderImg = sliderWrap.querySelector(".slider__img"); 

: sliderWrap 내부에서 .slider__img 클래스를 가진 요소를 찾아서 sliderImg 변수에 할당한다.


const slider = sliderWrap.querySelectorAll(".slider"); 

: sliderWrap 내부에서 .slider 클래스를 가진 모든 요소를 찾아서 slider 변수에 할당한다.


let currentIndex = 0; 

: 슬라이드의 초기값으로 가장 처음 이미지를 보이도록 한다.


let sliderCount = slider.length; 

: slider 변수에 저장된 모든 슬라이드의 개수를 구해 sliderCount 변수에 할당한다.


let sliderInterval = 3000; 

: 슬라이드가 변경되는 간격을 3초로 설정한다.


setInterval (()=> { ... },sliderInterval); 

: setInterval 함수를 사용해 일정한 시간 간격으로 함수를 반복 실행한다.


(currentIndex+1) % sliderCount 

: currentIndex에 1을 더한 후, sliderCount로 나눈 나머지 값으로 다음 슬라이드의 인덱스 값을 구한다.

이를 통해 마지막 슬라이드가 보여진 후 첫 번째 슬라이드로 돌아갈 수 있다.


slider[currentIndex].style.opacity = "0"; 

: 현재 보여지고 있는 슬라이드의 투명도(opacity) 값을 0으로 변경해 화면에서 숨긴다.


slider[nextIndex].style.opacity = "1"; 

: 다음 슬라이드의 투명도 값을 1로 변경해 화면에 나타낸다.


currentIndex = nextIndex; 

: nextIndex를 currentIndex에 할당해 다음번 슬라이드 변경 시 이전 슬라이드의 인덱스 값을 알 수 있다.

 

 

 

코드 보기  / JAVASCRIPT  - GSAP

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script>
        gsap.set(".slider:nth-child(n+2)",{opacity:0});

         setInterval(()=>{
            let nextIndex = (currentIndex + 1) % sliderCount;

                gsap.to(`.slider:nth-child(${currentIndex+1})`,{
                   opacity: 0,
                    duration : 1,
                    ease: "power2.inOut"
                });

                gsap.to(`.slider:nth-child(${nextIndex+1})`,{
                   opacity: 1,
                    duration : 1,
                    ease: "power2.inOut"
                });

                currentIndex = nextIndex;
        },sliderInterval);
    </script>

 

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>

:GSAP 라이브러리를 불러온다.

 

gsap.set(".slider:nth-child(n+2)",{opacity:0});

:슬라이드 쇼 이미지 중 첫 번째 이미지를 제외한 나머지 이미지를 숨긴다.

 

setInterval (()=> { ... },sliderInterval); 

: setInterval 함수를 사용해 일정한 시간 간격으로 함수를 반복 실행한다.

 

gsap.to(`.slider:nth-child(${currentIndex+1})`,{
        opacity: 0 or 1,
        duration : 1,
        ease: "power2.inOut"
    });

: gsap.to( )를 사용하여 현재 이미지와 다음 이미지를 페이드 인/ 아웃 효과와 함께 보여주고 숨긴다.

ease 속성은 애니메이션의 이징 효과를 설정한다.

power2.inOut은 느리게 시작하고 빠르게 가속하는 이징 효과이다.

 

currentIndex = nextIndex;

: 현재 이미지를 나타내는 currentIndex 변수를 업데이트 한다.

 

이렇게 구현된 코드는 기존의 setInterval( ) 함수 대신 gsap.to( ) 메서드를 사용하므로 애니메이션이 더 부드럽게 작동한다.

 

 

 

 

코드 보기  / JAVASCRIPT  - Jquery

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<script>
    setInterval(()=>{
        let nextIndex = (currentIndex+1) % sliderCount;

        $(slider[currentIndex]).animate({opacity: 0}, 500);
        $(slider[nextIndex]).animate({opacity: 1}, 500);

        currentIndex = nextIndex;
    },sliderInterval);
</script>

 

setInterval 함수를 이용하여 일정 간격으로 이미지를 변경한다.

currentIndex 변수는 현재 보이는 이미지의 인덱스를, sliderCount 변수는 전체 이미지의 개수를 저장한다. 

slider 변수는 이미지들을 나타내는 jQuery 객체이다.

jQuery의 animate 함수를 이용하여 이미지의 opacity 속성을 변경하여 이미지가 서서히 사라지거나 나타나도록 한다. 

이 때, 500은 애니메이션의 지속 시간을 나타내며, currentIndex 변수를 nextIndex로 변경하여 다음에 보일 이미지를 지정한다.

 

 

 

 

 

완성 화면 (Effect02)

 

 

 

 

 

코드 보기 / CSS

.slider__wrap {
        width: 100%;
        height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .slider__img {                /*이미지가 나타나는(보이는) 영역*/
        position: relative;
        width: 800px;
        height: 450px;
        overflow: hidden;
      }
      .slider__inner {              /*이미지가 슬라이드 되는(움직이는) 영역*/
        display: flex;
        flex-wrap: wrap;
        width: 4000px;
        height: 450px;
      }
      .slider {
        position: relative;
        width: 800px;
        height: 450px;
      }

 

 

 

코드 보기 / HTML

<div class="slider__wrap">
            <div class="slider__img">
                <div class="slider__inner">
                    <div class="slider"><img src="./img/sliderEffect06-min.jpg" alt="이미지1"></div>
                    <div class="slider"><img src="./img/sliderEffect07-min.jpg" alt="이미지2"></div>
                    <div class="slider"><img src="./img/sliderEffect08-min.jpg" alt="이미지3"></div>
                    <div class="slider"><img src="./img/sliderEffect09-min.jpg" alt="이미지4"></div>
                    <div class="slider"><img src="./img/sliderEffect10-min.jpg" alt="이미지5"></div>
                </div>
            </div>
        </div>

 

 

 

코드 보기  / JAVASCRIPT  - 기본

      const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const sliderInner = sliderWrap.querySelector(".slider__inner");
        const slider = sliderWrap.querySelectorAll(".slider");

        let currentIndex = 0;                   //현재 보이는 (가장 위에 있는) 이미지
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간

        sliderInner.style.transition = "all 0.8s";
        setInterval(()=>{
            currentIndex = (currentIndex+1) % sliderCount;
        
            sliderInner.style.transform = "translateX("+ -800 * currentIndex + "px)";
        },sliderInterval);

 

slider__wrap 클래스를 가진 요소 안에 여러 개의 이미지(slider 클래스)가 존재하며, slider__inner 클래스를 가진 요소를 사용해 이미지를 좌우로 이동시키는 방식으로 슬라이더를 구현한다.

currentIndex 변수는 현재 보이는(가장 위에 있는) 이미지의 인덱스를 저장한다.

sliderCount 변수는 전체 이미지의 총 개수를 나타내며, sliderInterval 변수는 다음 이미지로 넘어가는 간격의 시간을 나타낸다.

sliderInner.style.transition 속성은 슬라이드 이동 시 애니메이션 효과를 부드럽게 하기 위해 추가된 코드이다. 

setInterval() 함수를 사용하여 일정 시간마다 다음 이미지로 넘어가도록 구현되어 있으며, translateX() 함수를 사용하여 현재 이미지의 위치를 이동시키고, currentIndex 변수를 이용하여 다음 이미지로 인덱스를 변경한다.



 

 

코드 보기  / JAVASCRIPT  - GSAP

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script>
        setInterval(()=>{
            currentIndex = (currentIndex + 1) % sliderCount;

            gsap.to(".slider__inner",{
                x : -800 * currentIndex,
                duration : 1,
                ease: "elastic.out(1, 0.5)"
            })
        },sliderInterval);
    </script>

 

 GSAP의 gsap.to() 메소드를 사용하여 이미지들의 opacity 속성을 변경해 슬라이드 애니메이션을 구현한다. 

초기에는 첫 번째 슬라이드만 보이도록 gsap.set() 메소드를 사용하여 나머지 슬라이드들의 opacity 속성을 0으로 설정합니다. 그리고 setInterval() 함수를 사용하여 일정한 시간 간격으로 gsap.to() 메소드를 실행한다.

gsap.to() 메소드는 첫 번째 매개변수로 애니메이션을 적용할 요소를 선택하고, 두 번째 매개변수로 애니메이션을 적용할 속성을 객체 형태로 전달한다.

이 코드에서는 슬라이드의 opacity 속성을 변경하도록 지정했습니다. 세 번째 매개변수로는 애니메이션 실행 시간(duration)을 전달하고, 네 번째 매개변수로는 애니메이션의 이징(ease)을 전달한다.

이 코드에서는 GSAP의 ease 중 하나인 power2.inOut를 사용하여 슬라이드 애니메이션을 부드럽게 만들었다. 

이 외에도 여러 가지 이징 중에서 선택할 수 있다.

 

 

코드 보기  / JAVASCRIPT  - Jquery

<!-- jquery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
    <script>
        setInterval(()=>{
            currentIndex = (currentIndex+1) % $(".slider").length;

            $(".slider__inner").css("position", "relative");
            $(".slider__inner").animate({left : -800 * currentIndex},700,"easeOutElastic");

            
        },sliderInterval);
    </script>

 

setInterval() 함수는 일정한 시간 간격으로 이미지 슬라이더를 동작시키는 함수입니다. 

슬라이더의 현재 이미지를 나타내는 변수 currentIndex와 슬라이더 이미지의 총 개수를 나타내는 변수 sliderCount는 이미 이전 코드에서 정의되어 있다.

$(".slider__inner")은 클래스가 slider__inner인 HTML 요소를 선택한다.

이 요소는 전체 이미지가 담겨 있는 부모 요소이다.

.css() 함수는 해당 요소의 CSS 스타일 속성을 설정합니다. 이 코드에서는 .slider__inner 요소의 position 속성을 relative로 설정합니다.

.animate() 함수는 해당 요소를 애니메이션으로 움직이게 한다. 

이 코드에서는 .slider__inner 요소의 left 속성을 -800(이미지의 width값) * currentIndex로 설정한다. 

이렇게 함으로써, .slider__inner 요소가 좌우로 슬라이딩되며, 보여지는 이미지가 바뀌게 된다.

애니메이션의 지속시간은 700ms로 설정되어 있으며, easeOutElastic 이라는 이징 함수를 사용하여 자연스러운 슬라이딩 효과를 적용하고 있다.

 

 

 

완성 화면 (Effect03)

 

 

 

 

 

CSS는 가로와 세로만 차이가 있기 때문에 생략. 

(좌측으로 슬라이드 할 때는 width값 800 * 이미지 5장 = 4000이었지만 상측으로 슬라이드 시에는 height값 450 * 이미지 5장 이므로 = 2250이 된다.)

 

HTML 역시 구조가 완전히 같기 때문에 생략.

 

 

 

코드 보기  / JAVASCRIPT  - 기본

const sliderWrap = document.querySelector(".slider__wrap");
        const sliderImg = sliderWrap.querySelector(".slider__img");
        const sliderInner = sliderWrap.querySelector(".slider__inner");
        const slider = sliderWrap.querySelectorAll(".slider");

        let currentIndex = 0;                   //현재 보이는 (가장 위에 있는) 이미지
        let sliderCount = slider.length;        //전체 이미지의 총 수
        let sliderInterval = 3000;              //다음 이미지로 넘어가는 간격의 시간

        sliderInner.style.transition = "all 0.8s";
        setInterval(()=>{
            currentIndex = (currentIndex+1) % sliderCount;
        
            sliderInner.style.transform = "translateY("+ -450 * currentIndex + "px)";
        },sliderInterval);

 

sliderWrap 

: 슬라이더를 감싸는 div 엘리먼트를 참조한다.


sliderInner 

: 슬라이더 이미지들을 감싸는 div 엘리먼트를 참조한다.


slider 

: 슬라이더 이미지들을 참조한다.


currentIndex 

: 현재 보이는 (가장 위에 있는) 이미지의 인덱스를 저장한다.


sliderCount 

: 전체 이미지의 총 개수를 저장한다.


sliderInterval 

: 다음 이미지로 넘어가는 간격의 시간을 저장한다.


sliderInner.style.transition 

: 슬라이더 이동에 대한 CSS transition 속성을 설정한다.


setInterval() 

: 일정 시간 간격마다 실행되는 함수입니다. 슬라이더의 이미지를 변경하고 애니메이션을 적용한다.


currentIndex = (currentIndex+1) % sliderCount 

: 현재 인덱스에서 1을 더하고, 전체 이미지의 개수로 나누어 나머지를 구함으로써, 이미지 인덱스가 계속해서 순환하도록 한다.


sliderInner.style.transform = "translateY("+ -450 * currentIndex + "px)" 

: 현재 이미지 인덱스에 따라 sliderInner의 CSS transform 속성을 변경하여 슬라이더 이미지를 움직인다. 

여기서 -450은 이미지가 움직이는 거리이다. 

즉, currentIndex가 1 증가할 때마다 이미지가 450px(이미지의 height값)만큼 위로 이동한다.

 

 

 

 

 

코드 보기  / JAVASCRIPT  - GSAP

 <!--GSAP-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script>
        setInterval(()=>{
            currentIndex = (currentIndex + 1) % sliderCount;

            gsap.to(".slider__inner",{
                y : -450 * currentIndex,
                duration : 1,
                ease: "elastic.out(1, 0.5)"
            })
        },sliderInterval);
    </script>

 

 

슬라이더 이미지를 세로 방향으로 이동시키기 위해 translateY를 사용하였다.

이 부분을 GSAP에서 제공하는 y 속성으로 변경하여, GSAP의 애니메이션 기능을 이용하여 세로 방향으로 이동하도록 만들었다.

애니메이션 기능을 사용하기 위해서는 먼저 GSAP 라이브러리를 불러와야 하며, 이후 gsap.to() 메소드를 이용하여 원하는 요소를 선택하여 애니메이션을 적용할 수 있다.

 duration 속성을 이용하여 애니메이션이 진행되는 시간을 조절할 수 있으며, ease 속성을 이용하여 애니메이션의 가속도와 감속도를 조절할 수 있다.

위 코드에서는 elastic.out(1, 0.5) 값을 ease 속성으로 설정하여, 애니메이션의 마지막 부분에서 탄력적인 효과가 발생하도록 만들었다. 

 

 

 

 

코드 보기  / JAVASCRIPT  - Jquery

<!-- jquery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
    <script>
        setInterval(()=>{
            currentIndex = (currentIndex+1) % $(".slider").length;

            $(".slider__inner").css("position", "relative");
            $(".slider__inner").animate({top : -450 * currentIndex},700,"easeOutElastic");

        },sliderInterval);

 

querySelector와 querySelectorAll 함수를 사용하여 HTML 문서에서 각각 .slider__wrap, .slider__img, .slider__inner, .slider 클래스를 가진 요소들을 선택한다.

이들은 모두 슬라이드 컨테이너와 이미지, 이미지가 포함된 내부 컨테이너, 그리고 각 이미지를 나타내는 요소들이다.

그리고 나서 currentIndex를 0으로 초기화하고, sliderCount는 .slider 클래스를 가진 요소들의 수로 설정한다. 

sliderInterval은 3000ms로 설정되어 있다.
그 다음 sliderInner의 transition 속성을 "all 0.8s"로 설정하여, 슬라이드 전환시 0.8초 동안 애니메이션이 일어나도록 한다.

마지막으로 setInterval 함수를 사용하여 sliderInterval 간격으로 슬라이드가 전환되도록 한다. 

이때 currentIndex를 업데이트하여 다음에 보여질 이미지의 인덱스를 결정하고, sliderInner 요소의 transform 속성을 사용하여 슬라이드를 이동시킨다. 

이 코드에서는 translateX 또는 translateY 함수를 사용하여 각각 가로 방향 또는 세로 방향으로 이동시키도록 한다.



 

 

 

 

 

 

 

 

 

 

728x90
반응형

 

완성 화면

 

 

 

 

 

 

코드 보기 / HTML

 <main id="main">
        <div class="quiz__wrap__cbt">
            <div class="cbt__header">
                <h2>2020년 1회 정보처리기능사 기출 문제 </h2>
            </div>
            <div class="cbt__content">
                <div class="cbt__quiz">
                    <!-- <div class="cbt">
                        <div class="cbt__question"><span>1. </span>객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                        <div class="cbt__question__img"><img src="img/gineungsaJC2020-02.jpg" alt=""></div>
                        <div class="cbt__selects">
                        <div>
                                <input type="radio" id="select1">
                                <label for="select1"><span>클래스</span></label>
                                <input type="radio" id="select2">
                                <label for="select2"><span>메서드</span></label>
                                <input type="radio" id="select3">
                                <label for="select3"><span>상속</span></label>
                                <input type="radio" id="select4">
                                <label for="select4"><span>메시지</span></label>
                        </div>
                        <div class="cbt__desc">객체지향프로그램</div>
                        <div class="cbt__keyword">추상화 어쩌구</div>
                    </div> -->
                    <div class="cbt">
                        <div class="cbt__question"><span>1. </span>객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                        <div class="cbt__question__desc">객체 지향 언어는  ___________ 이다.</div>
                        <div class="cbt__selects">
                            <div>
                                <input type="radio" id="select1">
                                <label for="select1"><span>클래스</span></label>
                                <input type="radio" id="select2">
                                <label for="select2"><span>메서드</span></label>
                                <input type="radio" id="select3">
                                <label for="select3"><span>상속</span></label>
                                <input type="radio" id="select4">
                                <label for="select4"><span>메시지</span></label>
                            </div>
                        </div>
                        <div class="cbt__desc">객체지향프로그램</div>
                        <div class="cbt__keyword">추상화 어쩌구</div>
                    </div>
                </div>
            </div>
            <div class="cbt__aside">
                <div class="cbt__info">
                    <div>
                        <span class="cbt__time">남은 시간 :<em></em></span>
                        <button class="cbt__submit">답안지 제출</button>
                    </div>
                    <div>
                        <div class="cbt__title">수험자 : <em class="cbt__name"></em></div>
                        <div class="cbt__score">
                            <span> 전체 문항 수 : <em class="cbt__length"></em>문항</span> <br>
                            <span> 잔여 문항 수 : <em class="cbt__count"></em>문항</span> <br>
                        </div>
                    </div>
                </div>
                    <div class="cbt__omr">
                        <!-- <div class="omr">
                            <strong>1</strong>
                            <input type="radio" id="omr0_1">
                            <label for="omr0_1">
                                <span class="label-inner">1</span>
                            </label>
                            <input type="radio" id="omr0_2">
                            <label for="omr0_2">
                                <span class="label-inner">2</span>
                            </label>
                            <input type="radio" id="omr0_3">
                            <label for="omr0_3">
                                <span class="label-inner">3</span>
                            </label>
                            <input type="radio" id="omr0_4">
                            <label for="omr0_4">
                                <span class="label-inner">4</span>
                            </label>
                        </div> -->
                    </div>
            </div>
        </div>
        <div class="cbt__start">
            <div class="cbt__modal__start">
                <h2>종목 선택</h2>
                <div class="cbt__items">
                    <select name="cbtTime" id="cbtTime" class="items1" onchange="changeSelect(this)">
                        <option value="gineungsaJC2005_02">정보처리기능사 2005년 2회</option>
                        <option value="gineungsaJC2005_04">정보처리기능사 2005년 4회</option>
                        <option value="gineungsaJC2005_05">정보처리기능사 2005년 5회</option>
                        <option value="gineungsaJC2006_01">정보처리기능사 2006년 1회</option>
                        <option value="gineungsaJC2006_02">정보처리기능사 2006년 2회</option>
                        <option value="gineungsaJC2006_03">정보처리기능사 2006년 3회</option>
                        <option value="gineungsaJC2006_05">정보처리기능사 2006년 5회</option>
                        <option value="gineungsaJC2007_01">정보처리기능사 2007년 1회</option>
                        <option value="gineungsaJC2007_02">정보처리기능사 2007년 2회</option>
                        <option value="gineungsaJC2007_05">정보처리기능사 2007년 5회</option>
                        <option value="gineungsaJC2008_01">정보처리기능사 2008년 1회</option>
                        <option value="gineungsaJC2008_02">정보처리기능사 2008년 2회</option>
                        <option value="gineungsaJC2008_04">정보처리기능사 2008년 4회</option>
                        <option value="gineungsaJC2008_05">정보처리기능사 2008년 5회</option>
                        <option value="gineungsaJC2009_01">정보처리기능사 2009년 1회</option>
                        <option value="gineungsaJC2009_05">정보처리기능사 2009년 5회</option>
                        <option value="gineungsaJC2010_02">정보처리기능사 2010년 2회</option>
                        <option value="gineungsaJC2010_05">정보처리기능사 2010년 5회</option>
                        <option value="gineungsaJC2011_01">정보처리기능사 2011년 1회</option>
                        <option value="gineungsaJC2011_02">정보처리기능사 2011년 2회</option>
                        <option value="gineungsaJC2011_04">정보처리기능사 2011년 4회</option>
                        <option value="gineungsaJC2011_05">정보처리기능사 2011년 5회</option>
                    </select>
                    <select name="cbtTime" id="cbtTime" class="items2" onchange="changeSelect(this)">
                        <option value="gineungsaWD2009_05">웹디자인기능사 2009년 5회</option>
                        <option value="gineungsaWD2010_01">웹디자인기능사 2010년 1회</option>
                        <option value="gineungsaWD2010_02">웹디자인기능사 2010년 2회</option>
                        <option value="gineungsaWD2010_04">웹디자인기능사 2010년 4회</option>
                        <option value="gineungsaWD2010_05">웹디자인기능사 2010년 5회</option>
                        <option value="gineungsaWD2011_01">웹디자인기능사 2011년 1회</option>
                        <option value="gineungsaWD2011_02">웹디자인기능사 2011년 2회</option>
                        <option value="gineungsaWD2011_04">웹디자인기능사 2011년 4회</option>
                        <option value="gineungsaWD2011_05">웹디자인기능사 2011년 5회</option>
                        <option value="gineungsaWD2012_02">웹디자인기능사 2012년 2회</option>
                        <option value="gineungsaWD2012_04">웹디자인기능사 2012년 4회</option>
                        <option value="gineungsaWD2012_05">웹디자인기능사 2012년 5회</option>
                        <option value="gineungsaWD2013_02">웹디자인기능사 2013년 2회</option>
                        <option value="gineungsaWD2013_04">웹디자인기능사 2013년 4회</option>
                        <option value="gineungsaWD2013_05">웹디자인기능사 2013년 5회</option>
                        <option value="gineungsaWD2014_01">웹디자인기능사 2014년 1회</option>
                        <option value="gineungsaWD2014_04">웹디자인기능사 2014년 4회</option>
                        <option value="gineungsaWD2014_05">웹디자인기능사 2014년 5회</option>
                        <option value="gineungsaWD2015_01">웹디자인기능사 2015년 1회</option>
                        <option value="gineungsaWD2015_03">웹디자인기능사 2015년 3회</option>
                        <option value="gineungsaWD2015_04">웹디자인기능사 2015년 4회</option>
                        <option value="gineungsaWD2015_05">웹디자인기능사 2015년 5회</option>
                        <option value="gineungsaWD2016_01">웹디자인기능사 2016년 1회</option>
                        <option value="gineungsaWD2016_04">웹디자인기능사 2016년 4회</option>
                    </select>
                </div>
                <div class="cbt__view">
                    수험자의 성함은 <input type="text" class="name"> 입니다. <br>
                    종목은 <span class="subject"></span>가 선택 되었습니다.
                </div>
                <div data-lit-hue="20" data-lit-count="100" class="lit-container">
                    <button id="startbtn" class="minimal">시험 시작</button>
                </div>
            </div>
        </div>
        <div class="cbt__end">
            <div class="cbt__modal__end">
                <h2>🎊 수고하셨습니다.</h2>
                <div class="cbt__endscore"></div>
                <button class="return">시험지로 돌아가기 </button>
            </div>
        </div>
        
    </main>

 

 

 

코드 보기 / JAVASCRIPT

const cbtHeader = document.querySelector(".cbt__header h2");
        const cbtStart = document.querySelector(".cbt__start");
        const cbtEnd = document.querySelector(".cbt__end");
        const cbtStartBtn = document.querySelector(".cbt__start .minimal");
        const cbtEndBtn = document.querySelector(".cbt__end .return");
        const cbtTime = document.querySelector(".cbt__time em");
        const cbtEndscore = document.querySelector(".cbt__endscore");

        let questionAll = [];                          //모든 문제 정보
        let quizLength = 0;                     //전체 문항 수
        let questioncount = quizLength;         //남은 문항 수

        //시험 결과 관련 변수
        let truescore = 0;                  //맞은 갯수
        let falsescore = 0;                 //틀린 갯수

        //제한시간 변수
        let TimeLimit = "";
        let RemainTime = "3600";

        cbtEnd.classList.add("hide");
        //시험 시작
        const startQuiz = () => {
            cbtStart.classList.add("hide");          //modal 제거

            const inputEl = document.querySelector('.name');            // input에서 입력받은 요소 선택
            const userName = document.querySelector(".cbt__title em");  // em 요소 선택
            const inputValue = inputEl.value;                           //input에서 입력된 값 가져오기

            userName.textContent = inputValue;                          // em 요소에 입력된 값 넣기

            //제한시간
            TimeLimit = setInterval(reduceTime, 3600);
        }
        
        
        -----------<정답 확인 시>-------
        const cbtSelects = document.querySelectorAll(".cbt__selects");
                let Score = 0;

                questionAll.forEach((question, number) => {
                    const quizSelectsWrap = cbtSelects[number];
                    const userSelector = `input[name=select${number}]:checked`;
                    const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
                    const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;


                    if(numberAnswer == question.answer) {
                        console.log("정답")
                        truescore++;
                        cbtSelects[number].parentElement.classList.add("good");
                    } else {
                        console.log("오답")
                        falsescore++;
                        cbtSelects[number].parentElement.classList.add("bad");

                        //오답일 경우 정답 표시
                        const label = cbtSelects[number].querySelectorAll("label");
                        label[question.answer-1].classList.add("correct");
                    }
                    
                    //설명 숨기기
                    const quizDesc = document.querySelectorAll(".cbt__desc");
                    
                    if(quizDesc[number].innerText == "undefined"){
                        quizDesc[number].classList.add("hide");
                    } else {
                        quizDesc[number].classList.remove("hide");
                    }
                    
                });
                Score = Math.round((Score/questionAll.length)*100);
                cbtEnd.classList.remove("hide");
                cbtEndscore.innerHTML = "총"+truescore+"문항을 맞추셨습니다.<br> 틀린 문항 수는 "+falsescore+"개 이며, 총점은 "+Score+"입니다.";

            }
            
            ------------<제한시간>------------------
            //제한시간 설정
        const reduceTime = () => {
            RemainTime--;

            if(RemainTime == 0) endQuiz();

            cbtTime.innerText = displayTime();
        }

        //제한 시간 표시 
        const displayTime = () => {
            if(RemainTime <= 0){
                return "0분 00초";
            } else {
                let minutes = Math.floor(RemainTime / 60);
                let seconds = RemainTime % 60;

                //초의 단위가 한자리 수가 되면 앞에 0을 붙여주기
                if(minutes.toString().length == 1){
                    minutes = "0"+minutes;
                }

                if(seconds.toString().length == 1){
                    seconds = "0"+seconds;
                }

                return minutes + "분" + seconds + "초";
            }
        }
        
        
      -----------------<종목 선택>---------------
      //종목 선택
        const changeSelect = (ev) => {
            let selectValue = ev.value;
            let selectText = ev.options[ev.selectedIndex].text;

            cbtViewSubject.innerText = selectText;
            cbtHeader.innerText = selectText;

            dataQuestion(selectValue);
        }

 

 

 

 

 

제한 시간

 ----------<제한시간 변수>-----------
        let TimeLimit = "";
        let RemainTime = "3600";
        
        
        TimeLimit = setInterval(reduceTime, 3600);
        
        
        -------<제한시간 설정>-----------
           const reduceTime = () => {
            RemainTime--;

            if(RemainTime == 0) endQuiz();

            cbtTime.innerText = displayTime();
        }
        
        -----<제한 시간을 화면에 표시>---------
         const displayTime = () => {
            if(RemainTime <= 0){
                return "0분 00초";
            } else {
                let minutes = Math.floor(RemainTime / 60);
                let seconds = RemainTime % 60;

                //초의 단위가 한자리 수가 되면 앞에 0을 붙여주기
                if(minutes.toString().length == 1){
                    minutes = "0"+minutes;
                }

                if(seconds.toString().length == 1){
                    seconds = "0"+seconds;
                }

                return minutes + "분" + seconds + "초";
            }
        }

 

TimeLimit 변수의 초기값은 빈 문자열이며, RemainTime 변수의 초기값은 3600으로 설정된다.

이는 1시간에 해당하는 초수를 나타낸다.

setInterval 함수를 사용하여 reduceTime 함수를 3600밀리초(즉, 1시간)마다 호출하도록 설정된다.

reduceTime 함수는 남은 시간(RemainTime)을 1초씩 줄이고, 남은 시간이 0이 되면 endQuiz 함수를 호출한다.

또한 cbtTime 요소의 텍스트를 displayTime 함수가 반환하는 포맷된 문자열로 업데이트한다.

displayTime 함수는 남은 시간(RemainTime)을 입력으로 받아 카운트다운의 남은 분과 초를 계산하여, "mm분 ss초" 형식으로 남은 시간을 나타내는 포맷된 문자열을 반환한다.

여기서 "mm"은 분을, "ss"는 초를 나타냅니다. 남은 시간이 0보다 작거나 같으면 함수는 "0분 00초"를 반환한다.

reduceTime 함수에서 displayTime 함수를 호출하여 cbtTime 요소의 텍스트를 업데이트한다.

 

 

 

 

종목 선택

const changeSelect = (ev) => {
            let selectValue = ev.value;
            let selectText = ev.options[ev.selectedIndex].text;

            cbtViewSubject.innerText = selectText;
            cbtHeader.innerText = selectText;

            dataQuestion(selectValue);
        }

 

changeSelect 함수를 정의하는 것으로, 이 함수는 select 요소에서 옵션을 선택하면 호출된다.

ev는 이벤트 객체를 나타내며, 선택된 옵션의 값을 가져와 selectValue 변수에 할당하며, 선택된 옵션의 텍스트를 가져와 selectText 변수에 할당한다.
cbtViewSubject 요소의 텍스트와 cbtHeader 요소의 텍스트를 선택된 옵션의 텍스트로 변경한다.
마지막으로, dataQuestion 함수를 호출하여 선택된 옵션의 값을 인수로 전달한다.

이 함수는 이 값을 기반으로 데이터를 가져와 해당 데이터를 사용하여 문제를 표시하는 작업을 수행한다.

 

 

 

 

 

정답 확인 버튼 클릭 시, 점수와 틀린 문항과 맞은 문항 표시

 const answerQuiz = () => {
                const cbtSelects = document.querySelectorAll(".cbt__selects");
                let Score = 0;

                questionAll.forEach((question, number) => {
                    const quizSelectsWrap = cbtSelects[number];
                    const userSelector = `input[name=select${number}]:checked`;
                    const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
                    const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;


                    if(numberAnswer == question.answer) {
                        console.log("정답")
                        truescore++;
                        cbtSelects[number].parentElement.classList.add("good");
                    } else {
                        console.log("오답")
                        falsescore++;
                        cbtSelects[number].parentElement.classList.add("bad");

                        //오답일 경우 정답 표시
                        const label = cbtSelects[number].querySelectorAll("label");
                        label[question.answer-1].classList.add("correct");
                    }
                    
                    //설명 숨기기
                    const quizDesc = document.querySelectorAll(".cbt__desc");
                    
                    if(quizDesc[number].innerText == "undefined"){
                        quizDesc[number].classList.add("hide");
                    } else {
                        quizDesc[number].classList.remove("hide");
                    }
                    
                });
                FinalScore = Math.round((truescore/questionAll.length)*100);
                cbtEnd.classList.remove("hide");
                cbtEndscore.innerHTML = "총"+truescore+"문항을 맞추셨습니다.<br> 틀린 문항 수는 "+falsescore+"개 이며, 총점은 "+FinalScore+"입니다.";

            }

 

 

시험이 종료된 후 사용자의 답을 검사하고, 사용자가 맞춘 문제 수와 틀린 문제 수, 총점을 계산하여 화면에 출력하는 역할을 한다.


함수 내부에서는 우선 document.querySelectorAll(".cbt__selects")를 사용하여 HTML 문서 내의 모든 문제 선택지를 가져온다.

그 후,  questionAll 배열에 저장된 모든 문제에 대해 반복문을 실행하면서, 각 문제의 정답과 사용자의 선택지를 비교하고, 맞은 문제와 틀린 문제의 수를 카운트한다.

 

이 때, 맞은 문제일 경우 cbtSelects[number].parentElement.classList.add("good")를 사용하여 동그라미 표를 나타내고, truescore 변수를 1씩 증가시키며,  틀린 문제일 경우 cbtSelects[number].parentElement.classList.add("bad")를 사용하여 틀렸다는 표시인 붉은 사선을 나타내고, 맞는 선택지를 빨간색으로 바꾸어 정답을 표시하고 falsescore 변수를 1씩 증가시킨다.

또한, 각 문제에 대해 quizDesc를 사용하여 문제에 대한 설명을 가져와, 이 설명이 있는 경우에는 이를 화면에 보여주고, 없는 경우에는 숨긴다.

 

truescore 변수는 카운트 된 정답 수이며, falsescore 변수는 카운트 된 오답 수이다.

이 두 변수를 사용하여, 맞춘 문항 수와 틀린 문항 수를 화면에 출력한다.

FinalScore 변수는 총점을 계산한다.

총점은 맞춘 문항 수(truescore)를 전체 문항 수(questionAll)로 나눈 후, 100을 곱한 값입니다. Math.round() 함수를 사용하여 소수점 이하를 반올림하고, cbtEndscore.innerHTML을 사용하여 최종 결과를 화면에 출력한다.

 

 

 

 

 

 

시험 시작 버튼 클릭 시, OMR 답지 위에 입력 된 수험자의 이름을 표시

const startQuiz = () => {
            cbtStart.classList.add("hide");          //modal 제거

            const inputEl = document.querySelector('.name');            // input에서 입력받은 요소 선택
            const userName = document.querySelector(".cbt__title em");  // em 요소 선택
            const inputValue = inputEl.value;                           //input에서 입력된 값 가져오기

            userName.textContent = inputValue;                          // em 요소에 입력된 값 넣기

            //제한시간
            TimeLimit = setInterval(reduceTime, 3600);
        }

 

 

사용자가 입력한 이름을 가져와서 해당 이름을 모달 창의 제목에 넣는 역할을 하는 코드이다.

먼저 document.querySelector('.name')을 사용하여 HTML에서 name 클래스를 가진 요소를 찾는다.

그리고 inputValue 변수에 해당 요소의 값(value)을 할당한다.

그 후, document.querySelector(".cbt__title em")를 사용하여 HTML에서 cbt__title 클래스를 가진 요소의 자식 요소인 em 요소를 찾아 textContent를 사용하여 inputValue를 할당하여 OMR 답안지 위에 수험자의 이름을 표시한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형

 

 

완성 화면 (링크)

 

https://fitalux.github.io/web2023/javascript/quiz/quizEffect07.html

 

퀴즈 이펙트 07

1. 객체지향 프로그램에서 데이터를 추상화하는 단위는? 객체 지향 언어는 ___________ 이다.

fitalux.github.io

 

 

 

 

 

코드 보기 / JAVASCRIPT

const cbt = document.querySelectorAll(".cbt");
        const cbtQuiz = document.querySelector(".cbt__quiz");
        const cbtOmr = document.querySelector(".cbt__omr");
        const cbtSubmit = document.querySelector(".cbt__submit");
        const cbtCount = document.querySelector(".cbt__count");
        const cbtLength = document.querySelector(".cbt__length");
        const cbtStart = document.querySelector(".cbt__start");

        let questionAll = [];                          //모든 문제 정보
        let quizLength = 0;                     //전체 문항 수
        let questioncount = quizLength;         //남은 문항 수

        //데이터 가져오기
        const dataQuestion = () => {
            fetch("json/gisa2020_01.json")
            .then(res => res.json())
            .then(items => {
                questionAll = items.map((item, index)=>{
                    const formattedQuestion = {
                        question: item.question,
                        number: index + 1
                    };
                    const answerChoices = [...item.incorrect_answers];          //오답 불러오기
                    formattedQuestion.answer = Math.round(Math.random() * answerChoices.length)+1;
                    answerChoices.splice(formattedQuestion.answer - 1, 0, item.correct_answer);

                    //보기 추가
                    answerChoices.forEach((choice, index) => {
                        formattedQuestion["choice" + (index+1)] = choice;
                    });

                    //문제에 대한 해설 출력
                    if(item.hasOwnProperty("question_desc")) {
                        formattedQuestion.question_desc = item.question_desc;
                    }

                    //문제에 대한 이미지 출력
                    if(item.hasOwnProperty("question_img")) {
                        formattedQuestion.question_img = item.question_img;
                    }

                    //해설 출력
                    if(item.hasOwnProperty("desc")) {
                        formattedQuestion.desc = item.desc;
                    }

                    // console.log(formattedQuestion);
                    return formattedQuestion;
                });
                newQuestion();          //문제 만들기

                
                //modal창 제거
                document.getElementById("startbtn").addEventListener("click",() => {
                    cbtStart.style.display = "none";
                });

                //전체 문항 수
                quizLength = questionAll.length;
                cbtLength.innerHTML = quizLength;
                cbtCount.innerHTML = quizLength;
            })   
            .catch((err) => console.log(err));
        }
    
            //문제 만들기 
            const newQuestion = () => {
                const exam = [];
                const omr = [];

                questionAll.forEach((question, number) => {
                    exam.push(`
                        <div class="cbt">
                            <div class="cbt__question"><span>${question.number}</span>. ${question.question}</div>
                            ${question.question_img ?`<div class="cbt__question__img">${question.question_img}</div>` : ''}
                            ${question.question_desc ? `<div class="cbt__question__desc">${question.question_desc}</div>` : ''}
                            <div class="cbt__selects">
                                <input type="radio" id="select${number}_1" name="select${number}" value="${number}_1" onclick="answerSelect2(this)">
                                <label for="select${number}_1"><span>${question.choice1}</span></label>
                                <input type="radio" id="select${number}_2" name="select${number}" value="${number}_2" onclick="answerSelect2(this)">
                                <label for="select${number}_2"><span>${question.choice2}</span></label>
                                <input type="radio" id="select${number}_3" name="select${number}" value="${number}_3" onclick="answerSelect2(this)">
                                <label for="select${number}_3"><span>${question.choice3}</span></label>
                                <input type="radio" id="select${number}_4" name="select${number}" value="${number}_4" onclick="answerSelect2(this)">
                                <label for="select${number}_4"><span>${question.choice4}</span></label>
                                </div>
                            <div class="cbt__desc hide">${question.desc}</div>
                        </div>
                    `);

                    omr.push(`
                    <div class="omr">
                        <strong>${question.number}</strong>
                        <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_1" onclick="answerSelect(this)">
                        <label for="omr${number}_1"><span class="label-inner">1</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_2" onclick="answerSelect(this)">
                        <label for="omr${number}_2"><span class="label-inner">2</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_3" onclick="answerSelect(this)">
                        <label for="omr${number}_3"><span class="label-inner">3</span></label>
                        <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_4" onclick="answerSelect(this)">
                        <label for="omr${number}_4"><span class="label-inner">4</span></label>
                    </div>
                `)
            });                                                 
                cbtQuiz.innerHTML = exam.join('');
                cbtOmr.innerHTML = omr.join('');
        }

            //정답 확인
            const answerQuiz = () => {
                const cbtSelects = document.querySelectorAll(".cbt__selects");

                questionAll.forEach((question, number) => {
                    const quizSelectsWrap = cbtSelects[number];
                    const userSelector = `input[name=select${number}]:checked`;
                    const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
                    const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;


                    if(numberAnswer == question.answer) {
                        console.log("정답")
                        cbtSelects[number].parentElement.classList.add("good");
                    } else {
                        console.log("오답")
                        cbtSelects[number].parentElement.classList.add("bad");

                        //오답일 경우 정답 표시
                        const label = cbtSelects[number].querySelectorAll("label");
                        label[question.answer-1].classList.add("correct");
                    }

                    //설명 숨기기
                    const quizDesc = document.querySelectorAll(".cbt__desc");

                    if(quizDesc[number].innerText == "undefined"){
                        quizDesc[number].classList.add("hide");
                    } else {
                        quizDesc[number].classList.remove("hide");
                    }
                });
            }

            //선택지 체크
        const answerSelect2 = (el) => {
            const answer = el.value;
            const answerNum = answer.split("_");
            
            const select = document.querySelectorAll(".cbt__omr .omr");             //전체 문항수 
            //cbt 문제 (즉, content -> omr로 체크)
            const label = select[answerNum[0]].querySelectorAll("input");           //선택지 갯수 (4)
            label[answerNum[1]-1].checked = true;

            const answerInput = document.querySelectorAll(".cbt__selects input:checked");
            cbtCount.innerHTML = quizLength - answerInput.length;
        }

        const answerSelect = (el) => {
            const answer = el.value;
            const answerNum = answer.split("_");
            
            const select = document.querySelectorAll(".cbt__quiz .cbt");             //전체 문항수
            //omr -> content 박스로 체크
            const label = select[answerNum[0]].querySelectorAll("input");           //선택지 갯수 (4)
            label[answerNum[1]-1].checked = true;

            const answerInput = document.querySelectorAll(".cbt__selects input:checked");
            cbtCount.innerHTML = quizLength - answerInput.length;
        }

        cbtSubmit.addEventListener("click", answerQuiz);
        dataQuestion();


        const bubbleBttn = () => {
                const clip = (v, min, max = Infinity) => {
                    if (v < min) return min;
                    else if (v > max) return max;
                    else return v;
                };

                // generated random value from given range
                const randRange = (min, max) => Math.random() * max + min;

                // create bubble on x and y position inside target with given hue theme
                function bubble(x, y, rect, hue, target) {

                    // 변수 설정
                    const size = randRange(20, rect.width / 5);
                    const circleHue = hue + randRange(-20, 20);
                    const animDuration = randRange(clip(size ** 2/1000, 1), 6) 
                    const zIndex = Math.random() < 0.1 ? 2 : -1;


                    // 원
                    const circle = document.createElement("span");
                    circle.className = "lit";
                    circle.style.left = x + "px";
                    circle.style.top = y + "px";
                    circle.style.width = size + "px";
                    circle.style.height = size + "px";
                    circle.style.background = `hsl(${circleHue}deg, 100%, 60%)`;
                    circle.style.zIndex = zIndex
                    circle.style.animationDuration = animDuration + "s";
                    target.appendChild(circle);
                }

                document.querySelectorAll("[data-lit-hue]").forEach((target) => {
                    const rect = target.getBoundingClientRect();
                    const hue = Number(target.getAttribute("data-lit-hue"));
                    const count = Number(target.getAttribute("data-lit-count") || 50);

                    for (let i = 0; i < count; i++) {
                        const x = randRange(0, rect.width);
                        const y = randRange(0, rect.height);
                        bubble(x, y, rect, hue, target);
                    }
            });
        };

        bubbleBttn();

 

 

 

 

answerSelect, answerSelect2

answerSelect 함수와 answerSelect2 함수는 두 가지 다른 형식의 답안지를 처리하는 데 사용된다. 

answerSelect 함수는 omr 답안지에서 번호를 체크했을 때, 문제 선택지에 같은 번호를 체크 하는데 사용되며, answerSelect2 함수는 문제 선택지에서 번호를 체크했을 때, omr 답안지에 같은 번호를 체크 하는데 사용된다.

두 함수는 비슷한 구조를 가지고 있다.

먼저 선택한 답안의 값을 가져와서 해당 값을 사용하여 문제와 답안의 위치를 찾은 후 해당 위치의 라벨에서 선택지를 선택한다.

마지막으로, 응시자가 선택한 답안의 수를 계산하여 응시자가 아직 선택하지 않은 문제 수를 계산하고 이를 사이드에 있는 박스에  표시한다.

코드에서 querySelectorAll 함수를 사용하여 DOM 요소를 선택하며, querySelectorAll 함수는 CSS 선택자를 사용하여 요소를 선택한다.

이 함수를 사용하여 문제와 답안의 위치를 찾는다.

querySelectorAll 함수의 결과는 NodeList이며, 이 NodeList에서 요소를 선택하여 문제와 답안의 위치를 찾는다.

마지막으로, 이 코드는 innerHTML 속성을 사용하여 화면에 표시될 값들을 업데이트한다.

innerHTML 속성을 사용하면 HTML 태그를 사용하여 텍스트와 함께 다른 요소도 표시할 수 있다.

 

 

 

 

 

modal 창 제거

 

document.getElementById("startbtn").addEventListener("click",() => {
                    cbtStart.style.display = "none";
                }); 는 시험 시작 버튼(startbtn)을 클릭하면 모달 창(cbtStart)을 제거하는 역할을 한다.

document.getElementById() 함수는 문서에서 해당 ID를 가진 요소를 찾아서 반환한다.

(따로 선택자를 주지 않고 button에 지정된 ID를 찾도록 하였다.)

addEventListener() 함수는 해당 요소에 click 이벤트가 추가한다.
이벤트가 발생하면 () => { cbtStart.style.display = "none"; } 코드 블록이 실행되어 cbtStart 요소의 display 속성 값을 "none"으로 변경하여 모달 창이 화면에서 사라지도록 한다.

 

 

 

 

 

 

728x90
반응형

 

 

 

 

완성 화면

 

 

 

 

 

 

 

코드 보기 / CSS

 

.quiz__wrap__cbt {
    padding:  0 20px;
    font-family: 'ElandChoice';
}
.cbt__content {
    width: calc(100% - 300px);
    background-color: #fff;
}
.cbt__header {
    width: calc(100% - 300px);
    background-color: #f0d2fa;
    border: 8px ridge #440460;
    margin-bottom: 20px;
    padding: 10px 20px;
    background-color: #f1d8fe;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.cbt__aside {
    position: fixed;
    right: 20px;
    top: 180px;
    height: calc(100vh - 140px);
    width: 280px;
    background-color: #fff;
    border: 8px ridge #440460;
    overflow-y: auto;
}
.cbt__quiz {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}
.cbt__quiz .cbt {
    width: 49%;
    border: 8px ridge #440460;
    margin-bottom: 10px;
    padding: 20px;
}
.cbt__quiz .cbt {
    position: relative;
}
.cbt__quiz .cbt.good::after {
    content: '';
    background-image: url(../img/O.png);
    background-size: contain;
    background-repeat: no-repeat;
    width: 200px;
    height: 200px;
    position: absolute;
    left: 0;
    top: 0;
}
.cbt__quiz .cbt.bad::after {
    content: '';
    background-image: url(../img/X.png);
    background-size: contain;
    background-repeat: no-repeat;
    width: 200px;
    height: 200px;
    position: absolute;
    left: 0;
    top: 0;
}
.cbt__info {
    background-color: #f1d8fe;
}
.cbt__info > div {
    border-bottom: 5px ridge #440460;
}
.cbt__info > div:first-child {
    background-color: #f1d8fe;
    color: #000;
    padding: 10px 20px;
    text-align: center;
}
.cbt__time {    
    position: fixed;
    right: 180px;
    top:70px;
    padding-left: 20px;
    background: #440460;
    padding: 10px 27px 10px 44px;
    border-radius: 15px;
    color: #fff;
    margin: 10px 0;
}
.cbt__time::before{
    content: '';
    position: absolute;
    top: 5px;
    left: 10px;
    width: 22px;
    height: 22px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-alarm' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23ffffff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Ccircle cx='12' cy='13' r='7' /%3E%3Cpolyline points='12 10 12 13 14 13' /%3E%3Cline x1='7' y1='4' x2='4.25' y2='6' /%3E%3Cline x1='17' y1='4' x2='19.75' y2='6' /%3E%3C/svg%3E");
}
.cbt__submit {
    position: fixed;
    right: 175px;
    top:100px;
    padding-left: 20px;
    background: #440460;
    cursor: pointer;
    padding: 10px 27px 10px 44px;
    border-radius: 15px;
    color: #fff;
    margin: 25px 0;
}
.cbt__submit::before{
    content: '';
    position: absolute;
    top: 5px;
    left: 10px;
    width: 22px;
    height: 22px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-file-text' width='24' height='24' viewBox='0 0 24 24' stroke-width='2' stroke='%23ffffff' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M14 3v4a1 1 0 0 0 1 1h4' /%3E%3Cpath d='M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z' /%3E%3Cline x1='9' y1='9' x2='10' y2='9' /%3E%3Cline x1='9' y1='13' x2='15' y2='13' /%3E%3Cline x1='9' y1='17' x2='15' y2='17' /%3E%3C/svg%3E");
}
.cbt__info > div:last-child {
    padding: 20px;
}
.cbt__title {
    text-decoration: underline;
    text-underline-offset: 5px;
    margin-bottom: 5px;
}
.cbt__info span {
    display: inline-block;
}
.cbt__omr {
    padding: 20px;
}
.cbt__omr .omr {
    margin: 5px 0;
    display: grid;
    grid-template-columns: 50px 38px 38px 38px 38px;
    grid-template-rows: 20px;
    align-items: center;
}
.cbt__omr .omr input {
    opacity: 0;
    position: absolute;
    width: 0;
    height: 0;
}
.cbt__omr .omr strong{
    display: inline-block;
    text-align: center;
    padding: 2px;
    background-color: #eabcfb;
    font-family: 'Helvetica Neue';
    margin-right: 10px;
}
.cbt__omr .omr label {
    box-shadow: 0 0 0 1px #eabcfb;
    cursor: pointer;
    line-height: 0.5;
    text-align: center;
    width: 28px;
    height: 8px;
    font-family: 'Helvetica Neue';
    position: relative;
}
.cbt__omr .omr label::after {
    background-color: #555;
    content: "";
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 100%;
    z-index: 1;
    transition: width 0.1s linear;
}
.cbt__omr .omr input[type=radio]:checked + label::after {
    width: 100%;
}
.cbt__omr .omr .label-inner{
    background-color: #fff;
    padding: 0.25em 0.13em;
    transform: translateY(-0.25em);
    width: 20px;
    color: #440460;
}
.cbt__question {
    font-size: 1.4rem;
    margin-bottom: 10px;
}
.cbt__question__img img {
    max-width: 400px;
    margin-bottom: 15px;
}
.cbt__question__desc {
    border: 2px solid #cacaca;
    padding: 10px;
    margin-bottom: 15px;
}
.cbt__selects {
    margin-bottom: 15px;
}
.cbt__selects label {
    display: flex;
}
.cbt__selects label span {
    font-size: 1rem;
    padding: 10px 10px 10px 30px;
    cursor: pointer;
    color: #555;
    position: relative;
}
.cbt__selects label span::before {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    border: 1px solid #333;
    border-radius: 30%;
    text-align: center;
    font-family: 'Helvetia Neue';
    font-weight: bold;
    line-height: 1.3;
    font-size: 0.83em;
    transition: all 0.5s;
}
.cbt__selects label:nth-of-type(1) span::before {
    content: '1';
}
.cbt__selects label:nth-of-type(2) span::before {
    content: '2';
}
.cbt__selects label:nth-of-type(3) span::before {
    content: '3';
}
.cbt__selects label:nth-of-type(4) span::before {
    content: '4';
}
.cbt__selects input {
    position: absolute;
   left: -99999px;
}
.cbt__selects input:checked + label span::before {
    color: #fff;
    box-shadow: inset 0 0 0 10px #000;
    border-color: #000;
}
.cbt__selects label.correct span::before {
    border-color: red;
    box-shadow: inset 0 0 0 10px red;
    color: #fff;
}
.cbt__desc {
    background-color: #eabcfb;
    padding: 10px 20px 10px 40px;
    margin-bottom: 5px;
    position: relative;
    border-radius: 15px;
}
.cbt__desc.hide{
    display: none;
}
.cbt__desc::before {
    content: '';
    position: absolute;
    left: 10px;
    top:5px;
    width: 24px;
    height: 24px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-pencil' width='24' height='24' viewBox='0 0 24 24' stroke-width='2.5' stroke='%23ff4500' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M4 20h4l10.5 -10.5a1.5 1.5 0 0 0 -4 -4l-10.5 10.5v4' /%3E%3Cline x1='13.5' y1='6.5' x2='17.5' y2='10.5' /%3E%3C/svg%3E");
}
.cbt__keyword {
    background-color: #eabcfb;
    padding: 10px 20px 10px 40px;
    margin-bottom: 5px;
    position: relative;
    display: inline-block;
    border-radius: 35px;
}
.cbt__keyword::before {
    content: '';
    position: absolute;
    left: 16px;
    top: 10px;
    width: 20px;
    height: 20px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-notebook' width='20' height='20' viewBox='0 0 24 24' stroke-width='2.5' stroke='%23000000' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M6 4h11a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-11a1 1 0 0 1 -1 -1v-14a1 1 0 0 1 1 -1m3 0v18' /%3E%3Cline x1='13' y1='8' x2='15' y2='8' /%3E%3Cline x1='13' y1='12' x2='15' y2='12' /%3E%3C/svg%3E");
}

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

 

const cbt = document.querySelectorAll(".cbt");
            const cbtQuiz = document.querySelector(".cbt__quiz");
            const cbtOmr = document.querySelector(".cbt__omr");
            const cbtSubmit = document.querySelector(".cbt__submit");
    
            let questionAll = [];                          //모든 문제 정보
    
            //데이터 가져오기
            const dataQuestion = () => {
                fetch("json/gisa2020_01.json")
                .then(res => res.json())
                .then(items => {
                    questionAll = items.map((item, index)=>{
                        const formattedQuestion = {
                            question: item.question,
                            number: index+1
                        }
                        const answerChoices = [...item.incorrect_answers];          //오답 불러오기
                        formattedQuestion.answer = Math.floor(Math.random() * answerChoices.length)+1;
                        answerChoices.splice(formattedQuestion.answer - 1, 0, item.correct_answer);
    
                        //보기 추가
                        answerChoices.forEach((choice, index)=>{
                            formattedQuestion["choice" + (index+1)] = choice;
                        });
    
                        //문제에 대한 해설 출력
                        if(item.hasOwnProperty("question_desc")) {
                            formattedQuestion.questionDesc = item.question_desc;
                        }
    
                        //문제에 대한 이미지 출력
                        if(item.hasOwnProperty("question_img")) {
                            formattedQuestion.questionImg = item.question_img;
                        }
    
                        //해설 출력
                        if(item.hasOwnProperty("desc")) {
                            formattedQuestion.desc = item.desc;
                        }
    
                        // console.log(formattedQuestion);
                        return formattedQuestion;
                    });
                    newQuestion();          //문제 만들기
                })   
                .catch((err) => console.log(err));
        }
    
            //문제 만들기 
            const newQuestion = () => {
                const exam = [];
                const omr = [];
    
                questionAll.forEach((question, number) => {
                    exam.push(`
                        <div class="cbt">
                            <div class="cbt__question"><span>${question.number}</span>. ${question.question}</div>
                            <div class="cbt__question__img"></div>
                            <div class="cbt__selects">
                                <input type="radio" id="select${number}_1"  name="select${number}" value="${number+1}_1" onclick="answerSelect(this)">
                                <label for="select${number}_1"><span>${question.choice1}</span></label>
                                <input type="radio" id="select${number}_2"  name="select${number}" value="${number+1}_2" onclick="answerSelect(this)">
                                <label for="select${number}_2"><span>${question.choice2}</span></label>
                                <input type="radio" id="select${number}_3"  name="select${number}" value="${number+1}_3" onclick="answerSelect(this)">
                                <label for="select${number}_3"><span>${question.choice3}</span></label>
                                <input type="radio" id="select${number}_4"  name="select${number}" value="${number+1}_4" onclick="answerSelect(this)">
                                <label for="select${number}_4"><span>${question.choice4}</span></label>
                                </div>
                            <div class="cbt__desc hide">${question.desc}</div>
                        </div>
                    `);
                    
                    omr.push(`
                        <div class="omr">
                            <strong>${question.number}</strong>
                            <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_0">
                            <label for="omr${number}_1"><span class="label-inner">1</span></label>
                            <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_1">
                            <label for="omr${number}_2"><span class="label-inner">2</span></label>
                            <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_2">
                            <label for="omr${number}_3"><span class="label-inner">3</span></label>
                            <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_3">
                            <label for="omr${number}_4"><span class="label-inner">4</span></label>
                        </div>
                    `)
            });                                                 
                cbtQuiz.innerHTML = exam.join('');
                cbtOmr.innerHTML = omr.join('');
        }
        
            //정답 확인
            const answerQuiz = () => {
                const cbtSelects = document.querySelectorAll(".cbt__selects");
    
                questionAll.forEach((question, number) => {
                    const quizSelectsWrap = cbtSelects[number];
                    const userSelector = `input[name=select${number}]:checked`;
                    const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
                    const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;
    
    
                    if(numberAnswer == question.answer) {
                        console.log("정답")
                        cbtSelects[number].parentElement.classList.add("good");
                    } else {
                        console.log("오답")
                        cbtSelects[number].parentElement.classList.add("bad");
    
                        //오답일 경우 정답 표시
                        const label = cbtSelects[number].querySelectorAll("label");
                        label[question.answer-1].classList.add("correct");
                    }
    
                    //설명 숨기기
                    const quizDesc = document.querySelectorAll(".cbt__desc");
    
                    if(quizDesc[number].innerText == "undefined"){
                        quizDesc[number].classList.add("hide");
                    } else {
                        quizDesc[number].classList.remove("hide");
                    }
                });
            }
        
            const answerSelect = () => {
    
            }
        
        cbtSubmit.addEventListener("click", answerQuiz);
        dataQuestion();

 

 

 

데이터 가져오기

 

dataQuestion 함수는 fetch() 메서드를 사용하여 "json/gisa2020_01.json"에 위치한 JSON 파일로 HTTP 요청을 수행한다.

그 후 응답 객체에 대해 then() 메서드가 호출된다.

then() 메서드는 응답이 수신되면 실행되는 콜백 함수를 취하며, 응답 데이터는 json() 메서드를 사용하여 JSON 형식으로 변환되고, 결과 Promise에 대해 또 다른 then() 메서드가 호출됩니다. then() 메서드는 다시 JSON 데이터를 매개변수로 받는 콜백 함수를 취한다.


이 콜백 함수 내부에서는 JSON 데이터에 대해 map() 메서드가 호출된다.

이 메서드는 JSON 데이터 배열의 각 항목을 반복하고 제공된 콜백 함수를 실행하여 새로운 배열을 만들며, 콜백 함수는 두 개의 매개변수를 취하는데 그 매개변수는 현재 반복 중인 항목과 그 인덱스가 된다.

map() 콜백 함수 내부에서는 formattedQuestion이라는 새로운 객체가 생성된다.

이 객체는 question 속성을 포함하고 있으며 현재 반복 중인 항목의 question 속성으로 설정되며 number 속성도 포함하고 있으며 현재 인덱스에 1을 더한 값으로 설정된다.

그런 다음 전체 항목에서 올바르지 않은 답변 선택지로 구성된 answerChoices 배열이 만들어지고 전개 연산자(...)를 사용하여 채워진다.

올바른 답변 선택지는 splice() 메서드를 사용하여 answerChoices 배열에 무작위로 인덱스에 삽입되며, 올바른 답변이 삽입되는 인덱스는 Math.floor() 및 Math.random() 메서드를 사용하여 무작위 숫자를 생성하여 결정된다.

다음으로, answerChoices 배열의 각 답변 선택지를 반복하는 루프가 실행된다.

forEach루프 내부에서는 대괄호 표기법을 사용하여 동적으로 생성된 속성 키를 사용하여 formattedQuestion 객체에 새 속성이 추가된다.

속성 키는 현재 반복 중인 답변 선택지의 인덱스를 기반으로 동적으로 생성되며, 속성 값은 답변 선택지 자체로 설정된다.

현재 반복 중인 항목에 desc 속성이 있다면, formattedQuestion 객체는 desc 속성을 포함하도록 업데이트 되며, 이 속성은 desc 속성의 값으로 설정된다.
그리고 map() 콜백 함수에 의해 formattedQuestion 객체가 반환되고, 이 객체는 questionAll 배열에 추가된다.

 JSON 데이터 배열의 모든 항목이 반복되면, newQuestion() 함수가 호출된다.

 

 

 

 

 

fetch() 메서드

: JavaScript에서 네트워크 요청을 보내고 응답을 받아오는 기능을 담당한다.

일반적으로 웹 애플리케이션에서 API 호출이나 서버로부터 데이터를 가져올 때 사용되며,  Promise 객체를 반환한다.

Promise 객체는 비동기 작업을 처리하기 위한 객체로, 작업이 완료되면 이행(resolve) 상태나 거부(reject) 상태가 되며, fetch() 메서드가 반환하는 Promise 객체는 HTTP 응답을 나타내는 Response 객체를 이행(resolve)한다.

 

 

 

 


then() 메서드

:Promise 객체의 상태가 이행(resolve) 상태가 되었을 때 호출되며, 이때 Response 객체를 인자로 받는다.

then() 메서드 안에서는 Response 객체를 가지고 데이터를 추출하고 처리할 수 있다.

 

 

 

 

문제 만들기


newQuestion 함수는 questionAll 배열의 모든 질문 객체를 반복하면서 HTML 요소들을 동적으로 생성하고 cbtQuiz 및 cbtOmr 요소의 내부 HTML로 추가한다.

각 질문 객체의 number, question, choice1 ~ choice4, 그리고 desc 속성 값을 이용하여 각 질문에 대한 HTML 문서 객체를 만든다.

exam 배열에는 cbtQuiz 요소에 들어갈 질문 HTML 코드가 추가되고, omr 배열에는 cbtOmr 요소에 들어갈 OMR HTML 코드가 추가되며, 마지막으로 cbtQuiz 및 cbtOmr 요소의 내부 HTML을 배열 요소를 구분자로 구분하여 exam 및 omr 배열의 값을 이용하여 대체한다.

 

 

 

 

정답 확인하기


answerQuiz 함수는 cbt__selects 클래스를 가진 HTML 요소를 찾아 각 문제의 사용자 선택지와 정답을 비교한다.
사용자의 선택지가 정답과 일치하면 해당 문제의 부모 요소에 good 클래스를 추가하고, 사용자의 선택지가 정답과 일치하지 않으면 해당 문제의 부모 요소에 bad 클래스를 추가하여 정답을 표시하며
해당 문제의 설명을 숨기거나 보여준다.


answerSelect 함수는 onclick 이벤트 시에 사용되며,
사용자가 선택지를 클릭하면 실행된다.
또한 cbtSubmit 버튼(답안지를 제출하는 버튼)에 click 이벤트 리스너를 추가하고 dataQuestion() 함수를 호출한다.

 

 

 

 

 

 

 

728x90
반응형

 

1. 다음의 결과값을 작성하시오.

let num = 0;

    while(false){
        num++;
        if( num == 3 ){
            continue;
        }
        if( num > 10 ){
            break;
        }
    }
    console.log(num);

 

A

:  0

 

while문의 조건이 false로 설정되어 있기 때문에 while문이 실행되지 않는다.

따라서 변수는 0으로 초기화 된 이후 값이 변하지 않는다.

 

 

 

 

 

2. 다음의 결과값을 작성하시오.

let a = 6, b = 9, c = 3, result;
    result = ++a + b++ + ++c;

    console.log(result);
    console.log(a+b+c);

 

A

: 20       21

 

해당 코드를 실행하면 변수 a, b, c가 순서대로 6, 9,3으로 초기화 된다.

그리고 다음 줄에서 변수 result에 ++a + b++ + ++c를 대입한다.

 

여기서 ++a 변수는 a를 1 증가시킨 후 그 값을 사용하므로 7이 되며,

b++는 변수 b를 현재 값인 9를 사용한 후에 1을 증가시키므로, 이항 연산의 결과는 9가 된다.

++c는 변수 c를 1 증가시킨 후 그 값을 사용하므로 4가 됩니다. 따라서 result 변수에는 7 + 9 + 4 = 20이 대입된다.

마지막으로 console.log(a+b+c)를 실행하면, a와 c는 이미 1씩 증가한 상태이므로 각각 7과 4가 되어있다.

b는 이전 연산에서 1 증가했으므로 10이 됩니다. 따라서 console.log(a+b+c)는 7+10+4 = 21을 출력한다.

 

 

 

 

 

3. 결과값을 작성하시오.

function func(){
        let a = [];

        for(i=1; i<=5; i++){
            a += [i];
        }
        console.log(a);
    }
    func();

 

:  1   2  3  4   5

 

해당 코드는 함수 func()를 정의하고, 함수 내에서 빈 배열 a를 선언합니다.

그리고 for 루프를 이용하여 1부터 5까지의 숫자를 배열 a에 추가한다.

그런데 배열에 값을 추가할 때 a += [i];와 같이 문자열 연결 연산자인 +=를 사용했는데, 이는 배열에 값을 추가하는 올바른 방법이 아니다.

올바른 방법은 a.push(i)와 같이 push() 메서드를 사용하는 것이다.

따라서 func() 함수의 실행 결과는 [1, "2", "3", "4", "5"]와 같이 배열의 첫 번째 요소는 숫자 1이지만 나머지 요소는 모두 문자열로 변환되어 들어갑니다. 이는 배열에 값을 추가할 때 문자열 연결 연산자를 사용했기 때문이다.

 

 

 

 

 

4. 결과값을 작성하시오.

let arr = [3,4,1,4,1,3,4,9,8,3];
        
    for(let i=0; i<10; i++){
        if(i % 3 == 2){
            console.log(arr[i]);
        }
    }

    console.log(sum);

:  1    3   8

 

반복문이 실행되면 i는 0부터 9까지 총 10번 반복하게 됩니다. 그리고 각 반복마다 i가 3으로 나누었을 때 나머지가 2인지 검사하게 된다..

배열 arr에서 0번째 원소는 3이며, i=0일 때는 조건식이 false가 되어 아무 동작도 하지 않는다. 

1번째 원소도 마찬가지이다.


2번째 원소는 1이며, i=2일 때 조건식이 true가 된다. 

따라서 console.log(arr[i]) 문장이 실행되어 1이 출력된다.

3번째 원소는 4이며, i=3일 때도 조건식이 false가 되어 아무 동작도 하지 않는다. 

4번째 원소도 마찬가지이다.

5번째 원소는 3이며, i=3일 때 조건식이 true가 된다.

따라서 console.log(arr[i]) 문장이 실행되어 4가 출력된다.

6번째 원소는 4이며, i=5일 때는 조건식이 false가 되어 아무 동작도 하지 않는다.
7번째 원소는 9이며, i=6일 때도 조건식이 false가 되어 아무 동작도 하지 않는다.

8번째 원소는 8이며, i=7일 때 조건식이 true가 돤다.

따라서 console.log(arr[i]) 문장이 실행되어 9가 출력된다.

9번째 원소는 3이므로, i=8일 때는 조건식이 false가 되어 아무 동작도 하지 않는다.

 

 

 

 

5. 결과값을 작성하시오.

function func(num1, num2){
        if(num1 > num2) return num1
        else return num2
    }
    console.log(func(17, 23) + func(50, 40))

 

A

:   73

 

func라는 함수를 정의하고, 해당 함수를 호출한 결과를 출력하는 코드이다.
func 함수는 두 개의 인자 num1과 num2를 받아서, 만약 num1이 num2보다 크다면 num1을, 그렇지 않다면 num2를 반환하는 동작을 한다.
따라서 func(17, 23)의 결과는 23이 되고, func(50, 40)의 결과는 50이 된다.

이 두 값을 더한 결과인 73이 console.log로 출력된다.

 

 

 

 

 

6. 결과값을 작성하시오.

function func(index){
        console.log("함수가 실행되었습니다." + index);
    }
    function callback(num){
        for(let i=0; i<=5; i++){
            num(i);
        }
    }
    callback(func);

 

A  : 

함수가 실행되었습니다. 0

함수가 실행되었습니다. 1

함수가 실행되었습니다. 2

함수가 실행되었습니다. 3

함수가 실행되었습니다. 4

함수가 실행되었습니다. 5

 

 

func 함수는 하나의 인자 index를 받아서, 해당 인자를 문자열과 함께 출력하는 역할을 한다.
callback 함수는 하나의 인자 num을 받아서, 0부터 5까지의 수를 num 함수의 인자로 넘겨준다.

이때 num은 함수이며, 함수를 인자로 받아서 실행하는 고차함수[각주:1]이다.
따라서 callback(func) 코드는 func 함수를 인자로 받아서 실행한다.

 callback 함수에서는 num(i)를 0부터 5까지 반복해서 실행하므로, func 함수는 6번 호출된다.

 

 

 

 

 

7. 결과값을 작성하시오.

 for(let i=1; i<=5; i++){
        console.log(i);

        if(i == 4){
            break;
        }
    }

 

:    1   2   3   4  

 

위 코드는 1부터 5까지의 숫자를 출력하고, 숫자가 4일 때 반복문을 종료하는 코드이다.

for문을 사용하여 i 변수를 1부터 5까지 증가시키면서, 각 i 값을 console.log로 출력한다.

그리고 if문을 사용하여 i가 4일 때, break 키워드를 사용하여 반복문을 종료 시키기 때문에  이후 console.log는 더 이상 실행되지 않는다.

 

 

 

 

 

8. 결과값을 작성하시오.

 const arr = [100, 200, 300, 400, 500];

    const text1 = arr.join("*");
    arr.push("600");
    const text3 = arr.join("");
    arr.pop();
    const text4 = arr.join(" ");

    console.log(text1);
    console.log(text3);
    console.log(text4);

 

A :

100*200*300*400*500
100200300400500600
100 200 300 400 500

 

arr.join("*")은 arr 배열의 각 원소를 * 문자로 연결하여 하나의 문자열로 만든다.

따라서 text1 변수에는 100*200*300*400*500 문자열이 할당된다.

arr.push("600")은 arr 배열의 끝에 600이라는 새로운 원소를 추가한다.

arr.join("")은 arr 배열의 각 원소를 연결하여 하나의 문자열로 만든다.

이때, 구분자를 지정하지 않았기 때문에 원소들이 그대로 이어진 문자열이 만들어진다.

따라서 text3 변수에는 100200300400500600 문자열이 할당됩니다.

arr.pop()은 arr 배열의 마지막 원소를 제거한다. 즉, 600이 제거된다.
arr.join(" ")은 arr 배열의 각 원소를 공백 문자로 연결하여 하나의 문자열로 만든다. 

따라서 text4 변수에는 100 200 300 400 500 문자열이 할당된다.

 

 

 

 

 

 

9. 다음의 결과값을 작성하시오.

 let a, b = 10;

    for(let i=0; i<5; i++){
        a = i;
        b -= a;
    }
    console.log(a, b)

 

:    4     0

 

 a 변수는 초기화되지 않았기 때문에 undefined 값이 할당되고, b 변수는 10으로 초기화 된다..

for문에서는 i 변수를 0부터 4까지 1씩 증가시키면서, a 변수에 i 값을 할당하고, b 변수에서 a 값을 빼준다.

즉, b 변수는 10에서 0, 1, 3, 6, 10을 차례로 빼면서 0이 된다,
따라서 console.log(a, b)를 실행하면 마지막 반복에서 a 변수에는 4가, b 변수에는 0이 할당되어 출력된다.

 

 

 

 

 

10. 다음의 결과값을 작성하시오.

function func(){
        let i = 10, j = 20, k = 30;
        i /= j;
        j -= i;
        k %= j;

        console.log(i);
        console.log(j);
        console.log(k);
    }
    func();

 

:  0.5     19.5     10.5 

 

i /= j; 

: i 변수의 값을 j 변수의 값으로 나눈 결과를 i 변수에 할당한다. 

이 때, /= 연산자는 i = i / j;와 같다.

따라서 i 변수의 값은 0.5가 된다.

j -= i; 

: j 변수의 값을 i 변수의 값으로 뺀 결과를 j 변수에 할당한다.

이 때, -= 연산자는 j = j - i;와 같다.

따라서 j 변수의 값은 19.5가 된다.

k %= j; 

: k 변수의 값을 j 변수의 값으로 나눈 나머지를 k 변수에 할당한다.

이 때, %= 연산자는 k = k % j;와 같습니다. 따라서 k 변수의 값은 10.5가 된다.

 

 

 

 

 

11. 다음의 결과값을 작성하시오.

let k = 2;
    let temp;
    for(let i=0; i<=3; i++){
        temp = k;
        k++;
        console.log(temp + "번");
    }

 

A

:  2번    3번     4번      5번

 

 let 키워드로 선언된 변수 k와 temp는 각각 2와 undefined로 초기화 된다.
for문에서는 i 변수를 0부터 3까지 1씩 증가시키면서, temp 변수에 k 값을 할당하고, k 값을 1 증가시킨 후 temp + "번"을 출력한다.
따라서 console.log 구문은 3번 실행되며, 각각 "2번", "3번", "4번", "5번"을 출력한다.

 

 

 

 

 

12.  다음의 결과값을 작성하시오.

let num = 10;
    num += 2;
    num -= 3;
    num *= 5;
    num /= 5;
    num %= 9;
    
    console.log(num)

 

: 0

 

let 키워드로 선언된 변수 num은 10으로 초기화 된다.

다음으로 num += 2;를  수행하면 num 변수의 값은 12가 된다.

num -= 3;를 수행하면 num 변수의 값은 9가 되며,
num *= 5;를 수행하면 num 변수의 값은 45가 된다.
num /= 5;를 수행하면 num 변수의 값은 9가 되며,
num %= 9;를 수행하면 num 변수의 값은 0이 된다.

이 때, %= 연산자는 num = num % 9;와 같다.
따라서 console.log 구문은 0을 출력합니다.

 

 

 

 

 

 

 

 

13. 다음의 결과값을 작성하시오.

let num = [1, 5, 1, 2, 7, 5];
    for(let i=0; i<6; i++){
        if((i+2) % 2 == 0){
            console.log(num[i]);
        }
    }

 

A

:   1     1       7

 

배열 num은 [1, 5, 1, 2, 7, 5]로 초기화 된다.
for문에서는 i 변수를 0부터 5까지 1씩 증가시키면서, (i+2) % 2 == 0 조건을 검사한다.

여기서 (i+2) % 2의 값은 항상 0이므로, if 구문 내의 코드는 항상 실행된다.

따라서 console.log 구문은 6번 실행되며, num 배열에서 0번 인덱스, 2번 인덱스, 4번 인덱스의 값인 1, 1, 7을 차례대로 출력한다.

 

 

 

 

 

 

14. 다음의 결과값을 작성하시오.

let num = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    for(let i=0; i<=9; i++){
        switch(num[i] % 2){
            case 1:
                console.log(num[i]);
                break;
            default:
                console.log("**");
        }
    }

 

:   **1**3**5**7**9

 

배열 num은 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]로 초기화된다.

for문에서는 i 변수를 0부터 9까지 1씩 증가시키면서, switch문을 실행한다.

switch문에서는 num[i] % 2의 값에 따라서 case문이 실행한다.
num[i] % 2가 1인 경우: case 1문이 실행되며, 이 경우 console.log(num[i])이 실행되어 배열 num에서 홀수를 출력한다.

num[i] % 2가 0인 경우: default문이 실행되어  이 경우 console.log("**")이 실행되어 **로 출력한다.

 

 

 

 

 

15. 다음의 결과값을 작성하시오.

  let cnt = 0;
    let sum = 0;
    for(let i=0; i<=7; i++){
        if(i%2 == 1){
            cnt++;
            sum += i;
        }
    }
    console.log(cnt + ", "+sum/2);

 

:   4    8

 

for문에서는 0부터 7까지의 정수를 반복하며, if문에서는 현재 정수(i)가 홀수인지를 확인한다.

만약 현재 정수(i)가 홀수라면 cnt 변수를 1 증가 시키고(cnt++) sum 변수에 현재 정수(i)를 더한다. (sum = sum+i)

 

그러나 console.log에서 sum을 2로 나누므로 홀수의 갯수인 4와 1+3+5+7=16/2인 8이 출력된다.

 

 

 

 

 

 

16. 다음의 결과값을 작성하시오.

let data = [70, 80, 75, 60, 90];
    let best = 1;
    let score = 0;

    for(let i=0; i<data.length; i++){
        if(data[i]>=80) {
            best++;
        }
        if(score < data[i]) {
            score = data[i];
        }
    }

    console.log(best, score)

 

:    3       90

 

주어진 데이터에서 80 이상의 수와 가장 높은 수를 출력하는 코드이다.

반복문을 통해 주어진 데이터를 모두 검사하면서, 80 이상의 수가 몇 개인지 best 변수에 누적한다. 

또한, score 변수에는 현재까지 가장 높은 수를 저장한다.

따라서, 주어진 데이터 [70, 80, 75, 60, 90]에서 80점 이상의 수는 2이고, 가장 높은 수는 90이다.

그러나 best의 초깃값이 1이므로 1+2가 되어 best에서는 3이 score에서는 90이 출력된다.

 

 

 

 

 

 

17. 다음의 결과값을 작성하시오.

 let a, b, result;
    a = 7, b = 4
    result = a | b;

    console.log(result)

 

A

:   7 (0111)

 

변수 a는 7(2진수로 111)이고, 변수 b는 4(2진수로 100)이다.

a | b 연산은 각 비트에 대해 OR 연산을 수행한다.

따라서 결과는 111 | 100이 되며, 이는 7과 4를 비트 OR한 결과인 7이 된다.

 

 

 

 

18. 다음의 결과값을 작성하시오.

function solution(a, b, c){
        let answer = "YES", max;
        let total = a + b + c;

        if(a > b) max = a;
        else max = b;
        if(c > max) max = c;
        if(total-max <= max) answer = "NO"; 
        
        return answer;
    }

    console.log(solution(53, 93, 107));

 

A

: YES

 

함수 solution에서는 먼저 answer 변수를 YES로 초기화 한다.

그리고 세 수 a, b, c를 모두 더한 값을 tot 변수에 저장한다.

a=53, b=93, c=107이므로 total = a+b+c = 253이다.

다음으로 세 수 a, b, c 중에서 가장 큰 값을 max 변수에 저장한다.

셋 중 가장 큰 값은 c, 즉 107이므로 total-max=146이 된다.

마지막으로  if(total-max <= max)문에서 total-max 값이 max 값보다 크므로 anwser 변수가 YES로 변경된다.

따라서 solution(53,93,107)은 YES를 반환한다.

 

 

 

 

 

19.다음의 결과값을 작성하시오.

 function solution(a, b, c){
        let answer;
        if(a < b) answer = a;
        else answer = b;
        if(c <= answer) answer = c; 
        return answer;
    }
    console.log(solution(15, 12, 11));

 

: 11

 

if(a < b) 구문에서 a와 b 중에서 작은 값을 answer 변수에 할당한다.
다음으로, if(c <= answer) 구문에서 c가 answer보다 작거나 같은 경우 answer 변수에 c를 할당한다.
마지막으로 answer 값을 반환한다.

solution(15, 12, 11)을 호출하면, a=15, b=12, c=11로 전달되므로, answer 변수에는 12가 할당된다.

이후, if(c <= answer) 구문에서는 11이 12보다 작으므로, answer 변수에 11이 할당된다.

따라서, 최종적으로 solution() 함수는 11을 반환합니다.

 

 

 

 

 

20. 다음의 결과값을 작성하시오.

function solution(day, arr){
        let answer = 0;
        for(let x of arr){
            if(x % 10 == day) answer++;
        }
        return answer;
    }
    
    arr = [25, 23, 11, 47, 53, 17, 33, 40];
    console.log(solution(0, arr));

 

 

: 1

 

이 함수는 day 변수로 주어진 수와 일의 자리가 일치하는 arr 배열 내의 요소 수를 반환한다.

위 코드에서는 0과 일의 자리가 0인 수의 개수를 세는 것이다.

함수 내에서는 for-of 반복문을 사용하여 arr 배열의 각 요소 x에 대해 다음을 수행한다.

x를 10으로 나눈 나머지가 day와 같으면, answer를 1 증가시킨다.
반복문이 끝나면, answer 변수에는 일의 자리가 day와 일치하는 arr 배열의 요소 수가 저장되어 있다.

마지막으로 answer 값을 반환한다.



 

 

 

 

 

 

  1. 함수를 인자로 받거나, 함수를 반환하는 함수를 말한다. [본문으로]
728x90
반응형

 

완성 화면

 

 

 

 

 

 

코드 보기 / HTML, JAVASCRIPT

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>연습문제 2</title>
  <link rel="stylesheet" href="ex2.css">
</head>
<body>
  <button id="bttn">&#9776;</button>

  <nav id="nav">
    <ul>
      <li class="active js"><a href="#">Javascript</a></li>
      <li class="active ts"><a href="#">Typescript</a></li>
      <li class="active node"><a href="#">Node.js</a></li>
    </ul>
  </nav>


  <script>
    let btn = document.querySelector("#bttn");
    let menu = document.querySelector("#nav")

    btn.addEventListener("click",()=>{
        btn.classList.add("active");
        nav.classList.add("active");
    });
    btn.addEventListener("mouseout",()=>{
        btn.classList.remove("active");
        nav.classList.remove("active");
    });

  </script>
</body>
</html>

 

HTML에는 버튼과 메뉴를 나타내는 요소가 정의되어 있으며, JAVASCRIPT에서는 버튼을 클릭할 때와 마우스가 버튼을 벗어날 때의 이벤트를 처리한다.

 

버튼 요소는 <button> 태그를 사용하여 정의되었다.이 버튼은 아이콘 모양을 나타내는 문자열 ☰을 포함하고 있다.이 버튼에는 bttn이라는 ID가 지정되어 있다.

 

메뉴는 <nav> 태그를 사용하여 정의되었다.이 메뉴는 세 개의 항목(li 태그)이 포함되어 있다.이 항목들은 각각 "Javascript", "Typescript", "Node.js"를 나타내며, 활성 항목은 "active" 클래스가 지정되어 있다.

 

JavaScript에서는 버튼 요소와 메뉴 요소를 선택하여 이벤트를 처리한다.먼저 querySelector를 사용하여 버튼 요소와 메뉴 요소를 선택한다.이후, addEventListener를 사용하여 버튼 클릭 이벤트와 마우스 벗어남 이벤트를 처리한다.

 

버튼 클릭 이벤트는 버튼을 클릭할 때마다 "active" 클래스를 버튼과 메뉴에 추가하여 메뉴를 나타내는 효과를 구현한다.마우스 벗어남 이벤트(mouseout)는 마우스가 버튼에서 벗어날 때 "active" 클래스를 버튼과 메뉴에서 제거하여 메뉴를 숨기는 효과를 구현한다.

 

 

 

 

 

코드 보기 / CSS

* {
    box-sizing: border-box;
  }
  
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    margin:0;
    min-height:100vh;
  }
  a {
    text-decoration: none;
  }
  #bttn {
    position:fixed;
    top:20px;
    right:20px;
    background-color:#639;
    padding:15px;
    border:none;
    outline: none;
    color:white;    
    transition: transform 0.3s ease-in-out;
    cursor: pointer;
  }
  
  #bttn.active {
    transform:translateX(-110px);
  
  }
  #nav {
    position:fixed;
    top:0;
    right:0;
    background-color:#639;  
    height:100vh;
    padding:2em;
    transform:translateX(100%);
    transition: transform 0.3s ease-in-out;
  }
  
  #nav.active {
    transform:translateX(0);
  }
  
  #nav ul {  
    padding:0;
    margin:0;
    list-style: none;
  }
  
  #nav ul li {
    padding:1em 0;
  }
  
  #nav a {
    color:white;
    text-decoration: none;
  }

 

 

이 CSS 코드는 다음과 같은 스타일을 가진 HTML 요소를 가지고 있다.

1. 버튼(#bttn)을 클릭하면 나타나는 사이드 메뉴(#nav)가 있습니다.

2. #bttn은 화면 오른쪽 상단에 고정되어 있으며, 배경색과 글자색이 지정되어 있다.

3. #bttn이 클릭되면, #nav가 화면으로 나타나며, 배경색과 글자색이 지정되어 있다.

4. #nav는 오른쪽에서 화면 안으로 슬라이딩되며, 텍스트 링크가 포함된 목록을 가지고 있다.

5. 링크를 클릭하면 새로운 페이지로 이동한다. 그러나 아직 링크가 지정되어 있지 않다.

 

 

각 요소의 CSS 속성은 다음과 같다.

 

: 모든 요소에 대한 box-sizing은 border-box로 설정된다.

 

body

: body 요소는 flex로 설정되어, 세로 가운데 정렬이 이루어진다.

 

a

: a 요소의 텍스트에 대한 효과는 제거 된다.

 

#bttn

: ttn 요소는 position 속성으로 고정되며, 우측 상단에 위치하도록 설정된다.

클릭 시 transform 속성을 이용하여 좌측으로 이동하며, 배경색과 글자색이 변경된다.

 

#nav

: #nav 요소는 position 속성으로 고정되며, 오른쪽에서 화면으로 나타나도록 transform 속성을 이용한다.

배경색과 글자색이 지정된다.

 

#nav ul

: #nav ul은 패딩과 마진 속성, 그리고 리스트 스타일이 제거된다.

 

#nav ul li

: #nav ul li는 패딩이 1em 만큼 추가된다.

 

#nav a

: #nav a 텍스트 색상이 흰색으로 지정된다.

 

 

 

 

 

 

 

728x90
반응형

 

 

완성 화면

 

 

 

 

 

 

 

 

 

코드 보기 ver. 1

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>연습문제 1</title>  
  <style>
    #container {
      width: 600px;
      margin: 20px auto;
    }
    h1 {
      font-size:1.5rem;
      text-align:center;
      margin-bottom:20px;
    }
    .img {
        cursor: pointer;
    }
  </style>
</head>
<body>
  <div id="container">
    <h1>마우스 오버하면 이미지 바꾸기</h1>
    <img class="img"src="pic-1.jpg" alt="">
  </div>

  <script>
    const imgChange = document.querySelector(".img")

    imgChange.addEventListener("mouseover", ()=>{
        imgChange.src = "pic-6.jpg";
    });
    imgChange.addEventListener("mouseout",()=>{
        imgChange.src = "pic-1.jpg";
    });
  </script>
</body>
</html>

 

 

 

HTML 코드

: 이미지를 포함하는 div 요소가 있다.

이 요소의 id는 container이며, css에서 스타일링 시 이 id를 기준으로 선택할 수 있다.

또한 이 div 요소 안에는 이미지를 표시하는 img 요소가 있으며, 이 img 요소는 "img"라는 클래스가 저장되어 있다.

 

 

CSS 코드

: #container 요소에 스타일링을 적용하고 있다.

이 요소의 너비(width)를 600px로 지정하고, margin  속성을 사용하여 수평 중앙 정렬을 적용한다.

h1 요소는 글자 크기가 1.5em으로 가운데 정렬되며, 하단에 20px의 마진이 적용된다.

 

img 클래스가 지정된 img 요소에는 cursor 속성이 포인터로 지정되어 있다.

이 스타일은 마우스를 올리거나 요소를 클릭했을 때 커서의 모양을 변경하는데 사용된다.

 

JAVASCRIPT

: document.querySelector( ) 함수를 사용하여 img 요소를 선택한다.

이 함수는 CSS 선택자를 이용해 요소를 선택할 수 있다.

.img 라는 클래스 선택자를 사용하여 img 요소를 선택한다.

 

선택한 img 요소에 대해 mouserover이벤트와 mouseout 이벤트가 각각 등록된다.

mouseover 이벤트는 마우스가 요소 위로 진입하면 발생하며, mouseout 이벤트는 마우스가 요소를 벗어나면 발생한다.

 

이벤트 발생 시 실행될 콜백 함수는 화살표 함수로 작성되어 있으며, 이 함수는 각각 imgChange.scr 속성을 변경하는 구문을 포함한다.

마우스가 요소 위로 진입하면 imgChange.scr를 pic-6.jpg로 변경하고, 마우스가 요소를 벗어나면 imgChange.scr 속성을 pic-1.jpg로 변경한다.

 

 

 

 

 

 

코드 보기 ver. 2

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>연습문제 1</title>  
  <style>
    #container {
      width: 600px;
      margin: 20px auto;
    }
    h1 {
      font-size:1.5rem;
      text-align:center;
      margin-bottom:20px;
    }
    .img {
        background-image: url(pic-1.jpg);
        cursor: pointer;
        width: 600px;
        height: 300px;
    }
    .img:hover {
        background-image: url(pic-6.jpg);
    }
  </style>
</head>
<body>
  <div id="container">
    <h1>마우스 오버하면 이미지 바꾸기</h1>
    <div class="img"></div>
  </div>
</body>
</html>

 

 

HTML 

: ver. 1 코드와 비슷하지만 이미지를 img 태그 대신 div 태그의 배경 이미지로 표시하는 방법을 사용한다.

이 방법은 원래 이미지와 대체 이미지를 모두 div 태그의 배경 이미지로 지정하고, 마우스 오버 시 CSS에서 이 배경 이미지를 변경하여 이미지를 교체하는 방식으로 동작한다.

 

div 요소에 img라는 클래스가 지정되어 있다.

CSS에서 이 클래스를 선택하여 해당  div 요소의 스타일을 지정할 수 있다.

 

 

 

CSS

: img 클래스를 가진 div 요소의 배경 이미지는 background-image 속성으로 지정되며, cursor 속성은 포인터로 변경한다.

div 요소의 너비(width)와 높이(height)는 각각 600px,300px로 지정된다.

 

CSS에서는 img:hover 선택자를 이용하여 마우스 오버 시의 스타일을 지정한다.

 img:hover 에서는 배경 이미지를 기존 이미지인 pic-1.jpg에서 다른 이미지인 pic-6.jpg로 변경한다.

 

 

 

이렇게 작성된 코드는 마우스를 div 요소 위로 올리면 배경 이미지가 교체되며, 마우스가 요소를 벗어나면 다시 원래 이미지로 돌아간다.

ver.1처럼 JAVASCRIPT를 사용하지 않기 때문에 대상 요소가 div와 같은 특정 태그로 제한된다는 단점이 있으나, 

코드가 간단하고 브라우저에서의 성능 문제가 적다는 장점이 있다.

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형

 

 

length

자바스크립트에서 배열과 문자열 등과 같은 객체의 크기(문자열의 길이)를 나타내는 속성이다.

배열과 문자열 객체에 존재하는 프로퍼티로,  해당 객체의 요소의 수를 반환한다.

 

배열의 경우, length 프로퍼티는 배열의 인덱스 중 가장 큰 값을 1 증가시킨 값과 같다.

인덱스가 0부터 시작하기 때문이다.

 

문자열의 경우, length의 프로퍼티는 문자열의 길이(공백을 포함)를 반환하며, 함수에서는 함수가 가지고 있는 매개변수의 갯수를 나타낸다.

 

length 프로퍼티는 읽기 전용 속성이기 때문에 코드에서 명시적으로 값을 할당할 수 없다.

또한 배열의 length 값을 직접 변경하여 배열의 길이를 늘이거나 줄일 수도 없다.

 

 

 

형식

문자열.length 

 

ex) 

let str = "I want to go home".length;			//문자열.length

//17

 

 

 

 

 

charAt( )

자바스크립트의 문자열 객체에서 사용되는 charAt( ) 메서드는 주어진 index(인덱스)에 해당하는 위치에 있는 문자를 반환한다.

 

charAt( ) 메서드는 문자열 인덱스를 인수로 받는다.

인덱스는 0부터 시작하며, 문자열의 마지막 인덱스는 문자열의 길이에서 1을 뺀 값이다.

만약 인덱스가 문자열의 범위를 벗어날 경우 빈 문자열(" ")을 반환한다.

따라서, 인덱스 값이 음수이거나 문자열의 길이가 큰 경우 charAt() 메서드는 빈 문자열을 반환한다.

 

참고로 문자열 객체의 문자에 접근할 때 인덱스가 아닌 대괄호 [ ]를 사용하는 방법도 있다.

 

 

 

형식

문자열.charAt(위치)

 

ex)

let str = "I want to go home"

str.chatAt(3)				//a
console.log(str[3])			//a

 

 

 

 

 

indexOf( )

이 메서드는 문자열에서 특정 문자열의 첫 번째 인덱스를 반환한다.

만약 문자열 안에 해당 문자열이 없으면 -1을 반환한다.

 

소괄호 ( ) 안에 찾고자 하는 문자열과 매개변수를 작성할 수 있다.

숫자는 검색을 시작할 인덱스이며, 이 매개변수를 생략하면 문자열의 처음부터 검색을 시작한다.

음수 값을 입력하면 문자열의 끝에서부터 검색을 시작한다.

 

 

 

형식

indexOf(문자열) or    indexOf(문자열, 위치)

 

ex)

"javascript reference".lastIndexOf("javascript");

console.log("javascript reference".lastIndexOf("r"));                               //15
console.log("javascript reference".lastIndexOf("javascript",0));                    //0
console.log("javascript reference".lastIndexOf("javascript",1));                    //0

 

 

 

 

 

 

startsWith( )

문자열이 특정 문자열로 시작하는지 여부를 확인하는 자바스크립트 내장 메서드이다.

찾고자 하는 문자열의 이름을 메서드의 앞에 작성하고 소괄호 ( ) 안에는 찾고자 하는 문자열과 검색을 시작할 인덱스를 작성할 수 있다.

이 메서드는 대소문자를 구분한다.

 

인덱스값은 선택사항이며, 이 인덱스를 포함하여 문자열에서 검색을 시작한다.

이 인자가 생략될 경우 검색은 문자열의 처음부터 시작된다.

 

startsWith( ) 메서드는 결과값으로 불린(true, false)를 반환한다.

 

 

 

 

형식

문자열.startsWith( )

 

ex)

const str = "Hello, world!";
console.log(str.startsWith("Hello")); // true
console.log(str.startsWith("World")); // false
console.log(str.startsWith("world", 7)); // true

 

 

 

 

 

 

EndsWith( )

이 메서드는 문자열이 특정 문자열 또는 문자로 끝나는지 여부를 확인하는데 사용된다.

EndsWith( ) 메서드는 두 개의 매개변수를 받을 수 있다.

첫 번째 매개변수는 검색하려는 문자열 또는 문자이며, 두 번째 매개변수는 선택적으로 검색을 종료할 인덱스를 지정할 수 있다.

 

EndsWith( ) 메서드 역시 불린 값을 반환하며, 문자열이 지정된 문자열 또는 문자로 끝나면 true를, 그렇지 않으면 false를 반환한다.

 

 

 

형식

문자열.endsWith( )

or

문자열.endsWith(찾을 문자열, 길이)

 

ex)

const str = "Hello, world!";
console.log(str.endsWith("!")); // true
console.log(str.endsWith("world")); // false
console.log(str.endsWith("Hello", 5)); // true

 

 

 

 

 

 

includes( )

자바스크립트에 있는 내장 메서드이다.

문자열에서 특정 부분 문자열이 존재하는지를 확인하기 위하혀 사용된다.

이 메서드는 문자열에 대해 참과 거짓(불린/true, false) 값을 반환한다.

만약 문자열이 특정 부분 문자열을 포함하고 있으면 참(true)를 반환하고 그렇지 않으면 거짓(false)를 반환한다.

 

 

 

형식

문자열.includes(찾을 문자열)

 

ex)

const str = 'Hello, world!';
const substring = 'world';
const result = str.includes(substring);
console.log(result); // 출력 결과: true

 

 

 

 

 

 

trim( )

문자열 양 끝의 공백을 제거하는데 사용된다.

trim( ) 메서드는 공백이 제거된 새 문자열을 반환한다.

원본 문자열은 변경시키지 않는다.

trim( ) 메서드는 사용자가 입력한 폼 데이터의 공백 제거, 문자열 검색을 위해 문자열의 앞뒤 공백 제거, 문자열을 비교하기 전에 앞뒤 공백을 제거하여 정확한 비교 수행 등에 사용된다.

 

형식

문자열.trim( )

 

ex)

const str = "   Hello, World!   ";

const trimmedStr = str.trim(); // "Hello, World!"

 

 

 

 

 

trimStart( )

자바스크립트의 내장 메서드로써, 문자열의 시작 부분에서부터 공백을 제거한다.

주어진 문자열의 시작 부분에서 모든 공백을 제거한 새로운 문자열을 반환한다.

이때, 원본 문자열은 변경되지 않는다.

이 메서드는 ES2019(또는 ES10)에서 추가되었으며,  이전에는 trimLeft( ) 메서드로 불렸으나 ECMAScript 2021에서 이름이 변경되었다.

 

 

 

형식

문자열.trimStart

 

ex)

const greeting = '     Hello, world!     ';
console.log(greeting); // '     Hello, world!     '
console.log(greeting.trimStart()); // 'Hello, world!

 

 

 

 

 

 

trimEnd( )

문자열의 끝에서부터 공백 문자를 제거한 후, 새로운 문자열을 반환한다.

즉, 문자열 끝에 여러 개의 공백이 있을 경우 모든 공백을 제거하는 것이다.

이 메서드는 ES2019(ES10)에서 추가되었다.

이전에는 이와 같은 기능을 수행하기 위해 String.prototype.trimRight( ) 메서드를 사용하였으나 trimEnd( )로 이름이 변경되었다.

trimEnd( ) 메서드 또한 원본 문자열을 변경하지 않는다.

대신, 공백을 제거한 새로운 문자열을 반환한다.

문자열의 시작부분에서부터 모든 공백을 제거하는 trimStart( )메서드와 달리 문자열의 끝의 공백만을 제거한다.

 

 

 

형식

문자열.trimEnd( )

 

ex)

const str = "     Hello World!     ";
console.log(str.trimEnd()); // "     Hello World!"

 

 

 

 

 

toUpperCase( )

자바스크립트에서 문자열을 대문자로 변환하는 함수이다.

이 함수는 문자열 객체의 메서드로 사용되며, 원래 문자열을 수정하지 않고 대문자로 변환된 새로운 문자열을 반환한다.

대문자로 변환된 문자열을 만들어야 할 때 유용하며, 대소문자 구분을 하지 않는 문자열 검색과 비교에도 사용할 수 있다.

 

 

 

형식

문자열.toUpperCase( )

 

ex)

let str = "hello world";
let upperCaseStr = str.toUpperCase();

console.log(upperCaseStr); // 출력결과: "HELLO WORLD"

 

 

 

 

 

 

toLowCase( )

자바스크립트에서 문자열을 소문자로 변환하는 함수이다.

이 함수는 문자열 객체의 메서드로 사용되며, 원래 문자열을 수정하지 않고 소문자로 변환된 새로운 문자열을 반환한다.

 

소문자로 변환된 문자열을 만들어야 할 때 유용하며, toUpperCase( )처럼 대소문자 구분을 하지 않는 문자열 검색과 비교에서 사용될 수 있다.

 

 

형식

문자열.toLowCase( )

 

ex)

let str = "HELLO WORLD";
let lowerCaseStr = str.toLowerCase();

console.log(lowerCaseStr); // 출력결과: "hello world"

 

 

 

 

 

 

substring( )

문자열에서 지정된 위치에 있는 문자들의 부분 문자열(substring)을 반환한다.

이 메서드는 문자열 객체의 메서드로 사용된다.

 

substring( ) 메서드는 두 개의 매개변수를 가질 수 있다. (추출할 부분의 시작 위치와 끝 위치를 인수로 받는다.)

첫 번째 매개변수는 부분 문자열의 시작 인덱스이고, 두 번째 매개변수는 부분 문자열의 끝 인덱스이다.

두 번째 매개변수는 생략할 수 있으며, 생략한 경우 문자열의 끝부분까지 부분 문자열을 반환한다.

 

substr( ) 함수와 비슷하게 동작하지만, substr( ) 함수는 첫 번째 인수로 시작 위치와 두 번재 인수로 추출할 문자열의 길이를 받는 것에 반해, substring( ) 함수는 시작 위치와 끝 위치를 받는다.

 

 

형식

문자열. substring(시작 위치)

or

문자열.substring(시작 위치, 끝 위치)

 

ex)

let str = "hello world";
let subStr = str.substring(0, 5);

console.log(subStr); // 출력결과: "hello"

 

 

 

 

 

 

slice( )

문자열에서 일부분을 추출하여 새로운 문자열을 반환하는 함수이다.

이 함수는 문자열 객체의 메서드로 사용되며, 추출할 부분의 시작 위치와 끝 위치를 인수로 받는다.

 

slice( ) 함수는 첫 번째 인수로 시작 위치를, 두 번째 인수로 추출할 부분의 끝 위치를 지정한다.

첫 번째 인수는 필수적이며, 두 번째 인수는 선택적이다.

두 번째 인수를 생략하면 추출할 문자열은 첫 번째 인수로 지정된 위치부터 문자열의 끝까지를 추출하여 반환한다.

 

slice( ) 함수는 substring( ) 함수과 비슷하게 동작하지만, substring( ) 함수는 음수 값을 받지 않고, 시작 위치와 끝 위치를 자동으로 정렬한다.

그러나 slice( ) 함수는 음수 값을 받을 수 있으며, 시작 위치와 끝 위치를 지정한대로 추출한다.

 

형식

문자열.slice(시작 위치)

or

문자열.slice(시작 위치, 끝 위치)

 

ex)

let str = "hello world";
let subStr = str.slice(0, 5);

console.log(subStr); // 출력결과: "hello"

 

 

 

 

 

 

split( )

 

문자열을 지정한 구분자를 기준으로 분할하여 배열로 반환하는 함수이다.

이 함수는 문자열 객체의 메서드로 사용되며, 구분자는 인수로 전달된다.

구분자는 문자열, 정규식, 혹은 구분자를 지정하지 않을 수도 있다.

 

split( ) 함수는 주로 문자열을 파싱[각주:1]하거나 특정 문자열을 기준으로 분할해야할 때 사용된다.

 

 

형식

문자열.split(구분자)

 

ex)

let str = "apple,banana,kiwi";
let arr = str.split(",");

console.log(arr); // 출력결과: ["apple", "banana", "kiwi"]

 

 

 

 

 

 

 

 

 

  1. 문자열을 의미 있는 단위로 분해하는 과정을 말한다. HTML 문서에서 특정 태그의 속성 값을 파싱하는 등의 작업이 문자열 파싱에 해당한다. [본문으로]
728x90
반응형

 

 

 

완 성 화 면

(https://fitalux.github.io/web2023/site/site1/index.html)

 

 

 

 

코드 보기 / CSS

(여러 타입의 화면을 합친 관계로 GitHub 주소로 대체)

https://github.com/Fitalux/web2023/tree/main/site/site1/assets/css

 

GitHub - Fitalux/web2023: 수업시간에 배운 사이트입니다.

수업시간에 배운 사이트입니다. Contribute to Fitalux/web2023 development by creating an account on GitHub.

github.com

 

 

 

 

 

코드 보기 / HTML - head

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>site 1</title>

    <!-- SEO -->
    <meta name="author" content="Fitalux">
    <meta name="description" content="About the milky way">
    <meta name="keyword" content="milky way, Galaxy, stars, site">
    <meta name="robots" content="all">

    <link rel="shortcut icon" type="image/x-icon" href="assets/ico/favicon.png"/>  
    <link rel="apple-touch-icon" sizes="114x114" href="assets/ico/favicon.png"/> 
    <link rel="apple-touch-icon" href="assets/ico/favicon.png"/>

    <!-- CSS -->
    <link rel="stylesheet" href="assets/css/fonts.css">
    <link rel="stylesheet" href="assets/css/reset.css">
    <link rel="stylesheet" href="assets/css/common.css">
    <link rel="stylesheet" href="assets/css/style.css">
</head>

 

HTML 문서의 head 섹션이다.

head 섹션에는 브라우저 창에는 표시지되지 않지만 웹 페이지의 기능과 외관에 대한 정보를 포함하고 있다.

 

 

<! DOCUTYPE html>

: 브라우저에게 문서가 작성된 HTML 버전을 알리는 선언입니다. 이 경우 HTML5이다.

 

 

 

<html lang="ko">

:  HTML 문서의 시작을 나타내며 언어를 한국어로 설정합니다.

 

 

 

<head>

:  head 섹션의 시작을 표시합니다.

 

 

 

<meta>

: 문자 인코딩, Internet Explorer 호환성, 뷰포트 설정 및 SEO 관련 정보(작성자, 설명, 키워드, 로봇 설정 등)를 포함한 문서의 메타데이터를 제공한다.

 

 


<title>

: 이 태그는 웹 페이지의 제목을 설정하며, 브라우저 타이틀 바와 검색 엔진 결과에 표시된다.

 

 


<link>

: 이웹 페이지가 필요로하는 외부 리소스를 정의한다.

이에는 파비콘(브라우저 탭과 즐겨찾기에 표시되는 작은 아이콘), 애플 터치 아이콘(북마크나 홈 화면에 추가될 때 Apple 기기에 표시되는 아이콘) 및 CSS 파일(페이지의 스타일링 및 레이아웃을 정의)이 포함된다.

같은 문서 내에 CSS를 작성하지 않고 외부에 작성하고 link로 연결해줌으로서 가독성을 높일 수 있다.

 

 

 

 

 

코드 보기 / HTML -  body / skip

<div id="skip">
        <a href="#">헤더 영역 바로가기</a>
        <a href="#">슬라이드 영역 바로가기</a>
        <a href="#">이미지 영역 바로가기</a>
        <a href="#">이미지, 텍스트 영역 바로가기</a>
        <a href="#">카드 영역 바로가기</a>
        <a href="#">배너 영역 바로가기</a>
        <a href="#">텍스트 영역 바로가기</a>
        <a href="#">푸터 영역 바로가기</a>
    </div>
    <!-- skip -->

 

웹 페이지의 스킵 내비게이션(skip navigation)을 구현한다.

 

스킵 내비게이션은 웹 페이지에 접근할 때 키보드만으로 해당 페이지의 중요한 부분으로 빠르게 이동할 수 있도록 돕는 역할을 한다.

이를 사용하면 페이지에 접근하는 사람들이 불필요한 컨텐츠를 건너뛰고 중요한 부분으로 바로 이동할 수 있기 때문에 웹 접근성을 향상 시킬 수 있다.

 

div 태그로  스킵 내비게이션을 감싸고  a 태그로 스킵 내비게이션의 각 링크를 만든다.

링크의 href 속성은 해당 영역의 id 값을 참조한다.

스킵 내비게이션 링크를 클릭하면 해당 영역으로 포커스가 이동한다.

(그러나, 아직 id값을 참조시키지 않은 상태.)

 

 

 

 

 

 

코드 보기 / HTML - body / headerType

 <header id="headerType" class="header__wrap nexon">
        <div class="header__inner">
            <h1 class="header__logo">🌌 MILKY WAY  </h1>
            <nav class="header__menu">
                <ul>
                    <li><a href="#">은하수</a></li>
                    <li><a href="#">우리 은하</a></li>
                    <li><a href="#">국부 은하군</a></li>
                    <li><a href="#">타원형 은하</a></li>
                    <li><a href="#">나선형 은하</a></li>
                    <li><a href="#">불규칙 은하</a></li>
                </ul>
            </nav>
            <div class="header__memder">
                <a href="#">로그인</a>
            </div>
        </div>
    </header>
    <!-- headerType -->
    
   
  ** CSS**

/* header__wrap */
.header__wrap {}
.header__inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px;
    background-color: #fff;
    border-bottom: 1px solid #ccc;
    font-weight: 500;
}
.header__logo {
    width: 20%;
}
.header__menu {
    width: 60%;
    text-align: center;
}
.header__menu li {
    display: inline-block;
}
.header__menu li a {
    display: inline-block;
    padding: 10px 20px;
    background-color: #fff;
}
.header__memder {
    width: 20%;
    text-align: right;
}
.header__memder a {
    border: 1px solid #000;
    padding: 10px 30px;
    border-radius: 50px;
    font-size: 16px;
}

 

header__wrap

: 헤더 영역을 감싸는 전체 영역을 지정한다.

 

 

header__inner

: 헤더 내부의 요소들을 가로 방향으로 배치하기 위해 display: flex 속성을 사용하고, 요소들 사이에 동일한 간격을 두기 위해 justify-content: space-between 속성을 사용한다.

그리고 요소들을 세로 중앙에 정렬하기 위해 align-items: center 속성을 사용한다.

헤더의 배경 색상을 #fff (흰색)으로 설정하고, 헤더와 하단 선을 구분하기 위해 border-bottom: 1px solid #ccc 속성을 사용한다.

또한 폰트의 굵기를 500으로 설정(font-weight: 500)한다.

 

 

header__logo

:헤더 중앙에 위치한 메뉴 영역을 지정한다.

너비를 20%로 조정한다.

 

 

 header__menu

: 너비(width)를 60%로 설정하고, 가운데 정렬을 위해 text-align: center 속성을 사용한다.

 

 

header__menu li , header__menu li a

: header__menu 내부의 li 태그에 있는 메뉴 항목을 가로로 나열하기 위해 display:inline-block 속성을 사용한다.

각 메뉴 항목은 a로 구성되며 padding: 10px 20px 속성을 사용하여 각 항목의 내부 여백을 설정하고 배경 색상을 흰색(#fff)로 설정한다.

 

 

header__member 

: 헤더 오른쪽에 위치한 로그인 버튼을 감싸는 영역이다.

너비를 20%로 설정하고, 오른쪽 정렬을 위해 text-align: right 속성을 사용한다.

 

 

header__member a

: 로그인 버튼을 지정하며, 테두리를 1px 두께의 검은색(#000)으로 설정하고, 테두리 반경을 50px로 설정하여 원형 모양을 만듭니다. 또한, 글꼴 크기를 16px로 설정한다.

 

 

 

 

 

코드 보기  / HTML - body / sliderType

<main id="mainType">
        <section id="sliderType" class="slider__wrap nexon">
            <h2 class="blind">메인 슬라이드 영역</h2>
        <div class="slider__inner">
            <div class="slider">
                <div class="slider__info container">
                    <span class="small">notice</span>
                    <h3 class="title">광활한 우주에 펼쳐진 길, 은하수</h3>
                    <p class="desc"> 은하수는 끝이 없는 우주의 신비로운 대상이며, 그 안에는 끊임없이 진화하는 별들과 이례적인 천문학적 현상들이 숨어 있습니다.</p>
                    <div class="btn">
                        <a href="#">자세히 보기</a>
                        <a href="#">알아보기</a>
                    </div>
                </div>
                <div class="slider__arrow">
                    <a href="#"><span class="blind">이전 이미지</span></a>
                    <a href="#"><span class="blind">다음 이미지</span></a>
                </div>
                <div class="slider__dot">
                    <a href="#" class="dot active"><span class="blind">첫번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">두번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">세번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">네번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">다섯째 이미지</span></a>
                    <a href="#" class="play"><span class="blind">play</span></a>
                    <a href="#" class="stop"><span class="blind">stop</span></a>
                </div>
            </div>
        </div>
        </section>
        <!--//sliderType -->

 

 

 

슬라이드 유형

: https://fitalux.tistory.com/41

 

[2023 사이트 프로젝트] 슬라이드 유형

슬라이드 유형 사이트 완성 화면 https://fitalux.github.io/web2023/site/sliderType/sliderType01.html 코드 보기 / CSS /* slider__wrap */ .slider__inner .slider { height: 600px; background-image: url(../asset/img/sliderType01_01.jpg); backgrou

fitalux.tistory.com

 

 

 

 

 

코드 보기 / HTML - body / imageType

 <section id="imageType" class="image__wrap section center nexon" >
            <div class="container">
                <h2 class="section__h2">Milky way</h2>
                <p class="section__desc">Milky way는 은하수 뿐 아니라 우리 은하를 가리키는 말이기도 합니다.</p>
                <div class="image__inner">
                    <article class="image">
                        <figure class="image__header">
                            <img src="assets/img/imageType01_01.jpg" alt="태양계가 속해 있는 우리 은하">
                        </figure>
                        <div class="image__body">
                            <h3 class="title">태양계가 속해 있는 우리 은하</h3>
                            <p class="desc">은하수는 밤하늘에 천구를 아치형으로 가로지르는 흰 빛의 흐릿한 띠 모양으로 보입니다. </p>
                            <a href="#" class="btn">자세히 보기</a>
                        </div>
                    </article>
                    <article class="image">
                        <figure class="image__header">
                            <img src="assets/img/imageType01_02.jpg" alt="우리 은하의 물리적 크기">
                        </figure>
                        <div class="image__body">
                            <h3 class="title">우리 은하의 물리적 크기</h3>
                            <p class="desc">우리 은하의 원반은 직경이 약 100,000광년이고, 평균적으로 약 1,000광년 두께입니다.</p>
                            <a href="#" class="btn">자세히 보기</a>
                        </div>
                    </article>
                </div>
            </div>
        </section> 
        <!--//imageType -->

 

 

 

이미지 유형 

: https://fitalux.tistory.com/37

 

[2023 사이트 프로젝트] 이미지 유형

이미지 유형 사이트 완성화면 코드 보기 / CSS /* reset */ * { margin: 0; padding: 0; } a { text-decoration: none; color:#000; } h1,h2,h3,h4,h5,h6 { font-weight: normal; } img { vertical-align: top; width: 100%; } .mt10 {margin-top: 10px !impo

fitalux.tistory.com

 

 

 

 

 

코드 보기 / HTML - body / img-textType

 <section id="img-textType" class="img-text__wrap section nexon gray">
            <h2 class="blind"></h2>
            <div class="img-text__inner container">
                <article class="text">
                    <span>notice</span>
                    <h3>나선형 은하(Spiral Galaxy)</h3>
                    <p class="subtitle">나선형 은하는 중심 부분에 바(bar)와 팔(arm) 형태로 뻗어나가는 구조입니다.</p>
                    <p>
                        나선형 은하 안에는 주로 별들이 모여있는 은하원반이 있습니다. 이 은하원반 안에는 다양한 크기와 모양의 은하들이 분포해 있습니다.
                        이러한 은하들은 대부분 나선형 은하 안의 중심 부분인 바 주변이나 나선형 팔 사이에 위치하고 있습니다. 이러한 은하들을 위성 은하(Satellite Galaxy) 또는 동반 은하(Companion Galaxy)라고 합니다.
                        이렇게 나선형 은하 안에 위치한 위성 은하들은 나선형 은하와 서로 상호작용하면서 형태를 바꾸는 등의 영향을 끼치기도 하며, 형태에 따라 다양한 종류가 있습니다.</p>
                </article>
                <article class="image img1">
                        <a href="#">나선형 은하</a>
                </article>
                <article class="image img2">
                        <a href="#">위성 은하</a>
                </article>
            </div>
        </section> 
        <!--//img-textType -->

 

 

 

이미지/텍스트 유형

: https://fitalux.tistory.com/40

 

[2023 사이트 프로젝트] 이미지/텍스트 유형

이미지 유형 사이트 완성 화면 코드 보기 / CSS /* reset */ * { margin: 0; padding: 0; } a { text-decoration: none; color:#000; } h1,h2,h3,h4,h5,h6 { font-weight: normal; } img { vertical-align: top; width: 100%; } .mt10 {margin-top: 10px !imp

fitalux.tistory.com

 

 

 

 

 

 

코드 보기 / HTML - body / cardType

 <section id="cardType" class="card__wrap section nexon">
            <div class="container">
                <h2 class="section__h2">About the Milky way</h2>
                <p class="section__desc">은하수는 우리 태양계가 속해 있는 막대 나선 은하로, 지름은 약 10만 광년이며 약 1000억 개 이상의 별과 더불어 행성과 소행성, 혜성, 가스 구름 등 다양한 천체들이 존재합니다.</p>
                <div class="card__inner">
                    <article class="card">
                        <figure class="card__header">
                            <img src="../asset/img/cardType01_01.jpg" alt="은하수의 구성">
                        </figure>
                        <div class="card__body">
                            <h3 class="title">은하수의 구성</h3>
                            <p class="desc">은하수는 약 130억 년 전에 처음으로 형성 되었으며, 암흑 물질, 별, 가스의 혼합물로 이루어져 있습니다. 은하수의 중심부에는 약 4백만 개의 태양 질량을 가진 거대한 블랙홀이 있습니다.</p>
                            <a href="#" class="btn">자세히 보기</a>
                        </div>
                    </article>
                    <article class="card">
                        <figure class="card__header">
                            <img src="../asset/img/cardType01_02.jpg" alt="은하수의 종류">
                        </figure>
                        <div class="card__body">
                            <h3 class="title">은하수의 종류</h3>
                            <p class="desc">은하수는 크게 타원형 은하와 나선형 은하, 불규칙형 은하까지 총  세 가지 종류로 분류 됩니다. 타원형 은하는 둥근 모양을 가지며, 별들이 잘 정렬되어 있다는 특징이 있습니다.</p>
                            <a href="#" class="btn">자세히 보기</a>
                        </div>
                    </article>
                    <article class="card">
                        <figure class="card__header">
                            <img src="../asset/img/cardType01_03.jpg" alt="은하수의 색">
                        </figure>
                        <div class="card__body">
                            <h3 class="title">은하수의 색</h3>
                            <p class="desc">은하수의 색은 그 안에 포함된 별들의  색과 빛을 반사하는 먼지와 가스의 성분, 그리고 은하의 나이 등에 따라 달라집니다. 보통 은하수는 주황, 노랑,  빨강 등의 색을 가집니다.</p>
                            <a href="#" class="btn">자세히 보기</a>
                        </div>
                    </article>
                    </div>
                </div>
            </div>
        </section> 
        <!--//cardType -->

 

 

 

카드 유형 

: https://fitalux.tistory.com/33

 

[2023 사이트 프로젝트] 카드 유형

카드 유형 사이트 완성화면 카드 유형 사이트 - 코드 notice About the Milky way 명칭 및 어원 우리 은하의 명칭은 “Milky Way(밀키 웨이)”입니다. 그러나 밀키 웨이는 우리 은하 뿐 아니라 은하수 자체

fitalux.tistory.com

 

 

 

 

 

코드 보기 / HTML - body / bannerType

<section id="bannerType" class="banner__wrap section nexon center">
            <h2 class="blind">배너</h2>
        <div class="banner__inner container">
            <h3>은하수 관측</h3>
            <p>우리나라에서도 도심에서 떨어진 산이나 산골 지역에서라면 은하수를 관측할 수 있습니다.<br> 하단 링크를 통해 자세히 알아볼 수 있습니다.</p>
            <a href="https://www.insight.co.kr/news/123352">https://www.insight.co.kr/news/123352</a>
        </div>
        </section>
        <!--//bannerType -->
        
        
        ** CSS **
        
        .banner__wrap {
    background-image: url(../img/bannerType01.jpg);
    top: 0;
    left: 0;
    width: 100%;
    box-sizing: border-box;
    color: #fff;
}
.banner__inner h3 {
    font-size: 50px;
    line-height: 1.5;
    font-weight: bold;
    margin-bottom: 40px;
}
.banner__inner p {
    font-size: 18px;
    line-height: 1.5;
    font-weight: 700;
    margin-bottom: 80px;
}
.banner__inner a {
    color: #fff;
    font-weight: 700;
}

/* 미디어쿼리 */
@media (max-width: 960px) {
    .banner__inner h3 {
        font-size: 40px;
    }
}
@media (max-width: 600px) {
    .banner__inner h3 {
        font-size: 30px;
    }
    .banner__inner p {
        margin-bottom: 50px;
    }
}

 

section 태그에 id 값으로 bannerType을 지정하고, class 값으로 banner_wrap,  section(padding속성 부여), nexon('NexonLv1Gothic'이라는 font family 속성을 부여), center(가운데 정렬 속성 부여)를 지정하였다.

h2 태그를 통해 "배너"라는 제목을 추가하고 h2 태그에 class로 blind를 주어 화면에서 숨김처리 하였다.

 

div 태그에 class 값으로 banner__inner와 container를 지정하였고, 배너 내부에는 다음과 같은 요소들이 있다.

h3 태그 - "은하수 관측"이라는 제목

p 태그 - h3 태그 제목에 대한 간단한 설명이 포함되어 있다.

a 태그 - h3 태그 제목에 관한 자세한 정보가 포함된 링크를 포함하고 있다.

 

 

 

 

 

코드 보기 / HTML - body / textType

 <section id="textType" class="text__wrap section center nexon">
            <div class="container">
                <span class="section__small">notice</span>
                <h2 class="section__h2 mb70">About the Milky way</h2>
                <div class="text__inner">
                    <div class="text">
                        <h3 class="text__title">명칭 및 어원</h3>
                        <p class="text__desc">우리 은하의 명칭은 “Milky Way(밀키 웨이)”입니다. 그러나 밀키 웨이는 우리 은하 뿐 아니라 은하수 자체를 가리키기도 합니다. 은하수들도 각각의 명칭이 있습니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                    </div>
                    <div class="text">
                            <h3 class="text__title">갤러틱 할로(Galactic Halo)</h3>
                            <p class="text__desc">은하 중심부를 둘러싸고 있는 둥근 모양의 거대한 구조물 입니다. 은하 중심부에 위치한 은하 플레어와 달리, 할로는 무수히 많은 별, 암석체, 가스, 먼지 등이 혼합된 구조물입니다.</p>
                            <a class="text__btn" href="#">더 보기</a>
                    </div>
                    <div class="text">
                        <h3 class="text__title">은하 헤일로(Galaxy Hale)</h3>
                        <p class="text__desc">은하 헤일로는 아메리칸 천문학자 조지 엘리슨 헤일이 처음으로 제안한 은하 분류 체계입니다. 이 체계는 은하를 크기와 모양에 따라 4가지 유형으로 분류하고 있습니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                    </div>
                    <div class="text">
                        <h3 class="text__title">우리 은하의 구조</h3>
                        <p class="text__desc">우리 은하는 막대 나선 은하에 속하며, 허블의 은하 분류에 따르면 Sbc(중심에 막대가 존재하고 나선팔이 느슨히 감긴 형태)입니다. 막대 구조는 대부분 붉고 오래된 항성들로 구성되어 있습니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                    </div>
                    <div class="text">
                        <h3 class="text__title">우리 은하의 블랙홀</h3>
                        <p class="text__desc">우리 은하를 구성하는 별들은 은하의 중심부를 중심으로 나선팔 모양으로 공전합니다. 이는 은하 중심에 초대질량 블랙홀이 있기 때문이라 여겨집니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                    </div>
                    <div class="text">
                        <h3 class="text__title">우리 은하의 팔</h3>
                        <p class="text__desc">우리 은하에는 네 개의 큰 나선 팔이 있다고 여겨졌으나, 2008년에 스피처 적외선 망원경을 이용하여 1억 개 이상의 별의 분포를 분석한 결과, 단지 2개의 나선 팔만이 구분되었습니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                    </div>
                </div>
            </div>
        </section> 
        <!--//textType -->
    </main>
    <!-- mainType -->

 

 

텍스트 유형

: https://fitalux.tistory.com/45

 

[2023 사이트 프로젝트] 텍스트 유형

텍스트 유형 사이트 완성 화면 코드 보기 / CSS /* reset */ * { margin: 0; padding: 0; } a { text-decoration: none; color:#000; } h1,h2,h3,h4,h5,h6 { font-weight: normal; } img { vertical-align: top; width: 100%; } .mt10 {margin-top: 10px !imp

fitalux.tistory.com

 

 

 

 

 

코드 보기 / HTML - body / footerType

<footer id="footerType" class="footer__wrap section nexon">
        <div class="container">
            <h2 class="blind">footer</h2>
            <div class="footer__inner">
                <div class="footer__menu">
                    <div>
                        <h3>은하수 관련 정보</h3>
                        <ul>
                            <li><a href="#">은하수 소개</a></li>
                            <li><a href="#">은하수 어원</a></li>
                            <li><a href="#">우리은하 형태</a></li>
                            <li><a href="#">우리 은하 크기</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 종류</h3>
                        <ul>
                            <li><a href="#">나선형 은하</a></li>
                            <li><a href="#">타원형 은하</a></li>
                            <li><a href="#">불규칙 은하</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 구조</h3>
                        <ul>
                            <li><a href="#">은하 헤일로</a></li>
                            <li><a href="#">은하의 중심</a></li>
                            <li><a href="#">블랙홀</a></li>
                            <li><a href="#">나선 팔</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>국부 은하군</h3>
                        <ul>
                            <li><a href="#">안드로메다 은하</a></li>
                            <li><a href="#">우리 은하</a></li>
                            <li><a href="#">삼각형자리 은하</a></li>
                            <li><a href="#">대마젤란 은하</a></li>
                            <li><a href="#">바너드 은하</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 색</h3>
                        <ul>
                            <li><a href="#">청색(靑色)</a></li>
                            <li><a href="#">적색(赤色)</a></li>
                            <li><a href="#">자색(紫色)</a></li>
                            <li><a href="#">황색(黃色)</a></li>
                            <li><a href="#"> 백색(白色)</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>위성 은하</h3>
                        <ul>
                            <li><a href="#">큰개자리 왜소은하</a></li>
                            <li><a href="#">궁수자리 왜소타원은하</a></li>
                            <li><a href="#">작은곰자리 왜소은하</a></li>
                            <li><a href="#">사자자리 왜소은하</a></li>
                            <li><a href="#">목동자리 왜소은하</a></li>
                        </ul>
                    </div>
                </div>
                <address class="footer__right">
                    2023 Byun Woo Hyun 은하수 사이트 Portfolio is Power <br>All Right Reserved 
                </address>
            </div>
        </div>
    </footer>
    <!-- footerType -->

 

 

 

푸터 유형

: https://fitalux.tistory.com/50

 

[2023 사이트 프로젝트] 푸터(footer) 유형

완성 화면 푸터 유형 사이트 코드 보기 / HTML footer 은하수 관련 정보 은하수 소개 은하수 어원 우리은하 형태 우리 은하 크기 은하수의 종류 나선형 은하 타원형 은하 불규칙 은하 은하수의 구조

fitalux.tistory.com

 

728x90
반응형

 

 

 

 

완성 화면

 

 

 

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

 

//선택자
        const quizWrap = document.querySelector(".quiz__wrap");
        const quizTitle = quizWrap.querySelector(".quiz__title");
        const quizQuestion = quizWrap.querySelector(".quiz__question");
        const quizChoice = quizWrap.querySelector(".quiz__choice");
        const dogWrap = quizWrap.querySelector(".dog__wrap");
        const quizAnswer = quizWrap.querySelector(".quiz__answer");
        const quizNext = quizWrap.querySelector(".quiz__answer .next");
        const quizDesc = quizWrap.querySelector(".quiz__desc");

        let questionCount = 0;
        let quizCount = 0;
        let quizScore = 0;

        //문제출력
        const updateQuiz = (index) => {
            let TypeTag = `
                <span>${quizInfo[index].infoType}</span>
                <em>${quizInfo[index].infoTime}</em>
            `;

            let QuestionTag = `
                <em>${index+1}</em>.
                <span>${quizInfo[index].infoQuestion}</span>
            `;

            let ChoiceTag = `
                <label for="choice1">
                    <input type="radio" id="choice1" name="choice" value="1">
                    <span>${quizInfo[index].infoChoice[0]}</span>
                </label>
                <label for="choice2">
                    <input type="radio" id="choice2" name="choice" value="2">
                    <span>${quizInfo[index].infoChoice[1]}</span>
                </label> 
                <label for="choice3">
                    <input type="radio" id="choice3" name="choice" value="3">
                    <span>${quizInfo[index].infoChoice[2]}</span>
                </label> 
                <label for="choice4">
                    <input type="radio" id="choice4" name="choice" value="4">
                    <span>${quizInfo[index].infoChoice[3]}</span>
                </label> 
            `;

            let DescTag = `
                정답은 ${quizInfo[index].infoAnswer}.
                ${quizInfo[index].infoDesc}
            `;

            quizTitle.innerHTML = TypeTag;
            quizQuestion.innerHTML = QuestionTag;
            quizChoice.innerHTML = ChoiceTag;
            quizDesc.innerHTML = DescTag;


            //객관식 보기 선택자
            const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
            const quizChoiceInput = quizWrap.querySelectorAll(".quiz__choice input");
            
            // quizChoiceSpan.forEach((span, num)=>{
            //     span.setAttribute("onclick", "choiceSelected(this)");
            // });

            for(i=0; i<quizChoiceSpan.length; i++){
                quizChoiceSpan[i].setAttribute("onclick","choiceSelected(this)");
                quizChoiceInput.disabled = "true";
            }

            //다음 버튼 숨기기
            quizAnswer.style.display = "none";
            quizDesc.style.display = "none";

        };
        updateQuiz(quizCount);

        
        function choiceSelected(answer){
            let userAnswer = answer.textContent;                            //사용자 정답
            let currentAnswer = quizInfo[quizCount].infoAnswer;             //문제 정답
            
            if(userAnswer == currentAnswer) {
                console.log("O");
                dogWrap.classList.add("like");
            } else {
                console.log("X");
                dogWrap.classList.add("dislike");
            }

            //나타내기
            quizAnswer.style.display = "block";
            quizDesc.style.display = "block";
        }
        

        //정답 확인
        quizNext.addEventListener("click",()=>{
            quizCount++;
            updateQuiz(quizCount);
            dogWrap.classList.remove("like","dislike")
        });

 

 

 

 

 

const updateQuiz = (index) => { ...... }

 

:  updateQuiz 함수는 'index' 라는 매개변수를 받아들인다.

이 index는 quizInfo 배열에서 몇 번째 퀴즈 정보를 가져올지를 결정하는 인덱스 값이다.

 

 

 

 

 

let TypeTag = `

                           <span>${quizInfo[index].infoType}</span>

                           <em>${quizInfo[index].infoTime}</em>

                        `;

 

: TypeTag 변수는 HTML 태그 문자열을 저장하는 변수이다.

이 문자열은 quizInfo 배열에서 index에 해당하는 퀴즈 정보의 종류와 시간을 표시하는 HTML 태그 문자열이다.

 

 

 

 

 

let QuestionTag  = `

                           <span>${index+1}</span>

                           <em>${quizInfo[index].infoQuestion}</em>

                        `;

 

:QuestionTag 변수는 또 다른 HTML 태그 문자열을 저장하는 변수이다.

이 문자열은 quizInfo 배열에서 index에 해당하는 퀴즈 정보의 문제를 표시하는 HTML 태그 문자열이다.

index+1은 배열의 키가 0으로 시작한다는 것을 고려하여 실제 문제 번호와 맞추기 위해 1을 더해준 것이다.

 

 

 

 

let ChoiceTag = `
                <label for="choice1">
                    <input type="radio" id="choice1" name="choice" value="1">
                    <span>${quizInfo[index].infoChoice[0]}</span>
                </label>
                <label for="choice2">
                    <input type="radio" id="choice2" name="choice" value="2">
                    <span>${quizInfo[index].infoChoice[1]}</span>
                </label> 
                <label for="choice3">
                    <input type="radio" id="choice3" name="choice" value="3">
                    <span>${quizInfo[index].infoChoice[2]}</span>
                </label> 
                <label for="choice4">
                    <input type="radio" id="choice4" name="choice" value="4">
                    <span>${quizInfo[index].infoChoice[3]}</span>
                </label> 
            `;

 

: choiceTag 변수는 또 다른 HTML 태그 문자열을 저장하는 변수이다.

이 문자열은 quizInfo 배열에서 index에 해당하는 퀴즈 정보의 선택지를 표시하는 HTML 태그 문자열이다.

for  속성은 해당 선택지를 클릭하면 id 속성이 일치하는 input 요소가 선택되도록 한다.

 

 

 

 

let DescTag = `
                정답은 ${quizInfo[index].infoAnswer}.
                ${quizInfo[index].infoDesc}
            `;

 

: updateQuiz 함수 외부에서 호출되는 코드로, updateQuiz 함수에서 반환된  HTML 태그 문자열을 실제 문서에 삽입하는 역할을 한다.

DescTag 변수는 해당 문제의 정답과 설명을 담은 HTML 태그 문자열을 저장한다.

 

 

 

 

 

quizTitle.innerHTML = TypeTag;

quizQuestion.innerHTML = QuestionTag;

quizChoice.innerHTML = ChoiceTag;

quizDesc.innerHTML = DescTag;

 

: quizTitle, quizQuestion, quizChoice, quizDesc는 문서에서 해당 요소의 ID를 가진 HTML 태그들을 가리키는 변수이다.

이 변수들에 innerHTML 속성을 이용해서 updateQuiz 함수에서 반환된 태그 문자열을 삽입하면, 해당 페이지에서는 동적으로 생성된 퀴즈가 보여지게 된다.

즉, quizTitle에는 퀴즈의 종류와 시간을 표시하는 태그 문자열이, quizQuestion에는 문제를 표시하는 태그 문자열이, quizChoice에는 선택지를 표시하는 태그 문자열이, quizDesc에는 정답과 설명을 표시하는 태그 문자열이 삽입되게 된다.

 

 

 

 

const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
const quizChoiceInput = quizWrap.querySelectorAll(".quiz__choice input");

 

: 첫째 quizWrap 요소에서 quiz_choice span과 quiz__choice input을 모두 선택해서 각각  quizChoiceSpan과 quizChoiceInput 변수에 저장한다.

 

 

 

 

for (i = 0; i < quizChoiceSpan.length; i++) {
  quizChoiceSpan[i].setAttribute("onclick", "choiceSelected(this)");
  quizChoiceInput.disabled = "true";
}

 

: 반복문을 이용해  quizChoiceSpan의 모든 요소에 onclick 요소를 추가한다

setAttribute 메서드는 HTML 요소에 속성을 추가하거나 수정하는 메서드이다.

여기에서는 onclick 속성을 추가하고, 값으로 choiceSelected(this)를 할당한다.

this는 현재 클릭한 요소를 가리킨다.

따라서 choiceSelected 함수를 호출할 때, 해당 선택지에 대한 정보를 인자로 전달할 수 있다.

 

또한 quizChoiceInput.disabled = "true";는 선택지에 대응하는 input 요소를 비활성화 한다.

이는 선택지를 클릭했을 때, 선택지를 다시 클릭할 수 없도록 만드는 역할을 한다.

 

 

 

 

 

quizAnswer.style.display = "none";

quizDeac.style.display = "none";

};

        updateQuiz(quizCount);

 

:quizAnswer와 quizDesc 요소를 화면에서 숨긴다.

style 속성의 display 값으로 none을 지정함으로써 해당 요소를 화면에서 숨길 수 있다.

이 구문을 추가함으로써 초기 상태에서는 정답과 설명이 보이지 않는다.

 

updateQuiz 함수를 호출하고 quizCount 값을 전달한다.

quizCount는 현재 문제의 인덱스를 저장하는 변수이며, 페이지가 로드 되었을 때 첫 번째 문제가 화면에 나타나게 된다.

 

 

 

 

function choiceSelected(answer){
         
let userAnswer = answer.textContent;                                               // 사용자가 선택한 답변을 가져옴.    

          let currentAnswer = quizInfo[quizCount].infoAnswer;                         // 현재 문제의 정답을 가져옵니다.

 

 if(userAnswer == currentAnswer) {

        console.log("O");

       dogWrap.classList.add("like");

} else {

        console.log("X");

        dogWrap.classList.add("dislike");

}

    quizAnswer.style.display = "block";

    quizDesc.style.display = "block";

 

: answer 매개변수는 사용자가 선택한 답변을 나타내는 HTML 요소이다.

answer.textContent를 사용하여 사용자가 선택한 답변의 내용을 가져와 userAnswer 변수에 저장한다.

 

그리고 quizInfo[quizCount].infoAnswer를 사용하여 현재 문제의 정답을 가져와  currentAnswer 변수에 저장한다.

 

그 다음 if문을 사용하여 unswerAnswe와 currentAnswer를 비교한다.

만약 두 값이 같다면 "O"를 콘솔에 출력하고 강아지 이미지에 "like"  클래스를 추가한다.

두 값이 다르다면 "X"를 콘솔에 출력하고 강아지 이미지에 "dislike" 클래스를 추가한다.

 

quizAnswer와 quizDesc 요소의 display 요소의 속성을 block으로 변경하여 정답과 해설을 보여준다.

 

 

 

 

 

 

728x90
반응형

728x90
반응형

 

 

 

{
    let num = 0;
    while( num <= 5 ){
        num++;
        console.log(num);  
    }
}

 1 2 3 4 5 6

 


num 변수가 0으로 초기화되고, num이 5 이하일 동안 while문이  실행된다.

조건이 맞으므로, num을 1 증가시키고 console.log 함수를 통해 출력 시킨다.

console.log  함수는 num이 1 증가된 후 출력 되기 때문에 5까지 출력 되지 않고 6까지 출력된다.

 

 

 

 

 

function func(){
        let i = 5, j = 4, k = 1, l, m;
        l = i > 5 || j != 0;
        m = j <= 4 && k < 1;
        document.write(l);
        document.write(m);
    }
    func();

 

true     false

 


 

이 문제는 논리 연산자를 사용하는 문제이다.

함수 func( ) 안에서 변수 i, j, k, l, m을 선언하고 이들 변수에 값을 초기화 한다.

논리 연산자 || (OR)과 &&(AND)를 사용하여 l과 변수에 값을 할당하고, 두 개의 논리식을 평가한다.

 

i=5, j=4, k=1을 각각 할당한다.

l과 m 변수는 초기화 되지 않았고, 나중에 논리 연산의 결과로 값을 할당받게 된다.

 

|| 논리 연산자는 두 개의 연산자 중에 하나라도 참이면 결과값이 참이 되는 연산자이다.

첫 번째 논리식(l = i > 5 || j != 0;) 에서는 변수 i가 5보다 크거나 (j의 값은 무시) j가 0이 아니어야 한다는 뜻이다.

i의 값이 5보다 크다는 것은 거짓이기 때문에 j !=0 (j는 0이 아니다.)만 판단하면 된다.

j는 0이 아니므로 이 논리식의 값은 true가 된다.

따라서 l 변수에는 참(true)가 할당된다.

 

 

&& 논리 연산자는 두 개의 연산자가 모두 참일 때 결과값이 참이 된다.

두 번째 논리식(m = j <= 4 && k < 1;)에서는 변수 j가 4보다 작거나 같지 않으며 변수 k의 값이 1보다 작아야 한다는 의미이다.

j <=4 j는 4보다 작거나 같다는 식이 참이므로,  k<1도 판단해야 한다.

그러나 k는 1이므로 k<1은 거짓이 된다.

 따라서 m 변수의 값은 거짓( false)가 할당된다.

 

 

 

 

{
    function func(){
        let i = 10, j = 10, k = 30;
        i /= j;
        j -= i;
        k %= j;

        console.log(i);
        console.log(j);
        console.log(k);
    }
    func();
}

 

A :

1    9     3

 


 

 

i /= j  는 i = i / j와 동일한 의미이다.

i의 현재 값은 10이고, j의 현재 값도 10이므로 10/10은 1이다.

따라서 i의 값은 1이 된다.

 

j -= i 는 j = j - i와 동일한 효과를 가지는 복합 대입 연산자이다.

j의 현재 값은 10, i(10에서 1로 값이 바뀜)의 값은 1이므로,

j(10) - i (1) = 9.

j의 값은 9가된다.

 

k %= j 는  k = k % j와 동일한 효과를 가지는 복합 대입 연산자이다.

%연산자는 나머지 연산자로 k(30)를 j(9)로 나눈 나머지를 k에 할당한다.

k의 현재 값은 30, j의 현재 값은 9이므로 k의 값은 3이 된다.

 

 

 

 

{
    let num1 = 3;
    let num2 = 7;
    if(++num1 < 5 || ++num2 > 8){
        console.log(num1);
    }
    console.log(num2)
}

 

4   7

 

 

먼저 num1 변수에 3을 할당하고, num2 변수에 7을 할당한다.
그 다음으로, if 문이 실행된다.

if 문의 조건식은 ++num1 < 5 || ++num2 > 8 이다.

++num1은 num1의 값을 1 증가시키고, 그 증가된 값을 반환한다.

따라서 ++num1의 결과값은 4가 된다.

||는 논리 OR 연산자로, 왼쪽 피연산자가 true이면 전체 조건식이 true가 된다.

따라서 ++num1 < 5가 false이지만, ++num2 > 8은 true가 되므로, 전체 조건식은 true가 된다.
따라서 console.log(num1)이 실행되어 num1 변수의 값인 4가 출력됩니다.

그 다음으로, console.log(num2)가 실행되어 num2 변수의 값인 7이 출력된다.

이는 ++num2가 실행되지 않았기 때문이다.

++num2는 true인 경우에만 실행되기 때문이다.

 

 

 

{
    let num = [1, 5, 1, 2, 7, 5];
    for(let i=0; i<6; i++){
        if((i+1) % 2 == 0){
            console.log(num[i]);
        }
    }
}

 

 

5    2   5

 

배열 num에 1, 5, 1, 2, 7, 5 값을 저장하고, 반복문을 사용하여 num의 짝수 인덱스에 해당하는 값을 출력하는 문제이다.

 

먼저, num 변수에 1, 5, 1, 2, 7, 5 배열을 할당한다.
그 다음으로, for 문이 실행된다.

for 문의 초기식에서는 i 변수에 0을 할당한다. 

for 문의 조건식에서는 i 변수가 6보다 작은 동안 식을  반복한다.

 for 문의 증감식에서는 i 변수를 1씩 증가시킨다.

반복문 내부에서는, (i+1) % 2 == 0 조건식이 실행된다.

(i+1) % 2는 i에 1을 더한 값이 2로 나누어 떨어지는지 여부를 판별하는 것이다.

이 조건식이 true인 경우에는 num[i] 값을 출력합니다.

(즉, 인덱스가 짝수인 요소들이 출력되는 것이다.)

 

반복문에서는 i 변수가 0부터 5까지 1씩 증가하면서, (i+2)%2==0 조건식이 참이 되는 경우에 num의 i번째 값을 출력한다.

num 배열에서 2,4,6번째 요소가 각각 5,2,5이므로 이 값들이 순서대로 출력된다.

 

 

 

function func(num1, num2){
        if(num1 > num2) return num1
        else return num2
    }
    console.log(func(10, 23) + func(40, 50))

 

73

 

이 문제는 두 개의 숫자 중에서 더 큰 값을 반환하여 서로 더하는 문제이다.

 

func 함수는 두 개의 숫자를 인자로 받는다.

만약 첫 번째 인자 num1이 두 번째 인자 num2 보다 크다면 num1을 반환하고, 그렇지 않으면 num2를 반환한다.

console.log 함수에서는 func(10, 23)과 func(40, 50) 두 번의 함수 호출 결과값을 더한다.

첫 번째 func 함수 호출에서는 num1에 10을, num2에 23을 인자로 전달한다.

num1이(10) num2(23)보다 작기 때문에 else 블록이 실행되어 num2인 23을 반환한다.

 

두 번째 func 함수 호출에서는 num1에 40을, num2에 50을 인자로 전달한다.

num1(40)이 num2(50)보다 작기 때문에 else 블록이 실행되어 num2인 50을 반환한다.

 

따라서 func(10,23) + func(40,50)은 23+50 즉, 73이 된다.

728x90
반응형

 

 

 

 

 

완성 화면

 

 

 

 

 

코드 보기 / CSS

.quiz__choice{
    padding: 20px;
    border-bottom: 6px ridge #a12cd3;
    font-family: 'ElandChoice';
}
.quiz__choice label {
    display: flex;
}
.quiz__choice label input {
    position: absolute;
    clip: rect(0 0 0 0);
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
}
.quiz__choice label span {
    font-size: 20px;
    line-height: 1.5;
    padding: 6px;
    display: flex;
    cursor: pointer;
    margin: 2px 0;
}
.quiz__choice label span::before {
    content: '';
    width: 26px;
    height: 26px;
    border-radius: 50%;
    margin-right: 15px;
    background-color: #fff;
    box-shadow: inset 0 0 0 4px #63068a;
    transition: all 0.2s;
    flex-shrink: 0;
}
.quiz__choice label input:checked + span {
    background-color: #f6ecfa;
}
.quiz__choice label input:checked + span::before {
    box-shadow: inset 0 0 0 8px #63068a;
}
.quiz__check {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 110px;
    height: 110px;
    line-height: 110px;
    border-radius: 50%;
    z-index: 1000;
    background-color: #9d07f4;
    text-align: center;
    font-family: 'ElandChoice';
    color: #fff;
    cursor: pointer;
}
.quiz__info {
    position: fixed;
    width: 130px;
    height: 50px;
    border-radius: 10px;
    line-height: 50px;
    right: 20px;
    bottom: 170px;
    background-color: #9d07f4;
    text-align: center;
    font-family: 'ElandChoice';
    color: #fff;
}
.quiz__info::after {
    content: '';
    position: absolute; 
    left: 50%;
    bottom: -10px;
    border-top: 10px solid #9d07f4;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
}

 

 


 

quiz__ choice 

해당 클래스를 갖는 div 요소에 스타일을 적용한다.

이 div는 객관식 퀴즈에서 각 선택지를 감싸는 컨테이너로 사용된다.

 

padding: 20px

: 컨테이너의 안쪽 여백을 20px만큼 설정한다.

 

border-bottom: 6px ridge #a12 cd3

: 컨테이너의 아래쪽  경계선을 지정한다.

ridge는 경계선이 일반 실선이 아니라 옆에서 봤을 때 △ 모양으로 가운데가 튀어나온 스타일이다.

#a12cd3은 경계선의 색상(보라색)이다.

 

 


 

 

quiz__choice lable

:각 선택지의 라벨을 감싸는 label 요소.

 

display: flex

: 라벨 내부의 요소들을 수평으로 정렬한다.

 

 


 

 

quiz__choice label input

: 라벨 요소 내부에 위치한 라디오 버튼 (input 요소)에 스타일을 적용한다.

 

position: absolute

: 라디오 버튼을 페이지의 다른 요소와 겹치지 않도록 한다.

 

clip: rest(0 0 0 0)

: 라디오 버튼의 크기를 0으로 설정하여, 화면에 보이지 않게 한다.

 

 

width, height, margin, overflow

: 라디오 버튼과 라벨 텍스트를 정렬하기 위한 것이다.

 

 


 

 

quiz__choice label span 

: 라디오 버튼에 대응하는 라벨 텍스트(span 요소)에 스타일을 적용한다.

 

font-size: 20px

:텍스트의 크기를 설정한다.

 

line-height: 1.5

:텍스트의 높이를 설정한다.

 

padding: 6px

:텍스트 내부 여백을  6px만큼 설정한다.

 

display: flex

:라벨 내부의 요소들을 수평으로 정렬한다.

 

cursor: pointer

:마우스 커서가 텍스트 위에 올라가면 포인터 모양으로 변경한다.

 

 


 

 

quiz__choice label span::before

: 선택지의 선택 항목에서 선택되지 않은 원형 요소를 생성한다.

 

content: ' ';

:내용을 없앤다.

 

width, height, border-radius 

:가로 세로가 26px인 원형 모양을 만든다.

 

magin-right,

background-color,

box-shadow

:  내부 여백을 주고, 배경색을 설정하고 박스에 그림자 속성을 준다.

 

flex-shrink

:flex box 컨테이너 내에서 해당 요소가 줄어들지 않도록 한다.

 

 


 

 

quiz__choice label input:cheked + span

: 선택지의 선택 항목이 선택되었을 때의 스타일 지정한다.

 

input:cheked 

:선택된 항목의 span 요소 스타일을 변경한다.

 

background-color

: 선택되었을 때의 배경색을 변경.

 

 


 

 

quiz__choice lable input:checked + span::before

: 선택된 input 요소에 인접한 span 요소의 전/ 배경 색상이 변경되도록 한다.

 

box-shadow: inset 0 0 0 8px #63068a;

:그림자 효과를 만든다. 

inset은 그림자가 내부에 위치하도록 한다.

즉, span 요소의 내부에 테두리를 그린다.

그림자의 크기는 0 0 이며, 테두리의 두께는 8px이다.

그림자의 색상은 #63068a이다.

 

 

 

 

 


 

코드 보기 / JAVASCRIPT

//문제 정보
        const quizInfo = [
        {
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100101",
                infoQuestion: "스택 연산에서 데이터를 삽입하거나 삭제하는 동작을 나타내는 연산으로 바르게 나타낸 것은?",
                infoChoice: {
                    1:"ADD, SUB",
                    2:"LOAD, STORE",
                    3:"PUSH, POP",
                    4:"MOV, MUL"
                },
                infoAnswer:"3",
                infoDesc: "push( ) 메서드는 배열 마지막 요소를 추가하는 스택 연산을 하고, pop( ) 메서드는 배열 마지막 요소를 삭제하는 스택 연산을 합니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100102",
                infoQuestion: "MIMD(Multiple Instruction Multiple Data)구조를 갖는 것은?",
                infoChoice: {
                    1: "다중 처리기",
                    2: "배열 처리기",
                    3: "벡터 처리기",
                    4: "파이프라인 처리기"
                },
                infoAnswer:"1",
                infoDesc: "MIMD(Multiple Instruction Multiple Data) : <br>멀티 명령어 멀티 데이터란 뜻으로 다중 명령, 다중 데이터라고 해석할수 있습니다. 즉, 다중 처리기에 관한 내용이 됩니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100103",
                infoQuestion: "논리적 주소에서 물리적 주소 또는 다른 논리적 주소로 번역하는 것은?",
                infoChoice:{
                    1:"매핑",
                    2:"적재",
                    3:"재배치",
                    4:"주소 바인딩"
                },
                infoAnswer:"4",
                infoDesc: "물리적 주소 또는 논리적 주소로 번역하는 것을 주소 바인딩이라고 합니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100104",
                infoQuestion: "컴퓨터의 중앙처리장치(CPU)의 구성 부분에 해당되지 않는 것은?",
                infoChoice:{
                    1:"주기억 장치",
                    2:"연산 장치",
                    3:"보조기억 장치",
                    4:"제어장치"
                },
                infoAnswer:"3",
                infoDesc: "CPU의 주 기능은 연산과 제어입니다. 그러나 여기에 추가적으로 기억 기능이 포함될 수는 있습니다. <br> 보조기억장치의 대표적인 예로는 HDD와 SSD가 있습니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100105",
                infoQuestion: "명령어의 주소(Address)부를 연산주소(Address)로 이용하는 주소지정방식은?",
                infoChoice:{
                    1:"상대 Address 방식",
                    2:"절대 Address 방식",
                    3:"간접 Address 방식",
                    4:"직접 Address 방식"
                },
                infoAnswer:"4",
                infoDesc: "절대주소는 실제주소(유효주소)이며 0,1,2,3... 순서로 차례대로 지정되는 주소방식입니다. <br>절대주소는 1byte 마다 연속된 16진수 번호를 부여하며 기계어의 정보가 기억되어 있습니다.<br> 상대주소는 기준주소를 기준으로 상대적으로 얼만큼 떨어져있는지 표시하는 주소입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2010년 1회 (1월 31일)",
                infoNumber : "20100106",
                infoQuestion: "인터럽트 발생 시 인터럽트를 처리하고 원래 수행하고 있었던 프로그램으로 되돌아가는데 사용되는 레지스터는?",
                infoChoice:{
                    1:"Stack",
                    2:"PC",
                    3:"MBR",
                    4:"PSW"
                },
                infoAnswer:"1",
                infoDesc: "인터럽트 발생시 현재 수행하고 있던 프로그램 주소를 스택(Stack)에 기억시킨뒤 인터럽트 처리후 스택의 주소를 참조하여 원래 수행하던 프로그램으로 되돌아 갑니다."
            }
        ]
        
         //선택자
        const quizWrap = document.querySelector(".quiz__wrap");
        const dogWrapTrue = quizWrap.querySelectorAll(".true");
        const dogWrapFalse = quizWrap.querySelectorAll(".false");
        let quizScore = 0;

        //출력
        const updateQuiz = () => {
            const exam = [];

            quizInfo.forEach((question, number) => {
                exam.push(`
                <div class="quiz">
                    <div class="quiz__header">
                        <h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>
                    </div>
                    <div class="quiz__main">
                        <div class="quiz__question"><em>${number+1}</em>. ${question.infoQuestion}</div>
                        <div class="quiz__view">
                            <div class="dog__wrap">
                                <div class="true">정답</div>
                                <div class="false">오답</div>
                                <div class="card-container">
                                    <div class="dog">
                                        <div class="head">
                                            <div class="ears"></div>
                                            <div class="face"></div>
                                            <div class="eyes">
                                                <div class="teardrop"></div>
                                            </div>
                                            <div class="nose"></div>
                                            <div class="mouth">
                                                <div class="tongue"></div>
                                            </div>
                                            <div class="chin"></div>
                                        </div>
                                        <div class="body">
                                            <div class="tail"></div>
                                            <div class="legs"></div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="quiz__choice">
                            <label for="choice1${number}">
                                <input type="radio" id="choice1${number}" name="choice${number}" value="1">
                                <span>${question.infoChoice[1]}</span>
                            </label>
                            <label for="choice2${number}">
                                <input type="radio" id="choice2${number}" name="choice${number}" value="2">
                                <span>${question.infoChoice[2]}</span>
                            </label> 
                            <label for="choice3${number}">
                                <input type="radio" id="choice3${number}" name="choice${number}" value="3">
                                <span>${question.infoChoice[3]}</span>
                            </label> 
                            <label for="choice4${number}">
                                <input type="radio" id="choice4${number}" name="choice${number}" value="4">
                                <span>${question.infoChoice[4]}</span>
                            </label> 
                        </div>
                        <div class="quiz__desc">정답 : <em>${question.infoAnswer}</em>번<br>${question.infoDesc}</div>
                    </div>
                </div>
                `);
            });

            exam.push(`
            <div class="quiz__info">??점</div>
            <div class="quiz__check">정답 확인하기</div>
            `);
            quizWrap.innerHTML = exam.join(' ');

            //설명 숨기기
            document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "none");
        }
        updateQuiz();

        //정답 확인
        const answerQuiz = () => {
        const quizChoices = document.querySelectorAll(".quiz__choice");

            //사용자가 체크한 답과 문제의 정답이 일치하는지 확인
            quizInfo.forEach((question, number) => {
                const userSelector = `input[name=choice${number}]:checked`;
                const quizSelectorWrap = quizChoices[number];
                const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;
                const dogWrap = quizWrap.querySelectorAll(".dog__wrap");
                
                if(userAnswer == question.infoAnswer) {
                    dogWrap[number].classList.add("like");
                    quizScore++;
                } else {
                    dogWrap[number].classList.add("dislike");
                }
            });
            //해설보이기
            document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "block");
            
            //점수 보이기
            document.querySelector(".quiz__info").innerHTML = Math.round((quizScore / quizInfo.length) * 100) + "점";
        }

        //정답 클릭
        document.querySelector(".quiz__check").addEventListener("click", answerQuiz);

 

 

const exam = [ ];

: 빈 배열을 선언한다.

 

quizinfo.forEach((question, number)) => { .... });

: quizinfo 배열의 각 요소를 반복하여 HTML 문자열을 만든다.

forEach( )메서드를 사용하여 quizinfo 배열의 각 요소를 반복한다.

 

여기서 콜백 함수가 사용된다.

콜백함수의 첫 번째 매개변수인 question은 quizifo 배열의 현재 요소를 나타내며, number은 quizinfo 배열에서 현재 요소의 인덱스를 나타낸다.

 

 

 

exam.push( .... )

: HTML 문자열을 생성하고 exam 배열에 추가한다.

이 HTML 문자열은 quizWrap 요소에 추가된다.

 

` ` (백틱)을 사용하여 템플릿 리터럴을 만들고 HTML 문자열의 내용은 question 객체의 속성들을 이용하여 생성된다

예를 들어` ${question.infoType}` , ` ${question.intoTime}`은  question 객체의 infoType과infoTime  속성을 사용하여 문제의 유형과 시간 정보를 생성한다.

 

 

exam.push(`

<div class="quiz__info">??점</div>

<div class="quiz__check">정답 확인하기</div>

`);

 

:exam 배열에 최종 점수를 나타내는 요소와 정답 확인 버튼을 추가한다.

quiz__info와 quiz__check 클래스를 가진 요소를 추가한다.

 

 

 

quizWrap.innerHTML = exam.join(' ');

: exam 배열을 문자열로 변환하고, quizWrap 요소의 innerHTML에 할당하여 화면에 출력한다.

 

 

 

document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "none");

:quiz__desc 클래스를 가진 모든 요소에 대해 반복문을 실행하면서 style.display 속성을 none으로 주어 해당 요소를 숨긴다.

 

 

 

updateQuiz( );

: 함수는 quizInfo 배열을 참조하영 문제와 선택지를 생성하고, 마지막으로 정답 확인 버튼을 생성한다.

이 때, 정답 확인 버튼을 클릭하기 전까지는 정답에 대한 설명을 숨기기 위해 quiz__desc 클래스를 가진 요소를 숨기는 역할을 수행합니다.

 

 

 

document.querySelectorAll(".quiz__choic")

: 함수 내부의 HTML 문서에서 quiz__choice 클래스를 가진 모든 요소를 찾는다.

이는 사용자가 선택 가능한 모든 답안을 선택하는 것이다.

 

 

 

quizInfo.forEach((question, number) => { .... }

:  quizInfo 배열을 문제에 대한 정보를 포함하고 있으며, 각 항목은 문제와 답안의 정보를 저장한다.

이 배열을 사용하여 사용자가 선택한 답과 무제의 정답을 비교하고 점수를 계산한다.

quizInfo 배열을 순회하면서 현재 문제의 정보와 문제 번호를 가져온다.

 

 

const userSelector = `input[name=choice${number}]:checked`;

: 사용자가 선택한 답안 요소의 선택된 값을 가져온다. 

선택된 라디오 버튼의 값이 아닌 라디오 버튼 요소 자체의 값을 가져온다.

 

 

 

const quizSelectorWrap = quizChoices[number];

: quizSelectorWrap 변수는 현재 문제 번호에 해당하는 답안 요소를 가져온다. 이 변수는 quizChoic[number]

를 사용하여 quiz__choice 클래스를 가진 요소 중 numder 번째 요소를 선택한다.

 

 

 

const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;

: userAnswer 변수를 사용하여 사용자가 선택한 답안의 값을 가져온다. 

이때, quizSelectorWrap.querySelector(userSelector)를 사용하여 현재 문제 번호에 해당하는 답안 요소에서 선택된 라디오 버튼의 값을 가져온다.

만약 선택된 라디오 버튼이 없는 경우 { }를 사용하여 undefinde를 방지하고 value를 사용하여 해당 값을 가져온다.

 

 

 

const dogWrap = quizWrap.querySelectorAll(".dog__wrap");

:  dogWrap 변수를 사용하여 quizWrap.querySelectorAll(".dog__wrap") 을 사용하여 dog__wrap 클래스를 가진 모든 요소를 가져온다. 이 배열은 문제의 각 항목에 대한 강아지 이미지 요소를 저장한다.

 

 

 

if(userAnswer==question.infoAnswer) {.....}

: 사용자가 선택한 답안과 문제의 정답을 비교하고, 일치하는 경우 dogWrap[number].classList.add(
"like")를 사용하여 해당 문제의 강아지 이미지 요소에 like 클래스를 추가한다.

이를 통해 사용자가 정답을 맞춘 문제에 대한 피드백(웃는 모습의 강아지)을 제공한다.

 

반면, 사용자가 선택한 답안이 정답과 일치하지 않는 경우

dogWrap[number].classList.add("dislike"):해당 문제의 강아지 이미지 요소에 dislike 클래스를 추가한다.

 

 

 

document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "block");

:HTML 문서에서 quiz__desc 클래스를 가진 모든 요소를 찾아서, el.style.display="block"을 사용하여 해당 요소를 보이게 설정한다.

이는 사용자가 문제를 푼 후에 해설을 보여주는 역할을 한다.

quiz__desc 클래스를 가진 요소는 문제와 관련된 해설을 담고 있다.이를 통해 사용자는 문제에 대한 해설을 읽을 수 있다.

 

 

 

document.querySelector(".quiz__info").innerHTML = Math.round((quizScore / quizInfo.length) * 100) + "점"; }

: quiz__info 클래스를 가진 요소를 찾아서 해당 요소의 내용을 계산된 점수로 변경한다.

Math.round ( ....)는 사용자의 정답 수를 전체 문제수로 나눈 비율에 100을 곱하여 백분율 점수로 변환한다.

이때, Math.round( ) 함수는 소수점 이하를 반올림한다.

 

 

 

 

document.querySelector(".quiz__check").addEventListener("click", answerQuiz);

: quiz__check 클래스를 가진 요소를 찾아서 클릭 이벤트가 발생할 때 answerQuiz 함수를 실행한다.

 

즉, 사용자가 정답 확인 버튼인 quiz__check를 클릭하면 answerQuiz 함수가 실행되어 사용자의 답을 채점하고, 점수를 계산한 후 결과를 HTML 문서에 표시한다.

사용자는 자신의 시험 결과를 확인할 수 있다.

 

 

 

 

 

 

 

 

728x90
반응형

 

 

 

완성 화면

 

728x90
반응형

 

1. 결과값을 작성하시오.

    const str = "javascript";

    const text = str.indexOf("a");
    const text2 = str.lastIndexOf("a");
    const text3 = str.includes("a");

    console.log(text);
    console.log(text2);
    console.log(text3);

A

:  1    3   true

 

 

 

indexOf("a") 메서드는 문자열에서 a 문자의 첫 번째 인덱스를 반환한다.

lastindexOf("a") 메서드는 문자열에서 a 문자의 마지막 인덱스를 반환한다.

includes("a") 메서드는 문자열에 a 문자가 포함되어 있는지의 여부를 블린(true, false)으로 반환한다.

 

 

 

 

 

 

2. 다음의 결과값을 보고 빈 칸을 채우시오.

    function func(){
            document.write("함수2가 실행되었습니다.");
        }
        function callback(str){
            document.write("함수1가 실행되었습니다.");
            _______();
        }
        callback(func);

        //함수1가 실행되었습니다.
        //함수2가 실행되었습니다.

: str

 

빈 칸은 콜백 함수를 실행하는 부분이다.

따라서 callback 함수의 인자로 전달된 func 함수를 실행하기 위해 str이 들어가야 한다.

 

 

 

 

 

3. 결과값을 작성하시오.

 function func(a, b){
        console.log(arguments[0]);
        console.log(arguments[1]);
    }
    func("1", "2");

A

:1   2

 

 

함수 내부에서 arguments 객체를 사용하여 함수의 인자를 참조한다.

argument 객체는 0부터 인덱싱(자리값 배치)가 시작되기 때문에 arguments[0]은 첫 번째 인자인 1을, arguments[1]은 두 번째 인자인 2를 출력한다.

 

 

 

 

 

4. 결과값을 작성하시오.

{
    function func(num, name, word){
        this.num = num;
        this.name = name;
        this.word = word;
    }
    
    func.prototype = {
        result1 : function(){
            console.log(this.num + ". " + this.name + "가 "+ this.word + "되었습니다.");
        },
        result2 : function(){
            console.log(this.num + ". " + this.name + "가 "+ this.word + "되었습니다.");
        },
        result3 : function(){
            console.log(this.num + ". " + this.name + "가 "+ this.word + "되었습니다.");
        }
    }
    
    const info1 = new func("1", "함수", "실행");
    const info2 = new func("2", "자바스크립트", "실행");
    const info3 = new func("3", "제이쿼리", "실행");
    
    info1.result1();
    info2.result2();
}

 

A :

1. 함수가 실행되었습니다.

2. 자바스크립트가 실행되었습니다.

 

 

func 함수는 num, name, word까지 세 개의 인자를 받아서 이를 this 객체의 프로퍼티로 할당한다.

이렇게 생성된 func 객체는 result1, result2, result3 메서드를 갖는 프로토타입 객체로부터 상속 받는다.

 

const 키워드를 사용하여 info1, info2, info3 변수에 새로운 객체를 생성한다.

각각의 객체는 func 생성자 함수를 통해 생성되며, 생성자 함수에서 정의한 세 개의 프로퍼티를 가지게 된다

 

info.result1(), info.result2()를 호출하여 객체의 result1, result2 메서드를 실행한다.

 

 

 

 

 

5. 결과값을 작성하시오.

{
    function func(num, name, word){
        this.num = num;
        this.name = name;
        this.word = word;
    }

    func.prototype.result = function(){
        console.log(this.num + ". " + this.name + "가 "+ this.word + "되었습니다.");
    }

    const info1 = new func("1", "함수", "실행");
    const info2 = new func("2", "자바스크립트", "실행");
    const info3 = new func("3", "제이쿼리", "실행");

    info1.result();
}

 

A :

1. 함수가 실행되었습니다.

 

 

func 함수는 세 개의 인자 num, name, word를 받아서 객체의 프로퍼티로 할당한다.

그리고 func.prototype.result 메서드를 정의한다.

result 메서드는 객체의 프로퍼티를 참조하여 문자열을 출력하는 역할을 한다.

 

const 키워드를 사용하여 info1, info2, info3 변수에 새로운 객체를 생성한다.

각각의 객체는 func 생성자 함수를 통해 생성되며, 생성자 함수에서 정의한 세 개의 프로퍼티를 가지게 된다.

info,result( )를 호출하여 객체의 result 메서드를 실행한다.

 

 

 

 

 

6. 결과값을 작성하시오.

{
    function func(index){
        console.log("함수가 실행되었습니다." + index);
    }
    function callback(num){
        for( let i=1; i<=1; i++){
            num(i);
        }
    }
    callback(func);
}

 

A :

함수가 실행되었습니다. 1

 

 

func 함수는 하나의 인자 index를 받아서 "함수가 실행되었습니다."와 함께 인덱스를 출력한다.

callback 함수는 하나의 인자  num을 받아서 for 반복문을 통해 1부터 1까지만 반복하면서 num 함수를 호출한다.

여기서 num 함수는 func 함수를 참조하고 있다.

callback (func)를 호출하여 func 함수를 콜백으로 전달한다.

 

callback 함수에서 num(i)를 호출하면서 func(i) 함수를 실행하게 된다.

i가 1인 경우 func(1)이 호출되어 "함수가 실행되었습니다.1"을 출력하게 된다.

for 반복문에서 i의 범위가 1부터 1까지이기 때문에 func 함수는 한 번만 호출되고, 결과도 한 번만 출력된다.

 

 

 

 

 

 

7. 결괏값을 작성하시오. 

{
    let num = 1;

    do {
        num++;
        console.log("실행되었습니다.");
    } while (num <= 5);

}

 

A :

실행되었습니다. 

 

 

num이 1부터 시작해서 1씩 증가하면서 "실행되었습니다."를 출력하고, num이 5봐 작거나 같을 때까지 반복하는 do-while문이다.

 

반복문의 조건식이 do문 블록 안에서 작성되어 있기 때문에, 먼저 do문 블록 안의 코드가 한 번 실행되고 나서 num이 6이 되어 조건식이 false가 될 때까지 반복이 진행된다.

 

즉, num이 5일 때까지 "실행되었습니다."가 출력되고 num이 6이 되면 조건식이 fasle가 되어 반복이 종료된다.

 

 

 

 

 

 

8. 결괏값을 작성하시오.

{
    const arr = [100, 200, 300, 400, 500];

    const text1 = arr.join("*");
    const text2 = arr.join("-");
    const text3 = arr.join("");
    const text4 = arr.join(" ");

    console.log(text1);
    console.log(text2);
    console.log(text3);
    console.log(text4);

}

 

 

A :

100*200*300*400*500

100-200-300-400-500

100200300400500

100 200 300 400 500

 

 

join 메서드는 배열의 요소를 하나의 문자열로 합쳐주는 메서드이다.

이 메서드는 하나의 문자열 인자를 받는데, 이 인자는 배열 요소들 사이에 끼워넣을 구분자 역할을 한다.

인자를 생략하면 기본값으로 ","가 사용된다.

 

따라서 text1에는 *로 구분된 문자열이, text2에는 -로 구분된 문자열이, text3에서는 구분자 없이 배열 요소들만 합쳐진 문자열이, text4에는 공백으로 구분된 문자열이 출력된다.

 

 

 

 

 

9. 다음을 최대한 짧게 약식으로 표현하시오.

{
    function func(str){
        return str;
    }
    func("함수가 실행되었습니다.")
}

 

A :

func = str => str;

 

 

입력받은 문자열을 그대로 반환하는 함수를 변수 func에 할당하는 문제이다.

str이라는 매개변수를 가지고, 해당 매개변수를 그대로 반환하는 함수가 변수 func에 할당되는 것이다.

문자열을 인자로 전달하여, 그대로 반환하는 함수를 호출한 후 반환된 결과를 출력한다.

 

 

 

 

 

 

10. 다음의 결과값을 작성하시오.

{
    function func(){
        let i = 10, j = 10, k = 30;
        i /= j;
        j -= i;
        k %= j;

        console.log(i);
        console.log(j);
        console.log(k);
    }
    func();
}

 

A :

1    9     3

 

i /= j  

:i를 j로 나눈 후, 그 결과를 i에 할당한다. 따라서 i =1.

 

j -= i 

:j(10)에서 i(10에서 1로 값이 바뀜)를 뺀 후 그 결과를 j에 할당한다. 따라서 j=9.

 

k %= j 

:k(30)를 j(9)로 나눈 나머지를 k에 할당한다. 따라서 k=3.

 

 

 

 

 

 

11. 다음의 결과값을 작성하시오.

{
    let k = 0;
    let temp;
    for(let i=0; i<=3; i++){
        temp = k;
        k++;
        console.log(temp + "번");
    }
}

 

A :

0번 1번 2번 3번

 

 

변수 k를 0으로 초기화하고 반목문을 사용하여 0부터 3까지의 숫자를 출력한다.

반복문에서는 먼저 temp 변수에 k의 값을 할당한 후, k의 값을 1 증가 시킨다.

그리고 temp 변수에 할당된 값을 출력한다.

 

이후, i 변수가 1 증가하면서 반복문이 다시 실행된다.

이 과정은 i가 3일 때까지 반복된다.

 

 

 

 

 

12. 다음의 결과값을 작성하시오.

{
    let num1 = 3;
    let num2 = 7;
    if(++num1 < 5 || ++num2 > 8){
        console.log(num1);
    }
    console.log(num2)
}

 

A :

4   7

 

 

변수 num1을 3으로, 변수 num2를 7로 초기화 한 후, 조건문을 사용하여  num1이 5 미만이거나 num2가 8을 초과하는 경우에만 num1을 출력하는 문제이다.

 

조건문에서는 ++ 연산자를 사용하여 num1의 값을 증가 시키고, 그 결과를 비교한다.

만약 num1이 5 미만이라면 논리 연산자 ||의 뒷부분은 평가되지 않기 때문에 ++num2 > 8 연산은 수행되지 않는다.

 

 num1의 값이 1 증가하여 4가 되고, 이 값이 조건문에서 평가 된다.

이 값은 5 미만이므로, 조건문이 참이 된다. 따라서 num1은 4가 된다.

 

조건문 이후에는 num2의 값이 그대로 출력된다.

이는 조건문에서 ++num2 > 8 연산이 수행되지 않았기 때문이다.

 

 

 

 

 

 

13. 다음의 결과값을 작성하시오. 

{
    let num = [1, 5, 1, 2, 7, 5];
    for(let i=0; i<6; i++){
        if((i+1) % 2 == 0){
            console.log(num[i]);
        }
    }
}

A :

5    2   5

 

배열 num에 1, 5, 1, 2, 7, 5 값을 저장하고, 반복문을 사용하여 num의 짝수 인덱스에 해당하는 값을 출력하는 문제이다.

반복문에서는 i 변수가 0부터 5까지 1씩 증가하면서, (i+2)%2==0 조건식이 참이 되는 경우에 num의 i번째 값을 출력한다.

num 배열에서 2,4,6번째 요소가 각각 1,2,5이므로 이 값들이 순서대로 출력된다.

이는 반복문에서 i 변수의 값이 0일 때는 1번째 요소를, i변수의 값이 1일 때는 2번째 요소를 출력하는 방식으로 짝수번째 요소를 출력한다.

 

 

 

 

 

14. 다음의 결과값을 작성하시오. 

{
    let num = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    for(let i=9; i>=0; i--){
        switch(num[i] % 2){
            case 1:
                console.log(num[i]);
                break;
            default:
                console.log("*");
        }
    }
}

 

A :

9*7*5*3*1

 

for문에서는 i 변수가 9부터 시작하여 0까지 1씩 감소하며 반복한다

switch문에서는 현재 인덱스(i)에 해당하는 배열 num의 요소를 2로 나눈 나머지를 구한다.

만약 나머지가 1이라면(즉, 홀수 값이라면) console.log(num[i])문이 실행되어 현재 인덱스(i)에 해당하는 배열 num의 배열 요소가 출력된다.

 

반면 나머지가 1이 아닌 경우(즉, 짝수 값이라면) console.log("*")문이 실행되어, *이 출력된다.

 

 

 

 

 

15. 다음의 결과값을 작성하시오.

{
    let cnt = 0;
    let sum = 0;
    for(let i=0; i<=7; i++){
        if(i%2 == 1){
            cnt++;
            sum = sum + i;
        }
    }
    console.log(cnt + ", "+sum);
}

 

A :

4   16

 

 for문에서는 0부터 7까지의 정수를 반복하며, if문에서는 현재 정수(i)가 홀수인지를 확인한다.

만약 현재 정수(i)가 홀수라면 cnt 변수를 1 증가 시키고(cnt++) sum 변수에 현재 정수(i)를 더한다. (sum = sum+i)

 

따라서 홀수의 갯수 4와 1+3+5+7=16이 출력된다.

 

 

 

 

 

16. 다음의 결과값을 작성하시오. 

{
    let data = [70, 80, 75, 60, 90];
    let best = 1;
    let score = 0;

    for(let i=0; i<data.length; i++){
        if(data[i]>80) {
            best++;
        }
        if(score < data[i]) {
            score = data[i];
        }
    }

    console.log(best, score)
}

 

A :

2    90

 

 

for문에서는 배열 data의 모든 요소를 반복하며 if문에서는 현재 요소가 80보다 큰지를 확인한다.

만약 현재 요소가 80보다 크다면 best 변수를 1 증가 시킨다. (best++)

이렇게 함으로써 배열 data 안에서 80보다 큰 수를 구한다.

 

두 번째 if문에서는 현재 요소(data[i])가 score 변수에 저장된 값도다 큰지를 확인한다.

만약 현재 요소 (data[i])가 score 변수에 저장된 값보다 크다면, score 변수에 값을 현재 요소 (data[i])의 값으로 바꾼다. (score=data[i]) 

이렇게 함으로써 배열 data에서 가장 높은 수를 계산한다.

 

best의 초깃값이 1, 한 번 증가 했으므로 best는 2가 되고,

배열에서 가장 높은 수가 score에 저장되기 때문에 90이 된다.

 

 

 

 

 

17. 다음의 결과값을 작성하시오.

{
    let a, b, result;
    a = 7, b = 4
    result = a & b;

    console.log(result)
}

 

A :

4

 

a & b는 a와 b의 비트 AND 연산을 수행한 결과를 반환한다.

이진수로 나타내면 다음과 같다.

 

a: 0111

b: 0100

------------

     0100

 

이진수 0100은 10진수로 변환하면 4가 되므로 결과값은 4가 된다.

 

 

 

 

 

18. 다음의 결과값을 작성하시오.

{
    function solution(a, b, c){
        let answer="YES", max;
        let tot = a + b + c;

        if(a > b) max = a;
        else max = b;
        if(c > max) max = c;
        if(tot-max <= max) answer = "NO"; 
        
        return answer;
    }

    console.log(solution(13, 33, 17));
}

 

A :

NO

 

 

함수 solution에서는 먼저 answer 변수를 YES로 초기화 한다.

그리고 세 수 a, b, c를 모두 더한 값을 tot 변수에 저장한다.

a=13, b=33, c=17이므로 tot = a+b+c = 63이다.

다음으로 세 수 a, b, c 중에서 가장 큰 값을 max 변수에 저장한다.

셋 중 가장 큰 값은 b, 즉 33이므로 tot-max=30이 된다.

마지막으로  if(tot-max <= max)문에서 tot-max 값이 max 값보다 작으므로 anwser 변수가 NO로 변경된다.

따라서 solution(13,33,17)은 NO를 반환한다.

 

 

 

 

 

 19. 다음의 결과값을 작성하시오.   

{
    function solution(a, b, c){
        let answer;
        if(a < b) answer = a;
        else answer = b;
        if(c < answer) answer = c; 
        return answer;
    }
    console.log(solution(2, 5, 1));
}

 

A :     1

 

함수 solution에서는 먼저 answer 변수를 선언한다.

그리고 if문을 사용하여 세 수 a, b, c 중에서 가장 작은 값을 answer 변수에 저장한다.

먼저 a와 b를 비교하여 answer를 비교하여 c가 작으면 c를 answer 변수에 저장한다.

 

따라서, 위의 코드를 실행하면 a=2, b=5, c=1이므로 answer 변수는 먼저 a=2로 초기화 된다.

그리고 c와 answer를 비교하여 c=1이 더 작으므로 answer 변수가 1로 변경된다.

따라서 solution(2, 5, 1)은 1을 반환하고, console.log(solution(2,5,1))문이 실행되어 1이 출력된다.

 

 

 

 

 

 

20. 다음의 결과값을 작성하시오.

{
    function solution(day, arr){
        let answer = 0;
        for(let x of arr){
            if(x % 10 == day) answer++;
        }
        return answer;
    }
    
    arr = [25, 23, 11, 47, 53, 17, 33];
    console.log(solution(3, arr));
}

 

A :

3  (23, 53, 33)

 

배열 arr에서 각 요소의 일의 자리 숫자가 입력된 day와 같은 경우의 수를 세는 함수 solution이다.

 

함수 solution에서는 먼저 answer 변수를 0으로 초기화 한다.

그리고 for of문을 사용하여 배열 arr의 각 요소 x를 가져와서 if문을 사용하여 x의 일의 자리 숫자가 day와 같은 경우 answer 변수를 1씩 증가 시킨다.

 

arr 배열에 있는 숫자들 중에서 일의 자리 숫자가 3인 숫자는 23, 53, 33이므로 solution 함수는 3을 반환한다.

 

 

 

 

 

 

 

728x90
반응형

 

 

완성 화면

 

 

 

 

 

코드 보기 / HTML

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>검색 효과(seacrh Effect)</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/search.css">
</head>
<body class="pink">
    <header id="header">
        <ul>
            <li class="active"><a href="searchEffect01.html">1</a></li>
            <li><a href="#">2</a></li>
            <li><a href="#">3</a></li>
            <li><a href="#">4</a></li>
            <li><a href="#">5</a></li>
            <li><a href="#">6</a></li>
        </ul>
    </header>
    <main id="main">
        <div class="search__wrap">
            <div class="search__header">
                <h2 class="title">JAVASCRIPT</h2>
            </div>
            <div class="search__contents">
                <hgroup>
                    <h3>CSS 속성 검색하기</h3>
                    <h4>indexOf( ) / search( )</h4>
                </hgroup>
                <div class="search__box">
                    <label for="search">검색</label>
                    <input type="text" name="search" id="search" placeholder="CSS 속성을 입력해주세요">
                </div>
                <div class="search__info">
                    <div>
                        CSS 속성 : <span></span>개
                    </div>
                </div>
                <div class="search__list">
                    <ul class="listNumber">
                    	<li data-name="align-content"><strong>align-content</strong> : 콘텐츠 아이템의 상하관계 정렬 상태를 설정.</li>
                        <li data-name="align-items"><strong>align-items</strong> : 콘텐츠 아이템의 내부 상하관계 정렬 상태를 설정.</li>
                        <li data-name="align-self"><strong>align-self</strong> : 개별적인 콘텐츠 아이템의 정렬 상태를 설정.</li>
                        <li data-name="all"><strong>all</strong> : 요소의 속성을 초기화 또는 상속을 설정.</li>
                        <li data-name="animation"><strong>animation</strong> : 애니메이션과 관련된 속성을 일괄적으로 설정.</li>
                        <li data-name="animation-delay"><strong>animation-delay</strong> : 애니메이션 지연 시간을 설정.</li>
                    </ul>
                </div>
            </div>
        </div>
    </main>
    <footer id="footer">
        <a href="mailto:goed0522@gmail.com">goed0522@gmail.com</a>
    </footer>

 

 

 

 

 

코드 보기 / CSS

/* header */
#header {
    padding: 1.5vw 1.5vw 2.5vw 1.5vw;
    text-align: center;
}
#header li {
    list-style: none;
    display: inline-block;
}
#header li a{
    text-decoration: none;
    width: 55px;
    height: 55px;
    line-height: 55px;
    display: inline-block;
    font-size: 24px;
    color: #000;
    border: 2px solid #000;
    border-radius: 10%;
}
#header li:nth-child(3n+1) {
    background-color: #AF6EE3;
}
#header li:nth-child(3n+2){          
    background-color: #FFEF4A;
}
#header li:nth-child(3n+3){    
    background-color: #F76ECE;
}
/* main */
#main {}

/* main > search__wrap */
.search__wrap {
    width: 90%;
    margin: 0 auto;
    background-color: #fff;
    border: 0.3vw solid #000;
    border-top-left-radius: 3vw;
    border-bottom-right-radius: 3vw;
    box-shadow: 1vw 1vw 0px #000;
    transition: box-shadow 0.3s;
    overflow: hidden;
}
.search__wrap:hover {
    box-shadow: 0.5vw 0.5vw 0px #000;
}
.search__header {
    border-bottom: 0.3vw solid #000;
    padding: 0 0 0 3vw;
    background-color: #AF6EE3;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.search__header .title {
    position: relative;
    background: #AF6EE3;
    position: relative;
    z-index: 10;
    padding-right: 35px;
    padding: 0.6vw 8.5vw 0.6vw 5.5vw;
}
.search__header::before {
    content: "";
    width: 90%;
    height: 0.3vw;
    background: #000;
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-10px);
    border-radius: 5px;
}
.search__header::after {
    content: "";
    width: 90%;
    height: 0.3vw;
    background: #000;
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(4px);
    border-radius: 5px;
}
.search__header .btn {
    display: flex;
}
.search__header .btn span{
    display: block;
    width: 3vw;
    height: 3vw;
    line-height: 3vw;
    position: relative;
    z-index: 10;
    border-left: 0.3vw solid #000;
    box-sizing: content-box;
    text-align: center;
    font-size: 2vw;
    cursor: pointer;
}
.search__contents hgroup{
    padding: 3vw 5vw;
    text-align: center;
    border-bottom: 3px solid rgba(0, 0, 0, 0);
}
.search__contents hgroup h3{
    color: #FFEF4A;
    font-size: 8vw;
    text-shadow: 0.6vw 0.6vw 0px #000;
    -webkit-text-stroke: 0.3vw #000;
}
.search__contents hgroup h4 {
    color: #AF6EE3;
    font-size: 7vw;
    text-shadow: 0.6vw 0.6vw 0px #000;
    -webkit-text-stroke: 0.3vw #000;
}
.search__box label {
    padding: 1vw;
    padding: 1vw;
    font-size:2.5vw;
    font-family: 'CookieRun';
}
.search__box input {
    border: 0.4vw solid #000;
    width: 80%;
    box-shadow: 0.4vw 0.4vw 0 s#000;
    padding: 1.5vw 2.5vw;
    border-radius: 50px;
    font-family: 'CookieRun';
    font-size: 2vw;
    outline: none;
}
.search__info {
    text-align: right;
    padding: 0.5vw 2vw;
    border-bottom: 0.3vw dashed #000;
}
.search__list ul {
    padding: 3.5vw;
}
.search__list li {
 list-style: none;
 line-height: 2.5;
}
.search__list li.hide {
    display: none;
}
/* footer */
#footer {
    text-align: center;
    padding: 3.5vw;
}
#footer a {
    color: #000;
}

 

#header

padding: 1.5vw 1.5vw 2.5vw 1.5vw; - 뷰포트 width가 1.5, 2.5만큼 상하좌우의 여백을 지정한다.

text-align: center; - 헤더 안에 있는 텍스트들을 가운데 정렬한다.

 

 

 

#header li

list-style: none; - 리스트의 기본 스타일을 none으로 두어 리스트 마커를 없앤다.

display: inline-block; - 요소들의 속성을 inline-block으로 설정하여 요소들이 가로로 나열되도록 한다.

 

 

 

#header li a

text-decoration: none; - link 속성을 none으로 주어 하이퍼링크에 설정되는 밑줄과 색을 없앤다.

width: 55px; - 가로(너비)의 크기가 55px

height: 55px; - 세로(높이)의 크기가 55px

line-height: 55px; - 줄간격을 가로 세로 높이와 똑같이 두어 텍스트가 요소의 정가운데에 올 수 있도록 한다.

display: inline-block; - 요소들의 속성을  inline-block으로 설정하여 요소들이 가로로 나열되도록 한다.

font-size: 24px;  - 글자 크기를 24px로 설정한다.

color: #000; - 글자 색을 까만색으로 한다

border: 2px solid #000; - 테두리를 2px만큼 일반 실선, 검정색으로 설정한다.

border-radius: 10%; - 테두리의 모서리가 10%만큼 원형으로 둥글게 처리된다.

 

 

 

#header li:nth-child(3n+1)

background-color: #AF6EE3; - 헤더 안의 리스트 항목들 중 1,4,7, 10 ~ 번째 항목들에게 배경색을 보라색으로 지정한다.

 

 

 

#header li:nth-child(3n+2)

background-color: #FFEF4A; - 헤더 안의 리스트 항목들 중 2, 5, 8, 11 ~ 번째 항목들에게 배경색을 노란색으로 지정한다.

 

 

 

#header li:nth-child(3n+3)

background-color: #F76ECE; - 헤더 안의 리스트 항목들 중 3, 6, 9, 12 ~ 번째 항목들에게 배경색을 분홍색으로 지정한다.

 

 

 

.search__wrap  - 컨테이너 요소

width: 90%;   - 가로(너비)가 90%

margin: 0 auto;   - 가운데에 위치하도록 지정한다.

background-color: #fff;     - 검색 바의 배경색을 하얀 색으로 지정한다.

border: 0.3vw solid #000;   - 두께가 0.3vw (뷰포트)인 검은색 테두리를 지정한다.

border-top-left-radius: 3vw;  - 왼쪽 상단의 모서리를 3vw만큼 둥글게 지정한다.

border-bottom-right-radius: 3vw;  - 오른쪽 하단의 모서리를 3vw만큼 둥글게 지정한다.

box-shadow: 1vw 1vw 0px #000;  -  검색 바의 그림자 효과를 가로와 세로 방향으로 1vw만큼 지정한다.

transition: box-shadow 0.3s;  - 그림자 효과에 0.3초 동안 변화하는 효과를 지정한다.

overflow: hidden;  - 튀어나오는 부분은 보이지 않도록 설정한다.

 

 

 

.search__wrap:hover

box-shadow: 0.5vw 0.5vw 0px #000;  - 요소 위로 마우스를 가져갈 때, 그림자 효과가 가로 및 세로 방향으로 0.5vw로 변경되도록 설정한다.

 

 

 

.search__header  - 헤더 요소

border-bottom: 0.3vw solid #000;  - 하단 테두리를 검은색으로 0.3vw만큼 설정한다.

padding: 0 0 0 3vw;   - 검색 창 헤더의 좌측(왼쪽) 여백을 3vw만큼 설정한다.

background-color: #AF6EE3; - 검색 창 헤더의 배경 색상을 보라색으로 설정한다.

position: relative;  - 검색 창 헤더를 상대적인 위치로 설정한다.

display: flex; - 검색 창 헤더를 플렉스 박스로 설정한다.

align-items: center; - 검색 창 헤더 내의 요소들을 수직으로 중앙 정렬한다.

justify-content: space-between; - 검색 창 헤더 내의 요소들을 수평으로, 동일한 간격으로 배치한다.

 

 

 

.search__header .title - 헤더 내의 클래스 이름이 title인 요소

position: relative; -  제목 요소를 상대적인 위치로 설정한다.

background: #AF6EE3; - 제목 요소의 배경 색상을 보라색으로 설정한다.

z-index: 10; - 이 요소가 다른 요소드로가 겹치는 경우, 위로 올라오도록 한다.

padding-right: 35px; - 오른쪽 내부 여백을 35px로 설정한다.

padding: 0.6vw 8.5vw 0.6vw 5.5vw;  - 제목 요소 내부의 여백을 위, 오른쪽, 아래, 왼쪽 순서로 각각 다른 여백을 설정한다. 제목 내의 텍스트가 적절한 간격으로 배치되도록 하는 역할도 한다.

 

 

 

.search__header::before - 헤더의 가상 요소

content: " ";  - 가상 요소의 내용을 비운다.

width: 90%; - 가상 요소의 길이를 부모 요소의 90%로 설정한다.

height: 0.3vw; - 세로(높이)를 0.3vw(뷰포트)로 설정한다.

background: #000; - 배경색상을 검은색으로 지정한다.

position: absolute;  - 가상 요소를 절대적인 위치로 설정한다.

right: 0;  top: 50%; - 가상 요소를 부모의 오른쪽 끝, 상단에서 50% 높이에 위치 시킨다.

transform: translateY(-10px);  - 가상 요소를 y축으로 -10px만큼 이동시킨다. 요소의 중앙이 부모 요소의 상단에서 50% 높이에 위치하도록 하는 역할을 한다.

border-radius: 5px;  - 가상 요소의 테두리를 5px만큼 둥글게 처리한다.

 

 

 

.search__header::after - 헤더의 가상 요소

content: " "; - 가상 요소의 내용을 비운다.

width: 90%; - 가상 요소의 길이를 부모 요소의 90%로 설정한다.

height: 0.3vw; - 세로(높이)를 0.3vw(뷰포트)로 설정한다.

background: #000; - 배경색상을 검은색으로 지정한다.

position: absolute; - 가상 요소를 절대적인 위치로 설정한다.

right: 0; top: 50%; - 가상 요소를 부모의 오른쪽 끝, 상단에서 50% 높이에 위치 시킨다.

transform: translateY(4px);  - 가상 요소를 y축으로 4px만큼 이동시킨다. 요소가 아래쪽에 위치하도록 하는 역할을 한다.

border-radius: 5px; - 가상 요소의 테두리를 5px만큼 둥글게 처리한다.

 

 

 

.search__header .btn - 검색창 헤더 내의 클래스 이름이 btn인 요소

display: flex;  - 요소를 플렉스 박스로 지정한다.

 

 

 

.search__header .btn span - 클래스 이름이 btn인 요소 안에 있는 span 태그

display: block; - span 태그를 블록 레벨 요소로 표시한다.

width: 3vw; - 가로(너비)를 뷰포트의 너비 3%로 설정한다.

height: 3vw; - 세로(높이)를 뷰포트의 높이 3%로 설정한다.

line-height: 3vw; - span 태그의 행 높이를 뷰포트의 높이 3%로 설정한다.

position: relative;  - span 태그를 상대적 위치로 배치한다.

z-index: 10;  - 다른 요소들보다 위에 표시되도록 한다.

border-left: 0.3vw solid #000;  - span 태그의 왼쪽 테두리 두께를 뷰포트의 0.3만큼, 검정색으로 설정한다.

box-sizing: content-box;  - span 태그 요소의 크기 계산 방법을 컨텐츠 박스 기준으로 설정한다

text-align: center;  요소 내부 텍스트를 중앙 정렬 시킨다.

font-size: 2vw;  - 글자의 크기를 2vw(뷰포트)만큼 설정한다.

cursor: pointer;  - 해당 요소 위에 마우스 커서가 올라가면 포인터 모양으로 변경되게 설정한다.

 

 

 

.search__contents hgroup  - search__contents 클래스를 가진 요소 안에 있는 hgroup 태그

padding: 3vw 5vw; - 요소의 내부 여백을 위, 아래는 화면 너비의 3%, 좌우는 화면 너비의 5%로 설정한다

text-align: center; -요소 내부의 텍스트를 중앙 정렬한다

border-bottom: 3px solid rgba(0, 0, 0, 0);  - 요소의 하단 경계선을 3px의 두께와 투명한 색상으로 설정한다.

 

 

.search__contents hgroup h3 - search__contents 클래스를 가진 요소 안에 있는 hgroup 태그 내부의 h3 태그

color: #FFEF4A;  - 요소의 텍스트 색상을 노란색으로 설정한다.

font-size: 8vw;  - 글꼴 크기를 화면 너비의 8%로 설정한다.

text-shadow: 0.6vw 0.6vw 0px #000;  - 요소의 텍스트에 그림자 효과를 추가한다. 가로와 세로의 그림자 거리는 화면 너비의 0.6%, 색상은 검은색으로 설정한다.

-webkit-text-stroke: 0.3vw #000;   -  요소의 텍스트에 0.3%만큼의 굵기로 검은색 외곽선을 추가한다.

 

 

.search__contents hgroup h4  - search__contents 클래스를 가진 요소 안에 있는 hgroup 태그 내부의 h4 태그

color: #AF6EE3; - 요소의 텍스트 색상을 보라색으로 설정한다.

font-size: 7vw;  - 글꼴 크기를 화면 너비의 7%로 설정한다.

text-shadow: 0.6vw 0.6vw 0px #000;  - 요소의 텍스트에 그림자 효과를 추가한다. 가로와 세로의 그림자 거리는 화면 너비의 0.6%, 색상은 검은색으로 설정한다.

-webkit-text-stroke: 0.3vw #000;   -  요소의 텍스트에 0.3%만큼의 굵기로 검은색 외곽선을 추가한다.

 

 

 

.search__box label   - search__box 클래스를 가진 lable 요소

padding: 1vw;   - 내부 여백을 화면의 1%로 설정한다.

font-size:2.5vw;   - 요소의 텍스트 사이즈를 2.5%로 설정한다.

font-family: 'CookieRun';   - 텍스트의 글꼴은 CookieRun이라는 폰트를 사용한다.

 

 

 

.search__box input  - 검색 창의 입력 필드

border: 0.4vw solid #000;   - 테두리를 0.4%로 설정한다.

width: 80%;  - 요소의 너비를 부모 요소의 80%로 설정한다.

box-shadow: 0.4vw 0.4vw 0 s#000;  - 텍스트에 그림자 효과가 화면의 0.4%만큼 추가된다.

padding: 1.5vw 2.5vw;  - 입력 필드의 내부 여백을 상하로 1.5%만큼 좌우로 2.5%만큼 설정한다.

border-radius: 50px;  - 요소의 모서리를 50px만큼 둥글게 설정한다.

font-family: 'CookieRun';  - 텍스트의 글꼴은 CookieRun이라는 폰트를 사용한다.

font-size: 2vw;  - 텍스트의 크기는 화면의 2%만큼 설정한다.

outline: none;    - 입력 필드이 포커스가 되었을 때 테두리를 제거하는 속성이다.

 

 

.search__info - 검색 결과 페이지에서 사용돌 search__info  클래스를 정의

text-align: right; - 해당 요소 내에서 텍스트를 오른쪽으로 정렬하도록 지정한다.

padding: 0.5vw 2vw;  - 해당 요소의 내부 여백을 상하는 0.5%로 좌우는 2%를 각각 적용한다.

border-bottom: 0.3vw dashed #000;   - 해당 요소의 하단 경계선을 두께는 화면의 0.3%의 점선, 검정색으로 지정한다.

 

 

 

.search__list ul  - 검색 결과 페이지에서 사용되는 목록

padding: 3.5vw;   - 목록의 내부 여백을 뷰포트 너비의 3.5%로 정의한다

 

 

 

.search__list li   - 목록 내부의 각 항목을 정의

list-style: none;    - 리스트 스타일(목록 마커)를 표시하지 않도록 설정한다.

line-height: 2.5;   -  목록의 줄간격을 뷰포트의 2.5배로 설정한다.

 

 

 

.search__list li.hide   - 숨김 클래스가 적용된 목록 항목을 정의

display: none;   - 해당 항목을 화면에 표시하지 않도록 설정한다.

 

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

 //선택자
        const searchBox = document.querySelector(".search__box input");
        const searchList = document.querySelectorAll(".search__list li");
        const listNumber = document.querySelector(".search__info span")

        //검색
        searchBox.addEventListener("keyup",() => {
            const userWord = searchBox.value;             

            searchList.forEach((el,i) =>{
                // const cssName = el.getAnimations("data-name");
                const cssName = el.dataset.name;
                listNumber.innerHTML = i;
                
                if(cssName.indexOf(userWord)) {             
                    el.classList.add("hide");                 
                } else {                                    
                    el.classList.remove("hide");  
                }
            })
        });

 

 

const searchBox = document.querySelector(".search__box input");

const searchList = document.querySelectorAll(".search__list li");

const listNumber = document.querySelector(".search__info span");

 

: 검색창, 검색겨로가 목록, 검색결과 정보를 나타내는 요소들을 각각 찾아와서 변수에 할당한다.

querySelector( ) 메서드를 사용하여 CSS 선택자를 통해 요소를 찾아온다.

 

 

searhBox에 키보드 이벤트(keyup) 리스너를 등록하여 사용자가 키보드로 입력하는 값을 userWord에 할당한다.

 

forEach( ) 메서드를 사용하여 검색결과 목록의 각 요소를 순회한다.

각 요소의 dataset 속성 중 name 속성 값을 가져온 후 userWord 값이 포함되어 있지 않다면 hide 클래스를 추가하여 해당 요소를 화면에서 감추고, 포함되어 있다면 hide 클래스를 제거하여 화면에 표시한다.

 

검색결과 정보를 나타내는 요소에는 검색결과 목록에서 표시된 항목 수를 업데이트 한다.

 

 

 

 

 

 

 

 

728x90
반응형

 

완성 화면

 

 

 

 

 

푸터 유형 사이트

 

 

 

 

 

 

코드 보기 / HTML

  <footer class="footer__wrap section nexon">
        <div class="container">
            <h2 class="blind">footer</h2>
            <div class="footer__inner">
                <div class="footer__menu">
                    <div>
                        <h3>은하수 관련 정보</h3>
                        <ul>
                            <li><a href="#">은하수 소개</a></li>
                            <li><a href="#">은하수 어원</a></li>
                            <li><a href="#">우리은하 형태</a></li>
                            <li><a href="#">우리 은하 크기</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 종류</h3>
                        <ul>
                            <li><a href="#">나선형 은하</a></li>
                            <li><a href="#">타원형 은하</a></li>
                            <li><a href="#">불규칙 은하</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 구조</h3>
                        <ul>
                            <li><a href="#">은하 헤일로</a></li>
                            <li><a href="#">은하의 중심</a></li>
                            <li><a href="#">블랙홀</a></li>
                            <li><a href="#">나선 팔</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>국부 은하군</h3>
                        <ul>
                            <li><a href="#">안드로메다 은하</a></li>
                            <li><a href="#">우리 은하</a></li>
                            <li><a href="#">삼각형자리 은하</a></li>
                            <li><a href="#">대마젤란 은하</a></li>
                            <li><a href="#">바너드 은하</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>은하수의 색</h3>
                        <ul>
                            <li><a href="#">청색(靑色)</a></li>
                            <li><a href="#">적색(赤色)</a></li>
                            <li><a href="#">자색(紫色)</a></li>
                            <li><a href="#">황색(黃色)</a></li>
                            <li><a href="#"> 백색(白色)</a></li>
                        </ul>
                    </div>
                    <div>
                        <h3>위성 은하</h3>
                        <ul>
                            <li><a href="#">큰개자리 왜소은하</a></li>
                            <li><a href="#">궁수자리 왜소타원은하</a></li>
                            <li><a href="#">작은곰자리 왜소은하</a></li>
                            <li><a href="#">사자자리 왜소은하</a></li>
                            <li><a href="#">목동자리 왜소은하</a></li>
                        </ul>
                    </div>
                </div>
                <address class="footer__right">
                    2023 Byun Woo Hyun 은하수 사이트 Portfolio is Power <br>All Right Reserved 
                </address>
            </div>
        </div>
    </footer>

 

 

 

 

 

코드 보기 / CSS

 /* reset */
         * {
            margin: 0;
            padding: 0;
        }
        li {
            list-style: none;
        }
        a {
            text-decoration: none;
            color:#000;
        }
        h1,h2,h3,h4,h5,h6 {
            font-weight: normal;
        }
        img {
            vertical-align: top;
            width: 100%;
        }
        .blind {
            position:absolute;
            clip:rect(0 0 0 0);
            width:1px;
            height:1px;
            margin:-1px;
            overflow:hidden
        }
        .mt10 {margin-top: 10px !important;}
        .mt20 {margin-top: 20px !important;}
        .mt30 {margin-top: 30px !important;}
        .mt40 {margin-top: 40px !important;}
        .mt50 {margin-top: 50px !important;}
        .mt60 {margin-top: 60px !important;}
        .mt70 {margin-top: 70px !important;}

        .mb10 {margin-bottom: 10px !important;}
        .mb20 {margin-bottom: 20px !important;}
        .mb30 {margin-bottom: 30px !important;}
        .mb40 {margin-bottom: 40px !important;}
        .mb50 {margin-bottom: 50px !important;}
        .mb60 {margin-bottom: 60px !important;}
        .mb70 {margin-bottom: 70px !important;}

        /* common */
        .container {
            width: 1160px;
            margin: 0 auto;
            padding: 0 20px;
            /* background-color: rgba(0,0,0,0.1); */
        }
        .nexon {
            font-family: 'NexonLv1Gothic';
            font-weight: 400;
        }
        .section {
            padding: 120px 0;
        }
        .section.center {
            text-align: center;
        }
        .section__small {
            font-size: 14px;
            border-radius: 50px;
            background-color: #AC43FF;
            color: #fff;
            padding: 1px 23px;
            text-transform: uppercase;
            margin-bottom: 20px;
            display: inline-block;
        }
        .section__h2 {
            font-size: 50px;
            color: #000;
            font-weight: 400;
            margin-bottom: 30px;
            line-height: 1;
        }
        .section__desc {
            font-size: 22px;
            color: #666;
            margin-bottom: 70px;
            font-weight: 300;
            line-height: 1.5;
        }
        .footer__wrap {
            background-color: #7B06A4;
            color: #fff;
        }
        .footer__menu{
            display: flex;
        }
        .footer__menu >  div {
            width: 16.6666%;
        }
        .footer__menu >  div h3 {
            margin-bottom: 13px;
            font-size: 18px;
            font-weight: bold;
        }
        .footer__menu >  div li {
            line-height: 1.5;
            font-size: 14px;
        }
        .footer__menu >  div li a{
            color:#fff;
        }
        .footer__right {
            text-align: center;
            margin-top: 50px;
            border-top: 3px solid #fff;
            padding-top: 50px;
            font-style: normal;
            line-height: 1.55;
        }

 

.footer__wrap

: footer__wrap 클래스를 가진 요소에 대한 스타일링이다.

푸터 전체의 배경색과 글자 색상을 지정한다. 배경 색상은 #7B06A4이며, 글자 색상은 #fff이다.

 

 

 

.footer__menu > div  (> 는 자식 선택자로 footer__menu의 자식 요소인 div에만 속성을 적용)

: footer__menu 클래스를 가진 요소의 자식 요소들에 대한 스타일링이다. display 속성을 flex로 지정하여 자식 요소(내부의 메뉴항목)들을 가로 정렬하게 만든다.

자식 요소들의 너비를 16.6666%로 일정하게 지정하여 총 6개의 자식 요소가 동일한 너비를 갖게 한다.

 

 

 

.footer__menu > div h3

: 각 메뉴 항목의 제목에 대한 스타일을 지정한다.

요소의 아래 여백을 13px로 설정하여 h3 요소 아래쪽 여백을 만든다.

글자 크기는 18px로, 글자 굵기를 굵게 설정한다.

 

 

 

.footer__menu > div li

: 각 메뉴 항목 내부의 리스트 항목에 대한 스타일을 지정한다.

줄간격 속성을 1.5만큼 설정하여 li 요소의 라인 높이를 조절하고, 글자 크기를 14px로 지정한다.

 

 

 

.footer__menu > div li a

: 각 리스트 항목에 대한 링크의 스타일을 지정한다.

a 태그로 감싸진 글자들의 색상을 흰색(#fff)로 설정하여 하이퍼링크나 글자의 색상을 변경한다.

 

 

 

.footer__right

: 푸터의 오른쪽 영역에 대한 스타일을 지정한다.

이 영역은 텍스트 정렬을 가운데로 지정하고, 상단에 3px 두께의 흰색 선을 그려낸다.

그리고 위쪽 패딩값을 50px 지정하며, 폰트 스타일과 줄간격(line-height)에 대한 스타일을 지정한다.

 

 

 

 

 

 

 

 

 

 

728x90
반응형

 

 

완성 화면

 

 

코드 보기 / CSS

 #header {
            z-index: 20;
        }
        .mouse__wrap {
            cursor: none;
        }
        .mouse__text {
            width: 100%;
            height: 100vh;
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            position: relative;
            z-index: 10;
        }
        .mouse__text p {
            font-size: 2vw;
            line-height: 1.6;
        }
        .mouse__cursor {
            position: absolute;
            left: 0;
            top: 0;
            width: 200px;
            height: 200px;
            border-radius: 50%;
            border: 3px solid #fff;
            background-color: #ffffff7a;
            background-image: url(img/mouseEffect03-min.jpg);
            background-size: cover;
            background-position: center center;
            background-attachment: fixed;
        }

 

 

#header

: ID를 가진 요소에 z-index: 20을 적용하여 #header 요소(큰 제목과 소제목, 버튼 링크 요소)가 다른 요소들보다 더 위에 나

 

 

.mouse__wrap

:class를 가진 요소에 cursor: none; 속성을 주어 마우스 커서를 숨김 처리한다.

 

 

.mouse__text

: mouse__text라는  class를 가진 요소는 HTML 요소는 뷰포트 크기와 같은 전체 화면을 차지(width: 100%, height: 100vh)하면서 수직 및 수평 가운데로 정렬(align-item: center, justfy-content: center)되고, 이 요소 내부의 자식 요소들이 수직으로 배치(display:flex, flex-direction: column) 된다.

이 요소는 다른 요소들보다 위에 배치된다.(z-index: 10)

 

 

.mouse__text p

:mouse__text라는 class에 속한 모든 p 태그에 대한 스타일을 지정한다.

글꼴 크기는 2vw로, 현재 뷰포트 너비(%)에 따라 글꼴 크기가 조정되도록 설정하고, line-height로 1.6만큼 글자 높이의 1.6배 만큼 간격으로 줄간격을 넓힌다.

 

 

.mouse__cursor

: 마우스 커서를 디자인하는 구문이다.

 

position: absolute  - 마우스 커서를 절대 위치로 설정한다.

left: 0, top: 0 - 커서를 페이지 좌측 상단에 위치 시킨다.

width: 200px, height: 200px - 커서의 가로(width)와 세로(height)의 크기를 200px로 설정하다.

border-radius: 50% - 모서리를 둥글게 하여 원모양의 형태로 커서를 만든다.

border: 3px solid #fff - 흰색 테두리를 3px 두께로 설정한다.

background-color: #ffffff7a - 배경색을 흰색, 투명도 0.47의 색상으로 지정한다.

background-image: url(img/mouseEffect03-min.jpg) - 커서의 배경 이미지로 img/mouseEffect03-min.jpg로 설정한다.

background-size: cover - 배경 이미지의 크기를 자동으로 조절하여 커서 영역을 채우도록 한다.

background-position: center center - 배경 이미지를 커서 가운데로 정렬한다.

background-attachment: fixed - 배경 이미지를 고정 시켜 페이지 스크롤시 커서가 움직이지 않도록 한다.

 

 

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

const cursor = document.querySelector(".mouse__cursor");
        const circle  = cursor.getBoundingClientRect();
      
        console.log(cursor.getBoundingClientRect());
        window.addEventListener("mousemove", e => {
            gsap.to(cursor, {
                duration: 0.5, 
                left: e.pageX - circle.width/2, 
                top:e.pageY - circle.height/2});
        });

 

document.querySelector(".mouse__cursor")

:  class가 mousse__cursor인 요소(마우스 커서가 될 요소)를 가져온다.

 

 

 

const cicrcle = cursor.getBoundingClienRect( )

:cursor 요소의 위치와 크기 정보를 얻기 위해 getBoundingClientRect( ) 메서드를 사용한다.

이 메서드는 DOMRect 라는 이름의 객체를 반환하며, 이 객체는 해당 요소의 크기, 위치 등의 정보를 포함한다.

마우스 커서 요소의 위치와 크기 정보를 얻는다.

 

 

※ getBoundingClientRect( ) 메서드

:요소의 위치와 크기 정보를 DOMRect 객체로 반환하며, 객체의 프로퍼티로는 top, left, right, bottom, width, height 등을 사용할 수 있다.

 

 

 

window.addEventListenter("mousemove", e=> {.....});

:마우스의 움직임을 감지하는 이벤트 리스너이다.

마우스를 움직이는 이벤트가 발생하면 콜백 함수를 실행한다.

 

 

 

 

gsap.to(cursor, { duration: 0.5 ····

:gsap 라이브러리를 사용하여 cursor 요소를  자연스럽고 부드럽게 움직일 수 있도록 한다.

duration 속성은 애니메이션의 지속 시간을 나타낸다.

첫 번째 인자로 애니메이션의 대상이 될 요소, 두 번째 인자로 애니메이션 속성과 값들을 받는다.

 

 

left: e.pageX - circle.width/2 , top: e.pageY - circle.height/2

: 마우스의 현재 위치 정보를 반영하여, 마우스 커서의 요소를 해당 위치로 이동 시킨다.

이 때, cursor 요소를 마우스 커서 중심으로 정렬하기 위해 left, top 값을 계산할 때 circle.width/2와 cicle.height/2를 빼준다.

 

 

 

 

 

 

728x90
반응형

 

 

완성 화면

 

 

 

 

 

728x90
반응형

 

 

완성 화면

 

 

 

 

 

코드 보기 / CSS

.mouse__wrap {
            cursor: none;
        }
        .mouse__text {
            width: 100%;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            overflow: hidden;
        }
        .mouse__text p {
            font-size: 2.5vw;
            line-height: 2;
        }
        .mouse__text p:last-child {
            font-size: 2vw;
        }
        .mouse__text p span {
            color: #9b07f0;
        }
        .mouse__cursor {
            position: absolute;
            left: 0;
            top: 0;
            width: 10px;
            height: 10px;
            z-index: 9999;
            border-radius: 50%;
            background-color: rgba(255, 255, 255, 0.37);
            user-select: none;
            pointer-events: none;
            transform: 0.3s;
            transition: all 0.6s;
        }
        .mouse__cursor2 {
            position: absolute;
            left: 0;
            top: 0;
            width: 30px;
            height: 30px;
            z-index: 9999;
            border-radius: 50%;
            background-color: rgba(255, 255, 255, 0.37);
            user-select: none;
            pointer-events: none;
            transform: 0.3s;
            transition: all 0.6s;
        }
        .mouse__cursor.active {
            transform: scale(0);
        }
        .mouse__cursor2.active {
            transform: scale(5) rotateY(720deg);
            background-color: #4303698c;
        }
        .mouse__cursor.active2 {
            transform: scale(2) rotateX(720deg);
            background-color: #0340698d;
        }
        .mouse__cursor2.active2 {
            transform: scale(5) rotateY(720deg);
            background-color: #0340698d;
        }
        .mouse__cursor.active3 {
            transform: scale(3) rotateY(720deg);
            background-color: #6903288c;
        }
        .mouse__cursor2.active3 {
            transform: scale(5) rotateX(720deg);
            background-color: #6903288c;
        }

 

 

.mouse__wrap

: 커서를 감싸는 전체 영역에 대한 스타일을 정의한다.

여기에서는 마우스 커서를 숨기는 역할(cursor: none;)을 한다.

 

.mouse__text

: 커서 이펙트를 적용할 텍스트 영역에 대한 스타일을 정의한다.

텍스트를 가운데 정렬하고, 이 영역은 화면 전체 높이를 차지하도록( height: 100vh) 설정한다.

 

 

.mouse__text p

: 텍스트 영역 내부 단락에 대한 스타일을 정의한다.

여기에서는 텍스트의 글꼴 크기(font-size)와 줄 간격(line-height)을 설정한다.

 

 

.mouse__text p:last-child

: 마지막 단락에 대한 스타일을 정의한다.

여기에서는 글꼴 크기를 더 작게 조절한다.

 

 

.mouse__text p span

: 단락 내부의 특정 텍스트에 대한 스타일을 정의한다.

텍스트 중 일부를 강조하기 위해 글자색을 보라색(#9b07f0)으로 설정한다.

 

.mouse__cursor, .mouse__cursor2

: 두 가지 유형의 마우스 커서의에 대한 디자인을 설정한다.

크기, 배경색, 변형 및 애니메이션 속성을 사용하며, cursor보다 cursor2의 크기가 더 크다.

 

.mouse__cursor.active

: 커서가 활성화 될 때 적용되는 스타일을 정의한다. scale( ) 속성을 사용하여 마우스 커서의 크기를 줄이거나 키우는 효과를 주며, 배경색을 변경 시키는 등의 속성을 가지고 있다.

 

 

 

 

 

 

코드 보기 / JAVASCRIPT

 		//선택자
        const cursor = document.querySelector(".mouse__cursor");
        const cursor2 = document.querySelector(".mouse__cursor2");

        //좌표값
        window.addEventListener("mousemove", e =>{
            gsap.to(cursor,{duration:0.1, left: e.pageX-5, top: e.pageY-5});
            gsap.to(cursor2,{duration:0.3, left: e.pageX-15, top: e.pageY-15});

            document.querySelectorAll(".mouse__text span").forEach(span => {
               span.addEventListener("mouseenter", () => {
                cursor.classList.add(`active`);
                cursor2.classList.add(`active`);
               });
               span.addEventListener("mouseleave", () => {
                cursor.classList.remove(`active}`);
                cursor2.classList.remove(`active`);
               });
        });

            document.querySelectorAll("#header li a").forEach((e, i) => {
                    e.addEventListener("mouseenter", () => {
                        cursor.classList.add(`active${i}`);
                        cursor2.classList.add(`active${i}`);
                    });
                    e.addEventListener("mouseleave", () => {
                        cursor.classList.remove(`active${i}`);
                        cursor2.classList.remove(`active${i}`);
                    });
        });
    });

 

해당 코드는 마우스 커서가 움직일 때, 마우스 커서의 위치를 변경하고, 마우스 커서 위에 있는 요소에 대한 처리를 하는 JavaScript 코드이다.

 

 

const cursor = document.querySelector(".mouse__cursor");

const cursor2 = document.querySelector(".mouse__cursor2");

: const cursor, cursor2는 각각 class가 ".mouse__cursor"와 ".mouse__cursor2"인 요소를 찾아서 변수에 할당한다.

 

 

 

window.addEventListenter("mousemove", e => {

: 윈도우 전체에서 마우스 커서의 움직임을 감지하고, 이동한 위치의 좌표 값을 e.pageX, epageY로 받아온다.

 

 

 

gsap.to(cursor,{duration:0.1, left: e.pageX-5, top: e.pageY-5});
gsap.to(cursor2,{duration:0.3, left: e.pageX-15, top: e.pageY-15});} 

:gsap 라이브러리를 이용하여 cursor와 cursor2의 위치를 변경한다.

 

 

 

document.querySelectorAll(".mouse__text span").forEach(span => {...}

:class가 "mouse__text"인 요소 안에 있는 모든 span 요소를 찾아서 각각에 대하여 mouseente와 mouseleave 이벤트를 등록한다.

마우스가 span 요소 위에 올라갔을 때에는 cursor와 cursor2의 class 이름이 "active"인 클래스를 추가하고, 마우스가 span 요소에서 벗어나면 해당 class를 제거한다.

 

 

 

document.querySelectorAll("#header li a").forEach((e,i => {.....})

: 아이디(ID)가 header 요소 안에 있는 모든 li 요소 안의 모든 a 요소를 찾아서 각가에 대하여 mouseenter와 mouseleave 이벤트를 등록한다.

마우스가 a 요소 위에 올라갔을 때는 cursor와 coursor2 class에 이름이 active + i (0부터 시작하는 인덱스)인 class를 추가하고, 마우스가 a 요소에서 벗어나면 해당 class를 제거한다.

 

 

 

 

 

※ 비슷한 두 이벤트 속성의 차이

mouseover ↔ mouseenter , mouseout ↔ mouseleave

:마우스 이벤트 중에서도 유사한 역할을 하는 이벤트이다.

 

mouseover, mouseout mouseenter, mouseleave
마우스 포인터가 요소 안으로 진입할 때 발생한다.
즉, 마우스 포인터가 요소 내의 어떤 자식 요소 위에 올라가면 이벤트가 발생하는 것이다.
이벤트가 발생하면 이벤트 버블링[각주:1]이 발생하기 때문에 부모 요소까지 mouseover 이벤트가 발생한다.
마우스 포인터가 요소 안으로 진입할 때 발생하지만 이벤ㄴ트 버블링이 발생하지 않는다.

부모 요소에 mouseenter 이벤트가 등록되어 있다고 해도, 자식 요소에 마우스 포인터가 진입할 때에는 부모 요소의 mouseenter 이벤트가 발생하지 않는다.

 

mouseover와 mouseout이벤트는 필요한 경우에만 사용하고,  mouseenter, mouseleave 이벤트는 일반적으로 사용된다.

 

mouseout 이벤트는 요소를 벗어날 때 이벤트 버블링을 사용해 다른 요소에 대한 처리를 수행할 때 주로 사용하고, mouseleave 이벤트는 특정 요소에서 벗어났을 때의 처리를 수행하기 위해 사용한다.

 

 

 

 

 

 

 

 

 

  1. 이벤트가 발생한 요소에서 상위 요소까지 이벤트가 전파되는 것. [본문으로]
728x90
반응형

 

 

 

완성 화면

 

 

 

코드 보기 / CSS

.mouse__wrap {
            cursor: none;
        }
        .mouse__cursor {
            position: absolute;
            left: 0;
            top: 0;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            border: 2px solid #fff;
            background-color: (255, 255, 255, 0.2);
            user-select: none;
            pointer-events: none;
            transition: 
            background-color 0.3s,
            border-color 0.3s,
            transform 0.6s,
            border 0.3s 
            ;
        }
        .mouse__cursor.s1{
            background-color: #fac5647c;
            border-color: #f7a103;
        }
        .mouse__cursor.s2{
            background-color: #4142427d;
            border-color: #000;
            transform: scale(2) rotateY(720deg);
        }
        .mouse__cursor.s3{
            background-color: #f8ec035d;
            border-color: #f3df06;
            transform: scale(1.5) rotateX(720deg);
        }
        .mouse__cursor.s4{
            background-color: #03a6f85d;
            border-color: #03a6f8;
            transform: scale(10);
        }
        .mouse__cursor.s5{
            background-color: #4142427d;
            border-color: #000;
            transform: scale(3) skew(5deg);
            border-radius: 10px;
        }
        .mouse__cursor.s6{
            background-color: #f8ec035d;
            border-color: #f3df06;
            transform: scale(10);
        }
        .mouse__text {
            width: 100%;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }
        .mouse__text p {
            font-size: 1vw;
            line-height: 2;
        }
        .mouse__text p:last-child {
            font-size: 2vw;
        }
        .mouse__text p span {
            color: #FAAC01;
            border-bottom: 1.5px solid #FAAC01;
        }
        .mouse__info {
            position: absolute;
            left: 0;
            bottom: 0;
            padding: 20px;
            font-size: 16px;
            line-height: 1.6;
        }

 

 

코드 보기 / JAVASCRIPT

 window.addEventListener("mousemove", function(event){
            document.querySelector(".clientX").innerHTML = event.clientX;
            document.querySelector(".clientY").innerHTML = event.clientY;
            document.querySelector(".offsetX").innerHTML = event.offsetX;
            document.querySelector(".offsetY").innerHTML = event.offsetY;
            document.querySelector(".pageX").innerHTML = event.pageX;
            document.querySelector(".pageY").innerHTML = event.pageY;
            document.querySelector(".screenX").innerHTML = event.screenX;
            document.querySelector(".screenY").innerHTML = event.screenY;
        });

        //선택자
        const cursor = document.querySelector(".mouse__cursor");

        window.addEventListener("mousemove", function(e){
            cursor.style.left = e.clientX - 25 + "px"
            cursor.style.top = e.clientY - 25 + "px"
        });
    
   
        document.querySelectorAll(".mouse__text span").forEach(function(span){
            let attr= span.getAttribute("class");               // attr = s1 ~ s6
            span.addEventListener("mouseover", function(){
                cursor.classList.add(attr);
            });
            span.addEventListener("mouseout", function(){
                cursor.classList.remove(attr);
            });
        });

 

 

 

 

 

 

1. 마우스의 좌표를 나타내는 구문

      window.addEventListener("mousemove", function(event){
            document.querySelector(".clientX").innerHTML = event.clientX;
            document.querySelector(".clientY").innerHTML = event.clientY;
            document.querySelector(".offsetX").innerHTML = event.offsetX;
            document.querySelector(".offsetY").innerHTML = event.offsetY;
            document.querySelector(".pageX").innerHTML = event.pageX;
            document.querySelector(".pageY").innerHTML = event.pageY;
            document.querySelector(".screenX").innerHTML = event.screenX;
            document.querySelector(".screenY").innerHTML = event.screenY;
        });

: 마우스의 이동을 감지하고, 이벤트 객체의 다양한 속성을 사용하여 마우스 위치에 대한 정보를 출력하는 구문.

addEventListener 함수를 사용하여 mousemove 이벤트를 감지하고, 이벤트 핸들러 함수[각주:1]를 등록한다.

이 객체를 통해 마우스 위치와 관련된 다양한 정보를 가져올 수 있다.

 

clientX, clientY : 브라우저 화면에서 마우스 커서의 위치를 나타낸다.

offsetX, offsetY : 이벤트 대상 요소에서 마우스 커서의 위치를 상대적으로 나타낸다.

pageX, pageY : 문서 전체에서 마우스 커서의 위치를 상대적으로 나타낸다.

screenX, screenY :  모니터 화면을 기준으로 한 마우스 커서의 위치를 나타낸다.

 

각각의 위치 정보는 querySelector 함수를 사용하여 HTML 요소를 선택하고, innerHTML 속성을 사용하여 해당 요소의 내용을 변경하고 화면에 출력한다.

 

 

 

 

 

2. 마우스 커서에 스타일을 주는 구문

.mouse__cursor {
            position: absolute;
            left: 0;
            top: 0;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            border: 2px solid #fff;
            background-color: (255, 255, 255, 0.2);
            user-select: none;
            pointer-events: none;
            transition: 
            background-color 0.3s,
            border-color 0.3s,
            transform 0.6s,
            border 0.3s 
            ;
        }
        .mouse__cursor.s1{
            background-color: #fac5647c;
            border-color: #f7a103;
        }
        .mouse__cursor.s2{
            background-color: #4142427d;
            border-color: #000;
            transform: scale(2) rotateY(720deg);
        }
        .mouse__cursor.s3{
            background-color: #f8ec035d;
            border-color: #f3df06;
            transform: scale(1.5) rotateX(720deg);
        }
        .mouse__cursor.s4{
            background-color: #03a6f85d;
            border-color: #03a6f8;
            transform: scale(10);
        }
        .mouse__cursor.s5{
            background-color: #4142427d;
            border-color: #000;
            transform: scale(3) skew(5deg);
            border-radius: 10px;
        }
        .mouse__cursor.s6{
            background-color: #f8ec035d;
            border-color: #f3df06;
            transform: scale(10);
        }

 

: 마우스 커서 디자인을 구현하는 CSS 구문이다.

마우스 커서를 표현하는 요소의 클래스 이름이 .mouse__cursor로 지정 되어 있으며, position : absloute 속성을 사용하여 문서의 절대 위치에 배치되도록 지정한다.

 

width와 height 속성을 사용하여 마우스 커서의 크기를 지정하고, border-radius 속성을 사용하여 둥근 모서리를 생성한다.

border 속서을 사용하여 테두리의 굵기와 색상을 지정한다.

 

background-color 속성을 사용하여 배경색을 지정하고, user-select와 pointer-events 속성을 사용하여 마우스 커서 요소에 대한 선택과 이벤트를 무시하도록 지정한다.

 

transition 속성을 사용하여 마우스 커서 요소의 변화가 부드럽게 이루어지도록 지정한다.

 

클래스 이름 mouse__cursor에 더해진 s1부터 s6까지는 마우스 커서 요소에 추가적인 스타일을 적용하는 클래스 이름이다. 마우스 상호작용에 따라 마우스 커서를 다른 디자인으로 변경한다.

 

 

s1 

: 배경색과 테두리 색만 변경

 

s2

: 배경색과 테두리 색을 변경하면서 scale(2) 속성을 사용하여 원래 크기의 2배로 확대시켰고, rotateY(720deg) 속성을 사용하여 Y축으로 720도 회전 시킨다.

 

s3

:배경색과 테두리 색을 변경하고 scale(1.5)속성을 사용하여 원래 크기의 1.5배로 확대 시키며, rotateX축으로 720도 회전시킨다.

 

s4

: 배경색과 테두리 색을 변경하고 scale(10) 속성을 사용하여 원래 크기의 10배로 확대 시킨다.

 

s5

:배경색과 테두리 색을 변경하고 scale(3) 속성을 사용하여 원래 크기의 3배로 확대 시키며 skew(5deg) 속성을 사용하여 5도 만큼 기울이고, border-radius: 1opx 속성을 사용하여 둥근 테두리를 생성한다.

 

s6

:배경색과 테두리 색을 변경하고 scale(10) 속성을 사용하여 원래 크기의 10배로 확대 시킨다.

 

 

 

 

 

 

document.write.querySelector( )에 이벤트 효과를 주는 구문을 작성하는 4가지 방법.

1. 일일히 전부 작성하기

document.querySelector(".s2").addEventListener("mouseover", function(){
            cursor.classList.add("s2");
        });

        document.querySelector(".s2").addEventListener("mouseout", function(){
            cursor.classList.remove("s2");
        });

        document.querySelector(".s3").addEventListener("mouseover", function(){
            cursor.classList.add("s3");
        });

        document.querySelector(".s3").addEventListener("mouseout", function(){
            cursor.classList.remove("s3");
        });

        document.querySelector(".s4").addEventListener("mouseover", function(){
            cursor.classList.add("s4");
        });

        document.querySelector(".s4").addEventListener("mouseout", function(){
            cursor.classList.remove("s4");
        });

        document.querySelector(".s5").addEventListener("mouseover", function(){
            cursor.classList.add("s5");
        });

        document.querySelector(".s5").addEventListener("mouseout", function(){
            cursor.classList.remove("s5");
        });

        document.querySelector(".s6").addEventListener("mouseover", function(){
            cursor.classList.add("s6");
        });

        document.querySelector(".s6").addEventListener("mouseout", function(){
            cursor.classList.remove("s6");
        });

: 마우스 포인터에 반응하여 특정 요소들의 클래스를 추가하거나 제거하고, 커서의 모양을 변경하는 것을 목적으로 하는 구문이다.

 

각각의 요소에 대하여 mouseover 이벤트가 발생하면 해당 요소의 클래스를 cursor 요소에 추가하고, mouseout 이벤트가 발생하면 해당 요소의 클래스를 cursor 요소에서 제거한다.

 

 

 

 

 

2. for문 사용

for(let i=1; i<=6; i++) {
            document.querySelector(`.s${i}`).addEventListener("mouseover", function(){
                cursor.classList.add(`s${i}`);
            });
            document.querySelector(`.s${i}`).addEventListener("mouseout", function(){
                cursor.classList.remove(`s${i}`);
            });
        }

: for문을 사용하여 1부터 6까지 반복하면서, 템플릿 리터럴을 사용하여 선택적 문자열을 생성하고, 해당 요소에 대해 mouseover 및 mouseout 이벤트를 추가한다.

이벤트 핸들러 함수에서는 i 값을 포함하는 클래스 이름을 cursor 요소에 추가하거나 제거한다.

 

 

 

 

3. forEach문 사용

document.querySelectorAll(".mouse__text span").forEach(function(span, i){
            span.addEventListener("mouseover", function(){
                cursor.classList.add("s"+(i+1));
            });
            span.addEventListener("mouseout", function(){
                cursor.classList.remove("s"+(i+1));
            });
        });

:  forEach 문을 사용하여 여러 개의 span 요소를 포함하는 요소에서 각 span 요소에 대해 커서의 모양을 다르게 지정할 수 있다.

mouse__text 클래스를 가진 요소들의 하위 요소인 span 태그에 대해 mouseover 및 mouseout 이벤트를 추가하여, 각각의 span 요소에 마우스를 올리면 커서의 모양이 변경되는 것을 구현한다.

 

querySelectorAll 메서드를 사용하여 mouse__text span 선택자로 하위 요소들을 모두 선택하고, forEach 메서드를 사용하여 각 요소에 대해 mouseover 및 mouseout 이벤트를 추가한다.

이벤트 핸들러 함수는 i 값(인덱스 값)을 이용하여 클래스 이름을 동적으로 생성하고, cursor 요소에 추가하거나 제거한다.

 

 

 

 

 

4. getAttribute( ); 사용

document.querySelectorAll(".mouse__text span").forEach(function(span){
            let attr= span.getAttribute("class");               // attr = s1 ~ s6
            span.addEventListener("mouseover", function(){
                cursor.classList.add(attr);
            });
            span.addEventListener("mouseout", function(){
                cursor.classList.remove(attr);
            });
        });

 

: forEach문과 유사하지만 각 span 요소에 대해 클래스 이름을 가져오는 부분이 다르다.

 

querySeectorAll 메서드를 사용하여 mouse__text span 선택자로 하위 요소들을 모두 선택하고, forEach 메서드를 사용하여 각 요소에 대해 mouseover 및 mouseout 이벤트를 추가한다.

이벤트 핸들러 함수에서는 span 요소의 클래스 이름을 가져와서 attr 변수에 할당하고, 해당 클래스 이름을 cursor 요소에 추가하거나 제거한다.

 

각 span 요소가 s1부터 s6까지의 클래스 이름을 동적으로 생성하는 대신 각 요소의 클래스 이름을 가져와 사용할 수 있다.

 

 

  1. 브라우저에서 사용자의 조작이나 환경의 변화로 일어난 이벤트를 처리하기 위해 이벤트 객체를 매개변수로 전달받는 함수 [본문으로]
728x90
반응형

 

 

텍스트 유형 사이트

 

 

 

 

완성 화면

 

 

 

 

 

코드 보기 / CSS

/* reset */
         * {
            margin: 0;
            padding: 0;
        }
        a {
            text-decoration: none;
            color:#000;
        }
        h1,h2,h3,h4,h5,h6 {
            font-weight: normal;
        }
        img {
            vertical-align: top;
            width: 100%;
        }
        .mt10 {margin-top: 10px !important;}
        .mt20 {margin-top: 20px !important;}
        .mt30 {margin-top: 30px !important;}
        .mt40 {margin-top: 40px !important;}
        .mt50 {margin-top: 50px !important;}
        .mt60 {margin-top: 60px !important;}
        .mt70 {margin-top: 70px !important;}

        .mb10 {margin-bottom: 10px !important;}
        .mb20 {margin-bottom: 20px !important;}
        .mb30 {margin-bottom: 30px !important;}
        .mb40 {margin-bottom: 40px !important;}
        .mb50 {margin-bottom: 50px !important;}
        .mb60 {margin-bottom: 60px !important;}
        .mb70 {margin-bottom: 70px !important;}

        /* common */
        .container {
            width: 1160px;
            margin: 0 auto;
            padding: 0 20px;
            /* background-color: rgba(0,0,0,0.1); */
        }
        .nexon {
            font-family: 'NexonLv1Gothic';
            font-weight: 400;
        }
        .section {
            padding: 120px 0;
        }
        .section.center {
            text-align: center;
        }
        .section__small {
            font-size: 14px;
            border-radius: 50px;
            background-color: #AC43FF;
            color: #fff;
            padding: 1px 23px;
            text-transform: uppercase;
            margin-bottom: 20px;
            display: inline-block;
        }
        .section__h2 {
            font-size: 50px;
            color: #000;
            font-weight: 400;
            margin-bottom: 30px;
            line-height: 1;
        }
        .section__desc {
            font-size: 22px;
            color: #666;
            margin-bottom: 70px;
            font-weight: 300;
            line-height: 1.5;
        }
        .text__inner {
            text-align: left;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }
        .text__inner .text {
            width: 32.3333333%;
            border:  1px solid #f5f5f5;
            padding: 90px 20px 20px 20px;
            border-radius: 10px;
            box-sizing: border-box;
            margin-bottom: 20px;
            transition: all 0.3s;
            cursor: pointer;
            position: relative;
        }
        .text__inner .text:hover {
            background-color: #ece0f8;
        }
        .text__inner .text::before {
            content: '';
            width: 60px;
            height: 60px;
            background-color: rgba(147, 87, 245, 0.76);
            background-image: url(../asset/img/textType01_01.svg);
            background-repeat: no-repeat;
            background-position: center;
            position: absolute;
            left: 20px;
            top: 20px;
            border-radius: 50%;
        }
        .text__inner .text::after {
            content: '';
        }
        .text__title {
            font-size: 24px;
            margin-bottom: 10px;
        }
        .text__desc {
            font-size: 16px;
            color: #666;
            margin-bottom: 15px;
            line-height: 1.5;
        }
        .text__btn {
            float: right;
            position: relative;
            padding-right: 20px;
        }
        .text__btn:hover::before {
            transform: rotate(360deg);
        }
        .text__btn::before {
            content: '';
            position: absolute;
            right: 0;
            top: 0;
            width: 15px;
            height: 15px;
            background-image: url(../asset/img/icon_plus.svg);
            transition: all 0.3s;
        }

 

 

 

 

 

코드 보기 / HTML

<section class="text__wrap section center nexon">
        <div class="container">
            <span class="section__small">notice</span>
            <h2 class="section__h2 mb70">About the Milky way</h2>
            <div class="text__inner">
                <div class="text">
                    <h3 class="text__title">명칭 및 어원</h3>
                    <p class="text__desc">우리 은하의 명칭은 “Milky Way(밀키 웨이)”입니다. 그러나 밀키 웨이는 우리 은하 뿐 아니라 은하수 자체를 가리키기도 합니다. 은하수들도 각각의 명칭이 있습니다.</p>
                    <a class="text__btn" href="#">더 보기</a>
                </div>
                <div class="text">
                        <h3 class="text__title">갤러틱 할로(Galactic Halo)</h3>
                        <p class="text__desc">은하 중심부를 둘러싸고 있는 둥근 모양의 거대한 구조물 입니다. 은하 중심부에 위치한 은하 플레어와 달리, 할로는 무수히 많은 별, 암석체, 가스, 먼지 등이 혼합된 구조물입니다.</p>
                        <a class="text__btn" href="#">더 보기</a>
                </div>
                <div class="text">
                    <h3 class="text__title">은하 헤일로(Galaxy Hale)</h3>
                    <p class="text__desc">은하 헤일로는 아메리칸 천문학자 조지 엘리슨 헤일이 처음으로 제안한 은하 분류 체계입니다. 이 체계는 은하를 크기와 모양에 따라 4가지 유형으로 분류하고 있습니다.</p>
                    <a class="text__btn" href="#">더 보기</a>
                </div>
                <div class="text">
                    <h3 class="text__title">우리 은하의 구조</h3>
                    <p class="text__desc">우리 은하는 막대 나선 은하에 속하며, 허블의 은하 분류에 따르면 Sbc(중심에 막대가 존재하고 나선팔이 느슨히 감긴 형태)입니다. 막대 구조는 대부분 붉고 오래된 항성들로 구성되어 있습니다.</p>
                    <a class="text__btn" href="#">더 보기</a>
                </div>
                <div class="text">
                    <h3 class="text__title">우리 은하의 블랙홀</h3>
                    <p class="text__desc">우리 은하를 구성하는 별들은 은하의 중심부를 중심으로 나선팔 모양으로 공전합니다. 이는 은하 중심에 초대질량 블랙홀이 있기 때문이라 여겨집니다.</p>
                    <a class="text__btn" href="#">더 보기</a>
                </div>
                <div class="text">
                    <h3 class="text__title">우리 은하의 팔</h3>
                    <p class="text__desc">우리 은하에는 네 개의 큰 나선 팔이 있다고 여겨졌으나, 2008년에 스피처 적외선 망원경을 이용하여 1억 개 이상의 별의 분포를 분석한 결과, 단지 2개의 나선 팔만이 구분되었습니다.</p>
                    <a class="text__btn" href="#">더 보기</a>
                </div>
            </div>
        </div>
    </section>

 

 

 

 

.text__inner {
text-align: left; 
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}

:text__inner 클래스(class)는 텍스트 블록들을 감싸는 부모 요소를 나타낸다.

이 클래스는 왼쪽 정렬이 되며(text-align), 텍스트 블록들은 flexbox를 이용해(display: flex, flex-wrap: wrap) 감싸져서 각각의 텍스트 블록 사이에 공간이 생기도록 하는 속성(justify-content: space-between)이 적용된다.

 

 

 

.text__inner .text {
width: 32.3333333%;
border: 1px solid #f5f5f5;
padding: 90px 20px 20px 20px;
border-radius: 10px;
box-sizing: border-box;
margin-bottom: 20px;
transition: all 0.3s;
cursor: pointer;
position: relative;
}

 

: text__inner 클래스 안의 text 클래스는 텍스트 블록을 나타낸다.

text__inner .text 클래스는 각각의 텍스트 블록이 32.33%의 너비를 가지고 있으며(width:32.33%), 테두리가 (border: 1px) 있고, 패딩(텍스트를 기준으로 주는 여백, padding: 90px(상/위) 20px(우/오른쪽) 20px(하/아래) 20x(좌/왼쪽)))과 보더 라운딩(테두리를 둥글게 하는 것, border-radius : 10px), 마진 등의 속성을 준다.

마우스가 해당 텍스트 블록 위에 올라갔을 때 배경색이 변하도록 (:hover) 속성을 주었다.

 

 

 

 

 

 

.text__btn {
float: right;
position: relative;
padding-right: 20px;
}

: text__btn 요소는 오른쪽 끝으로 float 속성을 이용해 위치시킨다.

이어서 position 속성을 relative로 지정하여 text__btn 요소의 자식 요소의 배치를 위한 기준점으로 삼는다.

또한 padding-right 속성을 사용하여 오른쪽 패딩 값을 20px 지정해주었다.

 

 

 

 

 

 

.text__btn:hover::before {
transform: rotate(360deg);
}
.text__btn::before {
content: ' ';
position: absolute;
right: 0;
top: 0;
width: 15px;
height: 15px;
background-image: url(../asset/img/icon_plus.svg);
transition: all 0.3s;
}

 

: text__btn의 가상 요소이다.

content: ' '; 속성으로 컨텐츠를 추가하고, position 속성을 absolute로 설정하여 해당 요소의 위치를 text__btn 요소에서 상대적으로 지정한다.이 가상 요소의 위치는 right: 0과 top: 0으로 오른쪽 상단 모서리에 위치 시킨다.

 

width, height 속성은 각각 가상 요소의 너비와 높이를 15px로 설정한다.

background-image 속성은 가상 요소의 배경 이미지(까만 동그라미 배경의 +)를 지정한다.

 

또한 transiton 속성을 이용해 마우스가 까만 동그라미 배경의 + 요소 위에 마우스가 올라갔을 때의 변화를 부드럽게 처리할 수 있도록 설정하고,

transsform 속성을 이용해 가상 요소가 360도 회전 시키는 애니메이션 효과를 주었다.

 

 

 

 

 

 

728x90
반응형

 

완성 화면

 

 

 

 

 

코드 보기 / HTML

 <div class="quiz__wrap">
            <div class="quiz">
                <div class="quiz__header">
                    <h2 class="quiz__title"></h2>
                </div>
                <div class="quiz__main">
                    <div class="quiz__question"></div>
                    <div class="quiz__view">
                        <div class="dog__wrap">
                            <div class="true">정답</div>
                            <div class="false">오답</div>
                            <div class="card-container">
                                <div class="dog">
                                    <div class="head">
                                        <div class="ears"></div>
                                        <div class="face"></div>
                                        <div class="eyes">
                                            <div class="teardrop"></div>
                                        </div>
                                        <div class="nose"></div>
                                        <div class="mouth">
                                            <div class="tongue"></div>
                                        </div>
                                        <div class="chin"></div>
                                    </div>
                                    <div class="body">
                                        <div class="tail"></div>
                                        <div class="legs"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="quiz__choice">
                        <label for="choice1">
                            <input type="radio" id="choice1" name="choice" value="1">
                            <span></span>
                        </label>
                        <label for="choice2">
                            <input type="radio" id="choice2" name="choice" value="2">
                            <span></span>
                        </label> 
                        <label for="choice3">
                            <input type="radio" id="choice3" name="choice" value="3">
                            <span></span>
                        </label> 
                        <label for="choice4">
                            <input type="radio" id="choice4" name="choice" value="4">
                            <span></span>
                        </label> 
                    </div>
                    <div class="quiz__answer">
                        <button class="confirm">정답 확인하기</button>
                    </div>
                    <div class="quiz__desc"></div>
                </div>
            </div>
        </div>

 

 

 

 

 

코드 보기 / JAVASCRIPT

 const quizWrap = document.querySelector(".quiz__wrap");
        const quizTitle = quizWrap.querySelector(".quiz__title");
        const quizQuestion = quizWrap.querySelector(".quiz__question");
        const quizChoice = quizWrap.querySelectorAll(".quiz__choice span");
        const quizSelect = quizWrap.querySelectorAll(".quiz__choice input");
        const quizConfirm = quizWrap.querySelector(".quiz__answer .confirm");
        const quizDesc = quizWrap.querySelector(".quiz__desc");
        const quizAnswer = quizWrap.querySelector(".quiz__answer");
        const dogWrap = quizWrap.querySelector(".dog__wrap");

        //문제정보    
        const quizInfo = [
            {
                infoType: "웹디자인 기능사",
                infoTime: "2016년 4회",
                infoNumber : "1",
                infoQuestion: "다음 중 디자인의 기본 요소들로 옳은 것은?",
                infoChoice:["선, 색채, 공간, 수량","점, 선, 면, 질감","시간, 수량, 구조, 공간","면, 구조, 공간, 수량"],
                infoAnswer:"2",
                infoDesc: "디자인의 기본 요소에는 점, 선, 면, 질감이 있습니다."
            }
        ];

        //문제 출력
        function updateQuiz(){
            quizTitle.innerHTML = quizInfo[0].infoType + " " + quizInfo[0].infoTime;
            quizQuestion.innerHTML = "<em>"+quizInfo[0].infoNumber+"</em>. "+ quizInfo[0].infoQuestion;
            quizDesc.innerHTML = quizInfo[0].infoDesc;
            
            for(let i=0; i<4; i++){
                quizChoice[i].textContent = quizInfo[0].infoChoice[i];
            }
        }

        //정답확인
        function answerQuiz(){
            for(let i=0; i<quizChoice.length; i++) {
                if(quizSelect[i].checked == true) {          //사용자가 보기를 선택 유무
                    if(quizSelect[i].value == quizInfo[0].infoAnswer) {         
                        alert ("정답") //정답일 시
                        dogWrap.classList.add("like"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none;"                            
                    } else {                               
                        alert ("오답")    //오답일 시
                        dogWrap.classList.add("dislike"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none";                  
                    }
                }
            }
        }


        //사용자가 선택한 인풋박스가 문제 정답(quizInfo[0].infoAnswer과 일치하는지 확인

        //정답 체크박스 클릭
        quizConfirm.addEventListener("click", answerQuiz);
        updateQuiz();       //문제출력

 

 

 

 

 

코드 보기 / CSS

.quiz__choice{
    padding: 20px;
    border-bottom: 6px ridge #a12cd3;
    font-family: 'ElandChoice';
}
.quiz__choice label {
    display: flex;
}
.quiz__choice label input {
    position: absolute;
    clip: rect(0 0 0 0);
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
}
.quiz__choice label span {
    font-size: 20px;
    line-height: 1.5;
    padding: 6px;
    display: flex;
    cursor: pointer;
    margin: 2px 0;
}
.quiz__choice label span::before {
    content: '';
    width: 26px;
    height: 26px;
    border-radius: 50%;
    margin-right: 15px;
    background-color: #fff;
    box-shadow: inset 0 0 0 4px #63068a;
    transition: all 0.2s;
    flex-shrink: 0;
}
.quiz__choice label input:checked + span {
    background-color: #f6ecfa;
}
.quiz__choice label input:checked + span::before {
    box-shadow: inset 0 0 0 8px #63068a;
}
.quiz__check {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 110px;
    height: 110px;
    line-height: 110px;
    border-radius: 50%;
    z-index: 1000;
    background-color: #9d07f4;
    text-align: center;
    font-family: 'ElandChoice';
    color: #fff;
    cursor: pointer;
}

 

 

 

 

문제 출력 구문

function updateQuiz(){
            quizTitle.innerHTML = quizInfo[0].infoType + " " + quizInfo[0].infoTime;
            quizQuestion.innerHTML = "<em>"+quizInfo[0].infoNumber+"</em>. "+ quizInfo[0].infoQuestion;
            quizDesc.innerHTML = quizInfo[0].infoDesc;
            
            for(let i=0; i<4; i++){
                quizChoice[i].textContent = quizInfo[0].infoChoice[i];
            }
        }

 

quizTitle, quizQuestion, quizDesc

: HTML 문서에서 ID를 사용하여 가져온 요소.

각각 문제의 종목, 문제, 해설을 담게 될 요소들이다.

 

quizInfo

:배열로 정의된 객체를 담고 있는 변수

 

quizTitle.innerHTML = quizInfo[0].infoType + " " + quizInfo[0].infoTime;

: quizTitle 요소의 내부 HTML을 업데이트한다.
이 때, quizInfo 배열의 첫 번째 객체인 quizInfo[0]에서 infoType 속성과 infoTime 속성을 가져와 공백으로 구분한 문자열을 quizTitle 요소 내부 HTML로 설정합니다.

quizTitle 요소의 내용을 quizInfo 배열의 첫 번째 객체의 infoType(웹 디자인 기능사) 속성과 infoTime(2016년 4회) 속성을 이용해 설정한다.

 

 

quizQuestion.innerHTML = "<em>"+quizInfo[0].infoNumber+"</em>. "+ quizInfo[0].infoQuestion;

: quizQuestion 요소의 내부 HTML을 업데이트합니다.
이 때, quizInfo 배열의 첫 번째 객체인 quizInfo[0]에서 infoNumber 속성과 infoQuestion 속성을 가져와 <em> 태그로 감싸고 번호와 함께 문자열을 생성한 뒤, quizQuestion 요소 내부 HTML로 설정한다.

quizQuestion 요소의 내용을 quizInfo 배열의 첫 번째 객체의 infoNumber(1) 속성과 infoQuestion (다음 중 디자인의 기본 요소들로 ~)속성을 이용해 설정한다.

 

quizDesc.innerHTML = quizInfo[0].infoDesc;

: quizDesc 요소의 내부 HTML을 업데이트한다.
이 때, quizInfo 배열의 첫 번째 객체인 quizInfo[0]에서 infoDesc 속성을 가져와 quizDesc 요소 내부 HTML로 설정한다.

quizDesc 요소의 내용을 quizInfo  배열의 첫번째 객체의 infoDesc(디자인의 기본 요소에는 ~~) 속성을 이용해 설정한다.

 

 

 

for(let i=0; i<4; i++){ quizChoice[i].textContent = quizInfo[0].infoChoice[i]; }

: quizChoice 배열에 있는 네 개의 요소(quizChoice[0], quizChoice[1], quizChoice[2], quizChoice[3])의 내부 텍스트를 각각 quizInfo 배열의 첫 번째 객체인 quizInfo[0]에서 가져온 infoChoice 속성의 값으로 설정하고, for 루프를 사용하여 각 요소의 인덱스를 참조하고, textContent 속성을 사용하여 내부 텍스트를 업데이트한다.

for문을 사용하여 quizChoice 배열의 요소에 quizInfo 배열의 첫 번째 객체의 infoChoice 속성을 순서대로 설정한다.

 

 

 

 

 

정답 확인 구문

function answerQuiz(){
            for(let i=0; i<quizChoice.length; i++) {
                if(quizSelect[i].checked == true) {    
                    if(quizSelect[i].value == quizInfo[0].infoAnswer) {         
                        alert ("정답")
                        dogWrap.classList.add("like"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none;"                            
                    } else {                               
                        alert ("오답")    
                        dogWrap.classList.add("dislike"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none";                  
                    }
                }
            }
        }

 

 

for(let i=0; i<quizChoice.length; i++)

: for 루프를 이용하여 quizChoice 배열의 요소를 순서대로 확인한다.

 

 

 if(quizSelect[i].checked == true)

: if문은 해당 보기가 선택되었는지 확인한다.

quizSelect[i]는 해당 보기의 라디오 버튼 요소를 나타낸다.

checked 속성은 해당 라디오 버튼이 선택되었는지 여부를 확인하며, 선택된 보기가 정답인지 확인한다.

quizSelect[i].value는 해당 보기의 값(내용)을 나타낸다.

 

 

if(quizSelect[i].value == quizInfo[0].infoAnswer)  {         
                        alert ("정답")
                        dogWrap.classList.add("like"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none;"         

: quizInfo[0].infoAnswer는 퀴즈의 첫 번째 객체의 infoAnswer 속성으로, 정답의 값(내용)을 나타낸다.

정답일 경우, alert()를 이용하여 "정답" 메시지를 출력한다.

dogWrap은 HTML 문서에서 id를 이용해 가져온 요소로, classList.add() 메소드를 이용하여 like 클래스를 추가한다.

quizAnswer와 quizDesc 요소의 display 속성을 "none"으로 설정하여 숨긴다.

 

 

else {                               
                        alert ("오답")    
                        dogWrap.classList.add("dislike"); 
                        quizAnswer.style.display = "none";
                        quizDesc.style.display = "none";                  
                    }


:  오답일 경우, alert()를 이용하여 "오답" 메시지를 출력한다.

dogWrap은 HTML 문서에서 id를 이용해 가져온 요소로, classList.add() 메소드를 이용하여 dislike 클래스를 추가한다.

quizAnswer와 quizDesc 요소의 display 속성을 "none"으로 설정하여 숨긴다.

 

 

 

 

 

 

728x90
반응형

 

1. 결괏값을 작성하시오.

 (function(){
        console.log("함수가 실행되었습니다.");
    })();

: 함수가 실행되었습니다.

 

즉시 실행 함수로, 함수를 이름 없이 정의하고 즉시 실행하기 때문에 함수를 정의하는 즉시 함수 호출을 통해 실행된다.

 

 

 

 

2. 결괏값을 작성하시오.

 function func(str = "함수가 실행되었습니다."){
        document.write(str);
    }
    func();

 

A

: 함수가 실행되었습니다.

 

func라는 ㄴ함수를 정의하고, 문자열 매개변수 str을 전달받아 document.write( ) 메서드를 사용하여 화면에 출력한다.

str 매개 변수는 "함수가 실행되었습니다." 라는 기본값을 가지고 있다.

함수가 호출 될 때 인수를 전달하지 않으면, 이 기본값이 str인 매개 변수로 사용된다.

 

func( ); 구문은 func 함수를 호출하는데, 이 경우 인수를 전달하지 않았으므로 str 매개 변수의 기본값인 "함수가 실행되었습니다." 가 출력된다.

 

 

 

 

 

3. 결괏값을 작성하시오.

let sum = 0;
    for(var i=1; i<=10; i+=2) {
        sum += i;
    };
    document.write(sum);

 

A

: 25

 

변수 sum을 0으로 초기화 하고, 1부터 10까지의 홀수를 더하는 문제이다.

for문에서 i 변수를 1에서 시작하여 2씩 증가 시키면서 sum 변수에 i 값을 더한다.

for문이 실행되는 동안 sum 변수에 누적된 값은 1+3+5+7+9 = 25가 된다.

 

 

 

 

 

4. 결괏값을 작성하시오.

const obj = {
        a: 100,
        b: 200,
        c: "javascript"
    }
    const { a, b, c } = _______;

    document.write(a);
    document.write(b);
    document.write(c);

A

:obj

 

객체 리터럴을 사용하여 obj 변수를 정의하고 객체 속성 a, b, c에 각각 100, 200, javascript 값을 할당한다.

const {a,b,c} =                 ; 구문에서는 객체 디스트럭처링(Object destucturing) 문법을 사용하여 obj 객체의 속성을 각각 a, b, c 변수에 할당한다.

객체 obj에 값을 할당해야 하기 때문에 빈 칸에는 obj가 들어가야 한다.

 

 

✏ 객체 디스트럭처링 (Object destructuring) 문법

:ES6 (2015)부터 도입된 기능으로, 객체 속성의 값을 추출하여 변수에 할당하는 방법을 제공한다.

필요한 속성만을 선택하여 변수에 할당할 수 있으며, 기본값 설정도 가능하다.

객체에 해당 속성이 없는 경우 기본값이 할당 되는 것이다.

이 기능은 함수의 매개변수에서도 사용할 수 있다.

 

 

 

 

 

5. 결괏값을 작성하시오.

const objA = {
        a: 100,
        b: 200
    }
    const objB = {
        c: "javascript",
        d: "jquery"
    }
    const spread = {______, ______}

    document.write(spread.a);
    document.write(spread.b);
    document.write(spread.c);
    document.write(spread.d);

 

A

: ...objA, ...objB

 

객체 리터럴을 사용하여 objA, objB 변수를 정의하고, 각각의  객체 속성 a,b,c,d에 각각의 값을 할당하는 문제이다.

const spread = {                                   } 구문에서는 객체 스프레드 문법을 사용하여 objA, objB 객체의 속성을 모두 포함하는 새로운 객체를 생성한다.

따라서 spread 객체는 objA와 objB 객체의 모든 속성을 포함하게 된다.

 

 

 

 

 

6. 결괏값을 작성하시오.

 if( _____ ){
        document.write("조건문이 실행되었습니다.(true)");
    } else {
        document.write("조건문이 실행되었습니다.(false)");
    }

    //document.write("조건문이 실행되었습니다.(false)");
    //보기
    //true, false, 1, "1", "", 0, null, undefined, [], {}
더보기

작성한 답 : false, 0 , null, undefined 

 

※ 블린, 0, 값이 할당되지 않음(undefined), null은 전부 조건식에 작성했을 때 false가 되는 것들이다.

빈 객체와 빈 배열은 포함되지 않고 빈 "문자열"은 포함된다.

빈 "문자열"도 해당된다는 사실을 잊어버리지 않을 것.

: false,  " "(빈 문자열), 0, null, undefined

 

 0을 제외한 모든 숫자와 문자를 조건식에 넣게 되면 전부 true가 된다.

하물며 빈 배열을 넣어도 결과값은 true가 된다.

또한, 조건식에 불린도 넣을 수 있으며, true를 넣으면 true가, false가 된다.

데이터에 값이 없으면(null, undefined를 작성하면) false가 된다.

 

 

 

 

7. 결괏값을 작성하시오.

  if( num == 100 ){
        document.write("true");
    } else {
    	document.write("false");
    }

 

A

: (num == 100) ? document.write("true") : document.write("false")

 

삼항연산자의 형식은 (조건식) ? 참인 경우 실행문 : 거짓일 경우 실행문 이다.

조건식의 소괄호는 ( ) 생략할 수 있으며, 조건문과 실행문 사에는 ? (물음표)가 참일 때의 실행문과 거짓일 때의 실행문 사이에는 : (콜론)이 들어간다.

 

 

 

 

8. 결괏값을 작성하시오.

for(var i=1; i<=1; i++){
        document.write(i);
        for(var j=1; j<=5; j++){
            document.write(j);
        }
    }

 

A

: 1

  1 2 3 4 5

 

외부 for문은 변수 i가 1부터 1까지 반복된다. (i<=1이기 때문)

따라서 내부 for문도 한 번만 반복된다.

내부 for문의 변수 j는 1부터 5까지 반복된다. (j<=5이기 때문)

따라서 내부 for문은 1, 2, 3, 4, 5를 순서대로 출력한다.

 

 

 

 

 

9. 결괏값을 작성하시오.

  const num = [100, 200, 300, 400, 500];

    for(let i=0; i<num.length; i++){
        document.write(_______);
    }

 

A

: num [i]

 

for문에서 반복문 변수 i는 배열 num의 인덱스 값(자리값/키)을 나타낸다.

따라서 num[i]와 같이 인덱스 값을 사용하여 배열 요소에 접근할 수 있다.

 

 

 

 

 

10. 결괏값을 작성하시오.

 const num = [100, 200, 300, 400, 500];

    num.forEach(function(el){
        document.write(________);
    });

 

A

:el

 

forEach( ) 메서드는 배열의 요소 값, 키 값, 배열 전체를 받아올 수 있다.

이 문제에서는 배열의 요소 값만 받아오게 된다.

 

그 요소 값을 출력하기 위해서는 빈 칸에 el 즉 (element)가 들어가게 된다.

 

 

 

 

 

11. 다음을 보고 리턴값을 생략하여 한 줄로 표현하시오.

const func = str => {
        return str;
    }

 

 

A

: const func = str => str;

 

return값이 생략되기 때문에 return 구문 없이 바로 str이 된다.

 

 

 

 

 

12. 다음의 결괏값을 보고 빈 칸을 채우시오.

 const num = [100, 200, 300, 400, 500];

    for(let index of _____ ){
        document.write(index);
    }

 

A

: num

 

for of 문은 반복할 수 있는 객체의 모든 요소에 대해 반복문을 수행한다.

배열은 반복 가능한 객체이기 때문에 for of를 사용하여 배열의 모든 요소에 대해 반복문을 수행할 수 있다.

이 문제에서의 반복 변수 index는 배열 num의 요소 값 자체가 된다.

따라서 배열 num을 타깃으로 설정해 주기 위해 num을 작성한다.

 

 

 

 

13. 다음의 결괏값을 보고 빈 칸을 채우시오. 

function func(){
        let i = 5, j = 4, k = 1, l, m;
        l = i > 5 || j != 0;
        m = j <= 4 && k < 1;
        document.write(l);
        document.write(m);
    }
    func();
더보기

작성한 답

: 4

 

※논리 연산식이므로 값이 정수가 아니라 true와 false의 값을 반환한다.

 

A

: true     false

 

이 문제는 논리 연산자를 사용하는 문제이다.

함수 func( ) 안에서 변수 i, j, k, l, m을 선언하고 이들 변수에 값을 할당한다.

그 다음 논리 연산자 || (OR)과 &&(AND)를 사용하여 두 개의 논리식을 평가한다.

 

첫 번째 논리식(l = i > 5 || j != 0;) 에서는 변수 i가 5보다 크거나 (j의 값은 무시) j가 0이 아니어야 한다는 뜻이다.

그러나 i의 값은 5이고, j는 0이 이나므로 이 논리식의 값은 true가 된다.

 

두 번째 논리식(m = j <= 4 && k < 1;)에서는 변수 j가 4보다 작거나 같지 않으며 변수 k의 값이 1보다 작아야 한다는 의미이다.

그러나 변수 j가 4보다 작거나 같지 않으므로 m 변수의 값은  false가 된다.

 

 

 

 

14. 다음의 결괏값을 보고 빈 칸을 채우시오.

 const arr = [100, 200, 300, 400, 500];
    const text = arr.push(600);

    document.write(arr);

    const arr2 = [100, 200, 300, 400, 500];
    const text2 = arr2.unshift(600);

    document.write(arr2);

 

A

: 100, 200, 300, 400, 500, 600

   600, 100, 200, 300, 400, 500

 

문자열 메서드 push( )는 배열의 마지막 요소에 값을 추가하고 unshift는 문자열의 처음에 값을 추가한다.

 

 

 

 

 

15. 다음의 결괏값을 보고 빈 칸을 채우시오.

const obj = {
        a: 100, 
        b: 200
    };

    for(let key in obj) { 
        console.log(key);
    }

 

A

: a, b

 

이 문제는 obj(객체)의 키를 출력하는 구문이다.

여기서 객체의 키는 a, b이므로 출력되는 값은 a, b이다.

 

 

 

 

 

16. 다음의 결괏값을 보고 빈 칸을 채우시오.

let num = 0;

    while(false){
        num++;
        if( num == 3 ){
            continue;
        }
        if( num > 6 ){
            break;
        }
    }
    console.log(num);

 

A

: 0

 

while문을 사용하는 예시이다.

그러나 이 문제에서는 조건식이 항상 false이므로 while 문의 내부 코드는 실행되지 않는다.

즉, num 변수의 값은 0으로 유지된다.

 

 

 

 

17. 다음의 결괏값을 보고 빈 칸을 채우시오.

 let a, b, result;
    a = 7, b = 4
    result = a & b;

    console.log(result, a, b)

 

A

: 4   7    4

 

비트 AND 연산자(&)를 사용하여 두 개의 숫자를 비트 단위로 AND 연산하는 문제이다.

먼저 a와 b 변수에 각각 7과 4의 값을 할당한다.

그 다음 a & b 연산을 수행하고 결과값을 result 변수에 할당한다.

 

7은 2진수로 나타내면 0111이고, 4는 0100dlek.

비트 AND 연산은 각 비트별로 AND 연산을 수행하므로 다음과 같이 계산된다

   0111 (7)

&0100 (4)

------------

   0100 (4)

 

 

 

 

 

18. 다음의 결괏값을 보고 빈 칸을 채우시오.

 let a = 1, b = 2, c = 3, result;
    result = ++a + b++ + ++c;

    console.log(result);
    console.log(a);
    console.log(b+c);
    console.log(c);

 

A

: 8   2   7   4 

 

먼저 a, b, c 변수에 각각 1, 2, 3의 값을 할당한다.

그리고 ++a와 ++c를 실행하여 각각 1씩 증가시킨다.

그러면 a는 2, c는 4가 된다.

b는 후치 연산자로 2의 값을 그대로 가지고 있는 상태이다.

(b++는 후치 연산자이므로 =보다 우선순위가 낮아 연산되지 않는다)

 

++a의 값 2, 와 b (2)그리고 ++c의 값 4를 더한 결과를 result 변수에 할당한다.

즉, result의 값은 8이 된다.

 

cosole.log에서 ++a는 1에서 1을 증가시켜 2가 되고, 

b++는 2에서 1을 증가시켜 3이 되고,

++c는 3에서 1을 증가시켜 4가 된다.

 

 

 

 

 

19. 다음의 결괏값을 보고 빈 칸을 채우시오.

let data = [70, 80, 75, 60, 90];
    let best = 0;
    let score = 0;

    for(let i=0; i<data.length; i++){
        if(data[i]>80) {
            best++;
        }
        if(score < data[i]) {
            score = data[i];
        }
    }

    console.log(best, score)

 

best : 1     score: 90

 

이 문제에서 data 변수는 숫자 데이터를 담은 배열이다.

코드는 이 숫자들 중에 80 이상인 수의 개수와 가장 높은 수를 출력한다.

 

best 변수는 초기값으로 0을 가지고 있다.

이 변수는 for문을 통해 배열을 순회하면서, 80 이상인 수를 세기 위해 사용된다.

만약 배열에서 현재 값이 80 이상이라면 best 변수의 값을 1 증가 시킨다.

 

score 변수는 초기값으로 0을 가지고 있다.

이 변수는 for문을 통해 배열을 순회하면서 가장 높은 수를 찾기 위해 사용된다.

만약 배열에서 현재 수가 score 변수보다 크다면 score 변수의 값을 해당 점수로 대체한다.

 

실행 시 best 변수의 값은 1이 되고  (90만이 80보다 크기 때문) score 변수의 값은 90이 된다. (배열 안에서 가장 큰 수가 90이기 때문)

 

 

 

 

 

20. 다음의 결괏값을 보고 빈 칸을 채우시오.

function func(num1, num2){
        if(num1 > num2) return num1
        else return num2
    }
    console.log(func(10, 23) + func(40, 50))

 

A

: 73

 

이 문제는 두 개의 숫자 중에서 더 큰 값을 반환하여 서로 더하는 문제이다.

 

func 함수는 두 개의 숫자를 인자로 받는다.

만약 첫 번째 인자 num1이 두 번째 인자 num2 보다 크다면 num1을 반환하고, 그렇지 않으면 num2를 반환한다.

 

func(10,23)은 num1(10)이 num2(23)보다 작기 때문에 num2인 23을 반환하고,

func(40, 50)은 num1(40)이 num2(50) 작기 때문에 num2인 50을 반환한다.

 

따라서 func(10,23) + func(40,50)은 23+50 즉, 73이 된다.

 

 

 

 

 

 

 

728x90
반응형

 

 

 

 

 

화살표 함수 - 익명 함수 + 매개변수 함수 + 리턴값 함수

const func = (str) => {
        return str;
    };
    document.write(func("실행되었습니다"))

 

func 함수는 하나의 매개변수 str을 받아들이고, 이 매개변수를 그대로 반환한다.

함수가 호출될 때, func("실행되었습니다")와 같이 문자열 "실행되었습니다"가 매개변수로 전달된다.

이 문자열은 함수 내부에서 str이라는 매개변수에 저장된다.

 

그리고 이 함수는 return 키워드를 사용하여 매개변수 str을 반환한다.

즉, 문자열 "실행되었습니다"가 반환된다.

 

document.write() 함수를 사용하여 반환된 문자열이 화면에 표시된다.

 

 

 

 

 

화살표 함수 - 익명 함수 + 매개변수 함수 + 리턴값 함수 (괄호가 생략된 형태)

 const func = str => {
    return str;
    }
    document.write(func("실행되었습니다"))

 

함수의 이름은 func이고, 매개변수는 str이다.

화살표 함수의 형태를 사용하여 함수를 정의한다.

 

return 키워드를 사용하여 str 매개변수를 반환한다.

이 함수는 문자열을 받아들이고 그 문자열을 그대로 반환하는 기본적인 함수이다.

 

마지막으로 document.write( ) 함수를 사용하여 반환된 문자열을 추ㅜㄹ력한다.

func("실행되었습니다") 라인에서 함수가 호출되며, 이때 매개변수로 문자열 "실행되었습니다"가 전달된다.

그리고 함수는 전달받은 문자열 "실행되었습니다"를 반환하고, 이 문자열이 document.write( )를 통해 출력된다.

 

 

 

 

 

화살표 함수 - 익명 함수 + 매개변수 함수 + 리턴값 함수 (괄호와 return이 생락된 형태)

const func = str => str;
    document.write(func("실행되었습니다"))

 

const func = str => str; 라인에서 함수의 이름은 func이고, 매개변수는 str 이다.

화살표 함수의 형태를 사용하여 함수를 정의한다.

 

함수의 본문은 return 키워드 없이 str 매개변수를 그대로 반환한다.

이 함수는 문자열을 받아들이고, 받아들인 문자열을 그대로 반환하는 기능을 가졌다.

 

func("실행되었습니다")를 호출하여 문자열 "실행되었습니다"를 전달한다.

이때, 함수 내부에서는 매개변수 str이 문자열 "실행되었습니다"로 설정되고, 이 문자열이 함수 내부의 표현식으로 평가된다.

그리고 평가된 문자열이 바로 함수의 반환 값이 된다.

 

마지막으로 document.write( ) 함수를 사용하여 반환된 문자열을 출력한다.

func("실행되었습니다") 라인에서 함수가 호출되며, 이때 매개변수로 문자열 "실행되었습니다"가 전달된다.

그리고 함수는 전달받은 문자열 "실행되었습니다"를 반환하고, 이 문자열이 document.write( )함수를 통해 출력한다.

 

 

 

 

 

함수 유형 - 함수와 매개변수를 이용한 형태

{
    function func(num, str1, str2) {
        document.write(num + ". " + str1 + "가 " + str2 + "되었습니다", "<br>");
    }
    func("1", "함수", "실행");
    func("2", "자바스크립트", "실행");
    func("3", "리액트", "실행");
}
document.write("<br>",1,"<br>");

func 함수는 세 개의 매개변수 num, str1, str2를 가지고 있다.

이 함수는 document.write( ) 메서드를 사용하여 입력받은 세 개의 매개변수를 조합하여 문서에 출력한다.

 

먼저 "func" 라는 이름의 함수가 정의되어 있다.

이 함수는 세 개의 입력값 (num, str1, str2)을 받아서 document.write( ) 메서드를 사용하여 입력된 내용을 화면에 출력한다.

그리고 함수를 세 번 호출하면서, 각 호출마다 다른 입력값(num, str1, str2)를 전달한다.

함수를 호출하는 부분에서는 func( ) 함수에 첫 번째 인자로 1, 두 번째 인자로 "함수", 세 번째 인자로 "실행"을 전달하여 호출하고, 두 번째와 세 번 째 호출에서는 각각 "자바스크립트", "리액트"를 첫 번째 인자 대신 전달하여 호출한다.

 

 

 

 

 

함수 유형 - 함수와 변수를 이용한 형태

 function func(num, str1, str2) {
        document.write(num + ". " + str1 + "가 " + str2 + "되었습니다", "<br>");
    }
    const youNum1 = 1;
    const youNum2 = 2;
    const youNum3 = 3;

    const youStr1 = "함수";
    const youStr2 = "자바스크립트";
    const youStr3 = "리액트";

    const youCom1 = "실행 ";

    func(youNum1, youStr1, youCom1);
    func(youNum2, youStr2, youCom1);
    func(youNum3, youStr3, youCom1);

 

func()는 num, str1, str2까지 총 세 개의 매개변수를 가지며, 각각 숫자와 문자열 속성을 가진다.

주어진 매개변수를 사용하여 문장을 생성하고 이 문장을 document.write를 사용하여 웹 페이지에 출력한다.

이 함수를 사용하기 위해 youNum1, youStr1 등이 상수로 선언되어 있으며, 각각 숫자와 문자열을 저장하는데 사용된다.

func()함수를 호출하여 출력할 문장을 생성한다.

각각의 호출은 num으로 숫자열을, str1로 첫번째 문자열을, str2로 두번째 문자열을 전달한다.

이렇게 전달된 매개변수들은 함수에 의해 문장으로 조합되어 출력된다.

 

 

 

 

 

함수 유형 - 함수와 배열을 이용한 형태 

function func(num, str1, str2) {
        document.write(num + ". " + str1 + "가 " + str2 + "되었습니다", "<br>");
    }
    const num = [1, 2, 3];
    const info = ["함수", "자바스크립트", "리액트", "실행"];

    func(num[0], info[0], info[3]);
    func(num[1], info[1], info[3]);
    func(num[2], info[2], info[3]);

 

함수 func()는 세 개의 매개변수를 가지며, 문장을 생성하고 출력한다.

매개변수 num은 숫자, str1과 str2는 문자열 타입이다.

상수(const) num은 [1,2,3] 배열을 할당 받으며, 상수 info는 ["함수", "자바스크립트", "리액트","실행"] 배열을 할당받는다.

이 배열들은 각각 숫자와 문자열을 저장하는데 사용된다.

함수 func()를 호출할 때, 배열의 인덱스(키)를 사용하여 각가의 매개변수를 전달한다.

첫번째 호출에서는 num[0], info[0], info[3]을 전달하고,

두번째 호출에서는 num[1], info[1], info[3]을 전달한다. 같은 방식으로 인덱스만 바뀌어 세번째 호출도 수행된다.

함수 func()는 이러한 매개변수를 사용하여 문장을 생성하고, 문장은 document.write를 사용하여 출력된다.

출력된 문장은 "숫자. 문자열1 이 문자열2 가 되었습니다"의 형태를 갖는다.

 

 

 

 

 

함수 유형 - 함수와 객체를 이용한 형태

function func(num, str1, str2) {
        document.write(num + ". " + str1 + "가 " + str2 + "되었습니다", "<br>");
    }
    const info = {
        num1: 1,
        name1: "함수",
        num2: 2,
        name2: "자바스크립트",
        num3: 3,
        name3: "리액트",
        word: "실행"
    }
    func(info.num1, info.name1, info.word);
    func(info.num2, info.name2, info.word);
    func(info.num3, info.name3, info.word);

 

상수(const)info는 객체 형태를 띄며 num1, num2, num3, name1, name2, name3, word까지 7개의 속성을 가진다.

이 속성들을 각각 숫자와 문자열을 저장하며, 이들은 함수 호출 시에 매개변수로 사용된다.

함수 func()를 호출할 때는, 객체 info의 속성에 접근하여 각각의 매개변수를 전달한다.

첫번째 호출에서는 info.num1, info.name1, info.word를 전달하고,

두번째 호출에서는 info.num2, info.name2, info.word를 전달한다. 같은 방식으로 세번째 호출도 실행된다.

객체를 불러오는 방식으로 .(온점)을 찍어 속성에 접근하여 매개변수를 전달할 수 있게 한다.

 

 

 

 

 

함수 유형 - 함수와 배열, 객체를 이용한 형태

function func(num, str1, str2) {
        document.write(num + ". " + str1 + "가 " + str2 + "되었습니다", "");
    }
    const info = [
        {
            num: 1,
            name: "함수",
        }, {
            num2: 2,
            name: "자바스크립트"
        }, {
            num3: 3,
            name: "리액트",
            word: "실행"
        }
    ]
    func(info[0].num, info[0].name, info[2].word);
    func(info[1].num2, info[1].name, info[2].word);
    func(info[2].num3, info[2].name, info[2].word);

 

상수(const)info는 배열 형태를 띄며, 배열 안에는 세 개의 객체가 저장되어 있다.

객체마다 숫자와 문자열을 저장하며, 세번째 객체는 word라는 속성도 추가로 갖는다.

함수 func를 호출할 때는, 배열 info의 각 객체에 접근하여 각각의 매개변수를 전달한다.

배열의 값에 접근하기 위해 [ ] 대괄호를 사용하고 객체의 값에 접근하기 위해 .(온점)을 사용한다.

배열 안에 객체가 있는 형태를 갖추고 있기 때문에 배열의 값에 접근하는 방법과 객체의 값에 접근하는 방법 두 가지 모두를 사용한다.

 

 

 

 

 

함수 유형 - 객체 안에 함수를 이용한 형태

const info = {
        num1: 1,
        name1: "함수",
        num2: 2,
        name2: "자바스크립트",
        num3: 3,
        name3: "리액트",
        word: "실행",
        result1: function(){
            document.write(info.num1 + ". " + info.name1 + "가 " + info.word + "되었습니다", "<br>");
        },
        result2: function(){
            document.write(info.num2 + ". " + info.name2 + "가 " + info.word + "되었습니다", "<br>");
        },
        result3: function(){
            document.write(info.num3 + ". " + info.name3 + "가 " + info.word + "되었습니다", "<br>");
        }
    }
    info.result1();
    info.result2();
    info.result3();

 

상수 info는 객체를 나타내며, 속성으로 숫자와 문자열을 저장한다.

또한 result1~3까지 속성으로 추가되어 있다.

이들 속성은 함수를 나타내며, 문장을 생성하고 출력한다.

 

각각의 속성들은 다음과 같은 역할이다.

 

num1, num2, num3:  각각 숫자 값을 가진다.

name1, name2, name3: 각각 문자열 값을 가진다.

word: 문자열 값을 가진다.

result1, result2, result3: 함수 값을 가진다. 각각의 함수는 document.write 메서드를 사용하여 입력된 속성 값을 조합하여 웹 페이지에 출력한다.

 

result1, result2, result3이 전부 객체의 속성이기 때문에 함수를 세 번 호출하기 위해  info 뒤에 온점을 찍어 객체 안에 저장되어 있는 result에 접근한다.

 

 

 

 

 

함수 유형 - 객체 생성자 함수

function Func (num, name, word) {
        this.num = num;                
        this.name = name;
        this.word = word;

        this. result = function () {
            document.write(this.num + ". " + this.name + "가 " + this.word + "되었습니다", "<br>");
    }
    }
    //인스턴스 생성
    const info1 = new Func(1,"함수","실행");             
    const info2 = new Func(2,"자바스크립트","실행");  
    const info3 = new Func(3,"리액트","실행"); 

    info1.result();
    info2.result();
    info3.result();

 

Func라는 생성자 함수를 정의하고, 해당 함수를 통해 객체를 생성하는 방식이다.

생성자 함수는 num, name, word 3개의 인자를 받아서 해당 인자를 프로퍼티로 가지는 객체를 생성한다.

this 키워드를 통해 생성된 객체의 프로퍼티를 저장한다.

result라는 메서드는 생성자 함수 Func를 통해 생성된 객체에 포함되는 함수로, 프로퍼티를 참조하여 결과값을 출력하는 역할을 한다.

생성자 함수는 일반 함수와 차이를 두기 위해 함수명의 첫 문자를 대문자로 표현한다.

생성자 함수로 생성된 객체의 속성 추가, 삭제, 변경은 다른 객체의 속성에 영향을 주지 않는다.

또한, 함수 안의 this는 함수를 통하여 생성되는 객체를 의미한다.

 

 

 

 

 

함수 유형 - 프로토타입 함수

 function Func(num, name, word) {
        this.num = num;
        this.name = name;
        this.word = word;
    }
    Func.prototype.result = function (){
        document.write(this.num + ". " + this.name + "가 " + this.word + "되었습니다", "");
    }
    const info1 = new Func(1,"함수","실행");             
    const info2 = new Func(2,"자바스크립트","실행");  
    const info3 = new Func(3,"리액트","실행");

    info1.result();
    info2.result();
    info3.result();

 

생성자 함수 Func를 정의하고 Func.prototype 객체에 result 메서드를 추가한 후, "new" 연산자를 사용하여 생성자 함수를 호출하여

객체 인스턴스를 생성하고, 생성된 인스턴스에서 result 메서드를 호출한다.

Func 생성자 함수는 num, name, word 3개의 인자를 받아서 객체의 프로퍼티로 할당한다.

Func.prototype.result 메서드는 생성된 객체 인스턴스에서 호출될 수 있도록 프로토타입 체인에 추가된다.

result 메서드는 this를 통해 함수 안에 생성된 데이터를 이용하여 문장을 만들고 이를 document.write를 이용하여 출력한다.

생성자 함수에서 정의한 속성을 그대로 상속받는다.

생성자 함수 내에 정의하지 않고도 생성된 객체에서 호출하여 사용할 수 있다.

 

 

 

 

 

 

728x90
반응형

 

 

 

슬라이드 유형 사이트

 

 

 

완성 화면

https://fitalux.github.io/web2023/site/sliderType/sliderType01.html

 

 

 

 

 

코드 보기 / CSS 

 

/* slider__wrap */
        .slider__inner .slider {
            height: 600px;
            background-image: url(../asset/img/sliderType01_01.jpg);
            background-size: cover;
            background-repeat: no-repeat;
            background-position: center;
            position: relative;
            z-index: 1;
        }
        .slider__info {
            padding: 100px 0;
        }
        .slider__info .small {
            display: inline-block;
            padding: 1px 30px;
            background-color: #fff;
            color:#000;
            font-size: 16px;
            border-radius: 50px;
            text-transform: uppercase;
            margin-bottom: 10px;
        }
        .slider__info .title{
            font-size: 80px;
            color: #fff;
            margin-bottom: 40px;
            margin-right: -5px;
        }
        .slider__info .desc{
            font-size: 18px;
            line-height: 1.5;
            color: #fff;
            width: 50%;
            word-break: keep-all;
        }
        .slider__info .btn{
            margin-top: 100px;
        }
        .slider__info .btn a{
            width: 180px;
            background-color: #fff;
            font-size: 16px;
            display: inline-block;
            text-align: center;
            padding: 12px 0;
            margin-right: 4px;
        }
        .slider__info .btn a:last-child {
            background-color: #000;
            color: #fff;
        }
        .slider__arrow a {
            position: absolute;
            top: 50%;
            background-image: url(../asset/img/icon_main.svg);
            background-size: 500px;
            width: 30px;
            height: 56px;
            display: block;
            margin-top: -28px;
        }
        .slider__arrow a:first-child {
            left: 20px;
        }
        .slider__arrow a:last-child {
            right: 20px;
            background-position: -52px 0;
        }
        .slider__dot {
            position: absolute;
            left: 50%;
            bottom: 20px;
            transform: translateX(-50%);
        }
        .slider__dot a {
            width: 16px;
            height: 16px;
            display: inline-block;
            background-image: url(../asset/img/icon_main.svg);
            background-size: 500px;
            margin: 0 3px;
        }
        .slider__dot a.dot {
            background-position: -101px -1px;
        }
        .slider__dot a.active {
            background-position: -121px -1px;
        }
        .slider__dot a.play {
            background-position: -141px -1px;
        }
        .slider__dot a.stop {
            background-position: -161px -1px;
        }
        @media only screen and (-webkit-min-device-pixel-ratio: 2),
            only screen and (min-device-pixel-ratio: 2),
            only screen and (min-resolution: 2dppx) {
                .slider__inner .slider {
                    background-image: url(../asset/img/sliderType01_01@2x.jpg);
                }
    	}

 

 

 

 

 

코드 보기 / HTML

 

<section class="slider__wrap nexon">
        <h2 class="blind">메인 슬라이드 영역</h2>
        <div class="slider__inner">
            <div class="slider">
                <div class="slider__info container">
                    <span class="small">notice</span>
                    <h3 class="title">광활한 우주에 펼쳐진 길, 은하수</h3>
                    <p class="desc"> 은하수는 끝이 없는 우주의 신비로운 대상이며, 그 안에는 끊임없이 진화하는 별들과 이례적인 천문학적 현상들이 숨어 있습니다.</p>
                    <div class="btn">
                        <a href="#">자세히 보기</a>
                        <a href="#">알아보기</a>
                    </div>
                </div>
                <div class="slider__arrow">
                    <a href="#"><span class="blind">이전 이미지</span></a>
                    <a href="#"><span class="blind">다음 이미지</span></a>
                </div>
                <div class="slider__dot">
                    <a href="#" class="dot active"><span class="blind">첫번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">두번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">세번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">네번째 이미지</span></a>
                    <a href="#" class="dot"><span class="blind">다섯째 이미지</span></a>
                    <a href="#" class="play"><span class="blind">play</span></a>
                    <a href="#" class="stop"><span class="blind">stop</span></a>
                </div>
            </div>
        </div>
    </section>

 

 

 

 

 background-image: url(../asset/img/sliderType01_01.jpg);

:slider 요소의 배경 이미지를 sliderType01_01.jpg로 지정하는 것.

 

 

 

background-size

:배경 이미지의 크기를 설정하는데 사용된다.

속성  역할
cover 이미지를 요소의 크기에 맞게 늘려서 모두 보이도록 한다.
이미지의 일부가 잘릴 수 있다.
contain 이미지를 요소의 크기에 맞게 축소해서 모두 보이도록 한다.
요소의 일부가 노출될 수 있다.
길이 값 (ex. 100px, 50px 등) 이미지의 크기를 지정한 길이로 설정한다.
100px, 50px 등과 같이 가로와 세로의 크기를 각각 설정할 수 있다.
백분율 값 (ex. 50%, 100% 등) 이미지의 크기를 요소의 백분율로 설정한다.
50%, 100%와 같이 가로와 세로의 크기를 각각 설정할 수 있다.

 

    background-size: cover;

    :배경 이미지를 요소 크기에 맞게 늘리거나 줄여서 모두 보이도록 설정하는 것. 

 

 

 

 background-repeat

:배경 이미지가 반복되는 방식을 설정하는데 사용된다.

repeat 이미지를 수평, 수직 방향으로 반복해서 배치
repeat-x 이미지를 수평 방향으로 반복해서 배치
repeat-y 이미지를 수직 방향으로 반복해서 배치
no-repeat 이미지를 반복하지 않고 한 번만 배치

 

    background-repeat: no-repeat;

    :배경 이미지가 반복되지 않도록 설정하는 것.

 

 

 

    background-position: center;

    :배경 이미지가 요소 중앙에 위치하도록 설정하는 것.  

 

 

 

word-break

:한 줄에 글자가 너무 길어서 줄 바꿈이 필요할 때 단어를 분리하는 방식을 설정한다.

nomal 기본값으로 단어를 분리
break-all 모든 문자에서 줄바꿈을 하여 단어를 분리
keep-all 단어 중간에서는 분리하지 않고 다음 줄로 이동.
단어의 시작 부분에서만 분리.
break-word 단어가 아니라 긴 문자열에서 줄바꿈을 하여 분리.
단어가 아니라도 분리할 수 잇는 경우에는 break-all과 동일하게 처리.

 

word-break: keep-all

:클래스명이 desc인 요소 안의 텍스트들은 단어의 중간에서 분리하지 않고 다음 단어의 시작 부분에서 줄바꿈하도록 설정.

 

 

 

 @media only screen and (-webkit-min-device-pixel-ratio: 2),
            only screen and (min-device-pixel-ratio: 2),
            only screen and (min-resolution: 2dppx) {
                .slider__inner .slider {
                    background-image: url(../asset/img/sliderType01_01@2x.jpg);
                }

@media 를 사용하여 디바이스의 픽셀 밀도가 2x 이상인 경우에만 적용되는 스타일을 정의한다.

 

(-webkit-min-device-pixel-ratio: 2)

: 웹킷 기반 브라우저에서 디바이스의 픽셀 밀도를 지정하는 속성

 

min-device-pixel-ratio

: 그 외 브라우저에서 디바이스의 픽셀 밀도를 지정하는 속성.

 

min-resolution

:디바이스의 해상도를 지정하는 속성.

이 중 하나라도 해당되는 경우, 슬라이더의 이미지를 @2x의 해상도로 변경한다.

 

@2x 해상도 이미지는 고해상도 디스플레이에서 더욱 선명한 이미지를 제공한다.

 

 

 

 

 

 

728x90
반응형

이미지 유형 사이트

 

 

 

 

완성  화면

 

 

 

 

 

코드 보기 / CSS

 /* reset */
         * {
            margin: 0;
            padding: 0;
        }
        a {
            text-decoration: none;
            color:#000;
        }
        h1,h2,h3,h4,h5,h6 {
            font-weight: normal;
        }
        img {
            vertical-align: top;
            width: 100%;
        }
        .mt10 {margin-top: 10px !important;}
        .mt20 {margin-top: 20px !important;}
        .mt30 {margin-top: 30px !important;}
        .mt40 {margin-top: 40px !important;}
        .mt50 {margin-top: 50px !important;}
        .mt60 {margin-top: 60px !important;}
        .mt70 {margin-top: 70px !important;}

        .mb10 {margin-bottom: 10px !important;}
        .mb20 {margin-bottom: 20px !important;}
        .mb30 {margin-bottom: 30px !important;}
        .mb40 {margin-bottom: 40px !important;}
        .mb50 {margin-bottom: 50px !important;}
        .mb60 {margin-bottom: 60px !important;}
        .mb70 {margin-bottom: 70px !important;}

        /* common */
        .container {
            width: 1160px;
            margin: 0 auto;
            padding: 0 20px;
            /* background-color: rgba(0,0,0,0.1); */
        }
        .nexon {
            font-family: 'NexonLv1Gothic';
            font-weight: 400;
        }
        .section {
            padding: 120px 0;
        }
        .section.center {
            text-align: center;
        }
        .section__small {
            font-size: 14px;
            border-radius: 50px;
            background-color: #AC43FF;
            color: #fff;
            padding: 1px 23px;
            text-transform: uppercase;
            margin-bottom: 20px;
            display: inline-block;
        }
        .section__h2 {
            font-size: 50px;
            color: #000;
            font-weight: 400;
            margin-bottom: 30px;
            line-height: 1;
        }
        .section__desc {
            font-size: 22px;
            color: #666;
            margin-bottom: 70px;
            font-weight: 300;
            line-height: 1.5;
        }
        .img-text__inner {
            justify-content: space-between;
            display: flex;
            flex-wrap: wrap;
        }
        .img-text__inner .text {
            width: 374px;
            height: 500px;
            margin-right: 15px;
        }
        .image__body {
            width: 374px;
            height: 500px;
            margin-right: 10px;
            border-radius: 10%;
        }

        </style>

 

 

 

 

코드 보기 / HTML

<section class="img-text__wrap section nexon">
        <div class="container">
            <div class="img-text__inner">
                <article class="text">
                    <span class="section__small">notice</span>
                    <h2 class="section__h2">나선형 은하(Spiral Galaxy)</h2>
                    <span class="desc">나선형 은하는 중심 부분에 바(bar)와 팔(arm) 형태로 뻗어나가는 구조입니다.</span>
                    <p class="desc">
                        나선형 은하 안에는 주로 별들이 모여있는 은하원반이 있습니다. 이 은하원반 안에는 다양한 크기와 모양의 은하들이 분포해 있습니다.
                        이러한 은하들은 대부분 나선형 은하 안의 중심 부분인 바 주변이나 나선형 팔 사이에 위치하고 있습니다. 이러한 은하들을 위성 은하(Satellite Galaxy) 또는 동반 은하(Companion Galaxy)라고 합니다.
                        이렇게 나선형 은하 안에 위치한 위성 은하들은 나선형 은하와 서로 상호작용하면서 형태를 바꾸는 등의 영향을 끼치기도 하며, 형태에 따라 다양한 종류가 있습니다.</p>
                </article>
                    <article class="image">
                        <figure class="image__body">
                            <img src="../asset/img/img-textType01_01.jpg" alt="나선 은하">
                        </figure>
                    </article>
                    <article>
                        <figure class="image__body">
                            <img src="../asset/img/img-textType01_02.jpg" alt="나선형 은하">
                        </figure>
                    </article>
            </div>
        </div>
    </section>

 

 

 

.img-text__inner {
            justify-content: space-between;
            display: flex;
            flex-wrap: wrap;
        }

 

jusrify-content: space-between;

: img-text__inner  요소 안에 자식 요소로 있는 두 장의 이미지와 텍스트를 일정한 간격으로 떨어뜨리기 위해 요소들을 양끝으로 정렬하는 속성을 주었음.

 

 

display: flex;

:내부 요소들을 배치하기 위해 해당 요소를 플렉스 컨테이너로 만듦.

 

flex-wrap

:내부 요소들이 한 줄로 배치되는 것이 아니라 여러 줄로 나누어서 배치되도록 함.

요소들이 부모 요소의 너비를 벗어날 경우 자동으로 줄바꿈 되어 다음 줄에 배치됨.

 

 

또한, 이미지와 텍스트 박스를 정렬하기 위해서는 전부 article로 감쌀 필요가 있었음.

article로 감싸주지 않을 시, 독립적인 컨텐츠 영역이 정의되지 않아 jusrify-content: space-between; 속성이 먹히지 않음.

 

 

 

 

.image__body {
            width: 374px;
            height: 500px;
            margin-right: 10px;
            border-radius: 10%;
}

 

 

image__body 라는 클래스명을 가진 요소들의 너비와 높이를 지정해주는 속성으로, 여기서는 두 장의 이미지에 사용되었다.

이미지의 가로 너비(width)를 374px로 지정하였고, 세로 높이(height)를 500px로 지정하였다.

이미지 사이에 적당한 간격을 주기 위해 margin-bottom : 10px 속성을 주었고,

모서리를 살짝 둥굴게 처리하기 위해 border-radius: 10% 속성을 주었다.

 

 

 

<section class="img-text__wrap section nexon"> <seciton>

section 태그 안에 있는 모든 요소들에 폰트가 적용될 수 있도록 클래스명 nexon을  작성함.

section 안에 있는 small 태그나, h2 태그가 미리 작성해놓은 css의 속성을 상속받을 수 있도록 클래스명 section을 작성함

 

 

<span class="desc">나선형 은하는 중심 부분에 바(bar)와 팔(arm) 형태로 뻗어나가는 구조입니다.</span>
<p class="desc">
나선형 은하 안에는 주로 별들이 모여있는 은하원반이 있습니다. 이 은하원반 안에는 다양한 크기와 모양의 은하들이 분포해 있습니다.
이러한 은하들은 대부분 나선형 은하 안의 중심 부분인 바 주변이나 나선형 팔 사이에 위치하고 있습니다. 이러한 은하들을 위성 은하(Satellite Galaxy) 또는 동반 은하(Companion Galaxy)라고 합니다.
이렇게 나선형 은하 안에 위치한 위성 은하들은 나선형 은하와 서로 상호작용하면서 형태를 바꾸는 등의 영향을 끼치기도 하며, 형태에 따라 다양한 종류가 있습니다.</p>
</article>

 

이전의 유형들과는 다르게 소제목이 없으며, 큰 제목을 제외한 모든 텍스트들이 글자색과 글자 크기 등 자잘한 속성이 모두 같기 때문에  따로 속성을 주지 않고, 

각각 span 태그, p 태그에  desc 클래스를 추가하여 한꺼번에 같은 속성이 적용되도록 하였다.

 

 

+ Recent posts