circosJS icon indicating copy to clipboard operation
circosJS copied to clipboard

Zooming in CircosJS

Open jorgenunezsiri opened this issue 6 years ago • 7 comments

Hello @nicgirault,

Is there a way to implement normal D3 zooming abilities within Circos layouts?

I'm using the Chords track similar to this example: https://github.com/nicgirault/circosJS/blob/master/doc/chords.png. I want to implement normal pan and zoom by scrolling with the mouse (https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0), and this is what I'm trying to do:

var width = 1000;
var height = 850;

var svg = d3.select("body")
  .append("div")
  .attr('id', 'chart')
  .attr("width", width)
  .attr("height", height);

svg.select(".all")
  .call(d3.zoom().on("zoom", function() {
    svg.select(".all").attr("transform", d3.event.transform)
  }))
  .append("g");

var myCircos = new Circos({
  container: '#chart',
  width: width,
  height: height
});

// ...
// Adding the configuration data for the layout and chords, and rendering

The zooming is not working as expected. As you can see, I have to do svg.select(".all") to actually select the svg element within the div tag.

Thank you!

jorgenunezsiri avatar Mar 19 '18 14:03 jorgenunezsiri

Hi @jnunez17 sorry for the late answer. I don't know at all how zoom is working so I won't be able to help you without digging into the subject. I let the issue open so that I will work on it next time I maintain this project. If you found a solution, I would be really glad if you can share it so that I could add it to the documentation of this project.

nicgirault avatar Apr 13 '18 20:04 nicgirault

Hello @nicgirault, sorry for the late reply. The issue is that having the structure svg > div > svg or div > div > svg is not valid for adding zooming to the main container. So, I was able to add zooming by removing the div container, and changing the main container to svg. Solving it is as easy as going to these lines and changing them to:

const container = select(this.conf.container)

This small change will allow users to have SVG containers in their applications, by giving an id to an svg element instead of a div. Then, you should get the expected zooming by adding the following to the SVG:

svg.call(d3.zoom().on("zoom", function() {
  svg.attr("transform", d3.event.transform)
}));

There is more information about having an SVG container in the other discussion here.

jorgenunezsiri avatar Jul 18 '18 19:07 jorgenunezsiri

@jnunez17 Do you mind posting a code snippet on how you implemented this? I've been trying to make it work with react but I keep getting this error:

Uncaught TypeError: Cannot read property 'button' of null

Thank you!

mtwichan avatar Dec 02 '18 19:12 mtwichan

@matthewchan15 That does not seem to be an issue with the zoom itself, but with something you are missing for getting it to work, possibly how you are importing the d3 modules. One thing you can try is importing the whole d3 library at the top of your script (import * as d3 from 'd3';), and if that fixes your issue then perhaps you are missing a specific d3 module (in case you were importing them separately).

For the zoom, it should work just by removing the extra div container from the library and then calling the zoom event transform on the outer svg. I'm explaining the issue and the steps with more detail in my previous comment.

jorgenunezsiri avatar Dec 02 '18 19:12 jorgenunezsiri

@jnunez17 Ah yes I tried import * as d3 from 'd3';, as well as this method import {select} from 'd3-selection' (example). I am using the d3 package provided in this library with package.json -> https://github.com/nicgirault/circosJS/blob/master/package.json.

I think there may be a misunderstanding on my part. Did you specify this block of code in circos.js (this is what I'm trying to do) or when you were creating your instance such as in the first comment you posted?

svg.call(d3.zoom().on("zoom", function() {
  svg.attr("transform", d3.event.transform)
}));

mtwichan avatar Dec 02 '18 20:12 mtwichan

@matthewchan15 Sorry, I did not understand you before. You should be specifying the zoom call in your application, after creating the svg parent container (the same container that you use to create the Circos instance). Make sure you attach the zoom call to that parent container. Then, that svg is going to include an inner svg (coming from circos.js). The zoom should be working because the structure will be svg > svg, instead of svg > div > svg.

jorgenunezsiri avatar Dec 02 '18 20:12 jorgenunezsiri

@jnunez17 The issue was that I wrongly assumed that d3-zoom was included in the package,json. Once I installed it, everything worked wonderfully 👍

mtwichan avatar Dec 20 '18 19:12 mtwichan