Get pixel width of d3.js SVG element created with width as percentage

问题描述

借助d3.js画了一个力引导图(Force-Directed Graph) 官方示例
但是官方示例中将SVG元素的width和height都是设定为像素, 也就是是该SVG不能自适应了.

那么为了使SVG能够自适应, 自然而然将svg元素的width和height设置为百分比.

<svg width="100%" height="100%"></svg>

依然是官方示例, 力引导图却没有出现在网页上.

问题定位

借用chrome进行调试: 发现svg元素的height和width都是0.
查看网页源码, 发现所有的节点的坐标均为0, 那么就有可能问题出在js代码:

var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height");

var color = d3.scaleOrdinal(d3.schemeCategory20);

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

问题在于力导向图的中心点center为0 ⇒ width, height = 0 ⇒ 获取svg的width和height出错

解决问题

先由js动态生成svg, 再获取页面svg真正的width和height

<!DOCTYPE html>
<meta charset="utf-8">
    <style>

        .links line {
            stroke: #999;
            stroke-opacity: 0.6;
        }

        .nodes circle {
            stroke: #fff;
            stroke-width: 1.5px;
        }

    </style>
<!--添加了一个div元素-->
<div id="knowledgeGraph" style="height:600px">  
<#--此处将生成SVG-->
</div>
<script src="https://cdn.bootcss.com/d3/4.8.0/d3.js"></script>
<script>
  var w = "100%";

  var presvg = d3.select("#knowledgeGraph");
  //生成svgy元素
  presvg.append("svg")
         .attr(":xmlns:svg", "http://www.w3.org/2000/svg")
         .attr("id","shownSVG")
         .style("width", w)
         .style("height", h)
         .attr("class", "thumbnail");

   var svg = d3.select("svg");
   //获取svg的实际width和height, 注意原示例中的svg.attr("width")和svg.attr("height")均返回0
   var width = $("#shownSVG").width();
   var height = $("#shownSVG").height();

    var color = d3.scaleOrdinal(d3.schemeCategory20);

    var simulation = d3.forceSimulation()
        .force("link", d3.forceLink().id(function(d) { return d.id; }))
        .force("charge", d3.forceManyBody())
        .force("center", d3.forceCenter(width / 2, height / 2));

    d3.json("1.json", function(error, graph) {
        if (error) throw error;

        var link = svg.append("g")
            .attr("class", "links")
            .selectAll("line")
            .data(graph.links)
            .enter().append("line")
            .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

        var node = svg.append("g")
            .attr("class", "nodes")
            .selectAll("circle")
            .data(graph.nodes)
            .enter().append("circle")
            .attr("r", 5)
            .attr("fill", function(d) { return color(d.group); })
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));

        node.append("title")
            .text(function(d) { return d.id; });

        simulation
            .nodes(graph.nodes)
            .on("tick", ticked);

        simulation.force("link")
            .links(graph.links);

        function ticked() {
            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; });

            node
                .attr("cx", function(d) { return d.x; })
                .attr("cy", function(d) { return d.y; });
        }
    });

    function dragstarted(d) {
        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
    }

    function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
    }

    function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
    }
</script>

关键点

动态生成svg并非必要, 关键点在于正确获取svg元素的真实的width和height.
因此, 必须获取到页面的svg元素, 再获取真实的width和height.

var svg = d3.select("#shownSVG");
var width = $("#shownSVG").width();
var height = $("#shownSVG").height();

相关链接: https://stackoverflow.com/questions/31854267/get-pixel-width-of-d3-js-svg-element-after-its-created-with-width-as-percentage

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值