Browse Source

Build a multi-line chart.

Frederic G. MARAND 7 years ago
parent
commit
3cff2a684e
5 changed files with 231 additions and 90 deletions
  1. 1 0
      .gitignore
  2. 52 21
      .idea/workspace.xml
  3. 138 24
      data/data.json
  4. 0 4
      index.html
  5. 40 41
      src/app.js

+ 1 - 0
.gitignore

@@ -1 +1,2 @@
 node_modules
+.DS_Store

+ 52 - 21
.idea/workspace.xml

@@ -2,6 +2,8 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="048f5977-9ed4-45df-900a-ad0460ae8f41" name="Default" comment="">
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/data/data.json" afterPath="$PROJECT_DIR$/data/data.json" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/index.html" afterPath="$PROJECT_DIR$/index.html" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/app.js" afterPath="$PROJECT_DIR$/src/app.js" />
     </list>
@@ -31,7 +33,18 @@
     <favorites_list name="v4-tutorial" />
   </component>
   <component name="FileEditorManager">
-    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300" />
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file leaf-file-name="app.js" pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/src/app.js">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="588">
+              <caret line="56" column="39" selection-start-line="56" selection-start-column="39" selection-end-line="56" selection-end-column="39" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
   </component>
   <component name="FileTemplateManagerImpl">
     <option name="RECENT_TEMPLATES">
@@ -51,8 +64,10 @@
         <option value="$PROJECT_DIR$/package.json" />
         <option value="$PROJECT_DIR$/src/responsivefy.js" />
         <option value="$PROJECT_DIR$/data/data.js" />
-        <option value="$PROJECT_DIR$/data/data.json" />
         <option value="$PROJECT_DIR$/index.html" />
+        <option value="$PROJECT_DIR$/data/AMZN.csv" />
+        <option value="$PROJECT_DIR$/data/GOOG.csv" />
+        <option value="$PROJECT_DIR$/data/data.json" />
         <option value="$PROJECT_DIR$/src/app.js" />
       </list>
     </option>
@@ -264,18 +279,18 @@
       <updated>1478355759772</updated>
       <workItem from="1478355760990" duration="14794000" />
       <workItem from="1478430008755" duration="3280000" />
-      <workItem from="1478438832989" duration="7137000" />
+      <workItem from="1478438832989" duration="10159000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="15745000" />
+    <option name="totallyTimeSpent" value="18767000" />
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="916" height="877" extended-state="0" />
-    <editor active="false" />
+    <editor active="true" />
     <layout>
-      <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25743708" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25743708" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
       <window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
@@ -434,23 +449,23 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/node_modules/d3/build/d3.node.js">
+    <entry file="file://$PROJECT_DIR$/.gitignore">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="248">
-          <caret line="303" column="0" selection-start-line="303" selection-start-column="0" selection-end-line="303" selection-end-column="0" />
+        <state relative-caret-position="0">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/node_modules/d3/build/d3.js">
+    <entry file="file://$PROJECT_DIR$/data/AMZN.csv">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="248">
-          <caret line="6788" column="9" selection-start-line="6788" selection-start-column="9" selection-end-line="6788" selection-end-column="9" />
+        <state relative-caret-position="0">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/.gitignore">
+    <entry file="file://$PROJECT_DIR$/data/GOOG.csv">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="0">
           <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
@@ -458,26 +473,42 @@
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="308">
+          <caret line="22" column="0" selection-start-line="22" selection-start-column="0" selection-end-line="22" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
     <entry file="file://$PROJECT_DIR$/data/data.json">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="196">
-          <caret line="14" column="4" selection-start-line="14" selection-start-column="4" selection-end-line="14" selection-end-column="4" />
+        <state relative-caret-position="294">
+          <caret line="21" column="18" selection-start-line="21" selection-start-column="18" selection-end-line="21" selection-end-column="18" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/app.js">
+    <entry file="file://$PROJECT_DIR$/node_modules/d3/build/d3.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="647">
-          <caret line="65" column="27" selection-start-line="65" selection-start-column="27" selection-end-line="65" selection-end-column="27" />
+        <state relative-caret-position="253">
+          <caret line="16113" column="0" selection-start-line="16113" selection-start-column="0" selection-end-line="16113" selection-end-column="0" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/index.html">
+    <entry file="file://$PROJECT_DIR$/node_modules/d3/build/d3.node.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="248">
+          <caret line="154" column="0" selection-start-line="154" selection-start-column="0" selection-end-line="154" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/src/app.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="252">
-          <caret line="18" column="8" selection-start-line="18" selection-start-column="8" selection-end-line="18" selection-end-column="8" />
+        <state relative-caret-position="588">
+          <caret line="56" column="39" selection-start-line="56" selection-start-column="39" selection-end-line="56" selection-end-column="39" />
           <folding />
         </state>
       </provider>

+ 138 - 24
data/data.json

@@ -1,30 +1,144 @@
 [
   {
-    "country": "United States",
-    "population": 323050000,
-    "expectancy": 78.94,
-    "cost": 9024.21,
-    "code": "US"
+    "ticker": "AMZN",
+    "values": [
+      { "date": "2016/11/04","close": "755.0500" },
+      { "date": "2016/11/03","close": "767.0300" },
+      { "date": "2016/11/02","close": "765.5600" },
+      { "date": "2016/11/01","close": "785.4100" },
+      { "date": "2016/10/31", "close": "789.8200" },
+      { "date": "2016/10/28", "close": "776.3200" },
+      { "date": "2016/10/27", "close": "818.3600" },
+      { "date": "2016/10/26", "close": "822.5900" },
+      { "date": "2016/10/25", "close": "835.1800" },
+      { "date": "2016/10/24", "close": "838.0900" },
+      { "date": "2016/10/21", "close": "818.9900" },
+      { "date": "2016/10/20", "close": "810.3200" },
+      { "date": "2016/10/19", "close": "817.6900" },
+      { "date": "2016/10/18", "close": "817.6500" },
+      { "date": "2016/10/17", "close": "812.9500" },
+      { "date": "2016/10/14", "close": "822.9600" },
+      { "date": "2016/10/13", "close": "829.2800" },
+      { "date": "2016/10/12", "close": "834.0900" },
+      { "date": "2016/10/11", "close": "831.0000" },
+      { "date": "2016/10/10", "close": "841.7100" },
+      { "date": "2016/10/07", "close": "839.4300" },
+      { "date": "2016/10/06", "close": "841.6600" },
+      { "date": "2016/10/05", "close": "844.3600" },
+      { "date": "2016/10/04", "close": "834.0300" },
+      { "date": "2016/10/03", "close": "836.7400" },
+      { "date": "2016/09/30", "close": "837.3100" },
+      { "date": "2016/09/29", "close": "829.0500" },
+      { "date": "2016/09/28", "close": "828.7200" },
+      { "date": "2016/09/27", "close": "816.1100" },
+      { "date": "2016/09/26", "close": "799.1600" },
+      { "date": "2016/09/23", "close": "805.7500" },
+      { "date": "2016/09/22", "close": "804.7000" },
+      { "date": "2016/09/21", "close": "789.7400" },
+      { "date": "2016/09/20", "close": "780.2200" },
+      { "date": "2016/09/19", "close": "775.1000" },
+      { "date": "2016/09/16", "close": "778.5200" },
+      { "date": "2016/09/15", "close": "769.6900" },
+      { "date": "2016/09/14", "close": "761.0900" },
+      { "date": "2016/09/13", "close": "761.0100" },
+      { "date": "2016/09/12", "close": "771.4900" },
+      { "date": "2016/09/09", "close": "760.1400" },
+      { "date": "2016/09/08", "close": "784.0600" },
+      { "date": "2016/09/07", "close": "784.4800" },
+      { "date": "2016/09/06", "close": "788.8700" },
+      { "date": "2016/09/02", "close": "772.4400" },
+      { "date": "2016/09/01", "close": "770.6200" },
+      { "date": "2016/08/31", "close": "769.1600" },
+      { "date": "2016/08/30", "close": "767.5800" },
+      { "date": "2016/08/29", "close": "771.2900" },
+      { "date": "2016/08/26", "close": "769.0000" },
+      { "date": "2016/08/25", "close": "759.2200" },
+      { "date": "2016/08/24", "close": "757.2500" },
+      { "date": "2016/08/23", "close": "762.4500" },
+      { "date": "2016/08/22", "close": "759.4800" },
+      { "date": "2016/08/19", "close": "757.3100" },
+      { "date": "2016/08/18", "close": "764.4600" },
+      { "date": "2016/08/17", "close": "764.6300" },
+      { "date": "2016/08/16", "close": "764.0400" },
+      { "date": "2016/08/15", "close": "768.4900" },
+      { "date": "2016/08/12", "close": "772.5600" },
+      { "date": "2016/08/11", "close": "771.2400" },
+      { "date": "2016/08/10", "close": "768.5600" },
+      { "date": "2016/08/09", "close": "768.3100" },
+      { "date": "2016/08/08", "close": "766.5600" },
+      { "date": "2016/08/05", "close": "765.9800" },
+      { "date": "2016/08/04", "close": "760.7700" }
+    ]
   },
   {
-    "country": "Switzerland",
-    "population": 8306200,
-    "expectancy": 82.85,
-    "cost": 6786.57,
-    "code": "CH"
-  },
-  {
-    "country": "Norway",
-    "population": 5213985,
-    "expectancy": 81.75,
-    "cost": 6081,
-    "code": "NO"
-  },
-  {
-    "country": "France",
-    "population": 66627602,
-    "expectancy": 82.00,
-    "cost": 4366.99,
-    "code": "FR"
+    "ticker": "GOOG",
+    "values": [
+      { "date": "2016/11/04", "close": "762.0200" },
+      { "date": "2016/11/03", "close": "762.1300" },
+      { "date": "2016/11/02", "close": "768.7000" },
+      { "date": "2016/11/01", "close": "783.6100" },
+      { "date": "2016/10/31", "close": "784.5400" },
+      { "date": "2016/10/28", "close": "795.3700" },
+      { "date": "2016/10/27", "close": "795.3500" },
+      { "date": "2016/10/26", "close": "799.0700" },
+      { "date": "2016/10/25", "close": "807.6700" },
+      { "date": "2016/10/24", "close": "813.1100" },
+      { "date": "2016/10/21", "close": "799.3700" },
+      { "date": "2016/10/20", "close": "796.9700" },
+      { "date": "2016/10/19", "close": "801.5600" },
+      { "date": "2016/10/18", "close": "795.2600" },
+      { "date": "2016/10/17", "close": "779.9600" },
+      { "date": "2016/10/14", "close": "778.5300" },
+      { "date": "2016/10/13", "close": "778.1900" },
+      { "date": "2016/10/12", "close": "786.1400" },
+      { "date": "2016/10/11", "close": "783.0700" },
+      { "date": "2016/10/10", "close": "785.9400" },
+      { "date": "2016/10/07", "close": "775.0800" },
+      { "date": "2016/10/06", "close": "776.8600" },
+      { "date": "2016/10/05", "close": "776.4700" },
+      { "date": "2016/10/04", "close": "776.4300" },
+      { "date": "2016/10/03", "close": "772.5600" },
+      { "date": "2016/09/30", "close": "777.2900" },
+      { "date": "2016/09/29", "close": "775.0100" },
+      { "date": "2016/09/28", "close": "781.5600" },
+      { "date": "2016/09/27", "close": "783.0100" },
+      { "date": "2016/09/26", "close": "774.2100" },
+      { "date": "2016/09/23", "close": "786.9000" },
+      { "date": "2016/09/22", "close": "787.2100" },
+      { "date": "2016/09/21", "close": "776.2200" },
+      { "date": "2016/09/20", "close": "771.4100" },
+      { "date": "2016/09/19", "close": "765.7000" },
+      { "date": "2016/09/16", "close": "768.8800" },
+      { "date": "2016/09/15", "close": "771.7600" },
+      { "date": "2016/09/14", "close": "762.4900" },
+      { "date": "2016/09/13", "close": "759.6900" },
+      { "date": "2016/09/12", "close": "769.0200" },
+      { "date": "2016/09/09", "close": "759.6600" },
+      { "date": "2016/09/08", "close": "775.3200" },
+      { "date": "2016/09/07", "close": "780.3500" },
+      { "date": "2016/09/06", "close": "780.0800" },
+      { "date": "2016/09/02", "close": "771.4600" },
+      { "date": "2016/09/01", "close": "768.7800" },
+      { "date": "2016/08/31", "close": "767.0500" },
+      { "date": "2016/08/30", "close": "769.0900" },
+      { "date": "2016/08/29", "close": "772.1500" },
+      { "date": "2016/08/26", "close": "769.5400" },
+      { "date": "2016/08/25", "close": "769.4100" },
+      { "date": "2016/08/24", "close": "769.6400" },
+      { "date": "2016/08/23", "close": "772.0800" },
+      { "date": "2016/08/22", "close": "772.1500" },
+      { "date": "2016/08/19", "close": "775.4200" },
+      { "date": "2016/08/18", "close": "777.5000" },
+      { "date": "2016/08/17", "close": "779.9100" },
+      { "date": "2016/08/16", "close": "777.1400" },
+      { "date": "2016/08/15", "close": "782.4400" },
+      { "date": "2016/08/12", "close": "783.2200" },
+      { "date": "2016/08/11", "close": "784.8500" },
+      { "date": "2016/08/10", "close": "784.6800" },
+      { "date": "2016/08/09", "close": "784.2600" },
+      { "date": "2016/08/08", "close": "781.7600" },
+      { "date": "2016/08/05", "close": "782.2200" },
+      { "date": "2016/08/04", "close": "771.6100" }
+    ]
   }
 ]

+ 0 - 4
index.html

@@ -9,10 +9,6 @@
         background: lightgray;
         border: 1px solid black;
       }
-      circle {
-        fill-opacity: 0.5;
-        fill: steelblue;
-      }
     </style>
   </head>
 

+ 40 - 41
src/app.js

@@ -19,52 +19,51 @@ let svg = d3.select(".chart")
     .attr("transform", () => `translate(${margin.left},${margin.top})`);
 
 d3.json("data/data.json", function (err, data) {
-  let yScale = d3.scaleLinear()
-    .domain(d3.extent(data, d => d.expectancy))
-    .range([height, 0])
-    .nice();
-
-  let yAxis = d3.axisLeft(yScale);
-  svg.call(yAxis);
+  const parseTime = d3.timeParse("%Y/%m/%d");
+  // Normalize data.
+  data.forEach(company => {
+    company.values.forEach(d => {
+      d.date = parseTime(d.date);
+      // Ensure close is an integer.
+      d.close = +d.close;
+    });
+  });
 
-  let xScale = d3.scaleLinear()
-    .domain(d3.extent(data, d => d.cost))
-    .range([0, width])
-    .nice();
-  let xAxis = d3.axisBottom(xScale)
-    .ticks(5);
+  let xScale = d3.scaleTime()
+    .domain([
+      d3.min(data, company => d3.min(company.values, d => d.date)),
+      d3.max(data, company => d3.max(company.values, d => d.date))
+    ])
+    .range([0, width]);
 
-  svg.append("g")
-    .attr("transform", `translate(0, ${height})`)
-    .call(xAxis);
+  svg
+    .append("g")
+      .attr("transform", `translate(0, ${height})`)
+    .call(d3.axisBottom(xScale).ticks(5));
 
-  // To scale the area, we need the sqrt() of the value, since area = pi*r^2
-  let rScale = d3.scaleSqrt()
-    .domain([0, d3.max(data, d => d.population)])
-    .range([0, 40]);
+  let yScale = d3.scaleLinear()
+    .domain([
+      d3.min(data, company => d3.min(company.values, d => d.close)),
+      d3.max(data, company => d3.max(company.values, d => d.close))
+    ])
+    .range([height, 0]);
+  svg
+    .append("g")
+    .call(d3.axisLeft(yScale));
 
-  let circles = svg
-    .selectAll(".ball")
+  let line = d3.line()
+    .x(d => xScale(d.date))
+    .y(d => yScale(d.close))
+    .curve(d3.curveCatmullRom.alpha(0.5));
+  svg.selectAll(".line")
     .data(data)
     .enter()
-    .append("g")
-    .attr("class", "ball")
-    .attr("transform", d => {
-      return `translate(${xScale(d.cost)},${yScale(d.expectancy)})`;
-    });
-
-  circles
-    .append("circle")
-    // center X, center Y
-    .attr("cx", 0)
-    .attr("cy", 0)
-    .attr("r", d => rScale(d.population));
-
-  circles
-    .append("text")
-    .style("text-anchor", "middle")
-    .style("fill", "black")
-    .text(d => d.code)
-    .attr('y', 4);
+    .append("path")
+    .attr("class", "line")
+    .attr("d", d => line(d.values))
+    // i is the index, alternating 0 and 1 (AMZN orange, GOOG blue).
+    .style("stroke", (d, i) => ["#FF9900", "#3369E8"][i])
+    .style("stroke-width", 2)
+    .style("fill", "none");
 
 });