Advertisement
NTahmid

pointwise_comparison_scatter_v2

Feb 22nd, 2024
757
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 9.20 KB | None | 0 0
  1. Here is the modified code with annotations:
  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-line {
  51.       stroke: #c86984;
  52.       stroke-width: 2px;
  53.     }
  54.  
  55.     .annotation-circle {
  56.       fill: none;
  57.       stroke: #c86984;
  58.       stroke-width: 2px;
  59.     }
  60.  
  61.     .annotation-text {
  62.       fill: #c86984;
  63.       font-size: 14px;
  64.     }
  65.   </style>
  66.  
  67.   <body>
  68.     <div id="container" align="center"></div>
  69.  
  70.     <script type="text/javascript">
  71.       // Url to the input data
  72.       var url =
  73.         "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json";
  74.  
  75.       // Colors to differentiate riders with and without doping allegations
  76.       var colors = ["#27ae60", "#8e44ad"];
  77.  
  78.       // The attributes of the riders corresponding to the above colors
  79.       var legendKeys = ["No Doping Allegations", "Doping Allegations"];
  80.  
  81.       // Create an invisible div for the tooltip
  82.       const tooltip = d3
  83.         .select("body")
  84.         .append("div")
  85.         .attr("id", "tooltip")
  86.         .style("visibility", "hidden");
  87.  
  88.       // 1. Load the data from external source
  89.       d3.json(url).then(function (data) {
  90.         // 2. Append svg-object for the bar chart to a div in your webpage
  91.         // (here we use a div with id=container)
  92.         var width = 700;
  93.         var height = 500;
  94.         var margin = { left: 90, top: 80, bottom: 50, right: 20 };
  95.         var axisOffset = 10; // How for the axes are moved away from each other
  96.  
  97.         const svg = d3
  98.           .select("#container")
  99.           .append("svg")
  100.           .attr("id", "svg")
  101.           .attr("width", width)
  102.           .attr("height", height);
  103.  
  104.         // 3. Define scales to translate domains of the data to the range of the svg
  105.         var xMin = d3.min(data, (d) => d["Year"]);
  106.         var xMax = d3.max(data, (d) => d["Year"]);
  107.  
  108.         var parseTime = d3.timeParse("%M:%S");
  109.         var yMin = d3.min(data, (d) => parseTime(d["Time"]));
  110.         var yMax = d3.max(data, (d) => parseTime(d["Time"]));
  111.  
  112.         var xScale = d3
  113.           .scaleLinear()
  114.           .domain([xMin, xMax])
  115.           .range([margin.left + axisOffset, width - margin.right]);
  116.  
  117.         var yScale = d3
  118.           .scaleTime()
  119.           .domain([yMax, yMin])
  120.           .range([height - margin.bottom - axisOffset, margin.top]);
  121.  
  122.         // 4. Draw and transform/translate horizontal and vertical axes
  123.         var xAxis = d3.axisBottom().scale(xScale).tickFormat(d3.format("d"));
  124.         var yAxis = d3
  125.           .axisLeft()
  126.           .scale(yScale)
  127.           .tickFormat(d3.timeFormat("%M:%S"));
  128.  
  129.         svg
  130.           .append("g")
  131.           .attr("transform", "translate(0, " + (height - margin.bottom) + ")")
  132.           .attr("id", "x-axis")
  133.           .call(xAxis);
  134.  
  135.         svg
  136.           .append("g")
  137.           .attr("transform", "translate(" + margin.left + ", 0)")
  138.           .attr("id", "y-axis")
  139.           .call(yAxis);
  140.  
  141.         // 5. Draw individual scatter points and define mouse events for the tooltip
  142.         svg
  143.           .selectAll("scatterPoints")
  144.           .data(data)
  145.           .enter()
  146.           .append("circle")
  147.           .attr("cx", (d) => xScale(d["Year"]))
  148.           .attr("cy", (d) => yScale(parseTime(d["Time"])))
  149.           .attr("r", 5)
  150.           .attr("fill", (d) => (d["Doping"] == "" ? colors[0] : colors[1]))
  151.           .attr("class", "dot")
  152.           .attr("data-xvalue", (d) => d["Year"])
  153.           .attr("data-yvalue", (d) => parseTime(d["Time"]))
  154.           .on("mouseover", function (d) {
  155.             info = d["originalTarget"]["__data__"];
  156.             tooltip
  157.               .style("visibility", "visible")
  158.               .style("left", event.pageX + 10 + "px")
  159.               .style("top", event.pageY - 80 + "px")
  160.               .attr("data-year", info["Year"])
  161.               .html(
  162.                 info["Name"] +
  163.                   " (" +
  164.                   info["Year"] +
  165.                   ") <br> Time: " +
  166.                   info["Time"] +
  167.                   "<br><br>" +
  168.                   info["Doping"]
  169.               );
  170.           })
  171.           .on("mousemove", function () {
  172.             tooltip.style("left", event.pageX + 10 + "px");
  173.           })
  174.           .on("mouseout", function () {
  175.             tooltip.style("visibility", "hidden");
  176.           });
  177.  
  178.         // 6. Finalize chart by adding title, axes labels and legend
  179.        
  180.         //X-axis label
  181.         svg
  182.           .append("text")
  183.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  184.           .attr("y", height - margin.bottom / 5)
  185.           .attr("class", "label")
  186.           .text("Year");
  187.  
  188.  
  189.         //Y-axis label
  190.         svg
  191.           .append("text")
  192.           .attr("y", margin.left / 4)
  193.           .attr("x", -height / 2)
  194.           .attr("transform", "rotate(-90)")
  195.           .attr("class", "label")
  196.           .text("Time to finish");
  197.  
  198.         //Title of the chart
  199.         svg
  200.           .append("text")
  201.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  202.           .attr("y", margin.top / 2.6)
  203.           .attr("id", "title")
  204.           .text("Doping in professional bike racing");
  205.  
  206.         svg
  207.           .append("text")
  208.           .attr("x", margin.left + (width - margin.left - margin.right) / 2)
  209.           .attr("y", margin.top / 1.4)
  210.           .text("35 fastest times to finish Alpe d'Huez")
  211.           .style("font-size", "16px")
  212.           .style("text-anchor", "middle");
  213.  
  214.         //Chart Legends
  215.         svg
  216.           .selectAll("legendSymbols")
  217.           .data(legendKeys)
  218.           .enter()
  219.           .append("circle")
  220.           .attr("cx", width - margin.right - 200)
  221.           .attr("cy", (d, i) => 150 + i * 25)
  222.           .attr("r", 5)
  223.           .attr("fill", (d, i) => colors[i]);
  224.  
  225.         svg
  226.           .selectAll("legendTexts")
  227.           .data(legendKeys)
  228.           .enter()
  229.           .append("text")
  230.           .text((d) => d)
  231.           .attr("x", width - margin.right - 200 + 15)
  232.           .attr("y", (d, i) => 150 + i * 25 + 5)
  233.           .attr("class", "textbox");
  234.  
  235.         const legend = svg
  236.           .append("rect")
  237.           .attr("x", width - margin.right - 200 - 15)
  238.           .attr("y", 150 - 5 - 10)
  239.           .attr("rx", 5)
  240.           .attr("ry", 5)
  241.           .attr("width", 195)
  242.           .attr("height", 55)
  243.           .attr("id", "legend");
  244.  
  245.         // Annotations
  246.         const annotations = [
  247.           {
  248.             note: {
  249.               label: "Trend line showing decrease in race finishing times over the years",
  250.               title: "Trend",
  251.             },
  252.             x: xScale(1994),
  253.             y: yScale(parseTime("39:30")),
  254.             dx: xScale(2015) - xScale(1994),
  255.             dy: yScale(parseTime("36:50")) - yScale(parseTime("39:30")),
  256.             type: d3.annotationCalloutCurve,
  257.             subject: { radius: 50, radiusPadding: 10 },
  258.           },
  259.           {
  260.             note: {
  261.               label: "Outlier: cyclist with no doping allegations and fast finishing time",
  262.               title: "Outlier",
  263.             },
  264.             x: xScale(2008),
  265.             y: yScale(parseTime("39:32")),
  266.             dx: 50,
  267.             dy: -50,
  268.             type: d3.annotationCalloutElbow,
  269.           },
  270.           {
  271.             note: {
  272.               label: "Comparison: cyclists with and without doping allegations",
  273.               title: "Comparison",
  274.             },
  275.             x: xScale(2004),
  276.             y: yScale(parseTime("37:36")),
  277.             dx: 50,
  278.             dy: 50,
  279.             type: d3.annotationCalloutElbow,
  280.           },
  281.         ];
  282.  
  283.         const makeAnnotations = d3
  284.           .annotation()
  285.           .annotations(annotations)
  286.           .type(d3.annotationLabel)
  287.           .accessors({
  288.             x: (d) => xScale(d["Year"]),
  289.             y: (d) => yScale(parseTime(d["Time"])),
  290.           })
  291.           .accessorsInverse({
  292.             Year: (d) => xScale.invert(d.x),
  293.             Time: (d) => parseTime(yScale.invert(d.y)),
  294.           });
  295.  
  296.         svg.append("g").call(makeAnnotations);
  297.       });
  298.     </script>
  299.   </body>
  300. </html>
  301. ```
  302.  
  303. This code adds annotations to the scatter plot chart. The annotations include a trend line showing the decrease in race finishing times over the years, an outlier annotation for a cyclist with no doping allegations and a fast finishing time, and a comparison annotation for cyclists with and without doping allegations. The annotations are styled with a #c86984 color.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement