Adding labels to D3 generated circles - d3.js

I just started learning d3, and very first thing I made is this sorta lame fiddle
Now I wonder how should I attach labels to those circles. Is it possible to nest a label (let's say current radius value) in a circle so it would always move with the circle, or you have to treat labels like independent objects and manage everything accordingly?

You can use a grouping element (<g>) to hold both the circle and the associated text label so they are always together. Then you can position the enter group by using the translate command on the transform attribute (instead of positioning the circle directly as you're doing now).
So basically, you bind the data to the <g> elements instead of to the <circle> elements as you're doing now. Then you can just append a "circle" and a "text" to the "g" (no data join) and both of those child elements will automatically inherit the data themselves.

Related

Is it possible to change the position of a p5 text element after it is drawn?

Can you change the position of a p5 text element after it is draw without redrawing the entire canvas? If so, how would I be able to?
I'm trying to make text appear under players set to their current position, but when they move I want it to change its position to the player's position. I have the events with that setup, I just don't know how to change the position of the element.
Unlike some libraries, such as fabric.js, graphical elements in p5.js are not persistent objects that can be moved or modified once they are drawn. Instead, everything in p5.js is drawn in immediate mode. So when you are drawing text you specify it's attributes at the time you draw it, using the Typography functions, and the text(). In order to "move" text you would clear the canvas, or re-paint the background (using clear() or background() respectively, and then re-drawing the text with different settings or parameters.

D3 v4 Zooming Partition Layout in X dimension only

Trying to wrap my head around this particular use case of D3 v4 zooming. My example so far is available here:
http://bl.ocks.org/gmarler/f6d17432f6eea34318bff477eb9ebd27
I'm able to get my initial Partition Layout to draw as required (I've left out complexities such as text positioning and color), but I'm not getting very far with zooming properly.
The goal is to zoom whenever one of the svg rect elements is clicked on.
And by "zoom", I mean something somewhat different than the stated default behaviors:
Completely disable anything other than a click on an element - no drag, panning, or mouse wheel activity normally associated with D3 zoom.
When an svg rect element is clicked on, the element expands (or contracts) in the X dimension only, such that its left side abuts the left side of the top level svg's g container, and its right side abuts the right side of the top level svg's g container.
In other words, the element clicked on becomes exactly the width of the chart.
All other g/rect elements vertically "above" the clicked one should scale/translate appropriately.
All other elements vertically "below" the clicked one don't really need to change, as the one we've clicked on will take up 100% of the width of the chart container.
So, here's how far I've gone:
I've calculated the scaling factor (k) - not sure I've done it right. The goal is to set the scaling factor to whatever will make the width of the clicked element expand/contract to the width of the svg.
And I've calculated the transform for x (tx) to be whatever will cause the left side of the g element encapsulating the rect element to align with the left side of the svg.
Using k and tx, I create a zoom transform with d3.zoomIdentity.translate(tx, 0).scale(k)
Now I select all of the g elements that contain rects, tear the current transform="translate(x,y)" apart, and apply the zoom transform to the x portion of the translate - this should move the left side of the element to the left side of the svg
Next, I select the rect under each g element, and apply the zoom transform to the width attribute
This seems to get me closer to the end goal, but I'm sure I'm missing something:
Is it really necessary for me to tear apart the transform="translate(x,y)" the way I am for the g elements?
If I click on certain elements more than once, the scaling keeps increasing. I need to both:
Keep the original zoom ratio so that I can reset to it, or go back to it simply by clicking on the lowest rect element
If an element is clicked on, it's already at 100% width - I need to never allow scaling past 100% width
clicking on any given element the first time expands it to 100% width as expected, but not all elements' ancestors properly scale - I don't care if the the ancestors expand either end past the edge of the viewport, but some of the ancestor elements leave the viewport entirely, which I cannot account for.

Expand d3 map (not individual feature) to use entire svg area

I have map data for all of the towns in a state -- let's say California. I display every single town on a map using d3 -- everything is good so far. The projection I use makes use of the scale() and translate() functions, among others, to show my map how I want -- it looks nice.
Here is my problem. I need an automated way to expand my map projection so that it uses the entire svg area. In other words, I want to make my map bigger and bigger until either its width exactly equals the svg width or its height exactly equals the svg height.
I know the bounds function helps do this for an individual feature, but I want the entire state, not the individual town features, to fill the svg area.
Thank you for your help!

Add and remove data when panning bar chart in D3

I have a large dataset in an array which translates into about a million 6-pixel wide bars,
Given that about 130 bars fit into 800 pixels of screen, I need to only display a portion of the data at a time. Then, when the user pans the chart, new data will be added and non-visible data will be removed. The user could pan right or left so data need to be able to enter and exit from both sides of the chart.
I feel like the solution involves D3's enter and exit, but I'm unsure how to implement it.
One idea I've had is to use Array.prototype.concat and redraw on pan. Another idea would be to use Array.prototype.slice. I hope those are fast enough.
Any examples?
There are no examples that I'm aware of. Roughly, you would need to do the following.
Draw the initial bar chart. Pass in only the data you'll display (i.e. the first 130 data points if your screen is 800px wide).
On pan, get the translation for the pan. The x translation corresponds to a certain number of bars. Take off this many data points from the beginning of your data array and add that many to the end.
Pass that new data array to D3 and redraw. This tutorial should give you some pointers. Remember to pass a key function to .data() so it knows how to match data to DOM elements.
Similar thing on subsequent pans. Figure out how many bars have been panned and modify the data array accordingly (e.g. using slice and concat -- doesn't matter that much). Redraw the bars.
The concept is very similar to what's done in the tutorial I've linked to, except that the redraw isn't triggered by a timer, but by the pan event.
There are fundamentally two ways to do this. One is that you draw all 1M bars using svg and rely on svg's built in panning. The other is that you draw 130 bars and redraw each time the user pans. enter() and exit() are useful for doing things to data elements in your set that are entering or exiting the scene since the last time it rendered. (d3 determines which elements are
"new" by calling a predicate function on each element. The function has a default but can be user supplied.) You don't actually have to use them here unless you want to be fancy. You can just selectAll the rects from last draw, and .data() them with your new data, and supply the usual calls for drawing rects.

Circle packing within force graph nodes in D3?

I have a Force Directed Graph that I've generated with D3 and within each node (which are represented as large circles) I'd like to pack in a bunch of smaller circles using D3's Circle Packing. Is it possible to use both of these layouts in one visualization? How does one insert a layout into a node?
I figured it out once I realized that svg elements were just regular dom nodes and I could manipulate them with jquery. I ended up created two svg locations, one for display and one for creation of svg objects. I built one object at a time in the builder location and then moved it off to somewhere else in order to work on the next guy. When I was ready I built the force graph on the main display and populated the nodes there with the circle packed nodes that I had saved off somewhere else.

Resources