Vue項目裏使用d3實現摺疊樹圖流程圖

請勿複製源碼  代碼僅供參考 

首先 安裝d3和jquery

npm install d3 --save

npm install jquery --save-dev

在頁面中引入

import * as d3 from 'd3';
import $ from 'jquery'; 

 

<template>
    <div class="warp">  
    <el-button type="success" class="btn-success" @click="returnLast">返回上一頁</el-button>
    <div class="content">
    </div>
    <div class="looplist show">
        <div class="rightBtn" @click="changeShowRight">
          <label class="show" id="right_show">{{showRightText}}</label>
        </div>
        <div class="rightContent">
            <strong>漏洞信息</strong>
            <ul>
            </ul>
        </div>
    </div>

    <div class="systemlist" id="system_info">
        <!--<label class="show" id="left_show"><</label>-->
        <ul>
            <li>
                <label>操作系統:</label>
                <span id="operate_system">未知</span>
            </li>
            <li>
                <label>開發語言:</label>
                <span id="use_language">未知</span>
            </li>
            <li>
                <label>CDN:</label>
                <span id="use_cdn">未知</span>
            </li>
            <li>
                <label>WAF:</label>
                <span id="use_waf">未知</span>
            </li>
        </ul>
    </div>
    <div class="toolbar">
        <div class="btn-showOrHide">
          <label class="show" id="download_show"  @click="changeBottomShow">{{showBottomText}}</label>
        </div>
        <ul  v-show="showBottom"></ul>
    </div>
    </div> 
</template>
  
<style >
html,body{
  width:100%;
  overflow:hidden;
}
g.type-suss>rect {fill: #ddefd3;}
.node {
    cursor: pointer;
}

g.node circle {
  fill: #dff0e7;
  stroke: #3fc96e;
  stroke-width: 1px;
}
g.node rect {
  padding: 5px;
  fill: #dff0e7;
  stroke: #3fc96e;
  stroke-width: 1px;
}
g.node text {
  color: #2dbb8a;
  font: 14px sans-serif;
  font-weight:700;
}
.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
ul li{
  list-style: none;
}
.btn-success{
  width: 220px;
  position: absolute;
  top:16px;
  left: 20px;
  background: #2dbb8a;
  border-color: #2dbb8a;
}
.content{
    width: 100%;
    height: 100%;
}
.systemlist{
    position: absolute;
    left: 20px;
    top: 70px;
    width: 220px;
    height: 160px;
    background-color: #fff;
    border:1px solid #d8e1e4;
    border-radius: 4px;
    padding: 20px;
    padding-bottom: 0;
    box-sizing: border-box;
    font-size: 12px;
    color: #687386;
}
.systemlist ul{
  list-style: none;
  padding-left: 0px;
  margin:0;
}
.systemlist ul li{
    width: 100%;
    margin-bottom: 10px;
}
.systemlist ul li label{
    display: inline-block;
    font-weight: bold;
}   
.isRed{
  stroke: #f1602d;
}
.toolbar{
    padding: 0px 2px;
    position: absolute;
    left: 0px;
    bottom: 0;
    right:204px;
    background-color: #d8e1e4;
    border-radius: 2px;
    opacity:0.5;
    overflow-y:scroll;
}
.toolbar ul{
  height:216px;
}
.systemlist .show{
    position: absolute;
    width: 20px;
    height: 45px;
    top: 50%;
    margin-top: -16px;
    left: 199px;
    background-color: #fff;
    border:1px solid  #d8e1e4;
    color: #a1b0b5;
    text-align: center;
    line-height: 42px;
    cursor: pointer;
}

.btn-showOrHide{
  width:100%;
  height:24px;
}
.toolbar .show{
    width: 56px;
    display: block;
    height: 100%;
    background-color: #fff;
    border:1px solid  #d8e1e4;
    color: #a1b0b5;
    margin:0 auto;
    text-align: center;
    cursor: pointer;
}  
 /*漏洞信息*/
.looplist{
    position: absolute;
    right: 0;
    top: 0;
    background-color: #fff;
    height: 100%;
    box-sizing: border-box;
    border-left: 1px solid #d8e1e4;
}
.looplist ul{
  padding-left: 0px;
}
.looplist .rightBtn{
    width:21px;
    height: 100%;
    display: flex;
    align-items: center;
    float: left;
}
.looplist .rightBtn label{
    width: 20px;
    height: 45px;
    background-color: #fff;
    border:1px solid  #d8e1e4;
    color: #a1b0b5;
    text-align: center;
    line-height: 42px;
    cursor: pointer;

}
.looplist .rightContent{
    float:left;
    width: 196px;
    font-size: 14px;
    color: #687386;
    padding-top: 10px;
    padding-bottom: 10px;
    margin-left: -15px;
    padding-right:5px;
}
.looplist >div li{
    color: #687386;
    font-size: 12px;
    height: 40px;
    line-height: 40px;
    border-bottom: 1px solid #d8e1e4;
    display:block;
    overflow:hidden;
    white-space:nowrap;
    text-overflow:ellipsis;
}
</style>
<script>
export default({
    name:'experiencetree',
    data(){
        return{  
             treeData: [],
             showRight: true,
             showBottom: true,
             showRightText: '>',
             showBottomText: '∨'
        }
    }, 
    created:function(){
        this.$store.state.activefirstMenu="/tree";  
        API.findExperienceTree().then(res => {
            this.treeData =****** ;
            let that = this;
 
let reg = new RegExp("[\\u4E00-\\u9FFF]+","g");
         //定義樹圖的全局屬性(寬高)
    let margin = {top:0, right: 0, bottom: 0, left: 0},
        width = 1700 - margin.right - margin.left,
        height = 800 - margin.top - margin.bottom;

    let i = 0,
        duration = 750,
        root;

    let tree = d3.layout.tree()//創建一個樹佈局
        .size([height, width])
        .nodeSize([4, 1])
        .separation(function(a, b) { return (a.parent == b.parent ? 10 : 8); });

    let diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.y, d.x]; });


            // Setup zoom and pan
    let zoom = d3.behavior.zoom()
        .scaleExtent([.1,1])
        .on('zoom', function(){
          if($("#myMenu").css("display")=="block"){
            $('#myMenu').hide();
          }
          let tran = (Number(d3.event.translate.toString().split(',')[0])+100)+','+(Number(d3.event.translate.toString().split(',')[1])+400)
          svg.attr("transform", "translate(" + tran + ") scale(" + d3.event.scale + ")");
    });

 
    let svg = d3.select(".content").append("svg")
        .attr("width", width + margin.right + margin.left)
        .attr("height", height + margin.top + margin.bottom)
        .call(zoom)
        .append("g")
        .attr("transform", "translate(100,400)");
    generate();
    function generate(){
        root = that.treeData[0];
        root.x0 = height / 2;
        root.y0 = 0;
        update(root);
        d3.select(self.frameElement).style("height", "1600px");
    }

    function update(source) {
      let nodes = tree.nodes(root).reverse(),
          links = tree.links(nodes);

   
      nodes.forEach(function(d) { d.y = d.depth * 400; });

 
      let node = svg.selectAll("g.node")
          .data(nodes, function(d) { return d.id || (d.id = ++i); });//data():綁定一個數組到選擇集上,數組的各項值分別與選擇集的各元素綁定

 
      let nodeEnter = node.enter().append("g")  
          .attr("class", "node") 
          .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
          .on("click", click);

      //添加連接點---此處設置的是圓圈過渡時候的效果(顏色)
      // nodeEnter.append("circle")
        //   .attr("r", 1e-6)
        //   .style("fill", function(d) { return d._children ? "lightsteelblue" : "#357CAE"; });//d 代表數據,也就是與某元素綁定的數據。
    nodeEnter.append("rect")
    .attr("x",function(d) {  return 0})
    .attr("y", -8)
    .attr("width", function(d) {
        if (reg.test(d.name)){
            return d.name.length * 10 + 24;
        }else{
            if (d.name.length < 6){
                return d.name.length * 16;
            }else{
                return d.name.length * 8;
            }
        }
    })
    .attr("height",25)
    .attr("rx",10)
      .style("fill", function(d){
          if(d.isRed == true){
              return "#f1602d";
          }else{
            return "#dff0e7"
          }
      });//d 代表數據,也就是與某元素綁定的數據。// 小方塊的背景顏色綠色

  nodeEnter.append("text")
    .attr("x", function(d) {
        if (reg.test(d.name)){
            return (d.name.length * 10 + 24) / 2;
        }else{
            if (d.name.length < 6){
                return d.name.length * 16 / 2;
            }else{
                return d.name.length * 8 / 2;
            }
        }
        })
    .attr("dy", "10")
    .attr("text-anchor", "middle")
    .text(function(d) { return d.name; })
    .style("fill", function(d){
          if(d.isRed == true){
            console.log(d);
            paint_right_message(d);
            return "#fff";
          }else{
            return "#2dbb8a";
          }
      })
    .style("fill-opacity", 1);

      let nodeUpdate = node.transition()  
          .duration(duration)  
          .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });//Y


      let nodeExit = node.exit().transition()
          .duration(duration)
          .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })//Y
          .remove();

  

      //再處理連線集合
      let link = svg.selectAll("path.link")
          .data(links, function(d) { return d.target.id; });


      // Enter any new links at the parent's previous position.
      link.enter().insert("path", "g")
          .attr("class", "link")
          .attr("d", function(d) {
            let o = {x: source.x0, y: source.y0};//YES
            return diagonal({source: o, target: o}); 
          })
        .attr('marker-end', 'url(#arrow)');


      link.transition()
          .duration(duration)
          .attr("d", diagonal);


      link.exit().transition()
          .duration(duration)
          .attr("d", function(d) {
            let o = {x: source.x, y: source.y};//NO
            return diagonal({source: o, target: o});
          })
          .remove();

      // Stash the old positions for transition.將舊的斜線過渡效果隱藏
      nodes.forEach(function(d) {
        d.x0 = d.y;
        d.y0 = d.x;
      });
    }

    // Toggle children on click.切換子節點事件
    function click(d) {
      if($("#myMenu").css("display")=="block"){
        $('#myMenu').hide();
      }
      if (d.children) {
        d._children = d.children;
        d.children = null;
      } else {
        d.children = d._children;
        d._children = null;
      }
      update(d);
    }
          }) 
    },
    mounted:function(){ 
      
    },
    methods: {
      returnLast(){
        this.$router.push({name: 'createtask'})
      },
      changeShowRight(){
        if(!this.showRight){
          $('.looplist').animate({'right': '0px'}, 800);
          this.showRightText=">"
        }else{
          $('.looplist').animate({'right': '-180px'}, 800);
          this.showRightText="<"
        }
        this.showRight = !this.showRight
      },
      changeBottomShow(){
        if(!this.showBottom){
          this.showBottomText="∨"
        }else{
          this.showBottomText="∧"
        }
        this.showBottom = !this.showBottom
      }
    }
})
</script>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章