The D3 gradient example does work in Firefox and IE (obviously), but I've created an AngularJS directive that can update the stop values as well as linearGradient attributes dynamically after inserting the gradient into the DOM which it doesn't seem to like.
The code (which uses AngularJS) looks like this:
gradient = svg.insert("defs", 'g') .append("linearGradient") .attr("id", $attrs.id) ['x1', 'x2', 'y1', 'y2'].forEach (attr) -> $attrs.$observe attr, (val) -> gradient.attr(attr, val) $attrs.$observe 'transition', (val) -> transition = val if val? $scope.$watch $attrs.stops, (stops) -> return unless stops? stops = gradient.selectAll('stop').data(stops) stops.enter().append('stop') stops.attr('offset', (d) -> d.offset) .attr('stop-color', (d) -> d.color) .attr('stop-opacity', (d) -> if d.opacity? then d.opacity else 1) stops.exit().remove()
Essentially Angular will set x1, x2, y1 and y2 dynamically if the attributes change (this allows for variable interpolation on those attributes. And we bind the stops to a Javascript array of stop values and if they change Angulary will rerun the function attached to $watch. It uses a pretty standard D3 enter/exit setup as far as I can tell.
It works perfecting in Chrome and Safari but Firefox displays nothing. If I copy the resulting SVG to a JSFiddle and render it statically however it does work. I'm guessing a Firefox bug but I though it was worth it to get a second opinion from the experts.