score:3

The radius parameter on the circular fisheye puts a boundary to the magnification effects. In contrast, in the scale/Cartesian fisheye, the entire graph is modified. The focus cell is enlarged, and other cells are compressed according to how far away they are from the focus. There is no boundary, the compression continues smoothly (getting progressively more compressed) until the edge of the plot. See http://bost.ocks.org/mike/fisheye/#cartesian

If what you want is that cells near to the focus aren't compressed as much (so you can still compare adjacent cells effectively), then the parameter to change is the *distortion* parameter. Lower distortion will reduce the amount by which the focus cell is magnified, and therefore leave more room for adjacent cells. The default distortion parameter is 3, you're using higher values, which increases the magnification of the focus cell at the expense of all the others.

~~If changing the distortion doesn't satisfy you, try changing the scale type by using ~~`d3.fisheye.scale(d3.scale.sqrt)`

; this will change the function determining how the image magnification changes as you move away from the focus point. (I couldn't get other scale types to work -- log gives an error, and with power scales there is no way to set the exponent.)

**Edit**

After additional playing around, I'm not satisfied with the results from changing the input scale type. I misunderstood how that would affect it: it doesn't change the scale function for the distortion, but for the raw data, so that changes are different for points above the focus compared to point below the focus. The scale type you give as a parameter to the fisheye scale should be the underlying scale type that makes sense for the data, and is distinct from the fisheye effects.

Instead, I've tried some custom code to add an exponent into the calculation. To understand how it works, you need to first break down the original function:

The **original code** for the fisheye scale is:

```
function fisheye(_) {
var x = scale(_),
left = x < a,
range = d3.extent(scale.range()),
min = range[0],
max = range[1],
m = left ? a - min : max - a;
if (m == 0) m = max - min;
return a + (left ? -1 : 1) * m * (d + 1) / (d + (m / Math.abs(x - a)));
}
```

The `_`

is the input value, `scale`

is usually a linear scale for which domain and range have been set, `a`

is the focus point in the output range, and `d`

is the distortion parameter.

In other words: to determine the point at which a value is drawn on the distorted scale:

- calculate the range position of the value based on the default/undistorted scale;
- calculate it's distance from the focal point ({distance},
`Math.abs(x-a)`

); - calculate the distance between edge of the graph and the focal point ({total distance},
`m`

); - the returned value is offset from the focal point by {total distance} multiplied by

`(d + 1) / (d + ({total distance} / {distance}) )`

; - adjust as appropriate depending on whether the value is below or above the focal point.

For an input point that is half-way between the focal point and the edge of the graph on the *undistorted* scale, the inner fraction {total distance}/{distance} will equal 2. The outer fraction will therefore be `(d+1)/(d+2)`

. If `d`

is 0 (no distortion), this will equal 1/2, and the output point will also be half-way between the focal point and the edge of the graph. As the distortion parameter, `d`

, increases, that fraction also increases: at `d=1`

, the output point would be 2/3 of the way from the focal point to the edge of the graph; at `d=2`

, it would be 3/4 of the way to the edge of the graph; and so on.

In contrast, when the input value is very close to the focal point, {distance} is nearly 0, so the inner fraction approaches infinity and the outer fraction approaches 0, so the returned point will be very close to the focal point.

Finally, when the input value is very close to the edge of the graph, {distance} is nearly {total distance}, and both the inner and outer fractions will be nearly 1, so the returned point will also be very close to the edge of the graph.

Those last two identities we want to keep. We just want to change the relationship in between -- how the offset from focal point changes as the input point gets farther away from the focal point and closer to the edge of the graph. Changing the distortion parameter changes the amount of distortion in both near and far values equally. If you reduce the distortion parameter you also reduce the overall magnification, since all the data still has to fit in the same space.

The OP wanted to reduce the rate of change in magnification between cells near the focal point. Reducing the distortion parameter does this, but only by reducing the magnification overall. The ideal approach would be to change the *relationship* between distance from the focal point and degree of distortion.

My **changed code** for the same function is:

```
function fisheye(_) {
var x = scale(_),
left = x < a,
range = d3.extent(scale.range()),
min = range[0],
max = range[1],
m = left ? a - min : max - a,
dp = Math.pow(d, p);
if (m == 0) return left? min : max;
return a + (left ? -1 : 1) * m *
Math.pow(
(dp + 1)
/ (dp + (m / Math.abs(x-a) ) )
, p);
}
```

I've changed two things: I raise the fraction `(d + 1)/(d + {total distance}/{distance})`

to a power, and I also replace the original `d`

value with it raised to the same exponent (`dp`

). The first change is what changes the relationship, the second is just an adjustment so that a given distortion parameter will have approximately the same overall magnification effect regardless of the power parameter.

The fraction raised to the power will still be close to zero if the fraction is close to zero, and will still be close to one if the fraction is close to one, so the basic identities remain the same. However, when the power parameter is less than one, the rate of change will be shallower at the edges, and steeper in the middle. For a power parameter greater than 1, the rate of change will be quite steep at the edges and shallower near the focal point.

Example here: http://codepen.io/AmeliaBR/pen/zHqac

The horizontal fisheye scale has a square-root power function (`p = 0.5`

), while the vertical has a square function (`p = 2`

). Both have the same unadjusted distortion parameter (`d = 6`

).

The effect of the square root function is that even the farthest columns still have some visible width, but the change in column width near the focal point is significant. The effect of the power of 2 function is that the rows far away from the focal point are compressed to nearly invisible height, but the rows above and below the focus are still of significant size. I think this latter version achieves what @piedpiper was hoping for.

I've of course also added a `.power`

function to the fisheye scale in order to set the `p`

parameter, and have set the default value for `p`

to 1, which will give the same results as the original fisheye scale. I use the name `power`

for the method to distinguish from the `exponent`

method of power scales, which would be used if they *underlying* scale (before distortion) had a power relationship.

Source: stackoverflow.com

#### Related Query

- How to modify d3js fisheye distortion so that it will support radius
- How to create a beeswarm plot with variable radius in d3js v5?
- How to achieve that bubbles are only clickable if completly zoomed d3js
- How to sort nodes in D3 so that connecting paths will be clear?
- Modify Cartesian DIstortion for D3js V4
- how to adjust parent circle radius using d3js pack layout
- svg: how to draw graph elements that will be crop outside a rectangular area
- How to tell d3js that this half donut chart should fill values from left to right corner
- How do you create a survey that will immediately display the results as a pie chart on a website?
- How to modify D3js graph depending on change of value?
- How do you create a d3 line function that will draw 2 lines for x, y1, y2 data?
- d3js - How to plot a multi line chart chart for multiple groups of items that can be updated?
- How to link multiple graph networks in d3js so that an event in one calls the same event in other networks
- if i pre-render d3js charts on the server, how will their width/height be calculated?
- How to create a grouping key in D3js that is a combination of two JSON attributes
- How to access the DOM element that correlates to a D3 SVG object?
- D3js how to append 2 children at the same level in .enter context
- d3js : How to select nth element of a group?
- How to create floor plans that work nice with mobile and desktop browsers?
- D3js : How to convert svg text to path?
- How can I change the radius and opacity of a circle in d3?
- How to use D3js on server side to generate SVG directly?
- how to deal with OnChanges that requires an AfterViewInit
- d3js - how to set albers projection properly?
- How to change line color in d3js according to axis value?
- How to create a reusable component in D3 with an API that manipulates each instance of the component?
- How to force nvd3 to display the equal number of ticks as that of the values plotted on the graph-nvd3
- How to control the order of the layers on a map in d3js
- dagre-d3 how to click node and run an event after that
- What is D3js version support policy?

#### More Query from same tag

- How to position svg circles on a line and curve it?
- How to select the color of node on data value and the Data value of tool as name?
- Javascript D3 not showing visualization
- Multi dynamics d3 charts on a same page
- Detecting visible nodes in d3.js force layout after zoom-pan
- ReferenceError: dc is not defined, even after importing d3,dc and crossfilter in order
- Angular d3 donut
- I unable show the x-axis year and month using d3.js
- <g> element does not adapt to <svg> on Firefox
- Display y-axis as percentages?
- D3 force layout: rotating text
- Accessing multi-dimensional D3 nest() rollup keys and values
- How to limit the text of polygons in Voronoi diagram with D3.js?
- XAxis repeats itself in Rechart's ScatterChart when type="category"
- Reorder group elements to a specific order
- dc.js BarChart yAxis range plus padding
- nvd3 graph not loading properly in firefox
- Multilevel Hierarchical Edge Bundling
- NVD3 stacked bar chart does not show x-axis properly
- How to transform JS nested object keys to hierarchical array schema
- Drawing elements on a bar chart in d3
- Using rollup.js with es6
- how to get attributes of element current pointed by mouse
- D3, SVG and textPath: How to move the text down?
- D3.time scale keeps returning default value
- D3.js - Conditional apply nest.key() function to array elements
- Setting pie chart colors using d3.js
- Style d3 svg line with css
- What does this d3 time format function mean?
- Extjs + D3; Load and draw onto image