Explorar el Código

Build a column chart from non-numeric data.

Frederic G. MARAND hace 8 años
padre
commit
59b47979e2
Se han modificado 5 ficheros con 215 adiciones y 73 borrados
  1. 117 13
      .idea/workspace.xml
  2. 18 0
      data/data.js
  3. 8 0
      index.html
  4. 34 60
      src/app.js
  5. 38 0
      src/responsivefy.js

+ 117 - 13
.idea/workspace.xml

@@ -2,9 +2,10 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="048f5977-9ed4-45df-900a-ad0460ae8f41" name="Default" comment="">
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/data/data.js" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/responsivefy.js" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/index.html" afterPath="$PROJECT_DIR$/index.html" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/package.json" afterPath="$PROJECT_DIR$/package.json" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/app.js" afterPath="$PROJECT_DIR$/src/app.js" />
     </list>
     <ignored path="v4-tutorial.iws" />
@@ -20,19 +21,68 @@
   <component name="CreatePatchCommitExecutor">
     <option name="PATCH_PATH" value="" />
   </component>
+  <component name="DatabaseView">
+    <option name="GROUP_SCHEMA" value="true" />
+    <option name="GROUP_CONTENTS" value="false" />
+    <option name="SORT_POSITIONED" value="false" />
+    <option name="SHOW_TABLE_DETAILS" value="true" />
+    <option name="SHOW_EMPTY_GROUPS" value="false" />
+    <option name="AUTO_SCROLL_FROM_SOURCE" value="false" />
+  </component>
   <component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
   <component name="FavoritesManager">
     <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="index.html" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/index.html">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="210">
+              <caret line="15" column="23" selection-start-line="15" selection-start-column="14" selection-end-line="15" selection-end-column="23" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <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="563">
+              <caret line="52" column="13" selection-start-line="52" selection-start-column="13" selection-end-line="52" selection-end-column="13" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="data.js" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/data/data.js">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="112">
+              <caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file leaf-file-name="responsivefy.js" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/responsivefy.js">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="140">
+              <caret line="10" column="14" selection-start-line="10" selection-start-column="14" selection-end-line="10" selection-end-column="14" />
+              <folding />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
   </component>
   <component name="FileTemplateManagerImpl">
     <option name="RECENT_TEMPLATES">
       <list>
         <option value="HTML File" />
-        <option value="JavaScript File" />
         <option value="package_json" />
+        <option value="JavaScript File" />
       </list>
     </option>
   </component>
@@ -43,8 +93,10 @@
     <option name="CHANGED_PATHS">
       <list>
         <option value="$PROJECT_DIR$/package.json" />
-        <option value="$PROJECT_DIR$/src/app.js" />
+        <option value="$PROJECT_DIR$/src/responsivefy.js" />
         <option value="$PROJECT_DIR$/index.html" />
+        <option value="$PROJECT_DIR$/data/data.js" />
+        <option value="$PROJECT_DIR$/src/app.js" />
       </list>
     </option>
   </component>
@@ -116,6 +168,34 @@
               <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
             </PATH_ELEMENT>
           </PATH>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="v4-tutorial" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="v4-tutorial" />
+              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="src" />
+              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
+            </PATH_ELEMENT>
+          </PATH>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="v4-tutorial" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="v4-tutorial" />
+              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
+            </PATH_ELEMENT>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="data" />
+              <option name="myItemType" value="com.jetbrains.php.projectView.PhpTreeStructureProvider$1" />
+            </PATH_ELEMENT>
+          </PATH>
         </subPane>
       </pane>
       <pane id="Scratches" />
@@ -227,22 +307,22 @@
       <updated>1478355759772</updated>
       <workItem from="1478355760990" duration="14794000" />
       <workItem from="1478430008755" duration="3280000" />
-      <workItem from="1478438832989" duration="2137000" />
+      <workItem from="1478438832989" duration="4623000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="10745000" />
+    <option name="totallyTimeSpent" value="13231000" />
   </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" />
-      <window_info id="Database" active="false" anchor="right" 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="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32951945" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Version Control" 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="2" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.23803967" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Mongo Explorer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
@@ -389,18 +469,42 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/index.html">
+    <entry file="file://$PROJECT_DIR$/src/responsivefy.js">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="140">
-          <caret line="10" column="0" selection-start-line="10" selection-start-column="0" selection-end-line="10" selection-end-column="0" />
+          <caret line="10" column="14" selection-start-line="10" selection-start-column="14" selection-end-line="10" selection-end-column="14" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/node_modules/d3/build/d3.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="253">
+          <caret line="16254" column="0" selection-start-line="16254" selection-start-column="0" selection-end-line="16254" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="210">
+          <caret line="15" column="23" selection-start-line="15" selection-start-column="14" selection-end-line="15" selection-end-column="23" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/data/data.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="112">
+          <caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" 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="675">
-          <caret line="86" column="0" selection-start-line="86" selection-start-column="0" selection-end-line="86" selection-end-column="0" />
+        <state relative-caret-position="563">
+          <caret line="52" column="13" selection-start-line="52" selection-start-column="13" selection-end-line="52" selection-end-column="13" />
           <folding />
         </state>
       </provider>

+ 18 - 0
data/data.js

@@ -0,0 +1,18 @@
+let data = [
+  { score: 63, subject: "Mathematics" },
+  { score: 82, subject: "Geography" },
+  { score: 74, subject: "Spelling" },
+  { score: 97, subject: "Reading" },
+  { score: 52, subject: "Science" }
+];
+
+data = [
+  { score: 63, subject: "Mathematics" },
+  { score: 82, subject: "Geography" },
+  { score: 74, subject: "Spelling" },
+  { score: 97, subject: "Reading" },
+  { score: 52, subject: "Science" },
+  { score: 74, subject: "Chemistry" },
+  { score: 97, subject: "Physics" },
+  { score: 52, subject: "ASL" }
+];

+ 8 - 0
index.html

@@ -9,12 +9,20 @@
         background: lightgray;
         border: 1px solid black;
       }
+      rect {
+        fill: steelblue;
+      }
+      rect:hover {
+        fill: turquoise;
+      }
     </style>
   </head>
 
   <body>
     <div class="chart"></div>
 
+    <script src="data/data.js"></script>
+    <script src="src/responsivefy.js"></script>
     <script src="src/app.js"></script>
   </body>
 </html>

+ 34 - 60
src/app.js

@@ -1,79 +1,40 @@
-/* global d3 */
+/* global d3, data, responsivefy */
 
 // D3 convention: define margin as an object called margin with these props:
 let margin = {
   top: 10,
   right: 20,
-  bottom: 30,
+  bottom: 60,
   left: 30
 };
 let width = 400 - margin.left - margin.right;
 let height = 600 - margin.top - margin.bottom;
 
-/**
- * Adjust SVG size.
- *
- * @param {Selection} svg
- *   An SVG D3 selection.
- *
- * @return {void}
- */
-function responsivefy(svg) {
-  // get container + svg aspect ratio.
-  // node() returns the raw DOM node -> parentNode returns the div.chart.
-  const container = d3.select(svg.node().parentNode);
-  const width = parseInt(svg.style("width"), 10);
-  const height = parseInt(svg.style("height"), 10);
-  const aspect = width / height;
-
-  // Get width of container and resize SVG to fit it.
-  function resize() {
-    let targetWidth = parseInt(container.style("width"), 10);
-    svg.attr("width", targetWidth);
-    svg.attr("height", Math.round(targetWidth / aspect));
-  }
-
-  // Add viewBox and preserveAspectRatio properties,
-  // and call resize to that svg resizes on initial page load
-  svg.attr("viewBox", "0 0 " + width + " " + height)
-    .attr("preserveAspectRatio", "xMinYMid")
-    .call(resize);
-
-  // To register multiple listeners for the same event type,
-  // you need to add namespace, i.e. 'click.foo'
-  // necessary if you call invoke this function for multiples SVGs
-  // api docs: https://github.com/mbostock/d3/wiki/Selections#on
-  d3.select(window)
-    .on("resize." + container.attr("id"), resize);
-}
-
-let svg = d3.select('.chart')
-  .append('svg')
-    // Match the size of the chart-containing <div> with the viewport.
-    .attr('width', width + margin.left + margin.right)
-    .attr('height', height + margin.top + margin.bottom)
+let svg = d3.select(".chart")
+  .append("svg")
+    .attr("width", width + margin.left + margin.right)
+    .attr("height", height + margin.top + margin.bottom)
     .call(responsivefy)
-    .append('g')
-    .attr('transform', () => `translate(${margin.left},${margin.top})`);
-// Everything below this line no longer needs to care about margins.
-
-// At this point, the "svg" variable actually contains the <g> selection.
-svg.append('rect')
-  .attr('width', width)
-  .attr('height', height)
-  .style('fill', 'lightblue')
-  .style('stroke', 'green');
+  .append("g")
+    .attr("transform", () => `translate(${margin.left},${margin.top})`);
 
 let yScale = d3.scaleLinear()
   .domain([0, 100])
-  // reversed because SVG coordinates are top to bottom.
   .range([height, 0]);
 
 let yAxis = d3.axisLeft(yScale);
 svg.call(yAxis);
 
-let xScale = d3.scaleTime()
-  .domain([new Date(2016, 0, 1, 6), new Date(2016, 0, 1, 9)])
+// Bar charts NEED a band scale, nothing else (?)
+let xScale = d3.scaleBand()
+  .padding(0.2) // 0..1, default 0
+  // Inned padding is the one between values.
+  //.paddingInner(0.2)
+  // Outer padding is the one on the sides of the graph.
+  // .paddingOuter(0.5)
+  // How to distribute the set of items along the axis.
+  .align(0.5) // 0 full left, to 1 full right.
+  .domain(data.map(d => d.subject))
   .range([0, width]);
 
 let xAxis = d3.axisBottom(xScale)
@@ -81,6 +42,19 @@ let xAxis = d3.axisBottom(xScale)
   .tickSize(10)
   .tickPadding(5);
 
-svg.append('g')
-  .attr('transform', `translate(0, ${height})`)
-  .call(xAxis);
+svg.append("g")
+  .attr("transform", `translate(0, ${height})`)
+  .call(xAxis)
+  .selectAll("text")
+  .style("text-anchor", "end") // start, middle, end
+  .attr("transform", "rotate(-45)");
+
+svg.selectAll("rect")
+  .data(data)
+  .enter()
+  .append("rect")
+  .attr("x", d => xScale(d.subject))
+  .attr("y", d => yScale(d.score))
+  // Automatically calculated value, unique to band scales.
+  .attr("width", xScale.bandwidth())
+  .attr("height", d => height - yScale(d.score));

+ 38 - 0
src/responsivefy.js

@@ -0,0 +1,38 @@
+/* global d3 */
+
+/**
+ * Adjust SVG size.
+ *
+ * @param {Selection} svg
+ *   An SVG D3 selection.
+ *
+ * @return {void}
+ */
+function responsivefy(svg) {
+  // get container + svg aspect ratio.
+  // node() returns the raw DOM node -> parentNode returns the div.chart.
+  const container = d3.select(svg.node().parentNode);
+  const width = parseInt(svg.style("width"), 10);
+  const height = parseInt(svg.style("height"), 10);
+  const aspect = width / height;
+
+  // Get width of container and resize SVG to fit it.
+  function resize() {
+    let targetWidth = parseInt(container.style("width"), 10);
+    svg.attr("width", targetWidth);
+    svg.attr("height", Math.round(targetWidth / aspect));
+  }
+
+  // Add viewBox and preserveAspectRatio properties,
+  // and call resize to that svg resizes on initial page load
+  svg.attr("viewBox", "0 0 " + width + " " + height)
+    .attr("preserveAspectRatio", "xMinYMid")
+    .call(resize);
+
+  // To register multiple listeners for the same event type,
+  // you need to add namespace, i.e. 'click.foo'
+  // necessary if you call invoke this function for multiples SVGs
+  // api docs: https://github.com/mbostock/d3/wiki/Selections#on
+  d3.select(window)
+    .on("resize." + container.attr("id"), resize);
+}