score:2

Accepted answer

The problem is the way you track the clicked state. Specifically, this variable for the line...

//Determine if current line is visible
var active = blueLine.active ? false : true;

... and this variable for the circles:

// Determine if dots are visible
var active = blackDot.active ? false : true;

The line (actually, a <path> element) has an id named blueLine. Because of that, the element itself is a property of the window object, that is, a global variable. For instance, have a look at this:

console.log(window.foo)
<div id="foo"></div>

Thus, blueLine.active works, even if you never declared blueLine anywhere in the code.

However, while the line has an id, your circle's don't (be it blackDot or not). Also, the line in question is just one and therefore can have an id, but you have several circles and, because of that, an id cannot be used (more on that below).

So, the solution is tracking the clicked state another way. For instance, using a property of the datum:

.on("click", function(d){
    // Determine if dots are visible
    var active   = d.active ? false : true;

Here is the code with that change:

var data = [{
    x: 0,
    y: 0
  }, {
    x: 5,
    y: 30
  }, {
    x: 10,
    y: 40
  },
  {
    x: 15,
    y: 60
  }, {
    x: 20,
    y: 70
  }, {
    x: 25,
    y: 100
  }
];

const margin = {
  left: 20,
  right: 20,
  top: 20,
  bottom: 80
};

const svg = d3.select('svg');
svg.selectAll("*").remove();

const width = 200 - margin.left - margin.right;
const height = 200 - margin.top - margin.bottom;

const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);


var x = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.x;
  })])
  .range([0, width])
  .nice();

var y = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.y;
  })])
  .range([0, height])
  .nice();

const xAxis = d3.axisTop()
  .scale(x)
  .ticks(5)
  .tickPadding(5)
  .tickSize(-height)

const yAxis = d3.axisLeft()
  .scale(y)
  .ticks(5)
  .tickPadding(5)
  .tickSize(-width);

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(20,${height-margin.top-60})`)
  .call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .attr("transform", "translate(20,20)")
  .call(yAxis);

var lineFunction = d3.line()
  .x(function(d) {
    return x(d.x);
  })
  .y(function(d) {
    return y(d.y);
  })
  .curve(d3.curveLinear);

//defining and plotting the lines
var path = g.append("path")
  .attr("class", "path1")
  .attr("id", "blueLine")
  .attr("d", lineFunction(data))
  .attr("stroke", "blue")
  .attr("stroke-width", 2)
  .attr("fill", "none")
  .attr("clip-path", "url(#clip)");

// plot a circle at each data point
g.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("cx", function(d) {
    return x(d.x);
  })
  .attr("cy", function(d) {
    return y(d.y);
  })
  .attr("r", 3)
  .attr("class", "blackDot")
  .attr("clip-path", "url(#clip)");

//************* Legend ***************
var legend = svg.selectAll(".legend")
  .data(data)
  .enter().append("g")

legend.append("rect")
  .attr("x", width + 65)
  .attr("y", 50)
  .attr("width", 18)
  .attr("height", 4)
  .style("fill", "blue")

legend.append("text")
  .attr("x", width + 60)
  .attr("y", 50)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .on("click", function() {
    // Determine if current line is visible
    var active = blueLine.active ? false : true,
      newOpacity = active ? 0 : 1;
    // Hide or show the elements
    d3.select("#blueLine").style("opacity", newOpacity);
    // Update whether or not the elements are active
    blueLine.active = active;
  })
  .text(function(d) {
    return "Value";
  });

var pointLegend = svg.selectAll(".pointLegend")
  .data(data)
  .enter().append("g")

pointLegend.append("circle")
  .attr("r", 3)
  .attr("cx", width + 70)
  .attr("cy", 70);

pointLegend.append("text")
  .attr("x", width + 60)
  .attr("y", 70)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .on("click", function(d) {
    // Determine if dots are visible
    var active = d.active ? false : true,
      newOpacity = active ? 0 : 1;
    // Hide or show the elements
    d3.selectAll(".blackDot").style("opacity", newOpacity);
    // Update whether or not the elements are active
    d.active = active;
  })
  .text(function(d) {
    return "Point";
  });
.xy_chart {
  position: relative;
  left: 50px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg class="xy_chart"></svg>

Bear in mind that, while setting a single id to several elements is not advisable, it will work, as you can see in the demo below, where I just take your code as it is and set the blackDot id to the circles:

var data = [{
    x: 0,
    y: 0
  }, {
    x: 5,
    y: 30
  }, {
    x: 10,
    y: 40
  },
  {
    x: 15,
    y: 60
  }, {
    x: 20,
    y: 70
  }, {
    x: 25,
    y: 100
  }
];

const margin = {
  left: 20,
  right: 20,
  top: 20,
  bottom: 80
};

const svg = d3.select('svg');
svg.selectAll("*").remove();

const width = 200 - margin.left - margin.right;
const height = 200 - margin.top - margin.bottom;

const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);


var x = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.x;
  })])
  .range([0, width])
  .nice();

var y = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.y;
  })])
  .range([0, height])
  .nice();

const xAxis = d3.axisTop()
  .scale(x)
  .ticks(5)
  .tickPadding(5)
  .tickSize(-height)

const yAxis = d3.axisLeft()
  .scale(y)
  .ticks(5)
  .tickPadding(5)
  .tickSize(-width);

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(20,${height-margin.top-60})`)
  .call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .attr("transform", "translate(20,20)")
  .call(yAxis);

var lineFunction = d3.line()
  .x(function(d) {
    return x(d.x);
  })
  .y(function(d) {
    return y(d.y);
  })
  .curve(d3.curveLinear);

//defining and plotting the lines
var path = g.append("path")
  .attr("class", "path1")
  .attr("id", "blueLine")
  .attr("d", lineFunction(data))
  .attr("stroke", "blue")
  .attr("stroke-width", 2)
  .attr("fill", "none")
  .attr("clip-path", "url(#clip)");

// plot a circle at each data point
g.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("cx", function(d) {
    return x(d.x);
  })
  .attr("cy", function(d) {
    return y(d.y);
  })
  .attr("r", 3)
  .attr("id", "blackDot")
  .attr("class", "blackDot")
  .attr("clip-path", "url(#clip)");

//************* Legend ***************
var legend = svg.selectAll(".legend")
  .data(data)
  .enter().append("g")

legend.append("rect")
  .attr("x", width + 65)
  .attr("y", 50)
  .attr("width", 18)
  .attr("height", 4)
  .style("fill", "blue")

legend.append("text")
  .attr("x", width + 60)
  .attr("y", 50)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .on("click", function() {
    // Determine if current line is visible
    var active = blueLine.active ? false : true,
      newOpacity = active ? 0 : 1;
    // Hide or show the elements
    d3.select("#blueLine").style("opacity", newOpacity);
    // Update whether or not the elements are active
    blueLine.active = active;
  })
  .text(function(d) {
    return "Value";
  });

var pointLegend = svg.selectAll(".pointLegend")
  .data(data)
  .enter().append("g")

pointLegend.append("circle")
  .attr("r", 3)
  .attr("cx", width + 70)
  .attr("cy", 70)

pointLegend.append("text")
  .attr("x", width + 60)
  .attr("y", 70)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .on("click", function() {
    // Determine if dots are visible
    var active = blackDot.active ? false : true,
      newOpacity = active ? 0 : 1;
    // Hide or show the elements
    d3.selectAll(".blackDot").style("opacity", newOpacity);
    // Update whether or not the elements are active
    blackDot.active = active;
  })
  .text(function(d) {
    return "Point";
  });
.xy_chart {
  position: relative;
  left: 50px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg class="xy_chart"></svg>

But, again, it's not recommended setting the same id to several elements: ids must be unique.

score:0

You can check out this example.

note the : .style("visibility", "hidden") in tooltip options.


Related Query

More Query from same tag