mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
[big number] various improvements (#2912)
* [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) * Fixing tooltips in heatmap viz
This commit is contained in:
parent
0e6f754af9
commit
24a2f5b8f0
@ -177,7 +177,7 @@ const px = function () {
|
|||||||
$(selector + ' div.alert').remove();
|
$(selector + ' div.alert').remove();
|
||||||
},
|
},
|
||||||
width() {
|
width() {
|
||||||
return token.width();
|
return container.width();
|
||||||
},
|
},
|
||||||
height() {
|
height() {
|
||||||
let others = 0;
|
let others = 0;
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
"d3-cloud": "^1.2.1",
|
"d3-cloud": "^1.2.1",
|
||||||
"d3-sankey": "^0.4.1",
|
"d3-sankey": "^0.4.1",
|
||||||
"d3-scale": "^1.0.3",
|
"d3-scale": "^1.0.3",
|
||||||
"d3-tip": "^0.7.1",
|
"d3-tip": "^0.6.7",
|
||||||
"datamaps": "^0.5.8",
|
"datamaps": "^0.5.8",
|
||||||
"datatables-bootstrap3-plugin": "^0.5.0",
|
"datatables-bootstrap3-plugin": "^0.5.0",
|
||||||
"datatables.net": "^1.10.13",
|
"datatables.net": "^1.10.13",
|
||||||
|
56
superset/assets/stylesheets/d3tip.css
Normal file
56
superset/assets/stylesheets/d3tip.css
Normal file
@ -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%;
|
||||||
|
}
|
@ -28,12 +28,4 @@
|
|||||||
stroke: black;
|
stroke: black;
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
}
|
}
|
||||||
.line-tooltip {
|
|
||||||
position: absolute;
|
|
||||||
text-align: left;
|
|
||||||
padding: 10px;
|
|
||||||
background: #ffffff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 2px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
|
import d3tip from 'd3-tip';
|
||||||
import { formatDate } from '../javascripts/modules/dates';
|
import { formatDate } from '../javascripts/modules/dates';
|
||||||
|
|
||||||
require('./big_number.css');
|
import './big_number.css';
|
||||||
|
import '../stylesheets/d3tip.css';
|
||||||
|
|
||||||
function bigNumberVis(slice, payload) {
|
function bigNumberVis(slice, payload) {
|
||||||
const div = d3.select(slice.selector);
|
const div = d3.select(slice.selector);
|
||||||
@ -39,9 +41,10 @@ function bigNumberVis(slice, payload) {
|
|||||||
const dateExt = d3.extent(data, d => d[0]);
|
const dateExt = d3.extent(data, d => d[0]);
|
||||||
const valueExt = d3.extent(data, d => d[1]);
|
const valueExt = d3.extent(data, d => d[1]);
|
||||||
|
|
||||||
const margin = 20;
|
const vMargin = 20;
|
||||||
const scaleX = d3.time.scale.utc().domain(dateExt).range([margin, width - margin]);
|
const hMargin = 10;
|
||||||
const scaleY = d3.scale.linear().domain(valueExt).range([height - (margin), margin]);
|
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 colorRange = [d3.hsl(0, 1, 0.3), d3.hsl(120, 1, 0.3)];
|
||||||
const scaleColor = d3.scale
|
const scaleColor = d3.scale
|
||||||
.linear().domain([-1, 1])
|
.linear().domain([-1, 1])
|
||||||
@ -126,17 +129,18 @@ function bigNumberVis(slice, payload) {
|
|||||||
const xAxis = d3.svg.axis()
|
const xAxis = d3.svg.axis()
|
||||||
.scale(scaleX)
|
.scale(scaleX)
|
||||||
.orient('bottom')
|
.orient('bottom')
|
||||||
.ticks(4)
|
.ticks(Math.round(2 + (width / 150)))
|
||||||
.tickFormat(formatDate);
|
.tickFormat(formatDate);
|
||||||
g.call(xAxis);
|
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()
|
const yAxis = d3.svg.axis()
|
||||||
.scale(scaleY)
|
.scale(scaleY)
|
||||||
.orient('left')
|
.orient('left')
|
||||||
.tickFormat(d3.format(fd.y_axis_format))
|
.tickFormat(d3.format(fd.y_axis_format))
|
||||||
.tickValues(valueExt);
|
.tickValues(valueExt);
|
||||||
|
|
||||||
g.call(yAxis);
|
g.call(yAxis);
|
||||||
g.selectAll('text')
|
g.selectAll('text')
|
||||||
.style('text-anchor', 'end')
|
.style('text-anchor', 'end')
|
||||||
@ -146,44 +150,44 @@ function bigNumberVis(slice, payload) {
|
|||||||
g.selectAll('text')
|
g.selectAll('text')
|
||||||
.style('font-size', '10px');
|
.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 renderTooltip = (d) => {
|
||||||
const date = formatDate(d[0]);
|
const date = formatDate(d[0]);
|
||||||
const value = f(d[1]);
|
const value = f(d[1]);
|
||||||
return `
|
return `
|
||||||
<div>
|
<div>
|
||||||
<span style="float: left; margin-right: 20px;"><strong>${date}</strong></span>
|
<span style="margin-right: 10px;">${date}: </span>
|
||||||
<span style="float: right">${value}</span>
|
<strong>${value}</strong>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
// Add the scatterplot and trigger the mouse events for the tooltips
|
||||||
svg
|
svg
|
||||||
.selectAll('dot')
|
.selectAll('dot')
|
||||||
.data(data)
|
.data(data)
|
||||||
.enter()
|
.enter()
|
||||||
.append('circle')
|
.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('cx', d => scaleX(d[0]))
|
||||||
.attr('cy', d => scaleY(d[1]))
|
.attr('cy', d => scaleY(d[1]))
|
||||||
.attr('fill-opacity', '0')
|
.attr('fill-opacity', 0)
|
||||||
.on('mouseover', (d) => {
|
.on('mouseover', function (d) {
|
||||||
tooltipEl.html(renderTooltip(d))
|
d3.select(this).attr('fill-opacity', 1);
|
||||||
.style('left', (d3.event.pageX) + 'px')
|
tip.show(d);
|
||||||
.style('top', (d3.event.pageY) + 'px');
|
|
||||||
tooltipEl.transition().duration(200).style('opacity', 0.9);
|
|
||||||
})
|
})
|
||||||
.on('mouseout', () => {
|
.on('mouseout', function (d) {
|
||||||
tooltipEl.transition().duration(500).style('opacity', 0);
|
d3.select(this).attr('fill-opacity', 0);
|
||||||
|
tip.hide(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
div.on('mouseover', function () {
|
div.on('mouseover', function () {
|
||||||
|
@ -28,61 +28,3 @@
|
|||||||
image-rendering: pixelated; /* Awesome future-browsers */
|
image-rendering: pixelated; /* Awesome future-browsers */
|
||||||
-ms-interpolation-mode: nearest-neighbor; /* IE */
|
-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%;
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import d3tip from 'd3-tip';
|
||||||
|
|
||||||
import { colorScalerFactory } from '../javascripts/modules/colors';
|
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
|
// Inspired from http://bl.ocks.org/mbostock/3074470
|
||||||
// https://jsfiddle.net/cyril123/h0reyumq/
|
// https://jsfiddle.net/cyril123/h0reyumq/
|
||||||
@ -105,15 +106,7 @@ function heatmapVis(slice, payload) {
|
|||||||
.style('top', headerHeight + 'px')
|
.style('top', headerHeight + 'px')
|
||||||
.style('position', 'absolute');
|
.style('position', 'absolute');
|
||||||
|
|
||||||
const rect = svg.append('g')
|
const tip = d3tip()
|
||||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
|
||||||
.append('rect')
|
|
||||||
.style('fill-opacity', 0)
|
|
||||||
.attr('stroke', 'black')
|
|
||||||
.attr('width', hmWidth)
|
|
||||||
.attr('height', hmHeight);
|
|
||||||
|
|
||||||
const tip = d3.tip()
|
|
||||||
.attr('class', 'd3-tip')
|
.attr('class', 'd3-tip')
|
||||||
.offset(function () {
|
.offset(function () {
|
||||||
const k = d3.mouse(this);
|
const k = d3.mouse(this);
|
||||||
@ -140,6 +133,17 @@ function heatmapVis(slice, payload) {
|
|||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const rect = svg.append('g')
|
||||||
|
.attr('transform', `translate(${margin.left}, ${margin.top})`)
|
||||||
|
.append('rect')
|
||||||
|
.attr('pointer-events', 'all')
|
||||||
|
.on('mousemove', tip.show)
|
||||||
|
.on('mouseout', tip.hide)
|
||||||
|
.style('fill-opacity', 0)
|
||||||
|
.attr('stroke', 'black')
|
||||||
|
.attr('width', hmWidth)
|
||||||
|
.attr('height', hmHeight);
|
||||||
|
|
||||||
rect.call(tip);
|
rect.call(tip);
|
||||||
|
|
||||||
const xAxis = d3.svg.axis()
|
const xAxis = d3.svg.axis()
|
||||||
@ -171,8 +175,6 @@ function heatmapVis(slice, payload) {
|
|||||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||||
.call(yAxis);
|
.call(yAxis);
|
||||||
|
|
||||||
rect.on('mousemove', tip.show);
|
|
||||||
rect.on('mouseout', tip.hide);
|
|
||||||
|
|
||||||
const context = canvas.node().getContext('2d');
|
const context = canvas.node().getContext('2d');
|
||||||
context.imageSmoothingEnabled = false;
|
context.imageSmoothingEnabled = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user