diff --git a/draftlogs/8119_fix.md b/draftlogs/8119_fix.md new file mode 100644 index 00000000000..7eb70155897 --- /dev/null +++ b/draftlogs/8119_fix.md @@ -0,0 +1 @@ + - Convert modern CSS color formats to rgba for scattergl based traces [[#8119](https://github.com/plotly/plotly.js/pull/8119)] diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js index 58afa2b70ae..7e5f0c0f464 100644 --- a/src/traces/scattergl/convert.js +++ b/src/traces/scattergl/convert.js @@ -2,7 +2,7 @@ var isNumeric = require('fast-isnumeric'); const svgSdf = require('svg-path-sdf').default; -const { normalize: rgba } = require('../../components/color'); +const { normalize: rgba, rgbaString } = require('../../components/color'); var Registry = require('../../registry'); var Lib = require('../../lib'); @@ -75,7 +75,7 @@ function convertStyle(gd, trace) { opts.line = { overlay: true, thickness: trace.line.width * plotGlPixelRatio, - color: trace.line.color, + color: rgbaString(trace.line.color), opacity: trace.opacity }; @@ -97,7 +97,7 @@ function convertStyle(gd, trace) { if (!!trace.fill && trace.fill !== 'none') { opts.fill = { closed: true, - fill: trace.fillcolor, + fill: rgbaString(trace.fillcolor), thickness: 0 }; } @@ -199,10 +199,10 @@ function convertTextStyle(gd, trace) { if (isArrayOrTypedArray(tfc)) { optsOut.color = new Array(count); for (i = 0; i < count; i++) { - optsOut.color[i] = tfc[i]; + optsOut.color[i] = rgbaString(tfc[i]); } } else { - optsOut.color = tfc; + optsOut.color = rgbaString(tfc); } if ( @@ -411,7 +411,7 @@ function convertMarkerSelection(gd, trace, target) { optsOut = convertMarkerStyle(gd, Lib.extendFlat({}, optsIn, target.marker)); } else if (target.marker) { if (target.marker.size) optsOut.size = target.marker.size; - if (target.marker.color) optsOut.colors = target.marker.color; + if (target.marker.color) optsOut.colors = rgbaString(target.marker.color); if (target.marker.opacity !== undefined) optsOut.opacity = target.marker.opacity; } @@ -444,11 +444,11 @@ function convertErrorBarStyle(trace, target, plotGlPixelRatio) { var optsOut = { capSize: target.width * 2 * plotGlPixelRatio, lineWidth: target.thickness * plotGlPixelRatio, - color: target.color + color: rgbaString(target.color) }; if (target.copy_ystyle) { - optsOut = trace.error_y; + optsOut = { ...trace.error_y, color: rgbaString(trace.error_y.color) }; } return optsOut; diff --git a/src/traces/scattergl/plot.js b/src/traces/scattergl/plot.js index 19d944ab376..5ba6087cea3 100644 --- a/src/traces/scattergl/plot.js +++ b/src/traces/scattergl/plot.js @@ -6,6 +6,7 @@ var createError = require('regl-error2d'); var Text = require('gl-text'); var Lib = require('../../lib'); +const { rgbaString } = require('../../components/color'); var selectMode = require('../../components/dragelement/helpers').selectMode; var prepareRegl = require('../../lib/prepare_regl'); @@ -226,7 +227,7 @@ var exports = module.exports = function plot(gd, subplot, cdata) { if(isNaN(xx) || isNaN(yy)) continue; pos.push(xx, yy); } - fillOptions.fill = nextTrace.fillcolor; + fillOptions.fill = rgbaString(nextTrace.fillcolor); } } } diff --git a/src/traces/splom/base_plot.js b/src/traces/splom/base_plot.js index a3486e64514..b9f7ed67085 100644 --- a/src/traces/splom/base_plot.js +++ b/src/traces/splom/base_plot.js @@ -3,6 +3,7 @@ var createLine = require('regl-line2d'); var Registry = require('../../registry'); +const { rgbaString } = require('../../components/color'); var prepareRegl = require('../../lib/prepare_regl'); var getModuleCalcData = require('../../plots/get_data').getModuleCalcData; var Cartesian = require('../../plots/cartesian'); @@ -116,7 +117,7 @@ function makeGridData(gd) { data: [x0, x1, y0, y1], join: 'rect', thickness: lwidth * plotGlPixelRatio, - color: lcolor, + color: rgbaString(lcolor), viewport: fullView, range: fullView, overlay: false diff --git a/test/jasmine/tests/scattergl_test.js b/test/jasmine/tests/scattergl_test.js index 8e3595ffd15..8e8f276effc 100644 --- a/test/jasmine/tests/scattergl_test.js +++ b/test/jasmine/tests/scattergl_test.js @@ -368,7 +368,7 @@ describe('end-to-end scattergl tests', function() { expect(scene.markerOptions.length).toBe(2); expect(scene.markerOptions[1].color).toEqual(new Uint8Array([255, 0, 0, 255])); expect(scene.textOptions.length).toBe(2); - expect(scene.textOptions[1].color).toEqual('#444'); + expect(scene.textOptions[1].color).toEqual('rgb(68, 68, 68)'); expect(scene.scatter2d.draw).toHaveBeenCalled(); return Plotly.restyle(gd, 'selectedpoints', null); @@ -427,6 +427,46 @@ describe('end-to-end scattergl tests', function() { .then(done, done.fail); }); + it('@gl should convert modern CSS colors for lines, fill, error bars and text', (done) => { + const orange = 'oklch(0.7 0.15 30)'; + const brown = 'lab(50% 40 59)'; + const orangeRgb = 'rgb(237, 118, 101)'; + const brownRgb = 'rgb(191, 87, 2)'; + + Plotly.newPlot(gd, [ + { + type: 'scattergl', + mode: 'lines+text', + x: [1, 2], + y: [1, 2], + text: ['a', 'b'], + line: { color: orange }, + fill: 'tozeroy', + fillcolor: brown, + textfont: { color: [orange, brown] }, + error_x: { array: [0.1, 0.1] }, + error_y: { array: [0.1, 0.1], color: orange } + } + ]) + .then(() => { + const scene = gd._fullLayout._plots.xy._scene; + + expect(scene.lineOptions[0].color).toBe(orangeRgb, 'line.color'); + expect(scene.fillOptions[0].fill).toBe(brownRgb, 'fillcolor'); + expect(scene.errorXOptions[0].color).toBe(orangeRgb, 'error_x.color with copy_ystyle'); + expect(scene.errorYOptions[0].color).toBe(orangeRgb, 'error_y.color'); + expect(scene.textOptions[0].color).toEqual([orangeRgb, brownRgb], 'textfont.color'); + + return Plotly.restyle(gd, 'error_x.color', brown); + }) + .then(() => { + const scene = gd._fullLayout._plots.xy._scene; + + expect(scene.errorXOptions[0].color).toBe(brownRgb, 'error_x.color'); + }) + .then(done, done.fail); + }); + it('@gl should be able to draw more than 4096 colors', function(done) { var x = []; var color = []; diff --git a/test/jasmine/tests/splom_test.js b/test/jasmine/tests/splom_test.js index 71b4d7a7559..d2d1928d21a 100644 --- a/test/jasmine/tests/splom_test.js +++ b/test/jasmine/tests/splom_test.js @@ -730,6 +730,24 @@ describe('Test splom interactions:', function() { .then(done, done.fail); }); + it('@gl when hasOnlyLargeSploms, should convert modern CSS grid colors for regl-line2d', (done) => { + const fig = Lib.extendDeep({}, require('../../image/mocks/splom_large.json')); + + _newPlot(gd, fig) + .then(() => { + spyOn(gd._fullLayout._splomGrid, 'update').and.callThrough(); + return Plotly.relayout(gd, 'xaxis.gridcolor', 'oklch(0.7 0.15 30)'); + }) + .then(() => { + const gridData = gd._fullLayout._splomGrid.update.calls.mostRecent().args[0]; + const colors = gridData.map((d) => d.color); + + expect(colors).toContain('rgb(237, 118, 101)'); + expect(colors).not.toContain('oklch(0.7 0.15 30)'); + }) + .then(done, done.fail); + }); + it('@gl should update properly in-and-out of hasOnlyLargeSploms regime', function(done) { var figLarge = Lib.extendDeep({}, require('../../image/mocks/splom_large.json')); var dimsLarge = figLarge.data[0].dimensions;