본문 바로가기
JavaScript/JQuery

타임슬라이더 구현

by amoomar 2022. 6. 24.
반응형

input range를 활용하여 time slider를 구현하게 되어, 그에 대한 코드들을 아래 정리해보았다

 

Edge, chorme에서는 정상 작동 되었으나, IE에서는 일부 JS코드와 스타일이 비정상 작동하여, 추후 동기화 되도록 작업 후 코드와 게시글을 수정하였다.

 

time slider

 

 


 

 

작업 단계는 아래와 같이 분류하였다.

 

1. 레이아웃
2. range 눈금 설정
3. 조작버튼
4. tooltip 생성
5. 이벤트

 

 

 

 


 

 

1. 레이아웃

 

우선 조작을 위한 버튼과 input을 배치할 위치를 정하고, 그에 대한 레이아웃을 먼저 정의하였다. 가급적 내용은 생략하고 어떤 요소들을 가질 것이며 누구의 자식요소로 배치할지를 먼저 작성하였다. 구현 완료된 jsp페이지의 코드를 첨부하자면 아래와 같다.

 

각 목차별로 뜯어가며 자세히 설명해 볼 예정이다.

 

참고로 본인의 경우 <table>을 활용하여 작업하였으므로 <tr>, <td>요소가 작성되어있지만 경우에 따라 태그를 다르게 하여도 무관할 것 같다.

<tr class="color_back03">
	<td colspan="2" style="height: 50px;">
		<div class="between">
        
			<%-- 조작버튼 --%>
			<div class="slider_controll">
				<button class="slider_button prev" title="이전"></button>
				<button class="slider_button play" title="재생"></button>
				<button class="slider_button next" title="다음"></button>
			</div>
			<%-- /조작버튼 --%>
            
			<%-- 그 외(input, tooltip, label, 눈금) --%>
			<div class="slider_wrapper" >
            
				<%-- tooltip --%>
				<div class="tooltip"  draggable="true"></div>
				<%-- /tooltip --%>
                
				<form action="" method="post">
					<input type="range" list="tickmarks" max="48" value="0">
				</form>
                
				<%-- label --%>
				<div class="labels between">									
					<div>+0h</div>
					<div style="margin-left: 6px;">+6h</div>
					<div style="margin-left: 3px;">+12h</div>
					<div>+18h</div>
					<div>+24h</div>
					<div>+30h</div>
					<div>+36h</div>
					<div>+42h</div>
					<div>+48h</div>
				</div>
				<%-- /label --%>
                
				<%-- 눈금 --%>
				<datalist id="tickmarks">
					<option value="0" />
					<option value="6"/>
					<option value="12"/>
					<option value="18"/>
					<option value="24"/>
					<option value="30" />
					<option value="36"/>
					<option value="42"/>
					<option value="48"/>
				</datalist>
				<%-- /눈금 --%>
                
			</div>
			<%-- /그 외(input, tooltip, label, 눈금) --%>
            
		</div>
	</td>
</tr>

 

 

 

 

각 class는 CSS의 적용을 용이하게 하기 위해 부여하였으며 그 요소들에 대한 스타일 정의는 다음과 같다.

.slider_control{
	margin-left: 20px;
}

.slider_button{
	background-color: transparent;
	display: inline-block;
	margin: 0;
	width: 23px;
	vertical-align: middle;
	height: 44px;
	cursor: pointer;
	border: none;
	outline: none;
}

.prev{
	height: 34px;
	background-image: url(../img/ico_timeSlider_backward.png);
	background-position: center;
	background-repeat: no-repeat;
}
.next{
	height: 34px;
	background-image: url(../img/ico_timeSlider_forward.png);
	background-position: center;
	background-repeat: no-repeat;
}

.play{
	width: 40px;
	height: 40px;
	border-radius: 100px;
	background-color: #000;
	background-position: 15px center;
	background-repeat: no-repeat;
	background-image: url(../img/icon_play.png);
}
.pause{
	width: 40px;
	height: 40px;
	border-radius: 100px;
	background-color: #000;
	background-position: 13px center;
	background-repeat: no-repeat;
	background-image: url(../img/icon_pause.png);
}

.slider_wrapper{
	margin-right: 20px;
	height: 35px;
	background-color: white;
	border-radius: 5px;
}

input[type="range"]{
	margin-left: 10px;
	margin-right: 10px;
	width: 500px;
	cursor: pointer;
	height: 22px;
}

/* IE에서는 기본으로 tooltip이 생성되는데, 이를 제거하기 위한 스타일 */
input[type="range"]::-ms-tooltip{
	display: none;
}

.labels{
	margin-left: 8px;
	margin-right: 7px;
}
.labels div{
	font-size: 8px;
	font-weight: bold;
	color: black;
}
.tooltip{
	display: none;
	width: 70px;
	height: 20px;
	color: #0083F5;
	border-color: #0083F5;
	background-color: #000;
	text-align: center;
	border-radius: 11px;
	font-size: 12px;
	font-weight: 700;
	border: solid;
	position: absolute;
	top: 277px;
	margin-left: -17px;
	line-height: 20px;
}

 

 

 


 

 

2. range 눈금 및 라벨 설정

 

 

눈금의 경우 <datalist>를 활용하여 작업하였으며, label속성을 통해 각 눈금에 라벨을 삽입하는 방법도 있다고는 하나 브라우저와 그 버전마다 사용유무가 갈리므로 사용을 지양하는 것이 좋다고 한다. 본인의 경우 <div>와 CSS속성을 활용하여 라벨 역할을 하도록 구현하였다.

 

				<%-- label --%>
				<div class="labels between">									
					<div>+0h</div>
					<div style="margin-left: 6px;">+6h</div>
					<div style="margin-left: 3px;">+12h</div>
					<div>+18h</div>
					<div>+24h</div>
					<div>+30h</div>
					<div>+36h</div>
					<div>+42h</div>
					<div>+48h</div>
				</div>
				<%-- /label --%>
                
				<%-- 눈금 --%>
				<datalist id="tickmarks">
					<option value="0" label="추천하지 않는 라벨 형식"/>
					<option value="6"/>
					<option value="12"/>
					<option value="18"/>
					<option value="24"/>
					<option value="30" />
					<option value="36"/>
					<option value="42"/>
					<option value="48"/>
				</datalist>
				<%-- /눈금 --%>

 

 

 

CSS 코드

input[type="range"]{
	margin-left: 10px;
	margin-right: 10px;
	width: 500px;
	cursor: pointer;
}
input[type="range"]::-ms-tooltip{
	display: none;
}

/*라벨의 위치를 더 상세히 컨트롤하여 배치*/
.labels{
	margin-left: 8px;
	margin-right: 7px;
}

/*라벨 text에 관한 style*/
.labels div{
	font-size: 8px;
	font-weight: bold;
	color: black;
}

 

 

 

range 눈금 및 라벨을 위한 작업과 관련하여 참고할 수 있는 링크를 첨부하였다.

 

https://runebook.dev/ko/docs/html/element/input/range

 

HTML - <input type = "range"> - <input> range 유형의 <input> 요소는 사용자가 주어진 값보다 작거나 다른 주

step 속성 은 값이 준수해야 하는 세분성을 지정하는 숫자 또는 아래에 설명된 특수 값 any 입니다.스테핑 기준과 동일한 값( 지정된 경우 min value , 둘 다 제공되지 않은 경우 적절한 기본값)만 유

runebook.dev

 

 

 


 

 

3. 조작버튼

 

 

조작버튼은 마찬가지로 보여지는 부분을 먼저 작업한 뒤, 후에 javascript를 활용하여 이벤트 관련 로직을 작성하였다.

재생버튼을 클릭하면 일시정지버튼이 되고, 일시정지 버튼을 클릭하면 재생버튼이 되도록 구현할 예정이다.

			<%-- 조작버튼 --%>
			<div class="slider_controll">
				<button class="slider_button prev" title="이전"></button>
				<button class="slider_button play" title="재생"></button>
				<button class="slider_button next" title="다음"></button>
			</div>
			<%-- /조작버튼 --%>

 

 

 

CSS 코드

/* 모든 버튼 요소를 감싸는 부모요소 */
.slider_controll{
	margin-left: 20px;
}

/* 버튼들의 공통 스타일 */
.slider_button{
	background-color: transparent;
	display: inline-block;
	margin: 0;
	width: 23px;
	vertical-align: middle;
	height: 44px;
	cursor: pointer;
	border: none;
	outline: none;
}

/* "이전"버튼의 스타일 */
.prev{
	height: 34px;
	background-image: url(../img/ico_timeSlider_backward.png);
	background-position: center;
	background-repeat: no-repeat;
}

/* "다음"버튼의 스타일 */
.next{
	height: 34px;
	background-image: url(../img/ico_timeSlider_forward.png);
	background-position: center;
	background-repeat: no-repeat;
}

/* "재생"버튼의 스타일 */
.play{
	width: 40px;
	height: 40px;
	border-radius: 100px;
	background-color: #000;
	background-position: 15px center;
	background-repeat: no-repeat;
	background-image: url(../img/icon_play.png);
}

/* "일시정지"버튼의 스타일 */
.pause{
	width: 40px;
	height: 40px;
	border-radius: 100px;
	background-color: #000;
	background-position: 13px center;
	background-repeat: no-repeat;
	background-image: url(../img/icon_pause.png);
}

 

 

 

 

 

각 버튼의 이미지를 첨부하였다.

 

ico_timeSlider_backward.png
0.00MB
ico_timeSlider_forward.png
0.00MB
icon_pause.png
0.00MB
icon_play.png
0.00MB

 

 

 

 


 

 

4. tooltip 생성

 

 

 

range의 버튼을 따라다니며 값을 나타낼 tooltip을 생성하였다. 타임슬라이드 중 이 부분이 제일 힘들었던 것 같다....

<%-- tooltip --%>
<div class="tooltip"></div>
<%-- /tooltip --%>

 

 

CSS 코드

.tooltip{
	display: none;
	width: 70px;
	height: 20px;
	color: #0083F5;
	border-color: #0083F5;
	background-color: #000;
	text-align: center;
	border-radius: 11px;
	font-size: 12px;
	font-weight: 700;
	border: solid;
	position: absolute;
	top: 277px;
	margin-left: -17px;
	line-height: 20px;
}

 

 

 


 

 

5. 이벤트

 

tooltip의 숨김과 표시, range의 값에 따른 tooltip의  위치 설정, 조작버튼과 관련된 이벤트에 대한 JS코드를 첨부하였으며, 주석을 통해 내용을 상세히 확인할 수 있으므로 별도 설명은 생략한다.

 

var result; //변경된 range의 value
var beforeResult; //변경 전 range의 value
var th;//setInterval() 수행할 thread
var flag=false; // range의 자동 동작이 멈춘상태

// 처음 상태에서 mouseover했을때 value가 표시되도록 result에 미리 값을 할당
$(document).ready(function() {
	result= $("input[type='range']").val();
	$(".tooltip").text('data+'+result+'h');
});

$(function(){
	
	// mouse on, out시 display설정 각각 적용
	$(".slider_control").on("mouseenter", function(){
		$(".tooltip").show();
	});
	$(".slider_control").on("mouseleave", function(){
		$(".tooltip").hide();
	});
	$("input[type='range']").on("mouseenter", function(){
		$(".tooltip").show();
	});
	$("input[type='range']").on("mouseleave", function(){
		$(".tooltip").hide();
	});
	
	// 감소인지, 증가인지 판단하기 위해 마우스가 눌렸을때의 값을 beforeResult에 할당
	$("input[type='range']").on("mousedown", function(){
		beforeResult= Number($("input[type='range']").val());
		console.log(beforeResult);
	});
	
	//"이전"버튼 클릭시 range의 value 1씩 감소
	$(".prev").on("click", function(){
		beforeResult=Number($("input[type=range]").val());
		$("input[type=range]").val(beforeResult-1);
		tooltip();
	});
	//"다음"버튼 클릭시 range의 value 1씩 증가
	$(".next").on("click", function(){
		beforeResult=Number($("input[type=range]").val());
		$("input[type=range]").val(beforeResult+1);
		tooltip();
	});
	
	//"재생"버튼 클릭시 일정시간에 한 번씩 같은 행위 반복 + 이미지 변경
	$(".play").on("click", function(){
		
		if(flag){
			// 멈추기
			flag=false;
			$(".pause").addClass('play');
			$(".pause").removeClass("pause");
			stop();
		}else{
			// 움직이기
			flag=true;
			$(".play").addClass("pause");
			$(".play").removeClass("play");
			move();
		}
		
	});
	
		
	
	
	
	// range값에 변화가 생겼다면 그 값을 tooltip에 표시 및 위치 이동
	$("input[type='range']").on("mouseup", tooltip);		
	
});

// 증가인지 감소인지를 판단하여 tooltip의 기존 margin-left값에 연산하여 css변경
function tooltip(){
		
		result=Number($("input[type='range']").val());
		
		$(".tooltip").text('data+'+result+'h');
		
			var margin_px=$(".tooltip").css('margin-left'); // "어쩌구px"
			var margin_int= Number(margin_px.substring(0, margin_px.length -2)); // px의 정수값만 담음
			var margin; // 최종적으로 부여할 margin값
			
			if(beforeResult<result){ //이전보다 커졌다면
				if($(".tooltip").attr('id')=="mini"){
					margin=(result-beforeResult)*9+margin_int;
				}else{
					margin=(result-beforeResult)*10+margin_int;	
				}
			}else{// 작아졌다면
				if($(".tooltip").attr('id')=="mini"){
					margin=margin_int-(beforeResult-result)*9;
				}else{
					margin=margin_int-(beforeResult-result)*10;	
				}
			}

			$(".tooltip").css('margin-left',margin+'px');
}

function move(){
	th=setInterval(function(){
		beforeResult=Number($("input[type=range]").val());
		$("input[type=range]").val(beforeResult+1);
		tooltip();
		
		// 끝에 도달하면 재생버튼으로 변경
		if(beforeResult==48){
			$(".pause").addClass('play');
			$(".pause").removeClass("pause");
		}
		
	}, 500);
}
function stop(){
	clearInterval(th);
}

 

 

 

 

아래 첨부된 게시글을 통해 setInterval()에 대한 내용을 조금 더 자세히 확인해 볼 수 있다.

 

 

https://gkawjdgml.tistory.com/62?category=1006829 

 

[JS] 타이밍 이벤트 & 단원 총정리

JS에서 애니메이션을 구현할 수 있는 타이밍 이벤트에 대해 학습하였고, JS파트의 총 내용을 활용한 예제 풀이를 통해 단원 복습을 진행하였다. 1. 타이밍 이벤트 1) 타이밍 이벤트란? js에서 애니

gkawjdgml.tistory.com

 

 

 

 


반응형