樹形操作2-或、且關係組合

dav2100發表於2021-09-09

樹形運算元據整理總結,這篇是第二篇。本篇是關於樹節點拖拽組合,實現或、且的關係,並支援刪除節點。demo 是基於 jquery 及 easy-ui 庫實現的。

  • 截圖:

圖片描述

圖片描述

具體實現-loading:

利用 css3 實現。主要運用了 :before:after 選擇器‘畫’了兩個圓點,最後利用animationtransform:translateX() scale()實現動畫。利用位移模擬的旋轉,為了使效果更好,加了一點點縮放。

html:

<div class="loading"></div>

css:

.loading {    position: relative;    height: 100%;    line-height: 100%;
}.loading:before,.loading:after {    position: absolute;    top: calc(50% - 5px);    left: calc(50% - 5px);    content: "";    width: 10px;    height: 10px;    border-radius: 100%;
}.loading:before {    background: skyblue;    animation: loading-reverse .8s linear infinite; 
}.loading:after {    background: yellow;    animation: loading .8s linear infinite; 
}
@keyframes loading {    from {        transform: translate(-20px) scale(.8);
    }    to {        transform: translate(20px) scale(1.1);
    }
}
@keyframes loading-reverse {    from {        transform: translate(20px) scale(.8);
    }    to {        transform: translate(-20px) scale(1.1);
    }
}

本想用一個 loading + reverse 實現,但實現效果不是很理想,就用了兩個。下面是一個 loading 的程式碼,可以試一下。

.loading:before {    background: skyblue;    animation: loading .8s linear infinite reverse; 
}.loading:after {    background: yellow;    animation: loading .8s linear infinite; 
}
@keyframes loading {    from {        transform: translate(-20px) scale(.8);
    }    to {        transform: translate(20px) scale(1.1);
    }
}

具體實現:

html 結構比較簡單,左右佈局;左邊是外加了一個 tab 切換及篩選。右側,預設一個清空按鈕。結構如下:

<div class="tree-drag-relation">    <div class="left">
        <ul class="nav loading" id="nav"></ul>
        <div class="search tree-header" id="search">
            <input class="search-input" placeholder="搜尋標籤" value="" />
        </div>
        <ul class="tree-con loading" id="tree_drag"></ul>
    </div>
    <div class='right'>
        <div class="relation-header">
            <span class="tip-num">已重組節點(<span class="num" id="node_num">0</span>)</span>
            <span class="clear-all" id="clear_all">清空</span>
        </div>
        <div class="relation-con and-wrap" id="relation_con">
        </div>
    </div></div>

為了使 js 程式碼邏輯清晰,結構組織分為了左右 2 部分。左側,負責 tab 切換及樹形資料的展示等,結構如下:

圖片描述

右側負責 或、且 邏輯的處理、刪除、展示及回填等,結構如下:

圖片描述

tab 切換
tab 切換比較簡單,就不上程式碼了。

樹形展示
資料樹形展示,利用的是 easyui 外掛的 tree 外掛,按照官方 API,很容易就能實現。

關鍵點一:要求資料格式為:

[{
    id: '',
    text: '',
    children: [{}] // 依次類推
}]

關鍵點二:設定支援拖拽,且在載入成功後,設定當前樹節點不可放置被拖拽的節點。具體可看renderDragTree這個方法。

treeDragMod.$treeTarget.tree({    data: treeData,    dnd: true, // 允許拖拽
    formatter: function(node) {        // 統計子節點個數
        var text = '<span class="node-name">' + node.text + '</span>';        if (node.children && node.children.length > 0) {
            text += '<i class="tip">(' + node.children.length + ')</i>';
        }        return text;
    },    onLoadSuccess: function(e, node) {        // 摺疊樹
        treeDragMod.$treeTarget.tree('collapseAll');        
        // 節點上禁止放置
        $.each($('#tree_drag .tree-node'), function(i, item) {
            $(item).droppable("disable");
        });
    }
});
relationMod.setDragAndDrop();

關鍵點三:放置,或且的渲染。拖拽實現的另一個點就是放置,因此另一個關鍵點就是設定放置點,並進行放置邏輯處理,這是實現 或、且 關係的重點。具體可看setDragAndDrop方法實現。

//設定被拖元素$("#tree_drag .tree-node").draggable({
    proxy: 'clone',
    revert: true, //拖動結束後節點將返回它的開始位置
    cursor: 'pointer',
    onStartDrag: function () {
        $(this).draggable('proxy').css({'background': '#fff', 'opacity': '0.5'});
    },
    onStopDrag: function (e) {        var $target = $(e.target),
            node = $('#tree_drag').tree('getNode', e.data.target), // 獲取被拖動的節點
            $clearAll = $('#clear_all');        
        // 判斷在可拖拽放置區域,才進行放置操作
        if ($target.hasClass('and-wrap') || $target.hasClass('or-wrap')) {
            $clearAll.show();
            $target.append(conHtml());
        }        function conHtml (relation) {            // 處理 and 且的關係
            var conHtml = '';            if ($target.hasClass('and-wrap')) {                if ($target.children().length) {
                    conHtml += relationMod.andHtml;
                }                var innerHtml = node.children ? relationMod.orConHtml(node.children) : relationMod.orItemHtml(node);
                conHtml += relationMod.orWrapLeftHtml + innerHtml + '</div>';
            } else if ($target.hasClass('or-wrap')) { // 處理 or 或的關係
                if ($target.children().length) {
                    conHtml += relationMod.orHtml;
                }
                conHtml += node.children ? relationMod.orConHtml(node.children) : relationMod.orItemHtml(node);
            }            return conHtml;
        }

        relationMod.setNodeNum();
        relationMod.resizeScrollTop();
    }
});// 設定目標物件允許放置被拖元素$(".and-con, .or-con").droppable();

或、且關係新增時,是透過判斷當前新增節點的元素是否有子元素,有那麼新增元素的時候,就需要新增對應的關係。考慮,新增元素沒有子節點時,是隻需新增節點,而不需要新增關係。

關鍵點四:節點刪除。

圖片描述

假如箭頭為或且,第一次刪除ABC都正確。

採用刪除字母的同時,判斷,上一個箭頭存在,則需要刪除上一個,否則需要刪除下一個箭頭。

刪除 或 item 的如下:

$('body').on('click', '.item-del', function () { // 刪除 item
    var $this = $(this),
        $item = $this.closest('.item'),
        $orWrap = $this.closest('.or-wrap');    // 刪除當前元素及關係
    // 上一個存在,刪上一個,否則刪下一個
    var $prev = $item.prev('.or');    if ($prev.length) {
        $prev.remove();
    } else {        var $next = $item.next('.or');        if ($next.length) {
            $next.remove();
        }
    }
    $item.remove();    // 刪除後,若其父元素無子元素,則刪除其父元素
    if ($orWrap.children('.item').length == 0) {
        $orWrap.remove();
    }

    relationMod.setNodeNum();
})

刪除且的邏輯和這個類似。

其他操作比較簡單,就不贅述了,具體實現可看。

最後就是,目前實現的方案,只支援二級樹結構,多級是不支援的。

原文出處:https://www.cnblogs.com/EnSnail/p/10268643.html 

作者: 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4479/viewspace-2820167/,如需轉載,請註明出處,否則將追究法律責任。

相關文章