In d3 zoom behavior, for linear scale, how can I gradually increase the zoom. I use it like
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
If I understand correctly, the chart will zoom up to 10x. Is it like, each double click will zoom it 1x times, till it reaches 10x? How can I make it even finer step like, 1, 1.2x, 1.4x,..
Thanks.
The zoom level increases as a geometric series. That is, each time you click, it doubles -- 1, 2, 4, etc. The default interaction doesn't allow you to have finer steps, but you can easily do this in your handler code -- there's nothing requiring you to zoom in exactly the same steps as the zoom behaviour's scale value. That is, for a zoom level of 2 you could set the zoom factor to 1.2, for 4 to 1.4 etc.
For finer control in general, you may also want to consider having another input element on the page (e.g. an input box for the zoom level or a slider).
Related
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.
I am using d3 axis to show the bar graph and i have added zoom interaction to it.
I am adding zoom interaction like this,
d3.zoom(xScale).on("zoom", jQuery.proxy(function(){
//Do somthing on zooming.
},this));
},this));
On Zooming the axis i have to get the at what level the axis is zoomed,
suppose consider i have time axis on zooming it will show the labels in day level, after zooming again it will show the axis in hour level. So how to get whether it is zoomed in day level or hour level after zooming?
Assuming you are targeting d3 version 4, the best way to handle this is with the zoom functionality's rescaleX. Say we have the following zoom handler where x is the scale tied to the x-axis:
function zoomed() {
var newScale = d3.event.transform.rescaleX(x));
console.log(newScale.domain());
}
Would log the bounds (min/max) of your zoomed axis.
I have setup this fiddle to try to figure out why the scale that I pass to d3.behavior.zoom() is being ignored. I am setting the scale to 10 but the effective scale is 1. Then if I try to pan the grid the scale jumps to 10. Same thing happens when I try to zoom the grid. The scale jumps to 10 and then the additional scale is applied. What am I doing wrong? How can I work this out in order to have an effective initial scale value?
You're initializing a var scale = 10 to represent that initial zoom, and you're applying that to zoomer via .scale(10). So zoomer knows the initial scale, but nothing in your code is doing the work of applying the initial scale to the d3 selection vis. The first time the scale is actually applied is once the user interacts, which in turn calls function zoom() {...}, where the scale is finally applied.
The time/place to apply the initial scale, is when you create vis:
//create a group that will hold all the content to be zoomed
var vis = graph.append("svg:g")
.attr("class", "plotting-area")
.attr("transform", "scale(" + scale + ")");// <-- THIS
Here's an updated fiddle
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
I've made zooming and brushing working together. The only problem is, when I've set the particular period on X axis via brushing and then trying to use zoom (on mouse drag or mouse wheel), it resets previous selected scales, so zoom doesn't store x axis domain that was set via brushing before.
zoomRight = d3.behavior.zoom()
.x(xScale)
.y(yRightScale)
.scaleExtent([1,20])
zoomed = ->
zoomRight.scale(zoom.scale()).translate(zoom.translate())
canvas.select("._x._axis").call xAxis
canvas.select(".axisLeft").call yLeftAxis
canvas.select(".axisRight").call yRightAxis
canvas.select(".y.grid").call make_y_axis().tickSize(-width, 0, 0).tickFormat("")
canvas.select(".line1").attr("d", line1(data))
canvas.select(".line2").attr("d", line2(data))
brush.extent(xScale.domain())
canvas.select(".brush").call(brush)
zoom = d3.behavior.zoom()
.x(xScale)
.y(yLeftScale)
.scaleExtent([1,20]) # 20x times zoom
.on("zoom", zoomed)
Full code is here fiddle. How can I force zoom to remember the previous brushing selection(position)?
Solved the problem by adding the following lines on brush:
zoom.x(xScale)
zoom.translate()
Working example is here.