diff --git a/src/components/charts/DistributionPlot/DistributionPlot.re b/src/components/charts/DistributionPlot/DistributionPlot.re index 7d3b3a1a..7de5506e 100644 --- a/src/components/charts/DistributionPlot/DistributionPlot.re +++ b/src/components/charts/DistributionPlot/DistributionPlot.re @@ -86,6 +86,21 @@ module Styles = { selector(".lollipops-x-axis .domain", [display(`none)]), selector(".lollipops-x-axis .tick line", [display(`none)]), selector(".lollipops-x-axis .tick text", [display(`none)]), + selector( + ".lollipop-tooltip", + [ + position(`absolute), + textAlign(`center), + padding(px(2)), + backgroundColor(hex("bfcad4")), + borderRadius(px(3)), + ], + ), + selector( + ".lollipops-circle-mouseover", + [SVG.fill(hex("ffa500")), SVG.stroke(`hex("fff"))], + ), + selector(".lollipops-line-mouseover", [SVG.stroke(`hex("ffa500"))]), ]); }; @@ -126,4 +141,4 @@ let make = showVerticalLine /> ; -}; \ No newline at end of file +}; diff --git a/src/components/charts/DistributionPlot/distPlotD3.js b/src/components/charts/DistributionPlot/distPlotD3.js index 91250879..b73085f9 100644 --- a/src/components/charts/DistributionPlot/distPlotD3.js +++ b/src/components/charts/DistributionPlot/distPlotD3.js @@ -2,6 +2,9 @@ const _ = require('lodash'); const d3 = require('d3'); const moment = require('moment'); +/** + * @todo: To rename as "DistPlotD3". + */ export class CdfChartD3 { constructor() { @@ -320,16 +323,48 @@ export class CdfChartD3 { .attr('transform', `translate(${this.calc.chartWidth}, 0)`) .call(d3.axisLeft(yScale)); + function showTooltip(d) { + d3.select('#lollipops-line-' + d.id) + .classed('lollipops-line-mouseover', true); + d3.select('#lollipops-circle-' + d.id) + .classed('lollipops-circle-mouseover', true) + .attr('r', 6); + tooltip.transition() + .style("opacity", .9); + tooltip.html(`X: ${d.x}, Y: ${d.y}`) + .style("left", (distributionChart.xScale(d.x) + 60) + "px") + .style("top", yScale(d.y) + "px"); + } + + function hideTooltip(d) { + d3.select('#lollipops-line-' + d.id) + .classed('lollipops-line-mouseover', false); + d3.select('#lollipops-circle-' + d.id) + .classed('lollipops-circle-mouseover', false) + .attr('r', 4); + tooltip.transition() + .style("opacity", 0); + } + // Lines. this.chart.selectAll('lollipops-line') .data(data) .enter() .append('line') .attr('class', 'lollipops-line') + .attr('id', d => 'lollipops-line-' + d.id) .attr('x1', d => distributionChart.xScale(d.x)) .attr('x2', d => distributionChart.xScale(d.x)) .attr('y1', d => yScale(d.y)) - .attr('y2', yScale(0)); + .attr('y2', yScale(0)) + .attr('pointer-events', 'all') + .on("mouseover", showTooltip) + .on("mouseout", hideTooltip); + + // Define the div for the tooltip + const tooltip = this._container.append("div") + .attr("class", "lollipop-tooltip") + .style("opacity", 0); // Circles. this.chart.selectAll('lollipops-circle') @@ -337,9 +372,13 @@ export class CdfChartD3 { .enter() .append('circle') .attr('class', 'lollipops-circle') + .attr('id', d => 'lollipops-circle-' + d.id) .attr('cx', d => distributionChart.xScale(d.x)) .attr('cy', d => yScale(d.y)) - .attr('r', '4'); + .attr('r', '4') + .attr('pointer-events', 'all') + .on("mouseover", showTooltip) + .on("mouseout", hideTooltip); } /** @@ -390,7 +429,7 @@ export class CdfChartD3 { const len = data.xs.length; for (let i = 0; i < len; i++) { - dt.push({ x: data.xs[i], y: data.ys[i] }); + dt.push({ x: data.xs[i], y: data.ys[i], id: i }); } return dt; diff --git a/src/components/charts/DistributionPlot/distPlotReact.js b/src/components/charts/DistributionPlot/distPlotReact.js index 8b5dd6e5..9bd9deee 100644 --- a/src/components/charts/DistributionPlot/distPlotReact.js +++ b/src/components/charts/DistributionPlot/distPlotReact.js @@ -14,6 +14,7 @@ function getRandomInt(min, max) { } /** + * @todo: To rename as "DistPlotReact". * @param props * @returns {*} * @constructor diff --git a/src/styles/index.css b/src/styles/index.css index 7f393742..e4ef2485 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -3,3 +3,14 @@ @tailwind components; @tailwind utilities; + +.lollipops-line-mouseover { + stroke-dasharray: 4; + animation: dash 2s linear infinite; +} + +@keyframes dash { + to { + stroke-dashoffset: 1000; + } +}