정보/블로그 운영팁

티스토리 플로팅 추천 글 기능 만들기

아미넴 2021. 9. 17.
반응형

블로그 방문자들이 다른 글을 보도록 유도하기 위해 이전 글, 다음 글을 추천하는 기능을 만들어 보겠습니다. 디자인은 제 전문 분야가 아니라 기대하시면 안 되구요 ㅎㅎ

 

먼저 이 기능을 사용하기 위해 카테고리 글 더 보기 플러그인 기능이 필요합니다. 관련 글 태그를 활용할 수도 있지만 저는 사용하고 있지 않으므로 따로 다루지 않겠습니다.

 

목차

     

    HTML 태그 작성

    관리 페이지 > 꾸미기 > 스킨 편집 으로 이동합니다.

     

    html 편집을 클릭합니다.

     

    그럼 다음과 같은 HTML 에디터가 뜨는데 여기에서 작업을 해 보겠습니다.

     

    먼저 추천할 글을 담기 위한 컨테이너 박스를 만들어 보겠습니다. 우리는 이전 글, 다음 글을 넣을 예정이므로 2개를 만들어야겠죠. 원하시는 곳 아무데나 작성하시면 되는데 저는 맨 아래 쪽에 작성했습니다.

    <div id="recommend-contents" class="recommend-contents-wrap" style="display:none;">
        <div class="content-comment">
            잠깐만요! 이 글도 한 번 보고 가세요 🧡
        </div>
        <div class="recommend-contents-body">
            <div class="content-box">
                <div class="content-arrow">&#xf0d9;</div>
                <div id="pre-content" class="pre-content"></div>
            </div>
            <div class="content-box">
                <div id="next-content" class="next-content"></div>
                <div class="content-arrow">&#xf0da;</div>
            </div>
        </div>
    </div>

    최초에는 박스를 숨기기 위해 display를 none으로 설정했습니다. 사실 화면 밖으로 벗어나도록 해서 안 보이긴 할텐데 혹시 몰라 완벽하게 숨겼습니다. 저는 이 정도로 구조를 잡았지만 각자 원하는 대로 잡으시면 됩니다.

     

    CSS 설정 참고 사항

    CSS도 참고로 작성했지만 각자 블로그에 맞게 수정해야 할 수도 있습니다. 아래 코드는 참고만 해주세요.

    미넴 스킨을 이용하시면 바로 적용이 가능합니다.

    .recommend-contents-wrap {
        position: fixed;
        z-index: 999;
    }
    .recommend-contents-body {
        display: flex;
    }
    .content-comment {
        margin: 0 0 5px 0;
        padding: 8px;
        width: 294px;
        font-weight: bold;
        font-style: italic;
        border-radius: 5px;
        font-size: 0.8em;
    }
    .content-box {
        padding: 5px;
        width: 142px;
        display: flex;
        align-items: center;
        border-radius: 5px;
        font-weight: bold;
    }
    .content-box .content-arrow:nth-child(1) {
        padding-right: 5px;
    }
    .content-box .content-arrow:nth-child(2) {
        padding-left: 5px;
    }
    .content-box:nth-child(1) {
        margin-right: 5px;
    }
    .pre-content,
    .next-content {
        font-size: 0.7em;
        overflow: hidden;
        text-overflow: ellipsis;
        display: block;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        text-align: center;
        width: inherit;
    }
    .no-post {
        opacity: 0.5;
    }

     

    자바스크립트 코드 작성

    body 태그 안쪽 제일 하단 script 태그 안에 붙여넣기 하시면 됩니다.

     

    이전 글, 다음글 존재 여부 판단 로직

    카테고리 글 더 보기 플러그인 사용 시 생성되는 요소에서 이전 글, 다음 글이 있는지 파악하는 로직입니다. 필요에 따라 관련 글 태그를 이용하셔도 됩니다.

    var anotherCategory = $('.another_category tr');
    var currentIndex = -1;
    if(anotherCategory.length > 1) {
        for(var i=0;i<anotherCategory.length;i++) {
            if(anotherCategory.eq(i).find('a.current').length > 0) {
                currentIndex = i;
                break;
            }
        }
        if(currentIndex > 0 && currentIndex < anotherCategory.length-1) { //이전 글, 다음 글 가능
            makeRecommendBlock('both', currentIndex); 
        } else {
            if(currentIndex == 0) { //이전 글 가능
                makeRecommendBlock('pre', currentIndex); 
            } else if(anotherCategory.length > 1) { //다음 글 가능
                makeRecommendBlock('next', currentIndex);
            }
        }
    }

    현재 글 시점으로 앞, 뒤 글 여부를 판단하여 추천 글 블럭을 생성해 주도록 하였습니다. makeRecommendBlock 함수는 따로 빼서 작성하도록 하겠습니다.

     

    추천 글 블럭 생성 로직

    추천 글에 포함시킬 이전 글, 다음 글 블럭을 생성하는 로직입니다. 마지막 글인 경우 다음 글이 없고 첫 글인 경우 이전 글이 없는 것에만 주의하여 작성하면 됩니다.

    var prePostFlag = true;
    var nextPostFlag = true;
    function makeRecommendBlock(type, currentIndex) {
        if(prePostFlag && type == 'pre') {
            prePostFlag = false;
            $('#pre-content').append($('.another_category tr').eq(currentIndex+1).find('a').clone());
            $('#next-content').append('<a href="#" class="no-post">다음 글 없음</a>');
            $('.content-box .content-arrow').eq(1).addClass('no-post');
        } else if(nextPostFlag && type == 'next') {
            nextPostFlag = false;
            $('#next-content').append($('.another_category tr').eq(currentIndex-1).find('a').clone());
            $('#pre-content').append('<a href="#" class="no-post">이전 글 없음</a>');
            $('.content-box .content-arrow').eq(0).addClass('no-post');
        } else if(prePostFlag && nextPostFlag && type == 'both') {
            prePostFlag = false;
            nextPostFlag = false;
            $('#pre-content').append($('.another_category tr').eq(currentIndex+1).find('a').clone());
            $('#next-content').append($('.another_category tr').eq(currentIndex-1).find('a').clone());
        }
    }

    혹시 몰라서 이전 글, 다음 글 생성 여부 플래그를 전역 변수로 각각 만들었는데 작성하고 나서 보니 하나로 해도 문제 없을 것 같습니다. append 메서드를 이용하여 그냥 덧 붙일 경우 카테고리 더 보기 요소에서 해당 항목이 사라지므로 꼭 clone 메서드를 이용하여 생성해 주어야 합니다.

     

    특정 위치에서 추천 글 띄우기

    이제 추천 글 블럭 생성 작업은 완료되었으니 생성한 블럭을 원하는 시점에 원하는 위치에 띄우는 로직을 작성해 보겠습니다.

    var recommendPostFlag = true;
    var recommendPostTimer = 0;
    var preRecommendPosition = -1;
    function recommendPost() {
        if($('.another_category').length > 0) {
            var position = window.scrollY/($('.another_category').offset().top-window.innerHeight);
            if(position > 1 && window.scrollY-$('.another_category').offset().top < 0 && preRecommendPosition < window.scrollY) {
                if(recommendPostFlag) {
                    recommendPostFlag = false;
    
                    /* 이전 글, 다음 글 파악 로직 영역 */
        
                    if((!prePostFlag || !nextPostFlag) && recommendPostTimer == 0) {
                        var rightMargin = 0;
                        if(window.innerWidth > 310) {
                            rightMargin = 10;
                        } else {
                            rightMargin = (window.innerWidth - 310) / 2;
                        }
    
                        var bottomMargin = addHeightByAnchorAds('bottom')>0?addHeightByAnchorAds('bottom')+55:75;
                        $('#recommend-contents').css('bottom', bottomMargin+'px');
                        $('#recommend-contents').css('right', '-350px');
                        $('#recommend-contents').css('display','block');
                        recommendPostTimer = $('#recommend-contents').animate({'right':rightMargin+'px'}, 1000, 'swing', function() {});
                        recommendPostTimer = setTimeout(function() {
                            $('#recommend-contents').animate({'right':'-350px'}, 1000, 'swing', function() {
                                $('#recommend-contents').css('display','none');
                                recommendPostTimer = 0;
                            });
                        }, 10000);
                    }
                }
            } else {
                recommendPostFlag = true;
            }
            preRecommendPosition = window.scrollY;
        }
    }
    
    $(window).on('scroll resize', function() {
        recommendPost();
    });

    recommendPostFlag는 추천 글을 띄울 위치에 한 번 진입하면 반복 실행되지 않도록 차단시키는 역할을 합니다. recommendPostTimer는 추천 글을 띄우면 타이머가 작동하기 시작하여 사라지면 0으로 변경하여 추천 글이 띄워졌는지 여부를 판단할 수 있도록 합니다. preRecommendPosition은 스크롤을 아래로 내릴 때만 기능이 동작하도록 하기 위한 보조 값입니다.

     

    완성 소스

    최종 점검을 위해 전체 소스도 제공을 하겠습니다.

    var prePostFlag = true;
    var nextPostFlag = true;
    function makeRecommendBlock(type, currentIndex) {
        if(prePostFlag && type == 'pre') {
            prePostFlag = false;
            $('#pre-content').append($('.another_category tr').eq(currentIndex+1).find('a').clone());
            $('#next-content').append('<a href="#" class="no-post">다음 글 없음</a>');
            $('.content-box .content-arrow').eq(1).addClass('no-post');
        } else if(nextPostFlag && type == 'next') {
            nextPostFlag = false;
            $('#next-content').append($('.another_category tr').eq(currentIndex-1).find('a').clone());
            $('#pre-content').append('<a href="#" class="no-post">이전 글 없음</a>');
            $('.content-box .content-arrow').eq(0).addClass('no-post');
        } else if(prePostFlag && nextPostFlag && type == 'both') {
            prePostFlag = false;
            nextPostFlag = false;
            $('#pre-content').append($('.another_category tr').eq(currentIndex+1).find('a').clone());
            $('#next-content').append($('.another_category tr').eq(currentIndex-1).find('a').clone());
        }
    }
    
    var recommendPostFlag = true;
    var recommendPostTimer = 0;
    var preRecommendPosition = -1;
    function recommendPost() {
        if($('.another_category').length > 0) {
            var position = window.scrollY/($('.another_category').offset().top-window.innerHeight);
            if(position > 1 && window.scrollY-$('.another_category').offset().top < 0 && preRecommendPosition < window.scrollY) {
                if(recommendPostFlag) {
                    recommendPostFlag = false;
                    var anotherCategory = $('.another_category tr');
                    var currentIndex = -1;
                    if(anotherCategory.length > 1) {
                        for(var i=0;i<anotherCategory.length;i++) {
                            if(anotherCategory.eq(i).find('a.current').length > 0) {
                                currentIndex = i;
                                break;
                            }
                        }
                        if(currentIndex > 0 && currentIndex < anotherCategory.length-1) { //이전 글, 다음 글 가능
                            makeRecommendBlock('both', currentIndex); 
                        } else {
                            if(currentIndex == 0) { //이전 글 가능
                                makeRecommendBlock('pre', currentIndex); 
                            } else if(anotherCategory.length > 1) { //다음 글 가능
                                makeRecommendBlock('next', currentIndex);
                            }
                        }
                    }
        
                    if((!prePostFlag || !nextPostFlag) && recommendPostTimer == 0) {
                        var rightMargin = 0;
                        if(window.innerWidth > 310) {
                            rightMargin = 10;
                        } else {
                            rightMargin = (window.innerWidth - 310) / 2;
                        }
    
                        var bottomMargin = addHeightByAnchorAds('bottom')>0?addHeightByAnchorAds('bottom')+55:75;
                        $('#recommend-contents').css('bottom', bottomMargin+'px');
                        $('#recommend-contents').css('right', '-350px');
                        $('#recommend-contents').css('display','block');
                        recommendPostTimer = $('#recommend-contents').animate({'right':rightMargin+'px'}, 1000, 'swing', function() {});
                        recommendPostTimer = setTimeout(function() {
                            $('#recommend-contents').animate({'right':'-350px'}, 1000, 'swing', function() {
                                $('#recommend-contents').css('display','none');
                                recommendPostTimer = 0;
                            });
                        }, 10000);
                    }
                }
            } else {
                recommendPostFlag = true;
            }
            preRecommendPosition = window.scrollY;
        }
    }
    
    $(window).on('scroll resize', function() {
        recommendPost();
    });

     

    결과 보기

    우측 하단에 다음과 같이 잘 나타나네요.

     

    모바일에서도 적절하게 표현이 되는 디자인 입니다.

     

    유용하게 사용하시기 바랍니다.

     

    반응형

    댓글

    💲 추천 글