D3 radial bar chart adjust radius scaling - javascript

If one examines this block:
https://bl.ocks.org/mbostock/8d2112a115ad95f4a6848001389182fb
The gridlines are in increments of 20. However the radius of each gridline does not appear to be equal as it scales up:
I'm guessing there is some geometric justification for this, but that's not what I'm after for my chart. I only want aesthetics, I need the gridline circles to be equidistant from each other.
Question
Using Bostock's radial scale script as seen in the above block, is there any way to adjust the scaling of the radii? I want the scaling to be equidistant.

The only thing you need is to change this...
var y = d3.scaleRadial()
... for this:
var y = d3.scaleLinear()
Here is the bl.ocks with that change only: https://bl.ocks.org/GerardoFurtado/0a0b22d15c4e715e4c748335e37330fb/1670bbcdfdcbed6b6a0ae2a56d5f153570d969d1
PS: There is indeed a geometrical explanation for this: a circle with radius 2r has an area four times bigger than a circle with a radius r. That's why we always (at least in truthful charts) scale the circle's radius to the square root of the encoded datum. Well, you mentioned that "I only want aesthetics". As a data visualisation specialist/enthusiast who happens to be a D3 programmer, not the other way around, I suggest you reconsider your approach and keep the radial scale. Charts that prioritise aesthetics over information are normally bad charts, and charts that impose aesthetics ignoring information are simply untruthful charts.

Related

Add grid lines compatible with zoom and drag in d3.js

I am trying to add grid lines to my existing code, and have seen many tutorials but none with zoomable and dragable grid lines.
A stripped version of my existing code is here :
http://jsfiddle.net/p4cmx1kj/
I understand that I must have a scale :
this.x = d3.scale.linear()
.domain([this.options.xmin, this.options.xmax])
.range([0, this.size.width]);
And draw it later. But I don't know how.
I would like to have vertical grid lines that "change" as I zoom (eg : go from 10-20-30-40 to 10-15-20-25) and move as I drag my graph around.
How can I do that ?
I guess you could do something like this example :
http://blog.scottlogic.com/2014/09/26/an-interactive-stock-comparison-chart-with-d3.html
And then add some limit, where if above a certain threshold it adds more / less tick labels on the axis. (At-least that is what I plan to attempt to do on a force layout now).
Or better still make your labels a function of the range, eg something along the lines of min + n*(min-max)/4 , where n is your tick label {1,4}.

How can I limit the length of a HighCharts PlotLine on the Y-Axis for a BoxPlot?

I am using highchairs 3.0 to create a graph that has N Boxes on it. So far so good. However, one of the user desires is to draw a few plotLines (based on values on the Yaxis) for each Box on the graph. The catch is that the information is different for each of the boxes, so they want the plotLine to just extend from the start of the box on the left side (x-axis basis) to the right of the single box.
Highchairs by default draws the y-axis plotLines (and plotBands, looked at those too) all the way from left to right, causing a very chaotic chart indeed!
Is there a way to limit the length (start / end on the x-axis I guess) of a plotLine in a box plot to just the width of the box?? I guess I basically want to overlay lines onto the area of each Box on the graph.
Thanks!
The best way that I have found to do this is by extending the marker symbol types to create a horizontal line.
Use this as the marker symbol type for a scatter series to accomplish what you're looking for.
Highcharts.Renderer.prototype.symbols.hline = function(x, y, width, height) {
return ['M',x ,y + height / 2,'L',x+width,y + width / 2];
};
Example:
http://jsfiddle.net/jlbriggs/m85yv3aq/
Required inputs of: radius, lineWidth, color
((also a useful way to build bullet charts:
http://jsfiddle.net/jlbriggs/UGs2E/
))

NVD3 legend Show/Hide chart getting scale / zoom feature disabling

I have 2 line chart shown side by side which has 5 lines being plotted on each chart. So there are 5 legend for each of them. Unchecking each legend would hide the respective line specific to legend and optimize(May be zooming or scale) the chart with new scale measurement.
This is default functionality of legend. What i am looking for is ONLY just show/hide respective line. No other functionality like zoom/scale so that user does get distracted by zooming as s/he is comparing 2 charts side by side. I hunted documentation but did not find these feature on/off information.
Force X
List of numbers to Force into the X scale (ie. 0, or a max / min, etc.). The numbers tell the d3.js the values to use in the scale, rather than d3.js determining the values.
Force Y
List of numbers to Force into the Y scale (ie. 0, or a max / min, etc.). The numbers tell the d3.js the values to use in the scale, rather than d3.js determining the values.
Datatype: Array of Numbers (i.e. [0, 50]
Reference: http://cmaurer.github.io/angularjs-nvd3-directives/line.chart.html

Is it possible to draw any arbitary degree Eliptical Arc with SVG?

I am trying to smoothen the transition from a diagonal line to a horizontal line by using arcs of circles that I calculate with a little calculus. The problem I am running into is that it seems as though I can't get the arcs to be positioned correctly.
For example: jsfiddle.net/5Wa9e/2
It might just be a problem with my calculations but from "inspection" it seems as though I have the right circles. I want the red points on the right to always be at the bottom of the circle at the point where the tangent is horizontal.
I am using: A#{radius},#{radius} 0 0 0 #{curveEndX},#{curveEndY}" to define the arc. Am I missing something?
--edit--
It was just my math. Turns out the arcs I see are just fallback mechanisms for when the SVG renderer can't find a circle matching my constraints.
--edit--
end result: jsfiddle.net/5Wa9e/2

HTML5: inaccurate positioning of rectangles

I'm using canvas of HTML5 to create a "preview" image which mainly consists of some rectangles and simple lines. Works fine so far, but there's one problem I cannot fix somehow. Presume the following situation:
context.fillStyle = "rgba(0,0,0,0.75)";
context.fillRect(100.64646,100,50.94967,20);
context.fillRect(100.64646+50.94967,100,100,20);
So I'm drawing 2 rectangles with some opacity. The x-starting coordinate plus the x-length of the first rect is equal to the x-starting coordinate of the second rect, so in theory they should collide without any margin between. Sadly, the result is different:
(see http://files.clemensfreitag.de/thin_spacing.jpg)
There's a very tiny spacing between the boxes, and the background color is visible. But:
This problem doesn't occur if the coordinates and lengths are integer values.
Is there any way to get it done by using float values? Converting them to integers before drawing might be acceptable in my application, but I'm just wondering why this should not work with floats.
Best,
Clemens
What you're seeing is the result of overlaying two opaque colors. When the first rectangle ends at 151.59613, the rectangle is automatically antialiased, filling in the rightmost column with rgba(0,0,0,0.4470975). When the second rectangle starts at the same x coordinate, it is also antialiased, filling in the leftmost column (the same as the first rectangle's rightmost) with rgba(0,0,0,0.3029025). The two values do add up to rgba(0,0,0,0.75), but that's not how they are blended. Instead, the second color (rgba(0,0,0,.3029025)) is drawn on top of the first, resulting in rgba(0,0,0,0.4470975+(1-0.4470975)*0.3029025) = rgba(0,0,0,0.61457305). So there isn't actually a gap between the two rectangles, but rather a 1px column that is a slightly lighter shade of grey.
Similarly, if you were using solid colors then the second rectangle's antialiased column would overwrite the first's, resulting in an even lighter shade of grey in the "gap".
The issue does not show up with integer values because no antialiasing is required - each rectangle ends at the edge of a pixel.
It looks like none of the globalCompositeOperation settings fix this, and turning off antialiasing would sometimes result in a 1px gap, so I think your simplest solution is to force integer values (alternatively, you could clear that column then fill it in with the desired color).
This problem is related to the way objects are drawn on a float based grid (especially vertical and horizontal lines and thus rects).
See there for an explanation and a schema : http://canop.org/blog/?p=220
Depending on the size of your objects, you need to use integer or mid-integer coordinates and sizes for your shapes, the goal being to fill complete pixels in both dimensions.
For example :
use a mid-integer for a thin line (one pixel width)
use an integer coordinate for a 2 pixels wide line
(and extend the logic for rects)

Categories