npm i d3@3 -S

版本兼容问题需要指定版本

<template>
    <div>
        <button @click='draw'>lineChart</button>
    </div>
</template>
<script>
    const d3 = require('d3');
    export default {
        data() {
            return {
                msg: ''
            }
        },
        methods: {
            draw() {
                const width = 1100,
                    height = 600;
                const cluster = d3.layout.tree()
                    .size([width, height - 200]);

                let diagonal = d3.svg.diagonal()
                    .projection( (d) => {
                        return [d.x, d.y];
                    });
                // 画布位置、大小
                let svg = d3.select('body').append('svg')
                    .attr('width', width)
                    .attr('height', height)
                    .attr('transform', 'translate(' + 112 + ',' + 50 + ')');

                // 箭头
                const marker = svg.append('marker')
                    .attr('id', 'resolved')
                    .attr('markerUnits', 'strokeWidth') // 设置为strokeWidth箭头会随着线的粗细发生变化
                    .attr('markerUnits', 'userSpaceOnUse')
                    .attr('viewBox', '0 -5 10 10') // 坐标系的区域
                    .attr('refX', 10) // 箭头坐标
                    .attr('refY', -1)
                    .attr('markerWidth', 12) // 标识的大小
                    .attr('markerHeight', 12)
                    .attr('orient', 'auto') // 绘制方向,可设定为:auto(自动确认方向)和 角度值
                    .attr('stroke-width', 2) // 箭头宽度
                    .append('path')
                    .attr('d', 'M0,-5L10,0L0,5') // 箭头的路径
                    .attr('fill', '#cccccc'); // 箭头颜色

                console.log(marker)
                const threejson = {
                    'name': 'sys',
                    'id': '2000',
                    'children': [{
                        'name': 'ruler',
                        'id': '100',
                        'children': [{
                            'name': 'userX',
                            'id': '100'
                        }, {
                            'name': 'userX',
                            'id': '200'
                        }]
                    }, {
                        'name': 'ruler',
                        'id': '500',
                        'children': [{
                            'name': 'userX',
                            'id': '100'
                        }, {
                            'name': 'userX',
                            'id': '200'
                        }]
                    }, {
                        'name': 'ruler',
                        'id': '500',
                        'children': [{
                            'name': 'userX',
                            'id': '100'
                        }]
                    }, {
                        'name': 'ruler',
                        'id': '500',
                        'children': [{
                            'name': 'userX',
                            'id': '100'
                        }]
                    }]
                }
                const nodes = cluster.nodes(threejson).reverse();

                // 获取点定制坐标数据
                let points = [];
                let point = {};
                let pointC = {};
                let num = 0;
                nodes.forEach( (d) => {
                    // 200影响为线长
                    d.y = d.depth * 200;
                    if (d.depth == 2 && d.id == 100) {
                        if (num == 0) {
                            point.A = {
                                x: d.x,
                                y: d.y,
                                description: d.name
                            }
                            if (pointC.A) {
                                pointC.B = point.A;
                                points.push(pointC);
                                pointC = {};
                            }
                            num = 1;
                        } else {
                            // 有第二点
                            point.B = {
                                x: d.x,
                                y: d.y,
                                description: d.name
                            }
                            pointC.A = point.B;
                            points.push(point);
                            point = {};
                            num = 0;
                        }
                    }
                });

                // 定制线
                this.customLines(svg, points);

                const links = cluster.links(nodes);

                const linkEnter = svg.selectAll('path.link').data(links);
                linkEnter.enter().append('path') // 在指定元素之前插入一个元素
                    .attr('class', 'link')
                    .attr('d', diagonal)
                    .attr('stroke', 'gray') // 线颜色
                    .attr('marker-end', 'url(#resolved)') //根据箭头标记的id号标记箭头
                    .style('fill', 'white') // 填充颜色
                    .style('fill-opacity', 1)
                    // 首先为每条节点连线添加标识id
                    .attr('id', (d, i) => {
                        return 'mypath' + i;
                    });

                // 为连线添加文字
                linkEnter.enter().append('text')
                    .attr('x', 100)
                    .attr('y', 80)
                    .style('fill', 'green')
                    .style('font-size', '15px')
                    .style('font-weight', 'bold')
                    .append('textPath')
                    .attr({ //引用路径
                        'xlink:href': (d, i) => {
                            return '#mypath' + i;
                        }
                    })
                    .text( d => d.target.id);


                const node = svg.selectAll('.node')
                    .data(nodes)
                    .enter()
                    .append('g')
                    .attr('class', 'node')
                    .attr('transform', (d) => {
                        return 'translate(' + (d.x + -50) + ',' + (d.y) + ')';
                    })
                // 背景
                node.append('rect')
                    .attr('width', 100)
                    .attr('height', 50)
                    .attr('x', 0)
                    .attr('y', 0)
                    .attr('style', 'fill:#42b983;')
                    .attr('rx', 50);

                node.append('text')
                    .attr('dx', 30)
                    .attr('dy', 25)
                    .style('text-anchor', 'middle')
                    .style('fill', '#fff')
                    .text( d => d.name);

                node.append('text')
                    .attr('dx', 70)
                    .attr('dy', 25)
                    .style('text-anchor', 'middle')
                    .style('fill', '#fff')
                    .text( d => d.id);

            },
            customLines(svg, points) {
                // 自定义连接点数据
                // const points = [{
                //     A:{x:110,y:450},
                //     B:{x:165,y:500}
                // }, {
                //     A:{x:165,y:500},
                //     B:{x:220,y:450}
                // }];
                // diagonal曲线 分两段画
                let diagonalA = d3.svg.diagonal()
                    .source( (d) => {       //自定义访问器函数
                        return d.A;
                    })
                    .target( (d) => {
                        // return d.B;
                        return {
                            x: (d.A.x + d.B.x) / 2,
                            y: d.A.y + 130 // 向下偏移
                        }
                    })
                let diagonalB = d3.svg.diagonal()
                    .source( (d) => {       //自定义访问器函数
                        return {
                            x: (d.A.x + d.B.x) / 2,
                            y: d.A.y + 130
                        }
                    })
                    .target( (d) => {
                        return d.B;
                    })
                svg.selectAll('g')
                    .data(points)
                    .enter()
                    .append('g')
                    .append('path')
                    .attr('d',diagonalA)
                    .attr('stroke','green')
                    .attr('stroke-width',3)
                    .attr('fill','none')
                svg.selectAll('g')
                    .append('path')
                    .attr('d',diagonalB)
                    .attr('stroke','green')
                    .attr('stroke-width',3)
                    .attr('fill','none')
                svg.selectAll('g')
                    .append('text')
                    .attr('dx', d => (d.A.x + d.B.x) / 2 )
                    .attr('dy', d => d.B.y + 150 )
                    .style('text-anchor', 'middle')
                    .style('fill', 'gray')
                    .text( d => d.B.description + d.A.description);
            }
        },
        mounted: function () {

        }
    }
</script>
<style scoped>
.node {
    font: 12px sans-serif;
}

.link {
    fill: none;
    stroke: #ccc;
    stroke-width: 5px;
}
</style>

api中文文档

https://github.com/d3/d3/wiki/API–%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C

分类: d3js

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注