jiahuang / d3-timeline

Simple JS timeline plugin for d3
1.04k stars 280 forks source link

Zoomable timeline #57

Open inodb opened 9 years ago

inodb commented 9 years ago

It would be great if one could zoom in on the timeline with the mousewheel (perhaps only along x axis) and move the timeline with dragging. Currently there are only examples of using the mousewheel for horizontal scrolling. Any suggestions on how one could implement this?

jiahuang commented 9 years ago

I know that d3 has zoom and drag functions though I've never played around with them.

inodb commented 9 years ago

Ok, thanks for the reply. I might have a look at this.

JohnV7 commented 9 years ago

Any success implementing zooming ? Would indeed be a great feature for this nice timeline !

inodb commented 9 years ago

Not yet, I'm using d3-timeline to make a clinical timeline (https://github.com/cBioPortal/clinical-timeline/tree/gh-pages). The zoom feature has low priority at the moment.

teian commented 9 years ago

I Implemented something zoom like. I created a helper function which triggers when a select dropdown changes. in the select there are different zoom levels defined.

Code is like this

https://gist.github.com/Tak0r/ba4464078122f7748982

hope this helps

kwe7 commented 7 years ago

Has anyone gotten around to implementing this zoom with the d3-timeline.js script? I see the following code from d3-timeline.js, but is it enough to perform a scrollable zoom? How would one invoke this on a timeline object?

  if (width > gParentSize.width) {
    var move = function() {
      var x = Math.min(0, Math.max(gParentSize.width - width, d3.event.translate[0]));
      zoom.translate([x, 0]);
      g.attr("transform", "translate(" + x + ",0)");
          scroll(x*scaleFactor, xScale);
    };

    var zoom = d3.behavior.zoom().x(xScale).on("zoom", move);

    gParent
      .attr("class", "scrollable")
      .call(zoom);
  }

I have a feeling it's something along the lines of the following (I commented the portion of the code where I think I ought to be invoking the zoom):

 window.onload = function() {
         function timelineRelativeTime() {
           function to_relTime(sec) {
              var allsec = sec/1000;
              var sec = ~~(allsec % 60);
              if (sec < 10) {sec = "0" + sec};
              var allmin = allsec / 60;
              var allhour = ~~(allmin / 60);
              var hour = allhour % 60;
                  var min = ~~(allmin % 60);
                  var time = (hour + ":" + min + ":" + sec);

              return time;
           }

               var chart = d3.timeline()
                    .stack()
                    .margin({left:200, right:60, top:10, bottom:0})
                    .width($("#timelineRelativeTime").parent().width())
            .rotateTicks(45)
      //        .scroll(function ()
                    .hover(function (d, i, datum) {
                        tooltipDiv.transition().duration(200).style("opacity", .9);
                        tooltipDiv.html(d.label + " -- " + (to_relTime(d.starting_time) + " - " + to_relTime(d.ending_time))).style("left", (d3.event.pageX) + "px").style("top", (d3.event.pageY - 34) + "px");
        })
                    .mouseout(function (d, i, datum) {
                        tooltipDiv.transition().duration(500).style("opacity", 0);
                    })
                    .tickFormat({
                        format: function(d) { return d3.time.format.utc("%H:%M")(d) },
                        tickTime: d3.time.minutes,
                        tickInterval: 5,
                        tickSize: 15,
                    });
                var svg = d3.select("#timelineRelativeTime").append("svg").attr("width", chart.width())
            .datum(testDataRelative).call(chart)

                var x = d3.scale.linear()
                    .domain([{{ starting_time }}, {{ ending_time }}])
        .range([200, chart.width() - 60]);  

                var tooltipDiv = d3.select("body").append("div")
                    .attr("class", "tooltip")
                    .style("opacity", 0);

                {% for group in groups %}
                    {% for sequence in group.sequences %}
                        {% for activity in sequence.activities %}
                            svg.append("line")
                                .attr("x1", x({{ activity.starting_time }}))
                                .attr("y1", 35)
                                .attr("x2", x({{ activity.ending_time }}))
                                .attr("y2", chart.height()).style("stroke-width", 1)
                                {% if activity.has_overlap %}
                                    .style("stroke", "red")
                                {% else %}
                                    .style("stroke", "gray")
                                {% endif %}
                                    .style("fill", "none");

                        {% endfor %}
                    {% endfor %}
                {% endfor %}

            }

            timelineRelativeTime();       
   }

I should also like to mention that this is part of a project that was handed off to me, thus why I am consulting this thread and not utilizing other zoom documentation very well. Any help is much appreciated!

fidlr commented 7 years ago

@kwe7 check out my pull request above (#93), I hope it helps.