The .get() function doesn't seem to be working. It would also be nice to be able to grab the color from a specific position of a gradient.
Code? Error messages? Anything?
@medeor Can you explain what you're trying to do in more detail or provide some code that illustrate your issue?
If not, then I'm gonna close this in a few days.
First I created a gradient as a legend for my scatter plot using this code.
var gradient = legend.gradient('linear', function(stop) {
stop.at(0, '#799abc')
stop.at(0.5, '#ccc')
stop.at(1, '#e88081')
});
And then I wanted to paint the bubbles in the scatter plot normalizing their values and comparing them to the gradient scale. So for instance, if the value is 0 then the bubble should be '#799abc'. I thought the .get() function would be appropriate for this but then I found out that it's not used for such practical purposes. Then I found a workaround for that.
function GradientReader(colorStops) {
var canvas = document.createElement('canvas'), // create canvas element
ctx = canvas.getContext('2d'), // get context
gr = ctx.createLinearGradient(0, 0, 101, 0), // create a gradient
i = 0, cs;
canvas.width = 101; // 101 pixels incl.
canvas.height = 1; // as the gradient
for(; cs = colorStops[i++];) // add color stops
gr.addColorStop(cs.stop, cs.color);
ctx.fillStyle = gr; // set as fill style
ctx.fillRect(0, 0, 101, 1); // draw a single line
// method to get color of gradient at % position [0, 100]
this.getColor = function(pst) {
return ctx.getImageData(pst|0, 0, 1, 1).data;
};
}
var gr = new GradientReader([{stop: 0.0, color: '#799abc'},
{stop: 0.5, color: '#ccc'},
{stop: 1.0, color: '#e88081'}]);
var col = gr.getColor(100/(colorData[colorData.length-1]/allData[j][dataForCircleColor]));
The workaround worked but I still think it would be awesome to be able to pick a specific color from a gradient giving a value from 0 to 1.
You can achieve this by using the SVG.Color class:
var blend = new SVG.Color('#799abc').morph('#ccc')
blend.at(0.5)
http://svgjs.com/classes/color/#at
You'll have to find the two stops in a gradient at both sides of a given offset. Something like:
var first, offset = 0.4
gradient.each(function() {
if (this.attr('offset') < offset)
first = this
})
Then you can get the colors and make the blend:
var blend = new SVG.Color(first.attr('stop-color')).morph(first.next().attr('stop-color'))
Finally, you'll have to calculate the value for blend.at() in relation tot the total offset of the gradient (0 to 1).
And to make things really convenient, you can make a small plugin by extending SVG.Gradient:
SVG.extend(SVG.Gradient, {
// Get color at given offset
colorAt: function(offset) {
var first, last, blend
// find stops
this.each(function() {
if (this.attr('offset') < offset)
first = this
})
last = first.next()
// create morph
blend = new SVG.Color(first.attr('stop-color'))
blend.morph(last.attr('stop-color'))
// .. calculate relative offset
return blend.at( /* calculated offset */ )
}
})
So you can do:
var color = gradient.colorAt(0.4)
Actually that makes an awesome feature or at least a nice plugin :)
That's what I was looking for and and glad to know that it's supported. Thanks!
Great. Please consider creating a plugin or at least posting the final code so other people can enjoy this goodness :)
I guess the formular would be
relativeOffset = (offset - first.attr('offset')) / (second.attr('offset') - first.attr('offset'))
Thanks @Fuzzyma. So that would result in:
SVG.extend(SVG.Gradient, {
// Get color at given offset
colorAt: function(offset) {
var first, last
// find stops
this.each(function() {
if (this.attr('offset') <= offset) first = this
})
last = first.next()
// if first is the last stop, return color
if ( ! last ) return first.attr('stop-color')
var blend, relative, fo, lo
// create morph
blend = new SVG.Color(first.attr('stop-color'))
blend.morph(last.attr('stop-color'))
// calculate relative offset
fo = first.attr('offset')
lo = last.attr('offset')
relative = (offset - fo) / (lo - fo)
return blend.at( relative )
}
})
The plugin is now available at bower and npm.
Just run bower/npm install svg.colorat.js