D3.js v3报错:Cannot read property 'call' of undefined原因咨询
问题原因及解决方案
让我们一步步拆解你遇到的Cannot read property 'call' of undefined错误,以及代码里的其他问题:
1. D3版本API混用(最直接的错误原因)
你使用的是D3 v3,但代码里调用了d3.forceSimulation()、d3.forceCollide()、d3.forceRadial()这些只有D3 v4及以上版本才有的API。在D3 v3中,力布局的API完全不同,d3.forceSimulation根本不存在,所以调用它会返回undefined,后续链式调用.force()自然就会抛出Cannot read property 'force' of undefined的错误。
2. d3.json()用法错误
D3 v3中d3.json()的第一个参数是JSON文件的URL地址,用来加载远程或本地的JSON文件,而不是直接传入一个JSON对象。你现在直接把json变量传进去,D3会尝试请求一个以这个JSON对象字符串为路径的资源,显然不存在,导致回调里的data是undefined,后续基于data的数据绑定都会失效。
3. 语法错误
代码最后定义pie布局时,value函数的闭合不完整,少了一个)和},这会导致代码解析失败,影响整体执行。
修正后的完整代码
下面是针对以上问题修复后的代码,保留了你的核心需求(径向力布局的气泡图):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>D3 Test</title> <script src="https://d3js.org/d3.v3.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <link rel="stylesheet" type="text/css" href="./css/style.css"> </head> <body style="background-color: rgb(233, 236, 239);"> <br> <legend align="center">Convergencia de ODS con Plan Nacional de Desarrollo</legend> <hr> <div class="container"> <div class="jumbotron"> <!-- 添加缺失的msg元素 --> <div id="msg" style="display:none;"></div> <script> var w = 1200; var h = 550; var radius = Math.min(w, h); var dataset = [ [ 600, 150] ]; var json = [ { "pais": "Ecuador", "pais_nid": 14, "ods": "1. Fin a la pobreza", "ods_nid": 35, "ods_color_hex": "E5243B", "objetivos_plan_ods": 5 }, { "pais": "Ecuador", "pais_nid": 14, "ods": "2. Hambre cero", "ods_nid": 36, "ods_color_hex": "DDA63A", "objetivos_plan_ods": 9 } ]; // 直接使用本地json数据,无需d3.json加载 var data = json; var rScale = d3.scale.linear() .domain([0, d3.max(data, function(d) { return d.objetivos_plan_ods; })]) .range([2, 40]); // 创建SVG元素,将原点移到中心方便径向布局 var svg = d3.select("div.jumbotron") .append("svg") .attr("width", w) .attr("height", h) .attr("transform", "translate(" + w/2 + "," + h/2 + ")"); // 绘制中心圆圈 svg.append("circle") .attr("r", 125) .attr("stroke", "rgb(255, 255, 255)") .attr("stroke-width", "8") .attr("fill", "none"); svg.on("click", function() { document.getElementById("msg").setAttribute("style", "display:none;"); document.getElementById("msg").innerHTML = ''; d3.event.stopPropagation(); }); // 绑定数据创建节点 var node = svg.selectAll("circle.node") .data(data) .enter() .append("circle") .attr("class", "node") .attr("style", "cursor:pointer;") .attr("r", function(d) { return rScale(d.objetivos_plan_ods);}) .attr("fill", function(d) { // 使用JSON中提供的颜色,添加透明度 return "#" + d.ods_color_hex + "80"; }) .attr("id", function(d) { return "circle-" + d.ods_nid; }) .on("click",function(d) { document.getElementById("msg").removeAttribute("style"); d3.select("#circle-" + d.ods_nid) .attr("stroke", "rgb(140, 233, 255)") .attr("stroke-width", "6"); document.getElementById("msg").innerHTML = d.ods; d3.event.stopPropagation(); }) .on("mouseout", function(d) { document.getElementById("msg").setAttribute("style", "display:none;"); d3.select("#circle-" + d.ods_nid) .attr("stroke", null) .attr("stroke-width", null); document.getElementById("msg").innerHTML = ''; d3.event.stopPropagation(); }); // 使用D3 v3的力布局实现径向分布 var force = d3.layout.force() .nodes(data) .size([w, h]) // 电荷力防止节点重叠 .charge(function(d) { return -Math.pow(rScale(d.objetivos_plan_ods), 2.0) * 1.5; }) // 自定义径向约束力,让节点围绕中心分布 .on("tick", function(e) { node.each(radialForce(e.alpha)) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }) .start(); // 自定义径向力函数,让节点保持在半径125的圆附近 function radialForce(alpha) { return function(d) { var dx = d.x - w/2; var dy = d.y - h/2; var r = Math.sqrt(dx * dx + dy * dy); var k = (125 - r) * alpha * 0.1; d.x += dx * k; d.y += dy * k; }; } // 修正pie布局的语法错误 var color = d3.scale.category20(); var pie = d3.layout.pie() .value(function(d) { return 5; }); </script> </div> </div> </body> </html>
额外说明
- 移除了D3 v4+的独立模块,D3 v3已包含这些功能,无需额外引入。
- 将随机色替换为JSON中提供的
ods_color_hex,并添加了透明度,更贴合需求。 - 补充了缺失的
#msg元素,避免DOM操作报错。 - 使用D3 v3原生的
d3.layout.force()实现径向分布效果,替代v4版本的forceRadial。
内容的提问来源于stack exchange,提问作者beriliox
相关产品推荐
相关产品推荐

