changeset 2689:8f919fe629f9

client: waterlevel diagram: added tooltips showing date and waterlevel on the chart
author Markus Kottlaender <markus@intevation.de>
date Fri, 15 Mar 2019 16:41:16 +0100
parents d316a6e41f54
children ef59a4255670
files client/src/components/gauge/Waterlevel.vue
diffstat 1 files changed, 90 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/gauge/Waterlevel.vue	Fri Mar 15 16:35:08 2019 +0100
+++ b/client/src/components/gauge/Waterlevel.vue	Fri Mar 15 16:41:16 2019 +0100
@@ -49,6 +49,20 @@
       .handle
         stroke: rgba($color-info, 0.5)
         fill: rgba($color-info, 0.5)
+
+    .chart-dots
+      clip-path: url(#clip)
+      .chart-dot
+        fill: steelblue
+        stroke: steelblue
+        pointer-events: none
+    .chart-tooltip
+      rect
+        fill: #fff
+        stroke: #ccc
+      text
+        fill: #666
+        font-size: 12px
 </style>
 
 <script>
@@ -352,6 +366,14 @@
           navChart
             .select(".brush")
             .call(brush.move, x.range().map(t.invertX, t));
+        })
+        .on("start", () => {
+          svg.select(".chart-dot").style("display", "none");
+          svg.select(".chart-tooltip").style("display", "none");
+        })
+        .on("end", () => {
+          svg.select(".chart-dot").style("display", null);
+          svg.select(".chart-tooltip").style("display", null);
         });
 
       navChart
@@ -360,13 +382,80 @@
         .call(brush)
         .call(brush.move, x.range());
 
-      svg
+      let zoomRect = svg
         .append("rect")
         .attr("class", "zoom")
         .attr("width", width)
         .attr("height", mainHeight)
         .attr("transform", `translate(${mainMargin.left}, ${mainMargin.top})`)
         .call(zoom);
+
+      // TOOLTIPS
+
+      let dots = mainChart.append("g").attr("class", "chart-dots");
+      dots
+        .append("circle")
+        .attr("class", "chart-dot")
+        .attr("r", 4);
+      let tooltips = mainChart.append("g").attr("class", "chart-tooltip");
+      tooltips
+        .append("rect")
+        .attr("x", -25)
+        .attr("y", -25)
+        .attr("rx", 4)
+        .attr("ry", 4)
+        .attr("width", 105)
+        .attr("height", 40);
+      let tooltipText = tooltips.append("text");
+      tooltipText
+        .append("tspan")
+        .attr("x", -15)
+        .attr("y", -8);
+      tooltipText
+        .append("tspan")
+        .attr("x", 8)
+        .attr("y", 7)
+        .style("font-weight", "bold");
+
+      let bisectDate = d3.bisector(d => d.date).left;
+      zoomRect
+        .on("mouseover", () => {
+          svg.select(".chart-dot").style("display", null);
+          svg.select(".chart-tooltip").style("display", null);
+        })
+        .on("mouseout", () => {
+          svg.select(".chart-dot").style("display", "none");
+          svg.select(".chart-tooltip").style("display", "none");
+        })
+        .on("mousemove", () => {
+          let x0 = x.invert(d3.mouse(document.querySelector(".zoom"))[0]),
+            i = bisectDate(this.waterlevels, x0, 1),
+            d0 = this.waterlevels[i - 1],
+            d1 = this.waterlevels[i],
+            d = x0 - d0.date > d1.date - x0 ? d1 : d0;
+
+          svg
+            .select(".chart-dot")
+            .attr("transform", `translate(${x(d.date)}, ${y(d.waterlevel)})`);
+          svg
+            .select(".chart-tooltip")
+            .attr(
+              "transform",
+              `translate(${x(d.date) - 25}, ${y(d.waterlevel) - 25})`
+            );
+          svg.select(".chart-tooltip text tspan:first-child").text(
+            d.date.toLocaleString([], {
+              year: "2-digit",
+              month: "2-digit",
+              day: "2-digit",
+              hour: "2-digit",
+              minute: "2-digit"
+            })
+          );
+          svg
+            .select(".chart-tooltip text tspan:last-child")
+            .text(d.waterlevel + " cm");
+        });
     }
   },
   created() {