2

I'm creating a diverging scale using D3.js with:

scaleDiverging = d3.scaleDivergingSymlog(d3.interpolateBrBG)
    .domain([-0.1, 0, 0.1])

I can then call scaleDiverging(0.05) and I'll get back a value of 'rgb(87, 175, 165)'. This works great except that I need to fill a canvas image with RGB integers. So I have to parse those strings returned from scaleDiverging:

const parseRgb = color =>
    color.substring(4, color.length - 1).split(', ')
        .map(n => parseInt(n))

Easy solution, but this is the problematic part where my application spends most of its time and is the reason why my interactive graph is not smooth. You move a slider and 2 seconds later the image changes. If I replace parseRgb with a simple function that inaccurately returns back an array of numbers, the graph is smooth! I need the array of RGB values for Canvas' putImageData function:

const context = canvas.node().getContext('2d'),
    imageData = context.getImageData(0, 0, width, height),
    data = imageData.data
for (int i = 0; i < width * height * 4; i += 4) {
    const color = parseRgb(scaleDiverging(calcVal(i)))
    data[i] = color[0]
    data[i + 1] = color[1]
    data[i + 2] = color[2]
    data[i + 3] = 255
}
context.putImageData(imageData, 0, 0)

Can I get the scaleDivergingSymlog functionality from D3.js where I don't have to parse the resulting string? I know I can look up the code and implement it myself, but, in addition to avoiding that work, I'd like to know how to properly use D3.js in the future for interactive graphs.

Someone else on stackoverflow had a similar issue and the only answer was to use d3.color. This is essentially the same as my parseRgb function above, but has even worse performance :(.

at.
  • 50,922
  • 104
  • 292
  • 461
  • 1
    Modern browsers are quite fast and I really doubt that that little `parseRgb` function you created is responsible for such delay (it can be improved, though). If you knew how many functions that D3 scale calls in sequence you'd realise that `parseRgb` is nothing! I believe that, in your test, you used the *inaccurate* function without using the `scaleDiverging` scale. Try it again, but making sure you call `scaleDiverging` just like in the real, slow code (like this: `inaccurate(scaleDiverging(calcVal(i)))`). If you still have the delay, you'll see that the real culprit is `scaleDiverging`. – Gerardo Furtado Feb 20 '20 at 02:50
  • @GerardoFurtado, I should've been clear, I'm just replacing `parseRgb`'s body, so `scaleDiverging` is still being called. Then I get a relatively smooth and fluid interactive graph. Parsing strings and converting to ints can be very time consuming compared to calling many simple functions. Modern JS engines can optimize function calls considerably too. – at. Feb 20 '20 at 05:13

0 Answers0