简体   繁体   English

d3.js检查/计数系列图表

[英]d3.js Checking/Count series chart

I am working on an application that uses foursquare data. 我正在开发一个使用foursquare数据的应用程序。 在此输入图像描述

//this is the series chart that has had some delving into - but there are some bugs still running around here. //这是有一些深入研究的系列图表 - 但是这里仍然存在一些错误。

So we have a batch of data - Health & Beauty, Restaurants, Cafe, Public Houses. 所以我们有一批数据 - 健康与美容,餐厅,咖啡厅,公共房屋。 -- there would be a COUNT of them -- and a SUMMATION of checkout information. - 会有COUNT个 - 以及结帐信息的摘要。 So I want this chart to be able to show the NUMBER of venues, but also indicate how POPULAR they are.. so for example the number of pubs may be smaller, but the number of checkins higher as they are more popular. 所以我希望这个图表能够显示场地的数量,但也表明它们是多么流行......所以例如酒吧的数量可能会更小,但是因为它们更受欢迎,所以签到的数量更多。 So in that instance want to reverse the colors of the circles. 所以在那种情况下想要反转圆圈的颜色。

There are some bugs with the current code attempts. 当前的代码尝试存在一些错误。

  • the swapping of the circles/circle spacing causes tears in black paths and odd behaviors 圆圈/圆圈间距的交换会导致黑色路径中的撕裂和奇怪的行为
  • with the lines I would like to have a black line under the blue circle, but inside the blue circle show a cropped circle path orange line -- so a kind of masking ability. 我希望在蓝色圆圈下面有一条黑线,但是在蓝色圆圈内部显示一条裁剪的圆形路径橙色线 - 这是一种掩蔽能力。

_latest jsfiddle _latest jsfiddle

phase1 阶段1

using "V" instead of "L" but couldn't make it work properly for the time being. 使用“V”而不是“L”但暂时无法使其正常工作。

phase 2 I think it works more consistently but there are some issues. 第二阶段我认为它的工作更加一致但存在一些问题。 Also, I am not sure about the data and the scaling of the circles. 此外,我不确定圆圈的数据和缩放。 (I've added extra labels so that it is visible what the value of the circles are) (我添加了额外的标签,以便可以看到圆圈的价值)

phase 3 第3阶段

changed the getCircleSize a bit even though I believe a more consistent thing to do would be something like this layerSet.push(parseInt(getPercentage(layerArray[i], meansPerGroup[0])*60, 10)); 改变了getCircleSize,尽管我认为更一致的事情就是这样的layerSet.push(parseInt(getPercentage(layerArray[i], meansPerGroup[0])*60, 10));

so here the first step draws the circles by size order first... so in this case by count.. but maybe there is a bug here reversing the color to indicate the checkin count instead - so maybe we need to sort by count,checkin order - that way the first circle to get painted follows correctly. 所以这里第一步首先按大小顺序绘制圆圈...所以在这种情况下通过计数..但也许这里有一个错误反转颜色来指示签入计数 - 所以也许我们需要按计数排序,检查顺序 - 这样第一个要绘制的圆正确遵循。

  // Create Circles
  function setCircles(items) {
    // sort elements in order to draw them by size
    items.sort(function(a, b) {
      return parseFloat(b.value) - parseFloat(a.value);
    });

    var circlelayer = svg.append("g")
      .attr("class", "circlelayer");

    var circle = circlelayer.selectAll("circle")
      .data(items);

    circle.enter().append("circle")
      .attr("class", function(d, i) {
        if (d.l == 0) {
          return "blue";
        }
        return "gold";
      })
      .attr("cy", 60)
      .attr("cx", function(d, i) {
        var distance = calculateDistance(d, items);
        if (d.l == 1) {
          distancesL1.push(distance);
        } else {
          distancesL0.push(distance);
        }
        return distance;
      })
      .attr("r", function(d, i) {
        return Math.sqrt(d.value);
      })
      .attr("filter", function(d) {
        return "url(#drop-shadow)";
      });

    circle.exit().remove();
  }

json structure to look something like this json结构看起来像这样

[{
    "label": "Health and Beauty",
    "count": 30,
    "checkin": 100
}, {
    "label": "Restaurants",
    "count": 23,
    "checkin": 200
}, {
    "label": "Cafes",
    "count": 11,
    "checkin": 900
}, {
    "label": "Public Houses",
    "count": 5,
    "checkin": 1000
}]

I'm not sure I understand what is your problem but I've decided to try to create that chart from you screenshot with sample data from your plunker. 我不确定我明白你的问题是什么,但我决定尝试使用你的plunker的样本数据从你的截图创建该图表。 Here is my result: 这是我的结果: 在此输入图像描述

My script is making sure that smaller circle is always on top of the rage one so both circles are always visible. 我的脚本确保较小的圆圈始终位于愤怒之上,因此两个圆圈始终可见。 Here you can find my code: 在这里你可以找到我的代码:

 <!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v5.min.js"></script> <style> html { font-family: sans-serif; } </style> </head> <body> <div id="container"> </div> <script> const data = [{ "name": "Twitter", "vists": "15 billion", "unit": "per day", "layer1value": 15000000, "layer2value": 450 }, { "name": "Facebook", "vists": "5 billion", "unit": "per day", "layer1value": 4000000, "layer2value": 5000000 }, { "name": "Google", "vists": "5 billion", "unit": "per day", "layer1value": 5000000, "layer2value": 25000 }, { "name": "Netflix", "vists": "10 billion", "unit": "per day", "layer1value": 3000000, "layer2value": 2200 }, { "name": "Ebay", "vists": "8 billion", "unit": "per day", "layer1value": 2500000, "layer2value": 4900000 }, { "name": "Klout", "vists": "2 billion", "unit": "per day", "layer1value": 1000000, "layer2value": 45 }]; /* * Finding max and min layer size */ const values = data.reduce((acumulator, datum) => [...acumulator, datum.layer1value, datum.layer2value], []); const maxValue = Math.max(...values); const minValue = Math.min(...values); /* * Creating scale based on the smallest and largest layer1value or layer2value */ const radiusScale = d3.scaleLinear() .domain([minValue, maxValue]) .range([10, 150]); // min and max value of the circle const width = 900; const height = 500; const orangeColour = '#ffb000'; const blueColour = '#00a1ff'; // Creating svg element const svg = d3.select('#container').append('svg').attr('width', width).attr('height', height); let xPos = 0; // position of circle /* * iterate over each datum and render all associated elements: two circles, and two labels with pointer lines */ for (let i = 0; i < data.length; i++) { const d = data[i]; // current data point const currMaxRadius = radiusScale(Math.max(d.layer1value, d.layer2value)); // get largest radius within current group of two layers xPos += currMaxRadius; // add that radius to xPos // create group element containing all view elements for current datum const group = svg.append('g') .attr('transform', `translate(${xPos}, ${height / 2})`); group.append('circle') .attr('r', radiusScale(d.layer1value)) .style('fill', blueColour); group.insert('circle', d.layer2value > d.layer1value ? ':first-child' : null) // if layer2value is larger than layer1value then insert this circle before the previous one .attr('r', radiusScale(d.layer2value)) .style('fill', orangeColour); xPos += currMaxRadius * 0.9; /* * ADDING LABEL UNDERNEATH THE CIRCLES */ group.append('text') .text(d.name) .attr('dy', radiusScale(maxValue) + 40) // add 40px of padding so label is not just bellow the circle .style('text-anchor', 'middle'); group.append('line') .attr('y1', radiusScale(d.layer2value)) .attr('y2', radiusScale(maxValue) + 20) // add 20px of padding so the pointer line is not overlapping with label .style('stroke', orangeColour); /* * ADDING LABEL AT THE ANGLE OF 45deg RELATIVE TO THE CIRCLES */ // we are creating new group element so we can easily rotate both line and label by -45deg const rotatedLabelGroup = group.append('g').style('transform', 'rotate(-45deg)'); rotatedLabelGroup.append('line') .attr('x1', radiusScale(d.layer2value)) .attr('x2', radiusScale(maxValue) + 20) .style('stroke', orangeColour); rotatedLabelGroup.append('text') .text(d.vists) .attr('dx', radiusScale(maxValue)) .attr('dy', -5); // this way label is slightly above the line } </script> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM