Accepted answer

Calling y1.range() (without any arguments) will return you the [min, max] of the scale.

From the docs:

If values is not specified, returns the scale's current output range.

Most accessor functions in D3 work like this, they return you (get) the value if you call them without any arguments and set the value if you call them with arguments and return the this object for easy chaining:

d3Object.propertyName = function (_) {
    if (!arguments.length) return propertyName;
    propertyName = _;
    return this;

However, the zoom behaviour alters the domain and not the range of the scales.

From the docs:

Specifies an x-scale whose domain should be automatically adjusted when zooming.

Hence, you do do not need to get/set the range, but instead the domain of the scales y1 and y2: y2.domain(y1.domain()).


Since the zoom function already manages all the ratios, a more abbreviated answer would be:

var zoomFirst = d3.behavior.zoom()
  .scaleExtent([0, 3])
  .size([w, h])
  .on("zoom", function() {

    // Update visual. Both y domains will now be updated


// Create copy for y2 scale
var zoomSecond = d3.behavior.zoom()
  .y(y2)                // <-- second scale
  .scaleExtent([0, 3])  // <-- extent

This assumes you have called only zoomFirst to your visual.

Related Query