반응형

vis-timeline을 이용하여 아래와 같이 구현을 해보았습니다.

기능적으로 추가를 더 해야되지만 시간이 없어서 아래와 같이만 구현을 하였습니다.

 

 

아래는 소스 코드 입니다.

 

[React]

import React, { useEffect, useRef } from "react";
import vis from "vis-timeline";
import "vis-timeline/dist/vis-timeline-graph2d.min.css";
import "./index.scss";

const VisTimeLine = () => {
    const timelineRef = useRef(null);
    const today = new Date();
    const count = 2000;

    const SetStartTime = 9;
    const SetEndTime = 18; //24hr, 12hr, 6hr 등등 세팅 가능
    
    // 오늘 날짜를 기준으로 시작과 종료 시간을 설정
    const startDate = new Date(today.getFullYear(), today.getMonth(), today.getDate(), SetStartTime, 0, 0); 
    const endDate = new Date(today.getFullYear(), today.getMonth(), today.getDate(), SetEndTime, 0, 0); 

    // 타임라인 옵션
    const options = {
        locale: "en",
        locales: {
            en: {},
        },        
        //showCurrentTime : false, //현재 시간 표기
        showMajorLabels : false, //최상단 날짜 표기 막기
        //showMinorLabels : false, //시간 나오지 않게
        start : startDate,
        end : endDate,
        preferZoom: true,
        moveable : false, //마우스로 이동하는 것 막기
        // verticalScroll: true,
        orientation: { axis: "top", item: "top" },
        height: "92px",
        // maxHeight: 130,            // 최대 높이
        // minHeight: 130,            // 최소 높이
        // zoomMin: 1000 * 60 * 60,
        // zoomMax: 1000 * 60 * 60 * 24 * 365,
        zoomMin: 1000 * 60 * 60, // 최소 줌 레벨 (10분)
        zoomMax: 1000 * 60 * 60 * 44, // 최대 줌 레벨 (1일)
        // groupHeightMode: "fitItems",
        groupHeightMode: "fixed", // 그룹 높이 고정
        stack: false,     //items이 시간이 겹쳐도 겹치게 볼 수 있게 설정
    };

    // 타임라인의 아이템 생성 함수
    const generateItems = (count) => {
        const intervalSeconds = 30

        return Array.from(Array(count)).map((_, index) => ({
            id: index,            
            className : Math.floor(Math.random() * 4) % 2 == 0 ? 'danger' : 'warning',
            group: Math.floor(Math.random() * 4),            
            start: new Date(
                today.getTime() + (intervalSeconds * 1000 * (index+1))
            ),
            end: new Date(
                today.getTime() + (intervalSeconds * 1000 * (index+2))
            ),
        }));
    };    

    // 타임라인의 그룹 생성 함수
    const generateGroups = () => {
        return [
            {
                id: 0,
                content: `Alarm`,
            },
            {
                id: 1,
                content: `Asystole`,
            },
            {
                id: 2,
                content: `V-FIB`,
            },
            {
                id: 3,
                content: `V-TACH`,
            },
        ];
    };

    const handlePlus = () => {
        alert('plus');
    }

    const handleMinus = () => {
        alert('plus');
    }

    const items = generateItems(count);
    const groups = generateGroups();

    useEffect(() => {
        // 타임라인 초기화
        const timeline = new vis.Timeline(
            timelineRef.current,
            items,
            groups,
            options
        );
        
        return () => {
            timeline.destroy();
        };
    }, [items, groups, options]);

    return (
        <div className="timeline-area">
            <div
                ref={timelineRef}
                id="timeline"
                className="timeline"                
            ></div>     
            <div className="control-timeline">
                <div className="time-area">
                    <span>24 hr</span>
                </div>    
                <div className="button-area">
                    <p onClick={() => handlePlus()}>+</p>
                    <p onClick={() => handleMinus()}>-</p>
                </div>
            </div>       
        </div>
    );
};

export default VisTimeLine;

 

[SCSS]

body {
    background: #000;
    font-family: sans-serif;
    font-weight: 700;
}

.timeline-area {
    display:flex;
    align-items: center;
    margin: 20px;
    border: 1px solid #fff;
    border-radius: 10px;    
    overflow:hidden;

    .timeline{
        width:95%;
        height:92px;    
    }

    .control-timeline{
        width:120px;
        height:92px;   
        display:flex;
        justify-content:space-between;
        align-items: center;
        background-color:#2F2F2F;
        color:#fff;

        .time-area{            
            display:flex;
            justify-content: center;
            align-items: center;
            padding:0 20px;

            span{
                font-size:12px;
                white-space:nowrap;
            }
        }

        .button-area{
            width:50px;            
            height:100%;
            flex-direction: column;
            background:#4F4F4F;

            p{                
                height:50%;
                display:flex;
                align-items: center;
                justify-content: center;
                text-align: center;
                margin:0;
                cursor: pointer;
            }
        }
    }
}

// 아이템의 높이 및 기본 설정
.vis-item {
    top: 0 !important;
    height: 18px !important;
    line-height: 18px !important;

    &.danger {
        color: white;
        background-color: #ff6d87;
        border: none;
    }

    &.warning {
        color: white;
        background-color: #fff500;
        border: none;
    }
}

// 그룹의 높이 고정
.vis-group {
    height: 18px !important; 
}

// 아이템이 그룹의 영역을 초과하지 않도록 제한
.vis-label,
.vis-foreground .vis-item,
.vis-background .vis-item {
    max-height: 18px;
}

// Minor labels 스타일 설정
.vis-time-axis {
    .vis-text {
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        font-weight: 700;
        padding: 6px 0;
        height: 20px; 
        line-height: 20px; 
    }
}

// 그룹 레이블 스타일
.vis-labelset {
    .vis-label {
        width: 200px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        background-color: #2F2F2F;
    }
}

.vis-timeline {
    border: none;

     // 날짜 표시 숨기기
    .vis-date {
        display: none;
    }

    .vis-current-time {
        position: absolute;
        top: 27px !important;
        left: 0;
        width: 3px;
        text-align: center;
        z-index: 1;
        background-color: blue; // 현재 시간 CSS
    }    
}

+ Recent posts