From 9c58511099691e1802f17eedc7a632fe9715e0d8 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Mon, 5 Jun 2017 20:46:39 -0700 Subject: [PATCH] [big number] various improvements * dynamic number of X axis ticks based on width to prevent label overlap * corrected overflow on the x axis * improved tooltips (precise arrow and visible data point circle on hover) --- .../assets/javascripts/modules/superset.js | 2 +- superset/assets/package.json | 2 +- superset/assets/stylesheets/d3tip.css | 56 ++++++++++++++++++ superset/assets/visualizations/big_number.css | 10 +--- superset/assets/visualizations/big_number.js | 58 ++++++++++--------- superset/assets/visualizations/heatmap.css | 58 ------------------- superset/assets/visualizations/heatmap.js | 3 +- 7 files changed, 92 insertions(+), 97 deletions(-) create mode 100644 superset/assets/stylesheets/d3tip.css diff --git a/superset/assets/javascripts/modules/superset.js b/superset/assets/javascripts/modules/superset.js index 8f234395a3c2a..48dfc0e963471 100644 --- a/superset/assets/javascripts/modules/superset.js +++ b/superset/assets/javascripts/modules/superset.js @@ -174,7 +174,7 @@ const px = function () { $(selector + ' div.alert').remove(); }, width() { - return token.width(); + return container.width(); }, height() { let others = 0; diff --git a/superset/assets/package.json b/superset/assets/package.json index 8c7da61ed17e2..86f059162ced2 100644 --- a/superset/assets/package.json +++ b/superset/assets/package.json @@ -49,7 +49,7 @@ "d3-cloud": "^1.2.1", "d3-sankey": "^0.4.1", "d3-scale": "^1.0.3", - "d3-tip": "^0.7.1", + "d3-tip": "^0.6.7", "datamaps": "^0.5.8", "datatables-bootstrap3-plugin": "^0.5.0", "datatables.net": "^1.10.13", diff --git a/superset/assets/stylesheets/d3tip.css b/superset/assets/stylesheets/d3tip.css new file mode 100644 index 0000000000000..d22946d1e4c61 --- /dev/null +++ b/superset/assets/stylesheets/d3tip.css @@ -0,0 +1,56 @@ +/* from d3-tip */ +.d3-tip { + line-height: 1; + padding: 12px; + background: rgba(0, 0, 0, 0.8); + color: #fff; + border-radius: 2px; + pointer-events: none; + z-index: 1000; +} + +/* Creates a small triangle extender for the tooltip */ +.d3-tip:after { + box-sizing: border-box; + display: inline; + font-size: 10px; + width: 100%; + line-height: 1; + color: rgba(0, 0, 0, 0.8); + position: absolute; + pointer-events: none; +} + +/* Northward tooltips */ +.d3-tip.n:after { + content: "\25BC"; + margin: -1px 0 0 0; + top: 100%; + left: 0; + text-align: center; +} + +/* Eastward tooltips */ +.d3-tip.e:after { + content: "\25C0"; + margin: -4px 0 0 0; + top: 50%; + left: -8px; +} + +/* Southward tooltips */ +.d3-tip.s:after { + content: "\25B2"; + margin: 0 0 1px 0; + top: -8px; + left: 0; + text-align: center; +} + +/* Westward tooltips */ +.d3-tip.w:after { + content: "\25B6"; + margin: -4px 0 0 -1px; + top: 50%; + left: 100%; +} diff --git a/superset/assets/visualizations/big_number.css b/superset/assets/visualizations/big_number.css index 3e4734ece04a2..8fd5345ee793e 100644 --- a/superset/assets/visualizations/big_number.css +++ b/superset/assets/visualizations/big_number.css @@ -28,12 +28,4 @@ stroke: black; stroke-width: 1; } -.line-tooltip { - position: absolute; - text-align: left; - padding: 10px; - background: #ffffff; - border: 1px solid #ccc; - border-radius: 2px; - pointer-events: none; - } + diff --git a/superset/assets/visualizations/big_number.js b/superset/assets/visualizations/big_number.js index fbb6ab77cc7aa..51b08bffa70de 100644 --- a/superset/assets/visualizations/big_number.js +++ b/superset/assets/visualizations/big_number.js @@ -1,7 +1,9 @@ import d3 from 'd3'; +import d3tip from 'd3-tip'; import { formatDate } from '../javascripts/modules/dates'; -require('./big_number.css'); +import './big_number.css'; +import '../stylesheets/d3tip.css'; function bigNumberVis(slice, payload) { const div = d3.select(slice.selector); @@ -39,9 +41,10 @@ function bigNumberVis(slice, payload) { const dateExt = d3.extent(data, d => d[0]); const valueExt = d3.extent(data, d => d[1]); - const margin = 20; - const scaleX = d3.time.scale.utc().domain(dateExt).range([margin, width - margin]); - const scaleY = d3.scale.linear().domain(valueExt).range([height - (margin), margin]); + const vMargin = 20; + const hMargin = 10; + const scaleX = d3.time.scale.utc().domain(dateExt).range([hMargin, width - hMargin]); + const scaleY = d3.scale.linear().domain(valueExt).range([height - (vMargin), vMargin]); const colorRange = [d3.hsl(0, 1, 0.3), d3.hsl(120, 1, 0.3)]; const scaleColor = d3.scale .linear().domain([-1, 1]) @@ -126,17 +129,18 @@ function bigNumberVis(slice, payload) { const xAxis = d3.svg.axis() .scale(scaleX) .orient('bottom') - .ticks(4) + .ticks(Math.round(2 + (width / 150))) .tickFormat(formatDate); g.call(xAxis); - g.attr('transform', 'translate(0,' + (height - margin) + ')'); + g.attr('transform', 'translate(0,' + (height - vMargin) + ')'); - g = gAxis.append('g').attr('transform', 'translate(' + (width - margin) + ',0)'); + g = gAxis.append('g').attr('transform', 'translate(' + (width - hMargin) + ',0)'); const yAxis = d3.svg.axis() .scale(scaleY) .orient('left') .tickFormat(d3.format(fd.y_axis_format)) .tickValues(valueExt); + g.call(yAxis); g.selectAll('text') .style('text-anchor', 'end') @@ -146,44 +150,44 @@ function bigNumberVis(slice, payload) { g.selectAll('text') .style('font-size', '10px'); - // Define the div for the tooltip - const tooltipEl = - d3.select('body') - .append('div') - .attr('class', 'line-tooltip') - .attr('width', 200) - .attr('height', 200) - .style('opacity', 0); - const renderTooltip = (d) => { const date = formatDate(d[0]); const value = f(d[1]); return `
- ${date} - ${value} + ${date}: + ${value}
`; }; + const tip = d3tip() + .attr('class', 'd3-tip') + .direction('n') + .offset([-5, 0]) + .html(renderTooltip); + svg.call(tip); + // Add the scatterplot and trigger the mouse events for the tooltips svg .selectAll('dot') .data(data) .enter() .append('circle') - .attr('r', 10) + .attr('r', 3) + .attr('stroke-width', 15) + .attr('stroke', 'transparent') + .attr('stroke-location', 'outside') .attr('cx', d => scaleX(d[0])) .attr('cy', d => scaleY(d[1])) - .attr('fill-opacity', '0') - .on('mouseover', (d) => { - tooltipEl.html(renderTooltip(d)) - .style('left', (d3.event.pageX) + 'px') - .style('top', (d3.event.pageY) + 'px'); - tooltipEl.transition().duration(200).style('opacity', 0.9); + .attr('fill-opacity', 0) + .on('mouseover', function (d) { + d3.select(this).attr('fill-opacity', 1); + tip.show(d); }) - .on('mouseout', () => { - tooltipEl.transition().duration(500).style('opacity', 0); + .on('mouseout', function (d) { + d3.select(this).attr('fill-opacity', 0); + tip.hide(d); }); div.on('mouseover', function () { diff --git a/superset/assets/visualizations/heatmap.css b/superset/assets/visualizations/heatmap.css index 38d6d6cb2abfe..bfcc327e652f0 100644 --- a/superset/assets/visualizations/heatmap.css +++ b/superset/assets/visualizations/heatmap.css @@ -28,61 +28,3 @@ image-rendering: pixelated; /* Awesome future-browsers */ -ms-interpolation-mode: nearest-neighbor; /* IE */ } - -/* from d3-tip */ -.d3-tip { - line-height: 1; - font-weight: bold; - padding: 12px; - background: rgba(0, 0, 0, 0.8); - color: #fff; - border-radius: 2px; - pointer-events: none; - z-index: 1000; -} - -/* Creates a small triangle extender for the tooltip */ -.d3-tip:after { - box-sizing: border-box; - display: inline; - font-size: 10px; - width: 100%; - line-height: 1; - color: rgba(0, 0, 0, 0.8); - position: absolute; - pointer-events: none; -} - -/* Northward tooltips */ -.d3-tip.n:after { - content: "\25BC"; - margin: -1px 0 0 0; - top: 100%; - left: 0; - text-align: center; -} - -/* Eastward tooltips */ -.d3-tip.e:after { - content: "\25C0"; - margin: -4px 0 0 0; - top: 50%; - left: -8px; -} - -/* Southward tooltips */ -.d3-tip.s:after { - content: "\25B2"; - margin: 0 0 1px 0; - top: -8px; - left: 0; - text-align: center; -} - -/* Westward tooltips */ -.d3-tip.w:after { - content: "\25B6"; - margin: -4px 0 0 -1px; - top: 50%; - left: 100%; -} diff --git a/superset/assets/visualizations/heatmap.js b/superset/assets/visualizations/heatmap.js index 843ba70faec1d..07322cf39ca1a 100644 --- a/superset/assets/visualizations/heatmap.js +++ b/superset/assets/visualizations/heatmap.js @@ -1,10 +1,11 @@ import d3 from 'd3'; import { colorScalerFactory } from '../javascripts/modules/colors'; +import '../stylesheets/d3tip.css'; +import './heatmap.css'; const $ = require('jquery'); d3.tip = require('d3-tip'); -require('./heatmap.css'); // Inspired from http://bl.ocks.org/mbostock/3074470 // https://jsfiddle.net/cyril123/h0reyumq/