Home > Net >  Different shape based on datum
Different shape based on datum

Time:11-23

I am trying to append another shape when one of the values satisfy the condition as follows:

const keys = ["A", "B", "C", "D", "E", "E", "G"]
const colors = ['#1e90ff', '#008000', '#d3d3d3', '#d3d3d3', '#fe0000', '#ffa500', '#800080']

var triangle =  d3.symbol().type(d3.symbolTriangle).size(500);

const colorOrdinalScale = d3
.scaleOrdinal()
.domain(keys)
.range(colors);

const svg = d3
.select("#container")
.append("svg")
.attr("class", "svg-area")
.attr("width", 600)
.attr("height", 500)

const legend = svg
.append('g')
.attr('id', 'legend')
.selectAll("symbols")
.data(keys)
.enter()

legend
.each(d => {
  if (d === "D") {
    console.log("triangle", d)
    legend
    .append("circle")
    .attr("r", 15)
    .style("fill", (d) => colorOrdinalScale(d)) 
    .attr("transform", (d, i) => `translate(${100   i * 70}, 20)`)
  } 
  else {
    console.log("circle", d)
    legend
    .append("path")
    .attr("d", triangle)
    .attr("fill", (d) => colorOrdinalScale(d))
    .attr("transform", (d, i) => `translate(${100   i * 70}, 20)`);
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="container"></div>

What is supposed to happen is that when the key is equal to D it should print out a triangle and the rest should print out a circle.

As far as I understand, the logic seems to be working. But the result is that both a triangle and a circle are printed for each datum. However, the log shows that the appropriate block of code runs.

Basically, this is the result that I am looking forward to:

enter image description here

CodePudding user response:

Since you are already using d3.symbol, you could just use symbolCircle for the circle, which simplifies the code a lot:

.attr("d", d => symbol.type(d === "D" ? d3.symbolTriangle : d3.symbolCircle)())

Also, your each makes little sense, you're appending several elements on top of each other (you might think you have 7 elements, but have a look at your SVG, you have 49).

This is your code with those changes:

const keys = ["A", "B", "C", "D", "E", "E", "G"]
const colors = ['#1e90ff', '#008000', '#d3d3d3', '#d3d3d3', '#fe0000', '#ffa500', '#800080']

var symbol = d3.symbol().size(500);

const colorOrdinalScale = d3.scaleOrdinal()
  .domain(keys)
  .range(colors);

const svg = d3
  .select("#container")
  .append("svg")
  .attr("class", "svg-area")
  .attr("width", 600)
  .attr("height", 500)

const legend = svg
  .append('g')
  .attr('id', 'legend')
  .selectAll("symbols")
  .data(keys)
  .enter()
  .append("path")
  .attr("d", d => symbol.type(d === "D" ? d3.symbolTriangle : d3.symbolCircle)())
  .attr("fill", d => colorOrdinalScale(d))
  .attr("transform", (d, i) => `translate(${100   i * 70}, 20)`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="container"></div>

CodePudding user response:

You are doing a very basic mistake, when you are writing a statement legend.append("circle) you are appending circles and triangles at each key and its appending circle or triangle at each point. I have edited your code to filter legend based on index which is being processed and transform based on that index.

const keys = ["A", "B", "C", "D", "E", "E", "G"]
const colors = ['#1e90ff', '#008000', '#d3d3d3', '#d3d3d3', '#fe0000', '#ffa500', '#800080']

var triangle =  d3.symbol().type(d3.symbolTriangle).size(500);

const colorOrdinalScale = d3
.scaleOrdinal()
.domain(keys)
.range(colors);

const svg = d3
.select("#container")
.append("svg")
.attr("class", "svg-area")
.attr("width", 600)
.attr("height", 500)

const legend = svg
.append('g')
.attr('id', 'legend')
.selectAll("symbols")
.data(keys)
.enter()

legend
.each((d,index) => {
  if (d === "D") {
    console.log("triangle", index)
    legend
    .filter(function (d, i) { return i == index;})
    .append("circle")
    .attr("r", 15)
    .style("fill", (d) => colorOrdinalScale(d)) 
    .attr("transform", (d, i) => `translate(${100   index * 70}, 20)`)
  } 
  else {
    console.log("circle", index)
    legend
    .filter(function (d, i) { return i == index;})
    .append("path")
    .attr("d", triangle)
    .attr("fill", (d) => colorOrdinalScale(d))
    .attr("transform", (d, i) => `translate(${100   index * 70}, 20)`);
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="container"></div>

  • Related