D3js关系图谱(力导向布局)

在这里插入图片描述

   "d3": "^3.5.17",
import React, { Component } from 'react'
import * as d3 from 'd3'
import './chart.css'

import { List, message, Avatar, Spin } from 'antd';
import InfiniteScroll from 'react-infinite-scroller';

export class Chart1 extends Component {

    constructor(props) {
        super(props)

        this.state = {
            nodes: [],
            links: []
        }
    }

    componentWillMount() {

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.nodes.length && nextProps.nodes != this.props.nodes) {
            this.setState({
                nodes: nextProps.nodes,
                links: nextProps.links
            }, function () {
                this.drawChart()
            })
        }
    }

    componentDidMount() {
        if (this.props.nodes.length) {
            this.drawChart();
        }
    }

    _force = null;
    _svg = null;
    drawChart = () => {
        // 获取数据
        var graph = this.state;
        // 移除旧元素
        d3.select(".d3").selectAll('*').remove();

        var width = 880,
            height = 700;
        // 设置颜色
        var color = d3.scale.category20();
        // 设置布局
        this._force = d3.layout.force()
            .charge(-1500)//排斥力
            .linkDistance(50)//距离
            .size([width, height])
            .nodes(graph.nodes)
            .links(graph.links)
            .start();

        // 设置平移和缩放
        var zoom = d3.behavior.zoom()//缩放配置,
            .scaleExtent([0.4, 2])//缩放比例
            .on("zoom", zoomed);

        function zoomed() {//缩放函数
            d3.selectAll("g").attr("transform",//svg下的g标签移动大小
                "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }

        // 设置画布
        this._svg = d3.select(".d3").append("svg")
            .attr("width", width)
            .attr("height", height)
            .call(zoom);

        // 设置连线
        var link = this._svg.append("g").selectAll(".link")
            .data(graph.links)
            .enter()
            .append("line")
            .attr("class", "link");
        // .style("stroke", "#000")
        // .style("stroke-width", function (d) {
        //     return Math.sqrt(d.value);
        // });

        //边上的文字(人物之间的关系)            
        // var edges_text = this._svg.selectAll(".linetext")
        //     .data(graph.links)
        //     .enter()
        //     .append("text")
        //     .attr("class", "linetext")
        //     .text(function (d) {
        //         return d.type;
        //     })
        //     .style("fill-opacity", 1.0);

        // 设置节点
        var node = this._svg.selectAll(".node")
            .data(graph.nodes)
            .enter()
            .append("g")
            .attr("class", "node")
            .call(this._force.drag)
        // 节点圆
        node.append("circle")
            .attr("r", 10)//圆的大小
            .style("fill", function (d) {
                return color(d.group);
            })
        // 节点文字
        node.append("text")
            .attr("dx", 15)
            .attr("dy", ".25em")
            .attr("y", function (d) {
                // 多行文字显示
                if (d.name.length <= 17) {
                    d3.select(this).append('tspan').attr("ix", 0)
                        .text(function () { return d.name; });
                } else {//大于16个字符时,
                    var top = d.name.substring(0, 17) + "...";
                    d3.select(this).append('tspan').attr("ix", 0).text(top);
                    // var sum = d.name.length / 17
                    // console.log(d.name,sum);
                    // for (let i = 0; i < sum+1; i++) {
                    //     // const element = array[i];
                    //     var top = d.name.substring(i * 17, (i + 1) * 17);
                    //     d3.select(this).append('tspan').attr("ix", i).text(top);
                    // }
                }
            })

        // 添加箭头
        this._svg.append("g").append("defs").selectAll("marker")
            .data(["suit", "licensing", "resolved"])
            .enter().append("marker")
            .attr("id", function (d) { return d; })
            .attr("viewBox", "0 -5 10 10")
            .attr("refX", 25)
            .attr("refY", 0)
            .attr("markerWidth", 6)
            .attr("markerHeight", 6)
            .attr("orient", "auto")
            .append("path")
            .attr("d", "M0,-5L10,0L0,5 L10,0 L0, -5")
            .style("stroke", "#4679BD")
            .style("opacity", "0.6");

        //坐标计算
        this._force.on("tick", function () {

            link.attr("x1", function (d) {
                return d.source.x;
            })
                .attr("y1", function (d) {
                    return d.source.y;
                })
                .attr("x2", function (d) {
                    return d.target.x;
                })
                .attr("y2", function (d) {
                    return d.target.y;
                });
            d3.selectAll("circle")
                .attr("cx", function (d) {
                    return d.x;
                })
                .attr("cy", function (d) {
                    return d.y;
                });

            d3.selectAll("text")
                .attr("x", function (d) {
                    return d.x;
                })
                .attr("y", function (d) {
                    return d.y;
                });

            d3.selectAll("tspan")
                .attr("x", function (d) {
                    return d.x;
                })
                .attr("y", function (d) {
                    return d.y + (this.getAttribute('ix') * 20);
                });

            //更新连接线上文字的位置
            // edges_text.attr("x", function (d) { return (d.source.x + d.target.x) / 2; });
            // edges_text.attr("y", function (d) { return (d.source.y + d.target.y) / 2; });
            //End Changed11
        });

    }
    render() {
        return <div>
            <div className="d3" id='d33' style={{ background: '#ccc', width: '880px' }} />
            <div className="infinite-container">
                <List
                    dataSource={this.state.nodes}
                    renderItem={item => (
                        <List.Item key={item.id}>
                            <h3 style={{ width: '200px' }}>{item.type}</h3>
                            <h5 style={{ width: '1800px' }}>{item.name}</h5>
                        </List.Item>
                    )}
                >
                </List>

            </div>
        </div >

    }
}

export default Chart1

.link {
    stroke: #000;
    stroke-width: 0.5px;
}
  

.node {
    font-size: 12px;
    font-family: SimSun;
    fill:#000;
}

.linetext {
    font-size: 12px;
    font-family: SimSun;
    fill:#1f77b4;
    fill-opacity: 0.0;
}

.infinite-container {
    border: 1px solid #e8e8e8;
    border-radius: 4px;
    overflow: auto;
    padding: 8px 24px;
    height: 500px;
    width: 880px;
    margin-top: 20px;
  }
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
d3.js是一个基于数据操作文档的JavaScript库,可以帮助开发者使用HTML、SVG和CSS来展示数据。d3.js可以用来实现人物关系图谱,具体实现步骤如下: ```javascript // 引入d3.js库 <script src="https://d3js.org/d3.v3.min.js"></script> // 创建svg元素 var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); // 创建导向图 var force = d3.layout.force() .nodes(nodes) // 节点数组 .links(links) // 连线数组 .size([width, height]) // 画布大小 .linkDistance(150) // 连线长度 .charge(-400); // 节点间的斥 // 绘制连线 var links = svg.selectAll(".link") .data(links) .enter() .append("line") .attr("class", "link"); // 绘制节点 var nodes = svg.selectAll(".node") .data(nodes) .enter() .append("circle") .attr("class", "node") .attr("r", 20) .style("fill", function(d) { return color(d.group); }) .call(force.drag); // 节点可拖拽 // 绘制节点标签 var labels = svg.selectAll(".label") .data(nodes) .enter() .append("text") .attr("class", "label") .attr("fill", "black") .attr("font-size", "12px") .attr("dx", 20) .attr("dy", 8) .text(function(d) { return d.name; }); // 开始导向布局 force.start(); // 监听导向布局事件 force.on("tick", function() { // 更新连线位置 links.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); // 更新节点位置 nodes.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); // 更新节点标签位置 labels.attr("x", function(d) { return d.x; }) .attr("y", function(d) { return d.y; }); }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魑魅魍魉9527

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值