Skip to content

Commit

Permalink
Merge pull request #2910 from plotly/gradient-colorbar
Browse files Browse the repository at this point in the history
Use new multistop gradients for continuous colorbars
  • Loading branch information
alexcjohnson authored Aug 16, 2018
2 parents 7bba266 + c17b9bc commit fe709d0
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 110 deletions.
16 changes: 2 additions & 14 deletions src/components/colorbar/connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

'use strict';

var Colorscale = require('../colorscale');
var drawColorbar = require('./draw');

/**
Expand Down Expand Up @@ -48,20 +47,9 @@ module.exports = function connectColorbar(gd, cd, moduleOpts) {
gd._fullLayout._infolayer.selectAll('.' + cbId).remove();
if(!container || !container.showscale) return;

var zmin = container[moduleOpts.min];
var zmax = container[moduleOpts.max];

var cb = cd[0].t.cb = drawColorbar(gd, cbId);
var sclFunc = Colorscale.makeColorScaleFunc(
Colorscale.extractScale(
container.colorscale,
zmin,
zmax
),
{ noNumericCheck: true }
);

cb.fillcolor(sclFunc)
.filllevels({start: zmin, end: zmax, size: (zmax - zmin) / 254})
cb.fillgradient(container.colorscale)
.zrange([container[moduleOpts.min], container[moduleOpts.max]])
.options(container.colorbar)();
};
55 changes: 36 additions & 19 deletions src/components/colorbar/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ module.exports = function draw(gd, id) {
// opts: options object, containing everything from attributes
// plus a few others that are the equivalent of the colorbar "data"
var opts = {};
Object.keys(attributes).forEach(function(k) {
for(var k in attributes) {
opts[k] = null;
});
}
// fillcolor can be a d3 scale, domain is z values, range is colors
// or leave it out for no fill,
// or set to a string constant for single-color fill
Expand All @@ -57,17 +57,23 @@ module.exports = function draw(gd, id) {
// contour map) if this is omitted, fillcolors will be
// evaluated halfway between levels
opts.filllevels = null;
// for continuous colorscales: fill with a gradient instead of explicit levels
// value should be the colorscale [[0, c0], [v1, c1], ..., [1, cEnd]]
opts.fillgradient = null;
// when using a gradient, we need the data range specified separately
opts.zrange = null;

function component() {
var fullLayout = gd._fullLayout,
gs = fullLayout._size;
if((typeof opts.fillcolor !== 'function') &&
(typeof opts.line.color !== 'function')) {
(typeof opts.line.color !== 'function') &&
!opts.fillgradient) {
fullLayout._infolayer.selectAll('g.' + id).remove();
return;
}
var zrange = d3.extent(((typeof opts.fillcolor === 'function') ?
opts.fillcolor : opts.line.color).domain());
var zrange = opts.zrange || (d3.extent(((typeof opts.fillcolor === 'function') ?
opts.fillcolor : opts.line.color).domain()));
var linelevels = [];
var filllevels = [];
var linecolormap = typeof opts.line.color === 'function' ?
Expand All @@ -87,7 +93,10 @@ module.exports = function draw(gd, id) {
if(l > zr0 && l < zr1) linelevels.push(l);
}

if(typeof opts.fillcolor === 'function') {
if(opts.fillgradient) {
filllevels = [0];
}
else if(typeof opts.fillcolor === 'function') {
if(opts.filllevels) {
l0 = opts.filllevels.end + opts.filllevels.size / 100;
ls = opts.filllevels.size;
Expand Down Expand Up @@ -358,6 +367,12 @@ module.exports = function draw(gd, id) {
.classed(cn.cbfill, true)
.style('stroke', 'none');
fills.exit().remove();

var zBounds = zrange
.map(cbAxisOut.c2p)
.map(Math.round)
.sort(function(a, b) { return a - b; });

fills.each(function(d, i) {
var z = [
(i === 0) ? zrange[0] :
Expand All @@ -370,25 +385,27 @@ module.exports = function draw(gd, id) {

// offset the side adjoining the next rectangle so they
// overlap, to prevent antialiasing gaps
if(i !== filllevels.length - 1) {
z[1] += (z[1] > z[0]) ? 1 : -1;
}


// Tinycolor can't handle exponents and
// at this scale, removing it makes no difference.
var colorString = fillcolormap(d).replace('e-', ''),
opaqueColor = tinycolor(colorString).toHexString();
z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);

// Colorbar cannot currently support opacities so we
// use an opaque fill even when alpha channels present
d3.select(this).attr({
var fillEl = d3.select(this).attr({
x: xLeft,
width: Math.max(thickPx, 2),
y: d3.min(z),
height: Math.max(d3.max(z) - d3.min(z), 2),
fill: opaqueColor
});

if(opts.fillgradient) {
Drawing.gradient(fillEl, gd, id, 'vertical',
opts.fillgradient, 'fill');
}
else {
// Tinycolor can't handle exponents and
// at this scale, removing it makes no difference.
var colorString = fillcolormap(d).replace('e-', '');
fillEl.attr('fill', tinycolor(colorString).toHexString());
}
});

var lines = container.select('.cblines')
Expand Down Expand Up @@ -650,13 +667,13 @@ module.exports = function draw(gd, id) {

// or use .options to set multiple options at once via a dictionary
component.options = function(o) {
Object.keys(o).forEach(function(name) {
for(var name in o) {
// in case something random comes through
// that's not an option, ignore it
if(typeof component[name] === 'function') {
component[name](o[name]);
}
});
}
return component;
};

Expand Down
27 changes: 10 additions & 17 deletions src/traces/contour/colorbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,25 @@ var endPlus = require('./end_plus');


module.exports = function colorbar(gd, cd) {
var trace = cd[0].trace,
cbId = 'cb' + trace.uid;
var trace = cd[0].trace;
var cbId = 'cb' + trace.uid;

gd._fullLayout._infolayer.selectAll('.' + cbId).remove();

if(!trace.showscale) return;

var cb = drawColorbar(gd, cbId);
cd[0].t.cb = cb;
var cb = cd[0].t.cb = drawColorbar(gd, cbId);

var contours = trace.contours,
line = trace.line,
cs = contours.size || 1,
coloring = contours.coloring;
var contours = trace.contours;
var line = trace.line;
var cs = contours.size || 1;
var coloring = contours.coloring;

var colorMap = makeColorMap(trace, {isColorbar: true});

if(coloring === 'heatmap') {
cb.filllevels({
start: trace.zmin,
end: trace.zmax,
size: (trace.zmax - trace.zmin) / 254
});
}

cb.fillcolor((coloring === 'fill' || coloring === 'heatmap') ? colorMap : '')
cb.fillgradient(coloring === 'heatmap' ? trace.colorscale : '')
.zrange(coloring === 'heatmap' ? [trace.zmin, trace.zmax] : '')
.fillcolor((coloring === 'fill') ? colorMap : '')
.line({
color: coloring === 'lines' ? colorMap : line.color,
width: contours.showlines !== false ? line.width : 0,
Expand Down
Binary file modified test/image/baselines/16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/colorbar_enumerated_ticks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/colorscale_constraint.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/geo_multiple-usa-choropleths.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/gl2d_parcoords_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/gl2d_parcoords_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/hist2d_summed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/image/baselines/zsmooth_methods.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit fe709d0

Please sign in to comment.