Auto or Random Scatterplot Matrix Selections d3.js - javascript

I would like to know if there is a way to have some sort of random selection, or any selection happening when this loads and to stop when a user interacts with it. AS it stands now, people do not realize that they can interact with the chart.
Maybe the top left box could have a selection being drawn and receding?
http://mbostock.github.io/d3/talk/20111116/iris-splom.html
Thanks for any help or suggestions!

You could draw the brush programatically using the extent() method.
also, look at some of the examples in this discussion.
Using the same example you posted, add this to the end of the csv callback:
var e = [[0.4,1.4],[1.4,2.4]]; //set brush range
brush.extent(e);
cell.call(brush); //draw brush
and if you want the brush to simulate user interaction:
cell.select(".extent")
.transition()
.attr('width',20).attr('height',20)
.attr('x',10).attr('y',10)
.transition()
.attr('width',80).attr('height',80);

Related

Zoomable timeline with one element per tick (D3V6)

I'm working on a timeline-based chart that should always have one rect per x-axis tick. The idea is to use the color of each rectangle to convey the amount of data that's in that date (somewhat like a heatmap).
The chart also has grouped y values. That is, there are two y axes: one for each group, and inside each of those, three lines (subgroups). Semantically the intention is to say: "For this coupon, on this date, there are this many readings for each data type". To help clear up my intention further, this library has a very similar solution to what I'm aiming at.
OK, and your question...?
My question is about aligning the rectangles with the ticks, and keeping them that way. How can I make them always be aligned with the ticks? Is there a way to "tie" a rect to a tick?
To make matters worst, the chart has to be zoomable, so when you scroll and the dimensions of the ticks change, the rectangles should stick to their corresponding ticks: move with them, change their width accordingly and so on. Basically, I'd like to "marry" the rects to their corresponding ticks.
What have you tried?
My approach right now is to make the segments' width depend on the current tick count, and essentially treat the current ticks as if they were my data.
That is:
segmentWidth = state.width() / ticks.length;
And when updating/rendering the rects:
state.mainG.selectAll('g.couponData')
.selectAll('g.column')
.data(ticks)
...
One problem I see with this is that if you click and drag, the ticks expand, so having a single, global segmentWidth doesn't seem like the right approach. Seems like I'd need a way to grab each tick and get the distance to the next one, and use that as the width of each corresponding segment, but I haven't quite got there yet.
Here's a fiddle with an example of what I have:
https://jsfiddle.net/bnekvp0o/11/
TBH, I presume I'm making some dumb calculation mistakes, but I also feel like I'm bruteforcing the solution, so I'm hesitant to keep trying to make it work with my current approach, since I'm quite new to the framework.
Thanks in advance!

Alter first vertical grid line in nvd3

I want to remove (or make effectively hidden) the first vertical line in the grid for an nvd3 chart. I thought it was a problem with my chart, but after testing it, I realized it seems to be a more general problem.
I tested it by running the line:
d3.selectAll('.tick, .nv-axislabel, .nv-axis text').attr('fill','#999999')
in the console, at the simplest line chart I could find: http://nvd3.org/examples/line.html and it still didn't work! It changes all the lines except the very first vertical line. I'm baffled, I've tried every combination of classes with stroke, fill, opacity, etc - I can either affect the entire svg (with opacity), or nothing. Anyone have any ideas?
EDIT:
I should have specified this originally, I apologize - I do not want to remove the Y axis entirely. I still need the label and the tick marks - I just want to remove that one vertical line (or at least lighten it - it is much darker than the rest of my chart).
Going by your comments:
You don't want to see the " the first vertical line in the grid for an nvd3 chart"
Which is the y axis:
Two ways to achieve that:
Option1
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(false) //hide the y-axis
.showXAxis(true); //Show the x-axis
Option2:
Since in your example you are going for a CSS option
d3.selectAll('.nv-y').attr('display','none')
I will prefer Option1
EDIT post your clarification, you wish to make the y axis line light you can use:
d3.selectAll('.nv-y path').attr('opacity','0.1')
or if you want to hide it completely
d3.selectAll('.nv-y path').attr('display','none')
One solution is to specify an array of tick values that you want to use for each axis. Use axis.tickValues([values]) to explicitly declare which XAxis ticks you want for your graph. So you could pop .tickValues([1, 2, 3, 5, 8, 13, 21]); into either the chart.xAxis or the chart.yAxis, and ticks would only appear from the corresponding values in the array. In your case, you would want to put it in the chart.xAxis variable. However if you want to have a dynamic chart, explicitly declaring the tick values would pose a problem once the data is updated in the graph. If on the other hand you are using static data, this is a pretty easy fix. I've tested this solution in their live code editor and it seems to do the trick.
Refer to https://github.com/mbostock/d3/wiki/SVG-Axes#ticks to see some other directives that could be of use.

How do I make specific elements appear on top of others in D3.js?

I have a plot in D3 where I draw some circles and then some ellipses afterwards to show the median. I have a 1.5 second delay on my median, to try and draw it after the circles have appeared, but I still run into problems.
Here is a screenshot of an example: http://puu.sh/8csEK.png
The circle to the far right are behind it's median, the rest of the circles are all in front. When areas are crowded you cannot see the median anymore.
I have even tried using the following on transitions of my circles, but it's no use:
.each("end", <call function to draw ellipses>)
So my question is, how do i make sure that my ellipses are drawn on top of my circles?
I have a function that draws my ellipses and a function that draws my circles right now.
I'm assuming that you're using SVG to render your elements. In SVG, the display order is the order of drawing/appending to the DOM. That is, the element you append first is drawn at the back, the element you append last at the front. Child elements (e.g. something underneath a g) are drawn when their parent elements are drawn.
To make sure that groups of elements have the right order, it's usually easiest to add them to different SVG groups that are drawn in the right order. In code, this looks something like this.
var circles = svg.append("g");
var ellipses = svg.append("g");
// ...
ellipses.append(...); // this element appears in the front although it is drawn
// earlier because it is appended to the group appended last
circles.append(...); // this element appears behind the one appended to ellipses

d3.js - blank object when applying y-axis scale

I'm trying to apply a scale to y-axis in my chart, but when I do it I get a blank svg object.
I did the same thing with the x-axis and it's working fine.
Problem happens when you uncomment this section
// .y(function(d) {
// return yScale(d[1])
// })
http://jsfiddle.net/MgwR5/1/
Could anyone tell me what I'm doing wrong?
The area functions are y0() and y1(), not y(). Ref: D3 API documentation
Have a look at the js bin. I've put a bunch of comments in that should help and I've assumed that you wanted a line chart.
If you want to put axis's on your chart you should be looking to use the d3.svg.axis function. It does most of the heavy lifting for you. You also need to make space for the axis try using some padding and margins (you might want to look at this example or the example on the js bin d3 page - use the link at the top of the google groups d3 page). You also probably want to separate out your axis's and your plot by using svg's group ('g').
Cheers

KineticJS: Draw Arrow between two shapes

So, I want to create a finite state machine-visualizer/editor with the help of kineticjs and i'm stumbling with the following scenario:
I have two "nodes", let's say circle-objects (grouped with a label) which are draggable on my stage. Now I wan't to click on one circle, hold the mouse and move it and add a connection (an arrow, for simplicities sake) between the two shapes.
So it would be great to have any hints on how to accomplish this for I haven't found a solution yet.
To specify it: The nodes themselves should stay draggable. My thought was: Add a black circle and a white circle with a slightly smaller radius, group them. then on dragstart white circle -> drag node, on dragstart black circle -> draw arrow.
The Problem is how to draw an arrow starting from one shape and following the mouse to it's target (which can be another nodegroup => connection to this group or a blank point of the stage => an overlay opens which lets the user choose another node to draw or cancel the drawing).
I hope this is somewhat clear to understand. For more information please feel free to ask me.
Best regards,
Dominik
p.s.: The behaviour seems to be exactly like the behaviour lucidchart (dot com) uses when creating diagrams, so maybe you understand what I want to achieve better looking at their demo here: https://www.lucidchart.com/demo .
First off, for simplicity's sake here is a fiddle on how to draw a basic Line with your mouse and KineticJS: http://jsfiddle.net/projeqht/fF3hh/
Let's say you already have two circles on the stage, and you need to draw a line to connect them.
We can use e.targetNode to select the nodes on each event (mousedown, mouseup), for example:
layer.on("mousedown", function (e) {
var nodeDown = e.targetNode;
}
layer.on("mouseup", function (e) {
var nodeUp = e.targetNode;
}
We need to check if the parent of nodeDown is a Kinetic.Group or something else.
If the target node nodeDown has a Kinetic.Group for a parent, we can use this Group to store the new line, and the 2nd target node nodeUp.
If the target node nodeUp does not have a Kinetic.Group for a parent, we need to see if nodeUp has a Group for a parent. If nodeUp has a Kinetic.Group for a parent, then we can use that Group to store the new line, and the first target node nodeDown.
If neither nodeDown or nodeUp have a group for a parent, then we will need to create a new group for them and add all 3 shapes (2 circles and a line) to that new group.
Use this tutorial to learn how to move shapes from 1 group to another: http://www.html5canvastutorials.com/kineticjs/html5-canvas-move-shape-to-another-container-with-kineticjs/
Also, if you move a shape from one group to another, you may want to remove() or destroy() the extra group if it is no longer needed.
While drawing a Line, you will have to disable dragging the shapes, so that you can drag and draw with a mouse. You can do that by doing something similar to this:
function stopDrag() {
for (var i=0; i<layer.children.length; i++) {
layer.children[i].setDraggable(false);
}
}
function startDrag() {
for (var i=0; i<layer.children.length; i++) {
layer.children[i].setDraggable(true);
}
}
This will make all the children of layer draggable and undraggable, but you might want to limit that by being more specific than select layer.children. A nice trick I liked to use here was to name all groups that were draggable as "draggable_shapes" and then use var draggableArray = stage.get('.draggable_shapes') to select all the groups that are allowed to be dragged, then you could loop through that array and setDraggable().
Another point to note is that the X and Y coordinates of the Line will be a bit tricky to calculate, depending on if it has a Group as a parent or a Layer. If the Line is grouped, line's coordinates will be relative to the Group position, or else the Line's coordinates will be relative to the Stage (top left corner).
This will get you started on connecting a line with two different circles. It's up to you to do the coordinate logic if you want the lines to only connect on the outer rim of the circles.
Maybe you might want to add a transparent rectangle (attribute opacity: 0) behind each circle, so that on mousedown with the rectangle, you will call drawLine() to start drawing a line. Or else if the user clicks the circle, it will drag the group. At least that has similar functionality to the lucid charts application.
Custom Hit Function (http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/) would probably be a cleaner way to do this but I'm not 100% on using Custom Hit Functions, someone else might know better.
Let me know if you need further help. Good luck!

Categories