Reputation: 1363
I have 2 problems here:
1/ These buttons (you can run the code snippet below) should reverse back to their former opacity at the second click but they don't ! Can someone explain me what's wrong with the code ?
2/ How do I reverse back to the text
former color on the second click without having to define that former color (again!) in the toggle function. ?
Explanation: As you can see when running the following snippet, the text
(1,2,3...) turns white
at the first click
. I'd like to set it back to its former color at the second click without having to write:
var newTextFill = active ? "white" : "**former_color**";
For instance, in this example the author doesn't specify the font-size
the legend should return to on a second click and yet you can see it shrinking back to its original size. How can I do the same thing here with the font colors ?
var name = ["123456789"];
var color = d3.scaleOrdinal()
.range(["#00baff", "#0014fe", "#00dbaf", "#f4bf02", "#ffa600", "#ff0000", "#ff00c4", "#ee693e", "#99958f"]);
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height",300)
var legende = svg.selectAll("bar")
.data(name)
.enter()
.append("g")
.attr("x", 0)
.attr("y", function (d,i) {return 12 + i * 20})
legende.append("text")
.text(function(d,i) { return name[i]})
.attr("class", "legtext")
.style("font-family", "helvetica")
.style("fill-opacity", 0.8)
.attr("x", 4)
.attr("y", function (d,i) {return 12 + i * 20})
.style("font-size", 10)
.style("fill", function(d,i) { return color(i)})
.style("text-decoration", "none")
.style("opacity", 1);
legende.append("rect")
.attr("class", "recta")
.attr("x", 2)
.attr("y", function (d,i) {return 1 + i * 20})
.attr("width", 65)
.attr("height", 15)
.style("fill", function(d,i) { return color(i)})
.style("opacity", 0.09);
legende.append("rect")
.attr("class", "rectastroke")
.attr("id", function(d,i) {return "str" + i})
.attr("x", 2)
.attr("y", function (d,i) {return 1 + i * 20})
.attr("width", 65)
.attr("height", 15)
.style("stroke", function(d,i) { return color(i)})
.style("stroke-width", 0.5)
.style("fill", "none")
.attr("display", "none");
legende.on("click", function (d,i)
{var active = d.active ? false : true;
var newOpacity = active ? 1 : 0.1;
var newTextFill = active ? "white" : "blue";
d3.select(this)
.select("rect")
.style("opacity", newOpacity)
d3.select(this)
.select("text")
.style("fill", newTextFill)
.raise()
d.active = active });
legende.on("mouseover", function(d, i)
{d3.select(this).selectAll(".rectastroke").attr("display", "true")});
legende.on("mouseout", function(d, i)
{d3.select(this).selectAll(".rectastroke").attr("display", "none")});
body {font-family: 'Open Sans', sans-serif;
font-size: 11px;
font-weight: 300;
fill: #242424;
text-align: center;
cursor: default;}
.legende {cursor: pointer;}
.recta {cursor: pointer;}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="colored buttons"></div>
</body>
</html>
Upvotes: 1
Views: 1158
Reputation: 102218
In the bl.ocks you linked she is, in fact, specifying the font size the legend will return to on a second click... in the CSS.
What's happening is that if active
is false, the setter will return undefined
...
d3.select(this)
.style("font-size", function() {
if (active) {return "25px"}
})
... and the UA will set the style based on the CSS.
You can do the same thing to your rectangles without specifying any newOpacity
:
d3.select(this)
.select("rect")
.style("opacity", function() {
if (active) return 1;
})
Here is the demo:
var data = "123456789".split("").map(function(d) {
return {
value: d
}
});
var color = d3.scaleOrdinal()
.range(["#00baff", "#0014fe", "#00dbaf", "#f4bf02", "#ffa600", "#ff0000", "#ff00c4", "#ee693e", "#99958f"]);
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height", 300)
var legende = svg.selectAll("bar")
.data(data)
.enter()
.append("g")
.attr("x", 0)
.attr("y", function(d, i) {
return 12 + i * 20
})
legende.append("text")
.text(function(d, i) {
return d.value
})
.attr("class", "legtext")
.style("font-family", "helvetica")
.style("fill-opacity", 0.8)
.attr("x", 4)
.attr("y", function(d, i) {
return 12 + i * 20
})
.style("font-size", 10)
.style("fill", function(d, i) {
return color(i)
})
.style("text-decoration", "none")
.style("opacity", 1);
legende.append("rect")
.attr("class", "recta")
.attr("x", 2)
.attr("y", function(d, i) {
return 1 + i * 20
})
.attr("width", 65)
.attr("height", 15)
.style("fill", function(d, i) {
return color(i)
});
legende.on("click", function(d, i) {
var active = d.active ? false : true;
d3.select(this)
.select("rect")
.style("opacity", function() {
if (active) return 1;
})
d3.select(this)
.select("text")
.style("fill", function(e, j) {
if (active) {
return "white";
} else {
return color(i)
}
})
.raise()
d.active = active
});
.legende {
cursor: pointer;
}
.recta {
opacity: 0.1;
cursor: pointer;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
For the text color, however, since you are not specifying it in the CSS, you'll have to use a normal if...else
code.
Upvotes: 2