d3 change attribute of all elements - javascript

I want to change the color of all my svg elements with class "tmp-click" to yellow
var yellow = d3.select('svg')
.selectAll('.tmp-click')
.attr("fill","yellow);
When executing the code only one of the elements is changed, what did I miss?

Do it this way
var yellow = d3.selectAll('.tmp-click')
.style("fill","yellow");

Related

select colour from one object and then click on another object and change its background colour

Im making a game but I'm currently stuck on a problem that I've been trying to solve for a while now. I need to select a circle which is blue and then click on a clear circle and that clear circle needs to then change its attribute background to the blue but only when i click on the clear circle.
supposing the first circle has id "circle-1" and the second "circle-2", and supposing you specify the color of your elements using the css property "background-color", you can do the following:
document.querySelector('#circle-2').style.backgroundColor = window.getComputedStyle(document.querySelector('#circle-1')).getPropertyValue('background-color');
Of course you have to bind this code on click of the circle and adapt it using $(this) to select the current color in order to make it dynamic

Align svg text inline with d3.js legend

I'm trying to use Susie Lu's legend plugin.
Here is a plnk of work so far;
http://plnkr.co/edit/wrOWPYu4PAqwr8f5OOjw?p=preview
Image below is what I would like to achieve (just layout, content/colour doesn't matter)
I've tried the standard float:left + display: inline on the classes attached to the text/rectangles but it didn't work for me. Maybe I was making a mistake. I'm not sure If I should be doing this inside the d3 script or in the css file anyway?
Hope this is a simple fix - any help is much appreciated!
Thanks
Those attributes (float:left + display: inline) only work on html elements, what the legend library here produces is svg
It's possible, but needs a little bit of work
http://plnkr.co/edit/YRFRWEtMFDmje06Mg5KY?p=preview
var cells= d3.selectAll(".cell");
var cellGap = legendLinear.shapeWidth()+(legendLinear.shapePadding()/4);
cells.select("text")
.attr ("transform", "translate("+cellGap+" 13)")
.style ("text-anchor", "start")
;
var offset = 0;
cells.each (function(d,i) {
var d3sel = d3.select(this);
var textWidth = d3sel.select("text").node().getComputedTextLength();
var offsetInc = textWidth + legendLinear.shapeWidth() + legendLinear.shapePadding();
d3sel.attr("transform", "translate("+offset+" 0)");
offset += offsetInc;
});
This firstly moves the text element for each legend 'cell' to the right of the colour swatch rather than below.
Then it moves the g elements that hold the label and swatch horizontally apart dependent on the width of the label (and the swatch and the declared padding) using .getComputedTextLength() and a running total for the offset.

Gradient fill for circle in Leaflet

I am looking for a way to create a circle with a gradient fill in Leaflet.
My approach so far is to define the fillColor of the circle as 'url(#gradient)' and add the Gradient definition manually via the following code:
function createGradient (map) {
// Get the SVG element from the overlayPane
var svg = map.getPanes().overlayPane.firstChild;
var doc = document.implementation.createDocument(null, null, null);
// Create def element
var svgDef = doc.createElement('defs');
// Create gradient and stops element
var svgGradient = doc.createElement("radialGradient");
var svgStart = doc.createElement('stop');
var svgStop = doc.createElement('stop');
// Set ID attribute of gradient
svgGradient.setAttribute('id', 'gradient');
// set stops and colors
svgStart.setAttribute('offset', '0%');
svgStop.setAttribute('offset', '100%');
svgStart.setAttribute('class', 'circle-start');
svgStop.setAttribute('class', 'circle-stop');
svgGradient.appendChild(svgStart);
svgGradient.appendChild(svgStop);
// Append blur element to filter element
svgDef.appendChild(svgGradient);
// Append filter element to SVG element
svg.appendChild(svgDef);
}
The funny thing is, that the gradient fill is not shown initially. However, if I go into devtools and remove the 'defs' block and add it again it the gradient fill is shown correctly.
Can anyone help me to get rid of this issue or alternatively another way to get a gradient fill?
You cannot create SVG elements using createElement, that's only for html elements. If you want to create an SVG element you must create an element in the SVG namespace using createElementNS i.e.
var svgDef = doc.createElementNS('http://www.w3.org/2000/svg', 'defs');
// Create gradient and stops element
var svgGradient = doc.createElementNS("http://www.w3.org/2000/svg", "radialGradient");
var svgStart = doc.createElementNS('http://www.w3.org/2000/svg', 'stop');
var svgStop = doc.createElementNS('http://www.w3.org/2000/svg', 'stop');
Using devtools reruns the html parser on the content which magically corrects the namespace.

Modifying only changed elements with d3

I am using d3 to draw a grid of rectangles on a page.
There is an array that determines the color of each cell in the grid. Sometimes, elements of this array are updated to change their color.
Is there a d3 pattern or method to change only specific elements? I have a render function that re-renders the entire grid in d3, but I don't want to iterate over (and change the fill of) every rect element when only a few cells change color, as there could be thousands of cells.
I just checked the source and there doesn't seem to be. If performance was an issue, what I would do on every .enter call, is track any changes myself by setting a custom .attr('data-lastColor'). On every .data update call after that, I would do
.data(dataSet)
.attr('color', function(d){
var theElement = d3(this);
var newColor;
//set the new color here, under whatever conditions you want
if (foo==bar) {
newColor = 'green'
} else {
newColor = 'red'
}
if theElement.attr('data-lastColor') != newColor {
theElement.attr('color') = newColor;
theElement.attr('data-lastColor') = newColor;
} else {
//Don't do anything if the new color is the same as this color, saving valuable computing time
}
})
Sorry if the answer was a bit rough around the edges, but it should do what you want :)

Change the background colour of a Raphael "Label"

If I create a Label using Raphael, the default style is a black block with white text.
How can I change the background box colour, but not the text colour? I've tried:
paper.label(x, y, value).attr("fill", colour)
but that also fills the text and I end up with invisible text.
I also can't simply change the default colour in this function because I need to have a few different ones depending on a line that it's added to:
As you noticed,
Paper.label(x, y, value).attr(
fill : color
);
changes both the background fill color and the text fill color, resulting in invisible text.
Unspecified correctly explained that this is an array, so each portion must be altered separately, as they illustrated. However, they didn't mention the easiest way to change update both sets of attributes, so I wanted to share this tip. In order to do this, change the attributes into an array with two sets. The first element is the background, and the second is the text.
Paper.label(x, y, value).attr([{
fill : backgroundColor
}, {
fill : textColor
}]);
You can add any other applicable attributes to each part. Here is a working example: http://jsfiddle.net/VzpeG/1/
I was working on a graph similar to this and used:
.attr({fill: "#EF7C4D"})
Let me know how this goes...
var r = Raphael('divID', 320, 220);
text = r.text(100,100,"Hello").attr({fill:"#fff"});​​​​
text.label().attr({fill:"#f00"});
Here's a working fiddle http://jsfiddle.net/vpGyL/216/
Set any color on text or on label both apply separately...Hope this helps !
Digging in furthur...Paper.label(x,y,text) is different from Element.label()
If you look at the source code Paper.Label(x,y,text) is a set of rectangle element & text element, so doing .attr({fill:"SomeColor"}) applies to the entire set, hence both rectangle & text share same color(Hence the invisibility).
Oh yeah If you just want to change the text color do this Raphael.g.txtattr.fill = "#yourColorCode" But this changes the text color globally on all the charts and tooltips(don't seem to be a good idea).
While Element.Label as the documentation says is takes the context element & embed in a label tooltip, basically whatever element you use, applying .label will embed it inside a rectangle

Categories