第一次尝试加载时,d3.js 圆形绘图无法正常工作 [英] d3.js circle plotting does not working properly while trying to load after first time

查看:22
本文介绍了第一次尝试加载时,d3.js 圆形绘图无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的 d3.js 代码:

This is my d3.js piece of code :

<script>


var width = 300,
height = 300,
margin = 20;
var x_centre = width/2;
var y_centre = height/2;
var nuclear_radius = 15;

var vis = d3.select("#chart_container").append("svg:svg")
.attr("width", width)
.attr("height", height);

var radiuses = [1,2,3];

var multiplier = (d3.min([width, height]) - 2*margin - nuclear_radius) / (d3.max(radiuses) * 2);

var shells = vis.selectAll("circle.shell")
 .data(radiuses)
 .enter().append("circle")
 .attr("class", "shell")
 .attr("cx", x_centre)
 .attr("cy", y_centre)
 .attr("r", function(d, i) { 
     return (d * multiplier);
  });

var nucleus = vis.selectAll('circle.nucleus')
.data(['nucleus'])
.enter().append("circle")
.attr("class", "nucleus")
.attr("cx", x_centre)
.attr("cy", y_centre)
.attr("r", nuclear_radius);


function  showGraph(de)  {
var electrons = de


var radius_counts = {};
for (var i = 0; i < electrons.length; i++) { 
if (electrons[i].distance in radius_counts) { 
     radius_counts[electrons[i].distance] += 1;
} else { 
     radius_counts[electrons[i].distance] = 1;
} 
}

// Calculate the x- and y-coordinate values 
// for each electron.
var keep_count = {};
electrons.forEach(function(d) { 
var siblings = radius_counts[d.distance];
if (d.distance in keep_count) { 
  keep_count[d.distance] += 1;    
} else { 
    keep_count[d.distance] = 1;
}
var angle = (360/siblings) * keep_count[d.distance];
var hyp = d.distance * multiplier;  
if (angle <= 90) {
  var use_angle = (90 - angle) * (Math.PI/180);
  var opp = Math.sin(use_angle) * hyp;
  var adj = Math.cos(use_angle) * hyp;
    d.x = x_centre + adj;
    d.y = y_centre - opp;
}    else if (angle <= 180) { 
        var use_angle = (180 - angle) * (Math.PI/180);
      var opp = Math.sin(use_angle) * hyp;
      var adj = Math.cos(use_angle) * hyp;
        d.x = x_centre + opp;
        d.y = y_centre + adj;    
    } else if (angle <= 270) { 
    var use_angle = (270 - angle) * (Math.PI/180);
  var opp = Math.sin(use_angle) * hyp;
  var adj = Math.cos(use_angle) * hyp;
    d.x = x_centre - adj;
    d.y = y_centre + opp;    
} else { 
    var use_angle = (360 - angle) * (Math.PI/180);    
  var opp = Math.sin(use_angle) * hyp;
  var adj = Math.cos(use_angle) * hyp;
    d.x = x_centre - opp;
    d.y = y_centre - adj;
}

});

var electron_nodes = vis.selectAll('circle.electron')
.data(electrons)
.enter().append("circle")
.attr("class", "electron")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 7)
.on("mouseover", function(d) { 
   // how to drag the electron around the circle?
});
var svgData = vis.selectAll("circle.electron")
    .data(electrons);   
svgData.exit().remove();       
}

</script> 

现在我在每次点击事件时调用上面的 showGraph js 函数,它接受 count 参数

Now i am calling the above showGraph js function every time on click event which takes the count parameter

function add_py()
{
 var count = $( "#count" ).val();
    $.ajax({
        type: "get",
        url: "abc.py",
        data: {'count': count},
        datatype:"script",
        async: false,
        success: function(response) {
        var data= JSON.parse(response);
        //alert(response)
        showGraph(data);
        }, // success closed
        error:function(xhr,err)
        {
            alert("Error connecting to server, please contact system administator.");
        }
    })//ajax closed
}

现在当我给 count 10 时,SVG 是这样的:

Now when I give count 10 , the SVG is like this :

<svg width="300" height="300">
    <circle class="shell" cx="150" cy="150" r="40.833333333333336">
    <circle class="shell" cx="150" cy="150" r="81.66666666666667">
    <circle class="shell" cx="150" cy="150" r="122.5">
    <circle class="nucleus" cx="150" cy="150" r="15">
    <circle class="electron" cx="231.66666666666669" cy="150" r="7">
    <circle class="electron" cx="256.08811196359375" cy="211.25" r="7">
    <circle class="electron" cx="43.91188803640625" cy="211.25" r="7">
    <circle class="electron" cx="185.36270398786456" cy="170.41666666666669" r="7">
    <circle class="electron" cx="114.63729601213541" cy="170.41666666666666" r="7">
    <circle class="electron" cx="150" cy="231.66666666666669" r="7">
    <circle class="electron" cx="150" cy="27.5" r="7">
    <circle class="electron" cx="150" cy="109.16666666666666" r="7">
    <circle class="electron" cx="68.33333333333333" cy="150" r="7">
    <circle class="electron" cx="150" cy="68.33333333333333" r="7">
</svg>

使用具有不同 cx 和 cy 绘图的 class electron 精确地工作 10 个圆圈.但是,如果我先给出 7 或任何小于 10 然后 10 的值,则 svg 就像:

Works fine exactly 10 circles with class electron with different cx and cy plots . But if i give first count 7 or anything less then 10 then 10 , the svg is like :

<svg width="300" height="300">
    <circle class="shell" cx="150" cy="150" r="40.833333333333336">
    <circle class="shell" cx="150" cy="150" r="81.66666666666667">
    <circle class="shell" cx="150" cy="150" r="122.5">
    <circle class="nucleus" cx="150" cy="150" r="15">
    <circle class="electron" cx="150" cy="68.33333333333333" r="7">
    <circle class="electron" cx="150" cy="272.5" r="7">
    <circle class="electron" cx="150" cy="27.5" r="7">
    <circle class="electron" cx="150" cy="190.83333333333334" r="7">
    <circle class="electron" cx="150" cy="109.16666666666666" r="7">
    <circle class="electron" cx="150" cy="231.66666666666669" r="7">
    <circle class="electron" cx="150" cy="27.5" r="7">
    <circle class="electron" cx="150" cy="109.16666666666666" r="7">
    <circle class="electron" cx="68.33333333333333" cy="150" r="7">
    <circle class="electron" cx="150" cy="68.33333333333333" r="7">
</svg>

使用 class electron 精确绘制 10 个圆圈,但 cxcy 重复,因此它们重叠.但是如果我第一次给计数 10 它不会重叠.如果我给一个大计数然后小它工作正常.但不是小则大.预先感谢您帮助我.

Plots exactly 10 circles with class electron but the cx and cy repeats so they overlap . But it does not overlap if I give count 10 first time .It works fine if i give a big count then small. But not if small then big. Thanks in advance for helping me.

推荐答案

问题是当你从 7 到 10 时,你永远不会更新现有的电子".在你的代码中

The problem is you are never updating existing "electrons" when you go from 7 to 10. In your code

var electron_nodes = vis.selectAll('circle.electron')
.data(electrons)
.enter().append("circle")
.attr("class", "electron")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 7)
.on("mouseover", function(d) { 
   // how to drag the electron around the circle?
});

enter() 之后的所有内容仅适用于添加的新元素.

everything after enter() only applies to new elements added in.

这是一个常见的混淆;我今天早些时候回答了另一个类似的问题,所以我将尝试在这里非常清楚地解释它(然后每个人都可以在将来链接到这个解释!).

It's a common confusion; I answered another question like this earlier today, so I'm going to try to explain it really clearly here (and then everyone can just link to this explanation in future!).

链接方法是 D3 的重要组成部分,但它只能做这么多.每个人都想将所有内容链接在一起,但是您必须跟踪您的链何时分离为 enter()exit() 选择,然后返回主选择更新.

Chaining methods is a great part of D3, but it can only do so much. Everyone wants to chain everything together, but you have to keep track of when your chain separates out into an enter() or exit() selection, and go back to the main selection for updating.

一般更新例程通常有四个链"(每个以;结尾):

  • 一个选择链,它选择元素并更新数据并将选择保存在一个变量中,例如你可以称之为var元素

  • A Select Chain, that selects the elements and updates the data and saves the selection in a variable, for example you could call it var elements

一个 Enter Chain,以 elements.enter() 开头.(或用于保存 Select Chain 的任何变量名称),附加新元素并设置任何将保持不变的属性或样式(即不会在更新时更改)

An Enter Chain, starting with elements.enter(). (or whatever variable name you used to save the Select Chain), appending the new elements and setting any attributes or styles that are going to be constant (i.e., won't change on update)

一个退出链,以elements.exit().开头,带有过渡(如果使用)和remove()

An Exit Chain, starting with elements.exit()., with transitions (if using) and remove()

一个更新链,从您保存的选择变量开始,然后是设置需要更新的属性或样式的所有方法;这还将在您刚刚使用 .enter()

An Update Chain, starting just with your saved selection variable, followed by all the methods to set the attributes or styles that need to be updated; this will also set these attributes for the first time on the elements you just created with .enter()

是的,您可以以不同的方式做事,但前提是您清楚地了解正在发生的事情以及您为什么要改变这种模式.

Yes, you can do things differently, but only if you clearly understand what is happening and why you are changing from this pattern.

这种方法还避免了代码中的重复,即您重新选择电子并重新应用数据以获得 exit() 选择.

This approach also avoids the repetition in your code, where you re-select your electrons and re-apply the data to get at the exit() selection.

因此对于您的程序,4-chain update 方法的应用将如下所示:

So for your program, the application of the 4-chain update method would look like this:

//chain 1: select
var electron_nodes = vis.selectAll('circle.electron')
      .data(electrons); 

//chain 2: enter
electron_nodes.enter().append("circle")
  .attr("class", "electron")
  .on("mouseover", function(d) { 
   // Although this function uses data at the time the event happens, 
   // the actual definition of the function never changes,
   // so you only need to attach it once when you create the node.
  })
  .attr("r", 7); 

//chain 3: exit
electron_nodes.exit().remove(); 

//chain 4: update
electron_nodes.attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; });

抱歉这么久才有人回答你的问题;这是一个相当复杂的程序,可能会用所有的数学函数吓跑人们.将来,您不需要包含 AJAX 方法(假设您已检查它是否返回正确的值),但包含 AJAX 请求返回的数据示例会有所帮助.当然,一个关于 JSFiddle 或 Tributary 的工作示例会更好!

Sorry it took this long for someone to answer your question; it's a rather complicated program, and probably scared people off with all the math functions. For future, you don't need to include your AJAX method (assuming you've checked that it's returning the correct values), but it would help to include an example of the data that the AJAX request returns. And of course, a working example on JSFiddle or Tributary is even better!

最好的,
--ABR

Best,
--ABR

这篇关于第一次尝试加载时,d3.js 圆形绘图无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆