Reputation: 4461
QUESTION:
Why are not all my text labels showing in my Scatterplot ?
It should iterate over each element in my data, but it seems to stop after a few ?
What have I done wrong ?
Thanks in advance for your answers.
CODE:
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container-fluid">
<h1 class="text-center title">Doping and Performance for Cyclists</h1>
<div class="text-center">
<div id="results"></div>
</div>
</div>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script type="text/javascript">
d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json", function(error, json) {
if (error) {
return console.warn(error);
}
visualizeThe(json);
});
function visualizeThe(data) {
const margin = {
top: 10,
right: 6,
bottom: 20,
left: 70
}
const w = 900 - margin.left - margin.right;
const h = 500 - margin.top - margin.bottom;
const barWidth = Math.ceil(w / data.length);
const parse = d3.timeParse("%m:%s");
const format = d3.timeFormat("%m:%s");
const minTime = d3.min(data, (d) => (d["Seconds"]));
const maxTime = d3.max(data, (d) => (d["Seconds"]));
const xScale = d3.scaleTime()
.domain([maxTime, minTime])
.range([0, w]);
const yScale = d3.scaleLinear()
.domain([d3.max(data, (d) => d["Place"]), 0])
.range([h, 0]);
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale)
const svg = d3.select("#results")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
var div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
svg.append("g")
.attr("transform", "translate(40," + (h+margin.top) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(40," + margin.top + ")")
.call(yAxis);
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "dot")
.attr("r", 4)
.attr("cx", (d) => 40+xScale(d["Seconds"]))
.attr("cy", (d) => yScale(d["Place"]))
.attr("fill", (d) => (d["Doping"] == "" ? "black" : "red"))
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(d["Doping"] == "" ? "No Doping Allegations" : d["Doping"] )
.style("left", (d3.event.pageX - 7) + "px")
.style("top", (d3.event.pageY - 30) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.text((d) => d["Name"])
.attr("x", (d) => 40+xScale(d["Seconds"]))
.attr("y", (d) => yScale(d["Place"]))
.attr("transform", "translate(8,4)")
.style("font-size", 10);
}
</script>
</html>
Upvotes: 1
Views: 45
Reputation: 102174
In this statement...
svg.selectAll("text")
.data(data)
.enter()
.append("text")
... you start your enter selection for the texts.
However, when you get to that statement, you already have text elements in that SVG. The result is that some of the data points are bound to those texts, and your enter selection is shorter than what it should be.
Solution: select something that doesn't exist:
svg.selectAll("foo")
.data(data)
.enter()
.append("text")
Here is your updated CodePen: https://codepen.io/anon/pen/JNbYjj?editors=1000
Upvotes: 1