• 使用d3制作上下结构的股权穿透图


    <template>
      <div id="borrow">
        <div id="Main">
          <div class="tupu" id="tupu">
            <div class="tupu-toolbar">
              <ul>
                <li id="zoomOut">
                  <span class="big"></span>放大
                </li>
                <li id="zoomIn">
                  <span class="small"></span>缩小
                </li>
                <li id="reset">
                  <span class="refresh"></span>重置
                </li>
                <li @click="toggleFullScreen($event)">
                  <span class="screen"></span>
                  {{isFullscreen?"全屏":"退出"}}
                </li>
                <li id="TrSave" @click="downloadImpByChart('股权穿透图')">
                  <span class="save"></span>保存
                </li>
              </ul>
            </div>
            <div id="mountNode"></div>
          </div>
        </div>
        <div class="back" @click="onJumpReport">
          <!-- <img src="~@/assets/relation/back.svg" alt /> -->
          {{companyName}}
        </div>
        <div class="back2 back" @click="onJumpReport">
          <img src="~@/assets/relation/back.svg" alt />返回
        </div>
      </div>
    </template>
    

      

    export default {
        components: {},
        mixins: [D3Mixin],
        name: 'relation2',
        data() {
            return {
                companyName: this.$route.query.companyName,
                isFullscreen: true,
                rootData: {
                    "downward": {
                        "direction": "down",
                        "name": "origin",
                        "children": [
                            {
                                "name": "...有限公司",
                                "amount": "100",
                                "ratio": "55%",
                                "hasHumanholding":true,
                                "hasChildren":true,
                                "isExpand": false,
                                "type": 2,
                                "hasNode": 1,
                                "children": [
                                {
                                    "name": "公司名字",
                                    "hasHumanholding":false,
                                    "hasChildren":true,
                                    "amount": "100",
                                    "isHoldingCompany": true,
                                    "ratio": "55%",
                                    "type": 2,
                                    "children": []
                                },
                                {
                                    "name": "公司名字",
                                    "hasHumanholding":false,
                                    "hasChildren":true,
                                    "amount": "100",
                                    "isHoldingCompany": true,
                                    "ratio": "55%",
                                    "type": 2,
                                    "children": []
                                }
                                ]
                            },
                            {
                                "name": "...有限公司11",
                                "amount": "100",
                                "isHoldingCompany": true,
                                "ratio": "55%",
                                "hasHumanholding":true,
                                "hasChildren":true,
                                "isExpand": false,
                                "type": 2,
                                "hasNode": 1,
                                "children": [
                                    {
                                        "name": "公司名字",
                                        "hasHumanholding":false,
                                        "hasChildren":true,
                                        "amount": "100",
                                        "isHoldingCompany": true,
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    },
                                    {
                                        "name": "公司名字",
                                        "hasHumanholding":false,
                                        "hasChildren":true,
                                        "amount": "100",
                                        "isHoldingCompany": true,
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    }
                                ]
                            },
                            {
                                "name": "...有限公司",
                                "amount": "100",
                                "isHoldingCompany": true,
                                "ratio": "55%",
                                "hasHumanholding":true,
                                "hasChildren":true,
                                "isExpand": false,
                                "type": 2,
                                "hasNode": 1,
                                "children": [
                                    {
                                        "name": "公司名字",
                                        "hasHumanholding":false,
                                        "hasChildren":true,
                                        "amount": "100",
                                        "isHoldingCompany": true,
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    },
                                    {
                                        "name": "公司名字",
                                        "hasHumanholding":false,
                                        "hasChildren":true,
                                        "amount": "100",
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    }
                                ]
                            },
                            {
                                "name": "...有限公司",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "type": 2,
                                "children": []
                            },
                            {
                                "name": "...有限公司",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "isExpand": false,
                                "amount": "100",
                                "ratio": "55%",
                                "type": 2,
                                "hasNode": 1,
                                "children": [
                                    {
                                        "name": "公司或股东名字",
                                        "hasHumanholding":false,
                                        "amount": "100",
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    },
                                    {
                                        "name": "公司或股东名字",
                                        "hasHumanholding":false,
                                        "amount": "100",
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    },
                                    {
                                        "name": "公司或股东名字",
                                        "hasHumanholding":false,
                                        "amount": "100",
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    },
                                    {
                                        "name": "公司或股东名字",
                                        "hasHumanholding":false,
                                        "amount": "100",
                                        "ratio": "55%",
                                        "type": 2,
                                        "children": []
                                    }
                                ]
                            }
                        ]
                    },
                    "upward": {
                        "direction": "up",
                        "name": "origin",
                        "children": [
                        {
                            "name": "...(有限合伙)",
                            "hasHumanholding":false,
                            "amount": "100",
                            "isHoldingCompany": true,
                            "ratio": "55%",
                            "type": 2,
                        },
                        {
                            "name": "...(有限合伙)",
                            "hasHumanholding":false,
                            "amount": "100",
                            "isHoldingCompany": true,
                            "ratio": "55%",
                            "type": 2,
                            "hasNode": 1,
                            "children": [
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "isHoldingCompany": true,
                                "ratio": "55%",
                                "type": 1,
                                "children": [],
                                "isFHolder": true,
                                "holderPercent": '5%',
                            },
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "isExpand": false,
                                "amount": "100",
                                "isHoldingCompany": true,
                                "ratio": "55%",
                                "type": 2,
                                "hasNode": 1,
                                "children": [
                                {
                                    "name": "公司或股东名字",
                                    "hasHumanholding":false,
                                    "amount": "100",
                                    "isHoldingCompany": true,
                                    "ratio": "55%",
                                    "type": 1,
                                    "isFHolder": true,
                                    "isActualController": true,
                                    "holderPercent": '95%',
                                    "children": []
                                },
                                {
                                    "name": "公司或股东名字",
                                    "hasHumanholding":false,
                                    "amount": "100",
                                    "ratio": "55%",
                                    "type": 2,
                                    "children": []
                                }
                                ]
                            },
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "ratio": "55%",
                                "type": 1,
                                "children": []
                            }
                            ]
                        }
                        ]
                    }
                },
                rootName: '...有限公司',
                // beijingCrid: '98682337095518809'
                beijingCrid: this.$route.query.companyId ? decodeURIComponent(this.$route.query.companyId) : '98682337095519887'
            }
        },
        created () {
            
        },
        mounted () {
            this.getInitData()
            // this.drawing()
            window.addEventListener('resize',function(){
                const svg = document.getElementById('svg')
                svg.setAttribute('height',window.innerHeight)
            })
        },
        methods: {
            getInitData () {
                gqctt({
                    beijingCrid: this.beijingCrid,
                    direction: ''
                }).then(res => {
                    if (res.code === 0) {
                        this.rootData.upward.children = res.result.investorList
                        this.rootData.downward.children = res.result.holderList
                        this.rootData.upward.children.map(item => {
                            item.amount = Number(item.subConAm).toFixed(2)
                            
                            item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                          
                            item.name = item.entName
                            item.type = item.bz === '企业' ? 2 : 1
                            item.isHoldingCompany = item.isHolding == 1 ? true : false
                            item.isFHolder = item.subComBl >= 0.25 && item.type == 1
                            item.holderPercent = item.ratio
                            item.direction = 'up'
                        })
                        this.rootData.downward.children.map(item => {
                            item.amount = Number(item.subConAm).toFixed(2)
                           
                            item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                           
                            item.name = item.pentName
                            item.type = item.bz === '企业' ? 2 : 1
                            item.direction = 'down'
                        })
                        this.rootName = res.result.name
                        this.drawing()
                        console.log(this.rootData)
                    }
                })
            },
            addChildren (obj,beijingCrid,direction,cb) {
                gqctt({
                    beijingCrid: beijingCrid,
                    direction: direction
                }).then(res => {
                    if (res.code === 0) {
                        if (direction == 'up') {
                            obj.children = res.result.investorList
                            obj.children.map(item => {
                                item.amount = Number(item.subConAm).toFixed(2)
                                item.isFHolder = true
                           
                                item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                              
                                item.name = item.entName
                                item.type = item.bz === '企业' ? 2 : 1
                                item.isHoldingCompany = item.isHolding == 1 ? true : false
                                item.isFHolder = item.subComBl >= 0.25 && item.type == 1
                                item.direction = direction
                                item.holderPercent = item.ratio
                            })
                        } else {
                            obj.children = res.result.holderList
                                obj.children.map(item => {
                                item.amount = Number(item.subConAm).toFixed(2)
                                item.isFHolder = true
    
                                item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                  
                                item.name = item.pentName
                                item.type = item.bz === '企业' ? 2 : 1
                                item.isHoldingCompany = item.isHolding == 1 ? true : false
                                item.isFHolder = item.subComBl >= 0.25 && item.type == 1
                                item.direction = direction
                                item.holderPercent = item.ratio
                            })
                        }
                        
                        cb()
                    }
                })
            },
            drawing () {
                const width = document.getElementById('mountNode').scrollWidth
                const height = document.getElementById('mountNode').scrollHeight || 600
                const strokeColor = {
                    isActualController: '#FBC6C3',
                    isFHolder: '#F3DDB6',
                    person: '#0084FF',
                    default: '#CCC'
                }
                const lineColor = {
                    isActualController: '#FA6B64',
                    isFHolder: '#F1B03A',
                    person: '#0084FF',
                    default: '#919191'
                }
                const fillColor = {
                    isActualController: "#FFFBFB",
                    isFHolder: '#FEFBF3',
                    person: '#F5FAFF',
                    default: '#FFF'
                }
                var _this = this;
                // var rootName = ''; //根节点的名字
                var rootRectWidth = 0; //根节点rect的宽度
                var downwardLength = 0,
                upwardLength = 0;
                var forUpward = true
    
                var treeChart = function(d3Object) {
                    this.d3 = d3Object;
                    this.directions = ['upward', 'downward'];
                };
     
     
                treeChart.prototype.drawChart = function() {
                    // First get tree data for both directions.
                    this.treeData = {};
                    var self = this;
                    self.directions.forEach(function(direction) {
                        self.treeData[direction] = _this.rootData[direction];
                    });
                    // rootName = '上海冰鉴信息科技有限公司';
                    rootRectWidth = _this.rootName.length * 15 + 60;
                    //获得upward第一级节点的个数
                    upwardLength = _this.rootData.upward.children.length;
                    //获得downward第一级节点的个数
                    downwardLength = _this.rootData.downward.children.length;
                    self.graphTree(self.getTreeConfig());
                };
                treeChart.prototype.getTreeConfig = function() {
                    var treeConfig = {
                        'margin': {
                            'top': 10,
                            'right': 5,
                            'bottom': 0,
                            'left': 30
                        }
                    }
                    treeConfig.chartWidth = (width - treeConfig.margin.right - treeConfig.margin.left);
                    treeConfig.chartHeight = (height - treeConfig.margin.top - treeConfig.margin.bottom);
                    treeConfig.centralHeight = treeConfig.chartHeight / 2;
                    treeConfig.centralWidth = treeConfig.chartWidth / 2;
                    treeConfig.linkLength = 160;
                    treeConfig.duration = 500; //动画时间
                    return treeConfig;
                };
                treeChart.prototype.graphTree = function(config) {
                    var self = this;
                    var d3 = this.d3;
                    var linkLength = config.linkLength;
                    var duration = config.duration;
                    var hasChildNodeArr = [];
                    var id = 0;
                    var diagonal = function(obj) {
                        //折线
    
                        var s = obj.source;
                        var t = obj.target;
                        let multiplier = s.x > t.x ? -1 : s.x < t.x ? 1 : 0
                        let path = s.y > t.y ? (s.y / 3 + t.y * 2 / 3) : (s.y / 3 + t.y * 2 / 3 + 15)
                        return (
                            "M" +
                            s.x +
                            "," +
                            (s.y + 12) +
                            "L" +
                            s.x +
                            "," +
                            path +
                            "L" +
                            t.x +
                            "," +
                            path +
                            // pathA+
                            "L" +
                            t.x +
                            "," +
                            t.y
                        );
                    };
                    var zoom = d3.behavior.zoom()
                        .scaleExtent([0.5, 2])
                        .on('zoom', redraw);
    
                    var svg = d3.select('#mountNode')
                        .append('svg')
                        .attr('id','svg')
                        .attr('width', config.chartWidth + config.margin.right + config.margin.left)
                        .attr('height', config.chartHeight + config.margin.top + config.margin.bottom)
                        .attr('xmlns','http://www.w3.org/2000/svg')
                        .on('mousedown', disableRightClick)
                        .call(zoom)
                        .on('dblclick.zoom', null);
                    var treeG = svg.append('g')
                        .attr('class', 'gbox')
                        .attr('transform', 'translate(' + config.margin.left + ',' + config.margin.top + ')');
                    
                    d3.select("#reset").on("click", function(d){
                        interpolateZoom([0, 0], 1);
                    });
                    function interpolateZoom(translate, scale) {
                        var self = this;
                        return d3
                            .transition()
                            .duration(350)
                            .tween("zoom", function() {
                                var iTranslate = d3.interpolate(zoom.translate(), translate),
                                    iScale = d3.interpolate(zoom.scale(), scale);
                                return function(t) {
                                    zoom.scale(iScale(t)).translate(iTranslate(t));
                                    redraw();
                                };
                            });
                    }
    
                    function zoomClick() {
                        var clicked = d3.event.target,
                            direction = 1,
                            factor = 0.2,
                            target_zoom = 1,
                            center = [width / 2, height / 2],
                            extent = zoom.scaleExtent(),
                            translate = zoom.translate(),
                            translate0 = [],
                            l = [],
                            view = { x: translate[0], y: translate[1], k: zoom.scale() };
    
                        d3.event.preventDefault();
                        direction = this.id === "zoomOut" ? 1 : -1;
    
                        target_zoom = Number(zoom.scale()  + factor * direction).toFixed(1)
              
                        if (target_zoom === extent[0] || target_zoom === extent[1]) {
                            return false
                        }
                        if (target_zoom < extent[0]) {
                            target_zoom = extent[0]
                        }
                        if (target_zoom > extent[1]) {
                            target_zoom = extent[1]
                        }
                        translate0 = [(center[0] - view.x) / view.k, (center[1] - view.y) / view.k];
                        view.k = target_zoom;
                        l = [translate0[0] * view.k + view.x, translate0[1] * view.k + view.y];
    
                        view.x += center[0] - l[0];
                        view.y += center[1] - l[1];
    
                        interpolateZoom([view.x, view.y], view.k);
                    }
                    d3.select("#zoomIn").on("click", zoomClick);
                    d3.select("#zoomOut").on("click", zoomClick);
                    for(var d in this.directions) {
                        var direction = this.directions[d];
                        var data = self.treeData[direction];
                        data.x0 = config.centralWidth;
                        data.y0 = config.centralHeight;
                        data.children.forEach(collapse);
                        update(data, data, treeG);
                    }
                
                    function update(source, originalData, g) {
                        var direction = originalData['direction'];
                        forUpward = direction == 'up';
                        var node_class = direction + 'Node';
                        var link_class = direction + 'Link';
                        var downwardSign = (forUpward) ? -1 : 1;
                        var nodeColor = (forUpward) ? '#37592b' : '#8b4513';
                
                        var isExpand = false;
                        var statusUp = true;
                        var statusDown = true;
                        var nodeSpace = 210;
                        var tree = d3.layout.tree().sort(sortByDate).nodeSize([nodeSpace, 0]);
                        var nodes = tree.nodes(originalData);
                        var links = tree.links(nodes);
                        var offsetX = -config.centralWidth;
                        nodes.forEach(function(d) {
                            d.y = downwardSign * (d.depth * linkLength) + config.centralHeight;
                            d.x = d.x - offsetX;
                            if(d.name == 'origin') {
                                d.x = config.centralWidth;
                                d.y += downwardSign * 0; // 上下两树图根节点之间的距离
                            }
                        });
    
                        var node = g.selectAll('g.' + node_class)
                            .data(nodes, function(d) {
                                return d.id || (d.id = ++id);
                            })
                        var nodeEnter = node.enter().append('g')
                            .attr('class', node_class)
                            .attr('transform', function(d) {
                                return 'translate(' + source.x0 + ',' + source.y0 + ')';
                            })
                            .style('cursor', function(d) {
                                return(d.name == 'origin') ? '' : (d.children || d._children) ? 'pointer' : '';
                            })
                            .on('click',d => {
                                if (d.type == 2) {
                                    if ((d.direction == 'up' && d.beijingCrid) || (d.direction == 'down' && d.pbeijingCrid)) {
                                        _this.$router.push({
                                            path: '/search/detail',
                                            name: 'search-detail',
                                            query: {
                                                companyId: d.direction == 'up' ? d.beijingCrid : d.pbeijingCrid
                                            }
                                        })
                                    }
                                }
                            })
                            .on('mouseover',d => {
                                if (d.name === 'origin') {
                                    return false
                                }
                                let hoverLinkArr = [d.id]
                                let sColor = strokeColor.default
                                let lColor = lineColor.default
                                if (d.isActualController) {
                                    sColor = strokeColor.isActualController
                                    lColor = lineColor.isActualController
                                } else if (d.isFHolder) {
                                    sColor = strokeColor.isFHolder
                                    lColor = lineColor.isFHolder
                                } else {
                                    sColor = strokeColor.person
                                    lColor = lineColor.person
                                }
                                getRelationLink(d.id,lColor)
                                d3.selectAll('marker#resolved'+d.id).selectAll('path').attr('fill',lColor)
                                let link
                                if (d.direction == 'up') {
                                    link = d3.selectAll('.upLink')
                                } else {
                                    link = d3.selectAll('.downLink')
                                }
                                link.sort(function(a,b){
                                    if (a.target.id === d.id) {
                                        return 1
                                    } else {
                                        return -1
                                    }
                                })
                                rect.style('stroke-width',function(r) {
                                    if (r.id === d.id) {
                                        return '2'
                                    }
                                }).style('stroke', function(r) {
                                    if (r.id === d.id) {
                                        if (r.type == 2) {
                                            return '#0084FF'
                                        } else {
                                            if (r.type == 1) {
                                                if (r.isActualController) {
                                                    return "#FA6B64"
                                                } else if (r.isFHolder) {
                                                    return '#F1B03A'
                                                } else {
                                                    return '#0084FF'
                                                }
                                                
                                            } else{
                                                return "#CCC"
                                            }
                                        }
                                    } else {
                                        if (r.type == 1) {
                                            if (r.isActualController) {
                                                return "#FBC6C3"
                                            } else if (r.isFHolder) {
                                                return '#F3DDB6'
                                            } else {
                                                return '#83C6FF'
                                            }
                                        } else if (r.name === 'origin') {
                                            return '#0E78DB'
                                        } else{
                                            return "#CCC"
                                        }
                                    }
                                })
                            })
                            .on('mouseout',d => {
                                if (d.name === 'origin') {
                                    return false
                                }
                                d3.selectAll('marker#resolved'+d.id).selectAll('path').attr('fill',lineColor.default)
                                link.style('stroke',function(l){
                                    return '#919191'
                                }).style('stroke-width',function(l){
                                    return 1
                                })
                                rect.style('stroke-width',function(r) {
                                    if (r.id === d.id) {
                                        return '1'
                                    }
                                }).style('stroke', function(r) {
                                    if (r.type == 1) {
                                        if (r.isActualController) {
                                            return "#FBC6C3"
                                        } else if (r.isFHolder) {
                                            return '#F3DDB6'
                                        } else {
                                            return '#83C6FF'
                                        }
                                    } else if (r.name === 'origin') {
                                        return '#0E78DB'
                                    } else {
                                        return "#CCC"
                                    }
                                })
                            })
                        function getRelationLink (id,color) {
                            if (id == 1) {
                                return false
                            }
                            let sourceId = ''
                            link.style('stroke',function(l){
                                if (id === l.target.id) {
                                    sourceId = l.source.id
                                    return color
                                }
                            }).style('stroke-width',function(l){
                                if (id === l.target.id) {
                                    return 2
                                }
                            })
                            
                        }
                        const rect = nodeEnter.append("svg:rect")
                            .attr("x", function(d) {
                                return(d.name == 'origin') ? -(rootRectWidth / 2) : -100;
                            })
                            .attr("y", function(d) {
                                return(d.name == 'origin') ? -20 : forUpward ? -52 : 12;
                            })
                            .attr("width", function(d) {
                                return(d.name == 'origin') ? rootRectWidth : 200;
                            })
                            .attr("height", function(d) {
                                return(d.name == 'origin') ? 40 : 80;
                            })
                            .attr("rx", 0)
                            .style('cursor', "pointer")
                            .style("stroke", function(d) {
                                if (d.name == 'origin') {
                                    return "#0E78DB"
                                } else if (d.type == 1) {
                                    if (d.isActualController) {
                                        return "#FBC6C3"
                                    } else if (d.isFHolder) {
                                        return '#F3DDB6'
                                    } else {
                                        return '#83C6FF'
                                    }
                                } else{
                                    return "#CCC"
                                }
                            })
                            .style("fill", function(d) {
                                if (d.name == 'origin') {
                                    return "#0084FF"
                                } else if (d.type == 1) {
                                    if (d.isActualController) {
                                        return "#FFFBFB"
                                    } else if (d.isFHolder) {
                                        return '#FEFBF3'
                                    } else {
                                        return '#F5FAFF'
                                    }
                                } else{
                                    return "#fff"
                                }
                            })
                        
                        const personTopRect = nodeEnter.append("svg:rect")
                            .attr("x", function(d) {
                                return -100;
                            })
                            .attr("y", function(d) {
                                return !d.isFHolder ? 0 : d.isActualController ? -102 : -82;
                            })
                            .attr("width", function(d) {
                                return d.isFHolder ? 200 : 0;
                            })
                            .attr("height", function(d) {
                                return !d.isFHolder ? 0 : d.isActualController ? 50 : 30;
                            })
                            .attr("rx", 2)
                            .style("stroke", function(d) {
                                return d.isActualController ? "#FA6B64" : "#F1B03A";
                            })
                            .style("fill", function(d) {
                                return d.isActualController ? "#FA6B64" : "#F1B03A";   //节点背景色
                            })
                        nodeEnter
                            .append("svg:path")
                            .attr("fill", d => {
                                return d.isActualController ? "#FA6B64" : "#F1B03A"
                            })
                            .attr("d", function(d) {
                                if (d.isFHolder) {
                                    return "M0 -44 L-10 -54 L10 -54 Z"
                                } else {
                                    return ""; 
                                }
                            })
                        const holdingCompanyRect = nodeEnter.append('svg:rect')
                            .attr("x", "-40")
                            .attr("y", function(d) {
                                return(d.name == 'origin') ? '.35em' : forUpward ? '31' : '-9';
                            })
                            .attr("rx",2)
                            .attr("width", function(d) {
                                return d.isHoldingCompany ? 30 : 0;
                            })
                            .attr("height", function(d) {
                                return d.isHoldingCompany ? 20 : 0;
                            })
                            .style("fill", "#EBF5FF")
                        nodeEnter.append("text")
                            .attr("x", "-35")
                            .attr("dy", function(d) {
                                return(d.name == 'origin') ? '.35em' : forUpward ? '45' : '5';
                            })
                            .attr("text-anchor", "start")
                            .style("fill", "#0084FF")
                            .style('font-size', 10)
                            .text(function(d) {
                                return d.isHoldingCompany ? "控股" : "";
                            });
                        nodeEnter.append('circle')
                            .attr('r', 1e-6);
                        nodeEnter.append("text")
                            .attr("x", function(d) {
                                return '0'
                            })
                            .attr('dy', function(d) {
                                return(d.name == 'origin') ? '.35em' : forUpward ? '-24' : '40';
                            })
                            .attr("text-anchor", function(d) {
                                return 'middle'
                            })
                            .text(function(d) {
                                if(d.name == 'origin') {
                                    return _this.rootName;
                                } 
                                if(d.repeated) {
                                    return '[Recurring] ' + d.name;
                                }
                                return(d.name.length > 12) ? d.name.substr(0, 12) : d.name;
                            })
                            .style({
                                'fill': function(d) {
                                    if(d.name == 'origin') {
                                        return '#fff';
                                    } else {
                                        return '#333'
                                    }
                                },
                                'font-size': function(d) {
                                    return(d.name == 'origin') ? 16 : 14;
                                },
                                'cursor': "pointer"
                            })
                            .on('click', Change_modal)
                            .append('svg:title').text(d=>d.name)
                        nodeEnter.append("text")
                            .attr("x", "0")
                            .attr("dy", function(d) {
                                return(d.name == 'origin') ? '.35em' : forUpward ? '-5' : '59';
                            })
                            .attr("text-anchor", function() {
                                return 'middle'
                            })
                            .attr('fill', '#333')
                            .text(function(d) {
                                return d.name.length > 24 ? d.name.substr(12, 12) + '...' : d.name.substr(12, d.name.length);
                            })
                            .style({
                                'font-size': function(d) {
                                    return(d.name == 'origin') ? 16 : 14;
                                },
                                'cursor': "pointer"
                            })
                            .append('svg:title').text(d=>d.name)
    
                        nodeEnter.append("text")
                            .attr("x", "0")
                            .attr("dy", function(d) {
                                if (d.name === 'origin') {
                                    return '.35em'
                                } else {
                                    if (forUpward) {
                                        if (d.name.length > 12) {
                                            return '16'
                                        } else {
                                            return '6'
                                        }
                                    } else {
                                        if (d.name.length > 12) {
                                            return '80'
                                        } else {
                                            return '70'
                                        }
                                    }
                                }
                            })
                            .attr("text-anchor", "middle")
                            .attr("class", "linkname")
                            .style("fill", "#666")
                            .style('cursor', "pointer")
                            .style('font-size', 12)
                            .text(function(d) {
                                var str = (d.name == 'origin') ? '' : "认缴金额:"+ d.amount +"万人民币";
                                return(str.length > 18) ? str.substr(0, 18) + ".." : str;
                            });
                        nodeEnter.append("text")
                            .attr("x", "10")
                            .attr("dy", function(d) {
                                return(d.name == 'origin') ? '.35em' : forUpward ? '45' : '5';
                            })
                            .attr("text-anchor", "start")
                            .attr("class", "linkname")
                            .style("fill", "#0084FF")
                            .style('font-size', 10)
                            .text(function(d) {
                                return(d.name == 'origin') ? "" : d.ratio;
                            });
                        nodeEnter.append("text")
                            .attr("x", "0")
                            .attr("dy", function(d) {
                                return d.isActualController ? -87 : -72;
                            })
                            .attr("text-anchor", "middle")
                            .style("fill", "#fff")
                            .style('font-size', 12)
                            .text(function(d) {
                                return d.isActualController ? '疑似实际控制人' : '';
                            });
                        nodeEnter.append("text")
                            .attr("x", "0")
                            .attr("dy", function(d) {
                                return d.isActualController ? -65 : -63;
                            })
                            .attr("text-anchor", "middle")
                            .style("fill", "#fff")
                            .style('font-size', 12)
                            .text(function(d) {
                                return d.isFHolder ? "最终受益人:" + d.holderPercent : '';
                            });
                        var nodeUpdate = node.transition()
                            .duration(duration)
                            .attr('transform', function(d) {
                                return 'translate(' + d.x + ',' + d.y + ')';
                            });
                        nodeUpdate.select('circle')
                            .attr('r', function(d) {
                                return d.hasNode == 1 ? 10 : 0
                            })
                            .attr('cy', function(d) {
                                return(d.name == 'origin') ? -20 : (forUpward) ? -63 : 103;
                            })
                            .style('fill', function(d) {
                                return d.hasNode == 1 ? "#9CD0FF" : ""
                            })
                            .style('stroke', function(d) {
                                return d.hasNode == 1 ? "#9CD0FF" : ""
                            })
                            .style('stroke-width', function(d) {
                                if(d.repeated) {
                                    return 5;
                                }
                            });
                        //代表是否展开的+-号
                        nodeEnter.append("svg:text")
                            .attr("class", "isExpand")
                            .attr("x", "0")
                            .attr("dy", function(d) {
                                return forUpward ? -57 : 109;
                            })
                            .attr("text-anchor", "middle")
                            .style("fill", "#fff")
                            .style('font-size','20px')
                            .style('cursor','pointer')
                            .text(function(d) {
                                if(d.name == 'origin') {
                                    return '';
                                }
                                return d.hasNode == 1 ? "+" : ''
                            })
                            .on('click',click)
                
                        nodeUpdate.select('text').style('fill-opacity', 1)
                        
                        var nodeExit = node.exit().transition()
                            .duration(duration)
                            .attr('transform', function(d) {
                            return 'translate(' + source.x + ',' + source.y + ')';
                            })
                            .remove();
                        nodeExit.select('circle')
                            .attr('r', 1e-6)
                        nodeExit.select('text')
                            .style('fill-opacity', 1e-6);
    
                        var link = g.selectAll('path.' + link_class)
                            .data(links, function(d) {
                                return d.target.id;
                            });
    
                        link.enter().insert('path', 'g')
                            .attr('class', link_class)
                            .attr('stroke',function(d){
                                // return '#8b4513'
                                return '#919191'
                            })
                            .attr('fill',"none")
                            .attr('stroke-width','1px')
                            // .attr('opacity', 0.5)
                            .attr('d', function(d) {
                                var o = {
                                    x: source.x0,
                                    y: source.y0
                                };
                                return diagonal({
                                    source: o,
                                    target: o
                                });
                            })
                            .attr("marker-end",function (d, i) { 
                                return forUpward ? getMarkerUpArrow(d,i) : getMarkerDownArrow(d,i)
                            })
                            .attr("id", function(d, i) {
                                return "mypath" + "-" + d.source.id + "-" + d.target.id;
                            })
                        link.transition()
                            .duration(duration)
                            .attr('d', diagonal);
                        link.exit().transition()
                            .duration(duration)
                            .attr('d', function(d) {
                                var o = {
                                    x: source.x,
                                    y: source.y
                                };
                                return diagonal({
                                    source: o,
                                    target: o
                                });
                            })
                            .remove();
                        nodes.forEach(function(d) {
                            d.x0 = d.x;
                            d.y0 = d.y;
                        });
                        function getMarkerUpArrow(d,i) {
                            svg.append("defs").append("marker")   //箭头
                                .attr("id", "resolved"+d.target.id)
                                .attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
                                .attr("markerUnits", "userSpaceOnUse")
                                .attr("viewBox", "0 -5 10 10") //坐标系的区域
                                .attr("refX", -28) //箭头坐标
                                .attr("refY", 0)
                                .attr("markerWidth", 12) //标识的大小
                                .attr("markerHeight", 12)
                                .attr("orient", "90") //绘制方向,可设定为:auto(自动确认方向)和 角度值
                                .attr("stroke-width", 2) //箭头宽度
                                .append("path")
                                .attr("d", "M0,-5L10,0L0,5") //箭头的路径
                                .attr('fill', '#919191'); //箭头颜色 
                            return "url(#resolved" + d.target.id + ")";
                        }
                        function getMarkerDownArrow(d,i) {
                            svg.append("defs").append("marker")   //箭头
                                .attr("id", "resolved"+d.target.id)
                                .attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
                                .attr("markerUnits", "userSpaceOnUse")
                                .attr("viewBox", "0 -5 10 10") //坐标系的区域
                                .attr("refX", 0) //箭头坐标
                                .attr("refY", 0)
                                .attr("markerWidth", 12) //标识的大小
                                .attr("markerHeight", 12)
                                .attr("orient", "90") //绘制方向,可设定为:auto(自动确认方向)和 角度值
                                .attr("stroke-width", 2) //箭头宽度
                                .append("path")
                                .attr("d", "M0,-5L10,0L0,5") //箭头的路径
                                .attr('fill','#919191');
                            return "url(#resolved" + d.target.id + ")";
                        }
                        function Change_modal () {
                            _this.Modal = true
                        }
                        function click(d) {
                            event.stopPropagation()
                            if(forUpward) {
                
                            } else {
                                if(d._children) {
                                    console.log('对外投资--ok')
                                } else {
                                    console.log('对外投资--no')
                                }
                            }
                            isExpand = !isExpand;
                            if(d.name == 'origin') {
                                return;
                            }
                            if(d.children) {
                                d._children = d.children;
                                d.children = null;
                                d3.select(this).text('+')
                                update(d, originalData, g);
                            } else {
                                if (d._children && d._children.length > 0) {
                                    d.children = d._children;
                                    d._children = null;
                                    if(d.name == 'origin') {
                                        d.children.forEach(expand);
                                    }
                                    d3.select(this).text('-')
                                    update(d, originalData, g);
                                } else {
                                    gqctt({
                                        beijingCrid: d.direction == 'up' ? d.beijingCrid : d.pbeijingCrid,
                                        direction: d.direction
                                    }).then(res => {
                                        if (res.code === 0) {
                                            if (d.direction == 'up') {
                                                d.children = res.result.investorList
                                                d.children.map(item => {
                                                    item.amount = Number(item.subConAm).toFixed(2)
                                                    item.isFHolder = true
                                                    item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                                                    item.name = item.entName
                                                    item.type = item.bz === '企业' ? 2 : 1
                                                    item.isHoldingCompany = item.isHolding == 1 ? true : false
                                                    item.isFHolder = item.subComBl >= 0.25 && item.type == 1
                                                    item.direction = direction
                                                    item.holderPercent = item.ratio
                                                })
                                            } else {
                                                d.children = res.result.holderList
                                                d.children.map(item => {
                                                    item.amount = Number(item.subConAm).toFixed(2)
                                                    item.isFHolder = true
                                                    item.ratio = item.subComBl.length > 6 ? 
                                calculation.accMul(item.subComBl,100).toFixed(2) + '%' : 
                                calculation.accMul(item.subComBl,100) + '%'
                                                    item.name = item.pentName
                                                    item.type = item.bz === '企业' ? 2 : 1
                                                    item.isHoldingCompany = item.isHolding == 1 ? true : false
                                                    item.isFHolder = item.subComBl >= 0.25 && item.type == 1
                                                    item.direction = direction
                                                    item.holderPercent = item.ratio
                                                })
                                            }
                                            d._children = null;
                                            if(d.name == 'origin') {
                                                d.children.forEach(expand);
                                            }
                                            d3.select(this).text('-')
                                            update(d, originalData, g)
                                        }
                                    })
                                }
                            }
                        }
                    }
                    function expand(d) {
                        if(d._children) {
                            d.children = d._children;
                            d.children.forEach(expand);
                            d._children = null;
                        }
                    }
    
                    function collapse(d) {
                        if(d.children && d.children.length != 0) {
                            d._children = d.children;
                            d._children.forEach(collapse);
                            d.children = null;
                            hasChildNodeArr.push(d);
                        }
                    }
    
                    function redraw() {
                        treeG.attr('transform', 'translate(' + zoom.translate() + ')' +
                            ' scale(' + zoom.scale() + ')');
                    }
    
                    function disableRightClick() {
                        // stop zoom
                        if(d3.event.button == 2) {
                            console.log('No right click allowed');
                            d3.event.stopImmediatePropagation();
                        }
                    }
    
    
                    function sortByDate(a, b) {
                        var aNum = a.name.substr(a.name.lastIndexOf('(') + 1, 4);
                        var bNum = b.name.substr(b.name.lastIndexOf('(') + 1, 4);
                        return d3.ascending(aNum, bNum) ||
                            d3.ascending(a.name, b.name) ||
                            d3.ascending(a.id, b.id);
                    }
                };
     
                var d3GenerationChart = new treeChart(d3);
                d3GenerationChart.drawChart();
            },
            onJumpReport() {
                this.$router.push(...)
            }
        }
    }
    .g6-tooltip {
      border: 1px solid #e2e2e2;
      border-radius: 4px;
      font-size: 12px;
      color: #545454;
      background-color: rgba(255, 255, 255, 0.9);
      padding: 10px 8px;
      box-shadow: rgb(174, 174, 174) 0px 0px 10px;
    }
    .borrow{
        height: 1000px;
        position: relative;
        top: -66px;
    }

    D3Mixin.js

    /**
     * 全屏 toggleFullScreen
     * 保存 downloadImpByChart
     */
    export const D3Mixin = {
      data() {
        return {
          isFullscreen: true,
        }
      },
      methods: {
        downloadImpByChart(chartName) {
          var _this = this;
          var html = document.getElementsByTagName("html")[0]; //获取可视区域宽
    
          var Bwidth = html.clientWidth + 20; //转换屏幕宽高
          var Bheight = html.clientHeight + 150;
          var Bmax = Bwidth > Bheight ? Bwidth : Bheight;
          var Bmin = Bwidth > Bheight ? Bheight : Bwidth;
    
          var canvas = document.createElement("canvas");
          var g = document.getElementsByTagName("g")[0].getBBox();
          var svgbox = d3.select('#mountNode svg');
          var gbox = document.getElementsByClassName("gbox")[0] || document.getElementsByClassName("container")[0];
          var x = g.width / 2 - html.clientWidth / 2 + 20; //计算偏移位置
          var y = 0;
          g.y < 0 ? (y = Math.abs(g.y)) : (y = 0);
          // gbox.style.transform = "translate(" + x + 'px' + "," + (y-60) + "px" + ")  scale(1)"; //偏移位置
          gbox.style.transform =
            "translate(" + x + "px" + "," + y + "px" + ")  scale(1)"; //偏移位置
          svgbox.attr("width", g.width + 20);
          svgbox.attr("height", g.height + 150);
          var svg = document.getElementById("mountNode").innerHTML;
          var c = canvas.getContext("2d");
          //新建Image对象
          var img = new Image();
          //svg内容
          img.src = "data:image/svg+xml," + encodeURIComponent(svg); //svg内容中可以有中文字符
          // img.src = "data:image/svg+xml," + svg; //svg内容中不能有中文字符
          //图片初始化完成后调用
          var cwidth = g.width;
          img.onload = function () {
            //将canvas的宽高设置为图像的宽高
            canvas.width = cwidth + 20;
            canvas.height = g.height + 150;
            //canvcas画图片
            c.fillStyle = "#fff";
            c.fillRect(0, 0, canvas.width, canvas.height);
            c.drawImage(img, 0, 30);
            var a = document.createElement("a");
            a.download = `${chartName}-${_this.companyName}.png`;
            a.href = canvas.toDataURL("image/png");
            a.click();
          };
          //图片转换为base64后 传给后端 发邮件
          gbox.style.transform = "";
          svgbox.attr("width", Bmax);
          svgbox.attr("height", Bmin);
        },
        checkFull() {
          var isFull =
            document.fullscreenEnabled || window.fullScreen || document.webkitIsFullScreen || document.msFullscreenEnabled
          if (isFull === undefined) {
            isFull = false
          }
          return isFull
        },
        FullScreen(el) {
          if (this.isFullscreen) {
            //退出全屏
            if (document.exitFullscreen) {
              document.exitFullscreen()
            } else if (document.mozCancelFullScreen) {
              document.mozCancelFullScreen()
            } else if (document.webkitExitFullscreen) {
              document.webkitExitFullscreen()
            } else if (!document.msRequestFullscreen) {
              document.msExitFullscreen()
            }
          } else {
            //进入全屏
            if (el.requestFullscreen) {
              el.requestFullscreen()
            } else if (el.mozRequestFullScreen) {
              el.mozRequestFullScreen()
            } else if (el.webkitRequestFullscreen) {
              //改变平面图在google浏览器上面的样式问题
              el.webkitRequestFullscreen()
            } else if (el.msRequestFullscreen) {
              this.isFullscreen = true
              el.msRequestFullscreen()
            }
          }
        },
        toggleFullScreen(e) {
          this.isFullscreen = !this.isFullscreen
          this.FullScreen(document.getElementById('borrow'))
        }
      },
      mounted() {
        window.addEventListener('resize', () => {
          let that = this
          if (!that.checkFull()) {
            //要执行的动作
            that.isFullscreen = true
          }
        })
      }
    }
  • 相关阅读:
    TClientDataSet[7]: 辨析 Field、FieldDef、Fields、FieldDefs、FieldList、FieldDefList
    TClientDataSet[11]: 分组统计
    TClientDataSet[14]: 测试 FindFirst、FindNext、FindLast、FindPrior、Found
    TClientDataSet[9]: 计算字段和 State
    这两天的收获
    又去北京
    关于博客园融资的想法
    《别为小事抓狂》读书笔记
    下周将去北京寻找投资
    服务器搬迁预告
  • 原文地址:https://www.cnblogs.com/snowRock/p/14715368.html
Copyright © 2020-2023  润新知