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:
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>