Mercurial > gemma
changeset 2816:c02cebff3f16
client: SPUC7/8: fix tooltip size and positioning
The size is now dynamically calculated based on the content and the tooltip is now
guaranteed to be visible instead of reaching out of the viewport.
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Tue, 26 Mar 2019 19:37:55 +0100 |
parents | 12f053763be2 |
children | ff58440ce809 |
files | client/src/components/gauge/Waterlevel.vue |
diffstat | 1 files changed, 59 insertions(+), 41 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/gauge/Waterlevel.vue Tue Mar 26 16:36:48 2019 +0100 +++ b/client/src/components/gauge/Waterlevel.vue Tue Mar 26 19:37:55 2019 +0100 @@ -639,41 +639,40 @@ eventRect.call(zoom); }, createTooltips(eventRect) { - let dots = this.diagram.append("g").attr("class", "chart-dots"); - dots + // create clippable container for the dot + this.diagram + .append("g") + .attr("class", "chart-dots") .append("circle") .attr("class", "chart-dot") .attr("r", 4); - let tooltips = this.diagram.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"); + + // create container for the tooltip + const tooltip = this.diagram.append("g").attr("class", "chart-tooltip"); + tooltip.append("rect"); + + const padding = 5; + + // create container for multiple text rows + const tooltipText = tooltip.append("text").attr("text-anchor", "middle"); + tooltipText.append("tspan").attr("alignment-baseline", "hanging"); tooltipText .append("tspan") - .attr("x", -15) - .attr("y", -8); - tooltipText - .append("tspan") - .attr("x", 8) - .attr("y", 8); + .attr("dy", 18) + .attr("alignment-baseline", "hanging"); eventRect .on("mouseover", () => { - this.svg.select(".chart-dot").style("opacity", 1); - this.svg.select(".chart-tooltip").style("opacity", 1); + this.diagram.select(".chart-dot").style("opacity", 1); + this.diagram.select(".chart-tooltip").style("opacity", 1); }) .on("mouseout", () => { - this.svg.select(".chart-dot").style("opacity", 0); - this.svg.select(".chart-tooltip").style("opacity", 0); + this.diagram.select(".chart-dot").style("opacity", 0); + this.diagram.select(".chart-tooltip").style("opacity", 0); }) .on("mousemove", () => { - let x0 = this.scale.x.invert( + // find data point closest to mouse + const x0 = this.scale.x.invert( d3.mouse(document.querySelector(".zoom"))[0] ), i = d3.bisector(d => d.date).left(this.waterlevels, x0, 1), @@ -681,25 +680,19 @@ d1 = this.waterlevels[i] || d0, d = x0 - d0.date > d1.date - x0 ? d1 : d0; - this.svg + const coords = { + x: this.scale.x(d.date), + y: this.scale.y(d.waterlevel) + }; + + // position the dot + this.diagram .select(".chart-dot") .style("opacity", 1) - .attr( - "transform", - `translate(${this.scale.x(d.date)}, ${this.scale.y( - d.waterlevel - )})` - ); - this.svg - .select(".chart-tooltip") - .style("opacity", 1) - .attr( - "transform", - `translate(${this.scale.x(d.date) - 25}, ${this.scale.y( - d.waterlevel - ) - 25})` - ); - this.svg.select(".chart-tooltip text tspan:first-child").text( + .attr("transform", `translate(${coords.x}, ${coords.y})`); + + // write date + this.diagram.select(".chart-tooltip text tspan:first-child").text( d.date.toLocaleString([], { year: "2-digit", month: "2-digit", @@ -708,9 +701,34 @@ minute: "2-digit" }) ); - this.svg + // write waterlevel + this.diagram .select(".chart-tooltip text tspan:last-child") .text(d.waterlevel + " cm"); + + // get text dimensions + const textBBox = this.diagram + .select(".chart-tooltip text") + .node() + .getBBox(); + + this.diagram + .selectAll(".chart-tooltip text tspan") + .attr("x", textBBox.width / 2 + padding) + .attr("y", padding); + + // position and scale tooltip box + + let xMax = this.dimensions.width - textBBox.width; + let tooltipX = Math.min(coords.x - textBBox.width / 2, xMax); + let tooltipY = coords.y - textBBox.height * 2 + padding * 2; + this.diagram + .select(".chart-tooltip") + .style("opacity", 1) + .attr("transform", `translate(${tooltipX}, ${tooltipY})`) + .select("rect") + .attr("width", textBBox.width + padding * 2) + .attr("height", textBBox.height + padding * 2); }); }, isNext(seconds) {