롤링배너(?) 갤러리 > 개발자팁

개발자팁

개발과 관련된 유용한 정보를 공유하세요.
질문은 QA에서 해주시기 바랍니다.

롤링배너(?) 갤러리 정보

롤링배너(?) 갤러리

본문

 

https://sir.kr/qa/495896 - 질문이 올라와서 예전에 만들어 두었던 것을 약간 보층해서 코드 공유합니다.

제가 별로 안 쓰는 형태라 개별버튼은 안 만들었습니다.^^

장면전환시 애니메이션 css 를 쓰지 않고 레거시(?)한 방식으로 감속탄성 코드를 자바스크립트에서 만들었습니다.

 

https://wittazzurri.com/editor/html_editor.php 에서 확인해 보세요.

 

image_1 부터 image_n 까지 원하는 대로...

 


<style>
#galleryDiv { position:relative; margin:0 auto; }
#imageDiv { overflow:hidden; }
#imageDiv div { display:flex; width:200%; }
#imageDiv img { display:block; width:50%; }
#buttonDiv { position:absolute; top:0px; width:100%; height:100%; padding:20px; display:flex; justify-content:space-between; align-items:center; box-sizing:border-box; }
#buttonDiv img { display:block; cursor:pointer; width:50px; height:50px; }
</style>
<div id="galleryDiv">
    <div id="imageDiv"><div><img><img></div></div>
    <div id="buttonDiv"><img><img></div>
</div>
<script>
autoSec = 5; // 자동넘기기 - 초단위
targetSpeed = 10; // 장면전환 속도 - 숫자가 커질수록 느려짐
leftButton = "https://blog.kakaocdn.net/dn/I1GYB/btq8bL8uxVv/guiZYpTMedre9zj97Y1jk0/img.png"; // 좌버튼 이미지
rightButton = "https://blog.kakaocdn.net/dn/bniCh0/btq8bsg19MB/PJUsaJdJkpJdbkHcWUC9wk/img.png"; // 우버튼 이미지
image_1 = "https://blog.kakaocdn.net/dn/bS0Wvp/btr8J1cQhlx/hl8E8tv5M9rfwvuma8q6Fk/img.jpg";
image_2 = "https://blog.kakaocdn.net/dn/zYSgG/btr8P0DskTO/i6JzVmVy3gsM5by353o3E0/img.jpg";
image_3 = "https://blog.kakaocdn.net/dn/bD8PyW/btr8LgN5SsY/AvjSnqZ0xgsM3FvpHsaDh1/img.jpg";
image_4 = "https://blog.kakaocdn.net/dn/dSddpv/btr8Mn64wqT/b5P6xKyDYfVXuDOeEtcKtK/img.jpg";
image_5 = "https://blog.kakaocdn.net/dn/cBCuTv/btr8J48xbjE/e5z35o9vMjSJeYJA8auRJ1/img.jpg";
buttonDiv.querySelectorAll("img")[0].src = leftButton;
buttonDiv.querySelectorAll("img")[1].src = rightButton;
for (imgTotal = 0; this["image_" + (imgTotal + 1)]; imgTotal++);
function imageMode() {
    imageDiv.querySelectorAll("img")[0].src = this["image_" + arguments[0]];
    imageDiv.querySelectorAll("img")[1].src = this["image_" + (arguments[0] === imgTotal ? 1 : ++arguments[0])];
    targetCount = 0;
}
addEventListener("resize", galleryMode = () => {
    galleryDiv.style.width = "100%";
    galleryWidth = Math.floor(galleryDiv.offsetWidth);
    galleryDiv.style.width = galleryWidth + "px"; 
    galleryPoint = -galleryWidth;
    imageDiv.querySelector("div").style.marginLeft = "0px";
} );
galleryMode();
imageMode(img = 1);
buttonDiv.querySelectorAll("img")[0].onclick = () => {
    targetCount = autoSec * 100;
    for (ic of document.querySelectorAll("#imageDiv, #imageDiv img")) ic.style.transform = "rotateY(180deg)";
}
buttonDiv.querySelectorAll("img")[1].onclick = () => {
    targetCount = autoSec * 100;
    for (ic of document.querySelectorAll("#imageDiv, #imageDiv img")) ic.style.transform = "rotateY(0deg)";
} 
setInterval(() => {
    ++targetCount;
    changePoint = Number(imageDiv.querySelector("div").style.marginLeft.slice(0, -2));
    if (Math.abs(changePoint - galleryPoint) <= 0.5) {
        imageDiv.querySelector("div").style.marginLeft = "0px";
        imageMode(img = img === imgTotal ? 1 : ++img);
    }
    else {
        if (targetCount >= 0 && targetCount < autoSec * 100) changePoint = 0;
        else changePoint += (galleryPoint - changePoint) / targetSpeed;
        imageDiv.querySelector("div").style.marginLeft = changePoint + "px";
    }
}, 10);
</script>
추천
7

댓글 20개

@들레아빠 감사합니다. 참고로
image_1 에서 image_n 까지 최종숫자 n 을 추출하는 코드는 아래처럼 imgTotal 을 추출하는 것이 좋습니다. 최종숫자를 입력할 필요가 없거든요.

for (imgTotal = 0; this["image_" + (imgTotal + 1)]; imgTotal++);

https://sir.kr/g5_tip/16115
@들레아빠
<script>
image_1 = ["1.jpg"];
document.write(typeof image_1);
</script>
<br>
<script>
image_1 = "1.jpg";
document.write(typeof image_1);
</script>

이리하면 변수의 타입이 처음은 오브젝트(배열등) 다음은 스트링(문자열)으로 나타납니다.
단순 문자열을 굳이 배열에 담아 리소스를 키울 필요가 없거든요.
아래처럼 바꾸세요.

this['image_' + i] = "/img/banner/"+i+".jpg";
좋습니다^^
자바스크립트로 만든 갤러리가 오류도 안나고 그누보드 버전에 관계없이 사용할 수있어서 좋은것 같습니다
이미지에 링크를 주려면 이미지 앞에 a 태그를 사용해서 하는데요.
<a href="https://sir.kr">image_1 = "https://blog.kakaocdn.net/dn/bS0Wvp/btr8J1cQhlx/hl8E8tv5M9rfwvuma8q6Fk/img.jpg";</a>
이렇게 하면 될것 같은데, 적용해 보니 잘 안되는데요.
링크에도 for 문을 사용해야 되는지요.
감사합니다.
@김철용
1. 링크영역의 최대확보를 위해 #buttonDiv 의 padding 을
padding:20px; 에서 padding:0px 20px; 으로 바꿉니다.

2. css 에서 a 를 정의해 주구요. 시각화를 위해 배경색을 red 로 깔아줍니다.
#buttonDiv a { width:100%; height:100%; background-color:red; }

3. <div id="buttonDiv"><img><img></div> 를 아래처럼 고치고요.
<div id="buttonDiv"><img><a target="_blank"></a><img></div>

4. image_1 부터 image_5 아래에 같은 숫자의 링크 변수를 만들어 줍니다.
link_1 = "1번링크주소";
link_2 = "2번링크주소";
link_3 = "3번링크주소";
link_4 = "4번링크주소";
link_5 = "5번링크주소";

5. function imageMode() 의 가장 상단에 링크코드를 한줄만 더 첨가합니다.

function imageMode() {
	buttonDiv.querySelector("a").href = this["link_" + arguments[0]];
	imageDiv.querySelectorAll("img")[0].src = this["image_" + arguments[0]];
	imageDiv.querySelectorAll("img")[1].src = this["image_" + (arguments[0] === imgTotal ? 1 : ++arguments[0])];
	targetCount = 0; 
}

6. 확인이 끝났으면 2번에서 배경 빨간색을 삭제합니다.
#buttonDiv a { width:100%; height:100%; }

그래서 최종으로...

<style>
#galleryDiv { position:relative; margin:0 auto; }
#imageDiv { overflow:hidden; }
#imageDiv div { display:flex; width:200%; }
#imageDiv img { display:block; width:50%; }
#buttonDiv { position:absolute; top:0px; width:100%; height:100%; padding:0px 20px; display:flex; justify-content:space-between; align-items:center; box-sizing:border-box; }
#buttonDiv img { display:block; cursor:pointer; width:50px; height:50px; }
#buttonDiv a { width:100%; height:100%; }
</style>
<div id="galleryDiv">
	<div id="imageDiv"><div><img><img></div></div>
	<div id="buttonDiv"><img><a target="_blank"></a><img></div>
</div>
<script>
autoSec = 5; // 자동넘기기 - 초단위
targetSpeed = 10; // 슬라이드 속도 - 숫자가 커질수록 느려짐
leftButton = "https://blog.kakaocdn.net/dn/I1GYB/btq8bL8uxVv/guiZYpTMedre9zj97Y1jk0/img.png"; // 좌버튼 이미지
rightButton = "https://blog.kakaocdn.net/dn/bniCh0/btq8bsg19MB/PJUsaJdJkpJdbkHcWUC9wk/img.png"; // 우버튼 이미지
image_1 = "https://blog.kakaocdn.net/dn/bS0Wvp/btr8J1cQhlx/hl8E8tv5M9rfwvuma8q6Fk/img.jpg";
image_2 = "https://blog.kakaocdn.net/dn/zYSgG/btr8P0DskTO/i6JzVmVy3gsM5by353o3E0/img.jpg";
image_3 = "https://blog.kakaocdn.net/dn/bD8PyW/btr8LgN5SsY/AvjSnqZ0xgsM3FvpHsaDh1/img.jpg";
image_4 = "https://blog.kakaocdn.net/dn/dSddpv/btr8Mn64wqT/b5P6xKyDYfVXuDOeEtcKtK/img.jpg";
image_5 = "https://blog.kakaocdn.net/dn/cBCuTv/btr8J48xbjE/e5z35o9vMjSJeYJA8auRJ1/img.jpg";
link_1 = "https://blog.kakaocdn.net/dn/bS0Wvp/btr8J1cQhlx/hl8E8tv5M9rfwvuma8q6Fk/img.jpg";
link_2 = "https://blog.kakaocdn.net/dn/zYSgG/btr8P0DskTO/i6JzVmVy3gsM5by353o3E0/img.jpg";
link_3 = "https://blog.kakaocdn.net/dn/bD8PyW/btr8LgN5SsY/AvjSnqZ0xgsM3FvpHsaDh1/img.jpg";
link_4 = "https://blog.kakaocdn.net/dn/dSddpv/btr8Mn64wqT/b5P6xKyDYfVXuDOeEtcKtK/img.jpg";
link_5 = "https://blog.kakaocdn.net/dn/cBCuTv/btr8J48xbjE/e5z35o9vMjSJeYJA8auRJ1/img.jpg";
buttonDiv.querySelectorAll("img")[0].src = leftButton;
buttonDiv.querySelectorAll("img")[1].src = rightButton;
for (imgTotal = 0; this["image_" + (imgTotal + 1)]; imgTotal++);
function imageMode() {
	buttonDiv.querySelector("a").href = this["link_" + arguments[0]];
	imageDiv.querySelectorAll("img")[0].src = this["image_" + arguments[0]];
	imageDiv.querySelectorAll("img")[1].src = this["image_" + (arguments[0] === imgTotal ? 1 : ++arguments[0])];
	targetCount = 0; 
}
addEventListener("resize", galleryMode = () => {
	galleryDiv.style.width = "100%";
	galleryWidth = Math.floor(galleryDiv.offsetWidth);
	galleryDiv.style.width = galleryWidth + "px"; 
	galleryPoint = -galleryWidth;
	imageDiv.querySelector("div").style.marginLeft = "0px";
} );
galleryMode();
imageMode(img = 1);
buttonDiv.querySelectorAll("img")[0].onclick = () => {
	targetCount = autoSec * 100;
	for (ic of document.querySelectorAll("#imageDiv, #imageDiv img")) ic.style.transform = "rotateY(180deg)";
}
buttonDiv.querySelectorAll("img")[1].onclick = () => {
	targetCount = autoSec * 100;
	for (ic of document.querySelectorAll("#imageDiv, #imageDiv img")) ic.style.transform = "rotateY(0deg)";
} 
setInterval(() => {
	++targetCount;
	changePoint = Number(imageDiv.querySelector("div").style.marginLeft.slice(0, -2));
	if (Math.abs(changePoint - galleryPoint) <= 0.5) {
		imageDiv.querySelector("div").style.marginLeft = "0px";
		imageMode(img = img === imgTotal ? 1 : ++img);
	}
	else {
		if (targetCount >= 0 && targetCount < autoSec * 100) changePoint = 0;
		else changePoint += (galleryPoint - changePoint) / targetSpeed;
		imageDiv.querySelector("div").style.marginLeft = changePoint + "px";
	}
}, 10);
</script>
감사합니다.
배울게 산더미 같군요..ㅎ
배너 공부하는데 엄청 도움이 될 것 같습니다.

그런데 브라우저 리사이즈할 때 그림이 자동 확대,축소가 되지 않아

galleryWidth = Math.floor(galleryDiv.offsetWidth);

이 라인을

galleryWidth = window.innerWidth;

이렇게 바꿨더니 제대로 되는것 같습니다.
바꿔도 별 문제 없겠지요??
@도레미 리사이즈 이벤트의 경우 저는 모바일에서 가로 세로 전환  또는 그 역전환만 신경씁니다.
pc는 신경도 안 쓰거든요.ㅋ

그런데 도레미님처럼 하면 가령 갤러리 가로를 pc에서는 900픽셀 모바일에서는 100퍼센트로 주는 식은 힘들고 오직 가로 이빠이 이벤트만 될 터이라...

본인이 편한 방식대로 쓰면 되죠.
제가 Math.floor 을 준 이유는 예를 들어 상위 엘레먼트가 1001픽셀이고 여기에 90퍼센트로 크기를 주면 픽셀값이 소숫점으로 나와요.
그럼 셋인터벌을 오래 놔두면 사이즈 삑사리가 나서 보기가 싫어집니다.
그래서 버림값 자연수를 취해서 딱 떨어지게 맞추어야 장기간 셋인터벌에서도 소숫점 삑사리가 나지 않습니다.
@도레미
테이블 css 에 table-layout:fixed 를 주면 소숫점 삑사리가 나지 않습니다.
그외 다른 엘레먼트로 flex 또는 grid 로 만들면 테이블처럼 정확하지 않고 문제가 발생해서...
그렇게 테이블로 코드를  짜면 웹표준이네 뭐네 하는 소리 듣기 싫어서 첨부터 버림값 자연수를 취해 마진제로오토로 중앙정렬시켜서 코드를 짜게 되더라구요.ㅋ
@도레미
아 제일 중요한 걸 빼먹었네요. pc 에서도 리사이징을 원하시면...

galleryWidth = Math.floor(galleryDiv.offsetWidth);

이 코드 위에 한줄만 더 보태주면 됩니다. 아래처럼요.

galleryDiv.style.width = "100%";
galleryWidth = Math.floor(galleryDiv.offsetWidth);

본문코드도 고쳤어요
전체 5,352
개발자팁 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT