Advertisement
NTahmid

extrema_scatter_v2

Feb 22nd, 2024
697
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 8.08 KB | None | 0 0
  1. Here is the modified code with annotations for the extrema:
  2.  
  3. ```html
  4. <!doctype html>
  5. <meta charset="utf-8" />
  6. <html>
  7.   <head>
  8.     <script src="https://d3js.org/d3.v6.min.js" charset="utf-8"></script>
  9.     <script src="https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js"></script>
  10.   </head>
  11.  
  12.   <style>
  13.     * {
  14.       font-family: sans-serif;
  15.     }
  16.  
  17.     #tooltip {
  18.       visibility: hidden;
  19.       position: absolute;
  20.       opacity: 0.8;
  21.       padding: 10px;
  22.       vertical-align: middle;
  23.       border-radius: 5px;
  24.       background-color: #ecf0f1;
  25.       font-size: 14px;
  26.     }
  27.  
  28.     .textbox {
  29.       font-size: 14px;
  30.     }
  31.  
  32.     #legend {
  33.       opacity: 0.2;
  34.       fill: #2c3e50;
  35.     }
  36.  
  37.     #title {
  38.       text-anchor: middle;
  39.       font-size: 22px;
  40.     }
  41.  
  42.     .label {
  43.       text-anchor: middle;
  44.     }
  45.  
  46.     #svg {
  47.       background-color: white;
  48.     }
  49.  
  50.     .annotation {
  51.       fill: #c86984;
  52.       stroke: #c86984;
  53.     }
  54.   </style>
  55.  
  56.   <body>
  57.     <div id="container" align="center"></div>
  58.  
  59.     <script type="text/javascript">
  60.       // Url to the input data
  61.       var url =
  62.         "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json";
  63.  
  64.       // Colors to differentiate riders with and without doping allegations
  65.       var colors = ["#27ae60", "#8e44ad"];
  66.  
  67.       // The attributes of the riders corresponding to the above colors
  68.       var legendKeys = ["No Doping Allegations", "Doping Allegations"];
  69.  
  70.       // Create an invisible div for the tooltip
  71.       const tooltip = d3
  72.         .select("body")
  73.         .append("div")
  74.         .attr("id", "tooltip")
  75.         .style("visibility", "hidden");
  76.  
  77.       // 1. Load the data from external source
  78.       d3.json(url).then(function (data) {
  79.         // 2. Append svg-object for the bar chart to a div in your webpage
  80.         // (here we use a div with id=container)
  81.         var width = 700;
  82.         var height = 500;
  83.         var margin = { left: 90, top: 80, bottom: 50, right: 20 };
  84.         var axisOffset = 10; // How for the axes are moved away from each other
  85.  
  86.         const svg = d3
  87.           .select("#container")
  88.           .append("svg")
  89.           .attr("id", "svg")
  90.           .attr("width", width)
  91.           .attr("height", height);
  92.  
  93.         // 3. Define scales to translate domains of the data to the range of the svg
  94.         var xMin = d3.min(data, (d) => d["Year"]);
  95.         var xMax = d3.max(data, (d) => d["Year"]);
  96.  
  97.         var parseTime = d3.timeParse("%M:%S");
  98.         var yMin = d3.min(data, (d) => parseTime(d["Time"]));
  99.         var yMax = d3.max(data, (d) => parseTime(d["Time"]));
  100.  
  101.         var xScale = d3
  102.           .scaleLinear()
  103.           .domain([xMin, xMax])
  104.           .range([margin.left + axisOffset, width - margin.right]);
  105.  
  106.         var yScale = d3
  107.           .scaleTime()
  108.           .domain([yMax, yMin])
  109.           .range([height - margin.bottom - axisOffset, margin.top]);
  110.  
  111.         // 4. Draw and transform/translate horizontal and vertical axes
  112.         var xAxis = d3.axisBottom().scale(xScale).tickFormat(d3.format("d"));
  113.         var yAxis = d3
  114.           .axisLeft()
  115.           .scale(yScale)
  116.           .tickFormat(d3.timeFormat("%M:%S"));
  117.  
  118.         svg
  119.           .append("g")
  120.           .attr("transform", "translate(0, " + (height - margin.bottom) + ")")
  121.           .attr("id", "x-axis")
  122.           .call(xAxis);
  123.  
  124.         svg
  125.           .append("g")
  126.           .attr("transform", "translate(" + margin.left + ", 0)")
  127.           .attr("id", "y-axis")
  128.           .call(yAxis);
  129.  
  130.         // 5. Draw individual scatter points and define mouse events for the tooltip
  131.         svg
  132.           .selectAll("scatterPoints")
  133.           .data(data)
  134.           .enter()
  135.           .append("circle")
  136.           .attr("cx", (d) => xScale(d["Year"]))
  137.           .attr("cy", (d) => yScale(parseTime(d["Time"])))
  138.           .attr("r", 5)
  139.           .attr("fill", (d) => (d["Doping"] == "" ? colors[0] : colors[1]))
  140.           .attr("class", "dot")
  141.           .attr("data-xvalue", (d) => d["Year"])
  142.           .attr("data-yvalue", (d) => parseTime(d["Time"]))
  143.           .on("mouseover", function (d) {
  144.             info = d["originalTarget"]["__data__"];
  145.             tooltip
  146.               .style("visibility", "visible")
  147.               .style("left", event.pageX + 10 + "px")
  148.               .style("top", event.pageY - 80 + "px")
  149.               .attr("data-year", info["Year"])
  150.               .html(
  151.                 info["Name"] +
  152.                   " (" +
  153.                   info["Year"] +
  154.                   ") <br> Time: " +
  155.                   info["Time"] +
  156.                   "<br><br>" +
  157.                   info["Doping"]
  158.               );
  159.           })
  160.           .on("mousemove", function () {
  161.             tooltip.style("left", event.pageX + 10 + "px");
  162.           })
  163.           .on("mouseout", function () {
  164.             tooltip.style("visibility", "hidden");
  165.           });
  166.  
  167.         // 6. Finalize chart by adding title, axes labels and legend
  168.        
  169.         //X-axis label
  170.         svg
  171.           .append("text")
  172.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  173.           .attr("y", height - margin.bottom / 5)
  174.           .attr("class", "label")
  175.           .text("Year");
  176.  
  177.         //Y-axis label
  178.         svg
  179.           .append("text")
  180.           .attr("y", margin.left / 4)
  181.           .attr("x", -height / 2)
  182.           .attr("transform", "rotate(-90)")
  183.           .attr("class", "label")
  184.           .text("Time to finish");
  185.  
  186.         //Title of the chart
  187.         svg
  188.           .append("text")
  189.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  190.           .attr("y", margin.top / 2.6)
  191.           .attr("id", "title")
  192.           .text("Doping in professional bike racing");
  193.  
  194.         svg
  195.           .append("text")
  196.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  197.           .attr("y", margin.top / 1.4)
  198.           .text("35 fastest times to finish Alpe d'Huez")
  199.           .style("font-size", "16px")
  200.           .style("text-anchor", "middle");
  201.  
  202.         //Chart Legends
  203.         svg
  204.           .selectAll("legendSymbols")
  205.           .data(legendKeys)
  206.           .enter()
  207.           .append("circle")
  208.           .attr("cx", width - margin.right - 200)
  209.           .attr("cy", (d, i) => 150 + i * 25)
  210.           .attr("r", 5)
  211.           .attr("fill", (d, i) => colors[i]);
  212.  
  213.         svg
  214.           .selectAll("legendTexts")
  215.           .data(legendKeys)
  216.           .enter()
  217.           .append("text")
  218.           .text((d) => d)
  219.           .attr("x", width - margin.right - 200 + 15)
  220.           .attr("y", (d, i) => 150 + i * 25 + 5)
  221.           .attr("class", "textbox");
  222.  
  223.         const legend = svg
  224.           .append("rect")
  225.           .attr("x", width - margin.right - 200 - 15)
  226.           .attr("y", 150 - 5 - 10)
  227.           .attr("rx", 5)
  228.           .attr("ry", 5)
  229.           .attr("width", 195)
  230.           .attr("height", 55)
  231.           .attr("id", "legend");
  232.  
  233.         // Annotations
  234.         const annotations = [
  235.           {
  236.             note: {
  237.               label: "Fastest time: 36:50 by Marco Pantani in 1995",
  238.               title: "Minimum Value",
  239.             },
  240.             x: xScale(1995),
  241.             y: yScale(parseTime("36:50")),
  242.             dy: -30,
  243.             dx: -60,
  244.           },
  245.           {
  246.             note: {
  247.               label: "Slowest time: 39:50 by Nairo Quintana in 2013",
  248.               title: "Maximum Value",
  249.             },
  250.             x: xScale(2013),
  251.             y: yScale(parseTime("39:50")),
  252.             dy: 30,
  253.             dx: 60,
  254.           },
  255.         ];
  256.  
  257.         const makeAnnotations = d3
  258.           .annotation()
  259.           .annotations(annotations)
  260.           .type(d3.annotationLabel);
  261.  
  262.         svg.append("g").call(makeAnnotations);
  263.       });
  264.     </script>
  265.   </body>
  266. </html>
  267. ```
  268.  
  269. This code adds two annotations to the chart, one for the fastest time (minimum value) and one for the slowest time (maximum value). The annotations are positioned at the corresponding data points and include a title and label. The color of the annotations is set to #c86984.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement