input range를 활용하여 time slider를 구현하게 되어, 그에 대한 코드들을 아래 정리해보았다
Edge, chorme에서는 정상 작동 되었으나, IE에서는 일부 JS코드와 스타일이 비정상 작동하여, 추후 동기화 되도록 작업 후 코드와 게시글을 수정하였다.
작업 단계는 아래와 같이 분류하였다.
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
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);
}
각 버튼의 이미지를 첨부하였다.
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
'JavaScript > JQuery' 카테고리의 다른 글
[tooltip] JQuery-ui.js, 요소 tooltip 생성부터 커스텀까지 (4) | 2023.12.07 |
---|---|
AJAX로 json데이터 넘겨받기 (0) | 2022.08.04 |
요소의 조작 : 제이쿼리 (0) | 2022.05.31 |
aJax와 Json (0) | 2022.02.23 |
jQuery의 사용(연결방법 포함) (0) | 2022.02.22 |