最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3 Scatterplot from all circles to different shapes - Stack Overflow

programmeradmin0浏览0评论

I am trying to learn D3 and am looking at this example:

What I want to do now is change the shape of the dots, so I want circles, squares, and triangles based on the brand of the cereal in the data set instead of all circles as datapoints. This seems like it should be a simple change, but I can't get the shapes to show up when I make my change.

I know that this change needs to be made in this segment of the code:

  svg.selectAll(".dot")
      .data(data)
    .enter().append("circle")
      .attr("class", "dot")
      .attr("r", 3.5)
      .attr("cx", xMap)
      .attr("cy", yMap)
      .style("fill", function(d) { return color(cValue(d));}) 
      .on("mouseover", function(d) {
          tooltip.transition()
               .duration(200)
               .style("opacity", .9);
          tooltip.html(d["Cereal Name"] + "<br/> (" + xValue(d) 
            + ", " + yValue(d) + ")")
               .style("left", (d3.event.pageX + 5) + "px")
               .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
          tooltip.transition()
               .duration(500)
               .style("opacity", 0);
      });

I need to change the append of the circle and the attributes. I want to use a conditional so

    .attr("d", function(d,i) {if (d["Cereal Name"] == "Nabisco" return d3.svg.symbol().type("circle"); 
else if (d["Cereal Name"] == "Post" return d3.svg.symbol().type("triangle-down"); 
else return d3.svg.symbol().type("circle")

However, this is not working for me. Does anyone have an insight in how to do this? I don't want to have all circles, I want different shapes depending on the brand name of the cereal in the example. Thank you.

Edit: I tried looking at this:

Filter data in d3 to draw either circle or square

But I couldn't get this to work

I am trying to learn D3 and am looking at this example:

http://bl.ocks/weiglemc/6185069

What I want to do now is change the shape of the dots, so I want circles, squares, and triangles based on the brand of the cereal in the data set instead of all circles as datapoints. This seems like it should be a simple change, but I can't get the shapes to show up when I make my change.

I know that this change needs to be made in this segment of the code:

  svg.selectAll(".dot")
      .data(data)
    .enter().append("circle")
      .attr("class", "dot")
      .attr("r", 3.5)
      .attr("cx", xMap)
      .attr("cy", yMap)
      .style("fill", function(d) { return color(cValue(d));}) 
      .on("mouseover", function(d) {
          tooltip.transition()
               .duration(200)
               .style("opacity", .9);
          tooltip.html(d["Cereal Name"] + "<br/> (" + xValue(d) 
            + ", " + yValue(d) + ")")
               .style("left", (d3.event.pageX + 5) + "px")
               .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
          tooltip.transition()
               .duration(500)
               .style("opacity", 0);
      });

I need to change the append of the circle and the attributes. I want to use a conditional so

    .attr("d", function(d,i) {if (d["Cereal Name"] == "Nabisco" return d3.svg.symbol().type("circle"); 
else if (d["Cereal Name"] == "Post" return d3.svg.symbol().type("triangle-down"); 
else return d3.svg.symbol().type("circle")

However, this is not working for me. Does anyone have an insight in how to do this? I don't want to have all circles, I want different shapes depending on the brand name of the cereal in the example. Thank you.

Edit: I tried looking at this:

Filter data in d3 to draw either circle or square

But I couldn't get this to work

Share Improve this question edited May 23, 2017 at 10:34 CommunityBot 11 silver badge asked Sep 29, 2016 at 3:06 Mr.RobotoMr.Roboto 1913 silver badges14 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 5

First, you have to set the symbol generator (in d3 v4.x):

var symbol = d3.symbol();

And then appending a path element:

var dots = svg.selectAll(".dots")
    .data(data)
    .enter()
    .append("path");

After that, it es the most important part: you have to specify the type of your symbol generator. In the following demo, we can set the shape depending on the name of the brand (I'm using a dataset about chocolate that i found online):

dots.attr("d", symbol.type(function(d){
    if(d.name == "Lindt"){ return d3.symbolCross
    } else if (d.name == "Bournville"){ return d3.symbolDiamond
    } else if (d.name == "Dolfin"){ return d3.symbolSquare
    } else if (d.name == "Hershey"){ return d3.symbolStar
    } else if (d.name == "Galaxy"){ return d3.symbolTriangle
    } else if (d.name == "Dairy Milk"){ return d3.symbolCircle
}}))

Of course, you could avoid that ugly bunch of if...else defining the symbol type in the dataset itself, or just using an ordinal scale.

Check the working demo (using manufacturer instead, to have fewer shapes):

var data = [{
    "name": "Dairy Milk",
        "manufacturer": "cadbury",
        "price": 45,
        "rating": 2
}, {
    "name": "Galaxy",
        "manufacturer": "Nestle",
        "price": 42,
        "rating": 3
}, {
    "name": "Lindt",
        "manufacturer": "Lindt",
        "price": 80,
        "rating": 4
}, {
    "name": "Hershey",
        "manufacturer": "Hershey",
        "price": 40,
        "rating": 1
}, {
    "name": "Dolfin",
        "manufacturer": "Lindt",
        "price": 90,
        "rating": 5
}, {
    "name": "Bournville",
        "manufacturer": "cadbury",
        "price": 70,
        "rating": 2
}];

var w = 300, h = 300;

var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);
    
var xScale = d3.scaleLinear().domain([0, d3.max(data, function(d){ return d.price})]).range([30,w*0.9]);

var yScale = d3.scaleLinear().domain([d3.max(data, function(d){ return d.rating})*1.1, 0]).range([10,h*0.9]);

var symbol = d3.symbol();

var dots = svg.selectAll(".dots")
    .data(data)
    .enter()
    .append("path");
    
dots.attr("d", symbol.type(function(d){if(d.manufacturer == "Lindt"){ return d3.symbolCross} else if (d.manufacturer == "cadbury"){ return d3.symbolDiamond} else if (d.manufacturer == "Nestle"){ return d3.symbolSquare} else if (d.manufacturer == "Hershey"){ return d3.symbolStar} }))
    .attr('fill', "teal")
    .attr('stroke','#000')
    .attr('stroke-width',1)
    .attr('transform',function(d){ return "translate("+xScale(d.price)+","+yScale(d.rating)+")"; });

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

var gX = svg.append("g")
  .call(xAxis)
  .attr("transform", "translate(0," + w*0.9 + ")");

var gY = svg.append("g")
  .call(yAxis)
  .attr("transform", "translate(30,0)");
<script src="https://d3js/d3.v4.min.js"></script>

发布评论

评论列表(0)

  1. 暂无评论