8

I am making a page with dynamically created divs that resize on mouseover using a simple css class. I use it so these divs are small when the page is loaded then if a user wants a closer look they just mouse over.

CSS basically looks like this

.resize {
    width: 400px;
    height: 300px;
    transition: all 1s;
}

.resize:hover {
    width: 800px;
    height: 600px;
}

I am trying to make the plot I create with Plotly.js in this div automatically resize as the user mouses over.

JS code

function doGraph() {
    for(index = 0; index < divArr.length; ++index) {
        (function() {
            var d3 = Plotly.d3;

            var gd3 = d3.select("div[id='"+divArr[index]+"']");
                //.append('div')
                //.style({
                //    width: "95%", "margin-left": "2.5%",

                //    height: "95%", "margin-top": "2.5%"
                //});

            var gd = gd3.node();

            Plotly.newPlot(gd, [{
                mode:'lines',
                x: xArr[index],
                y: yArr[index], }], 
                        layout , {scrollZoom:true,modeBarButtonsToRemove:['sendDataToCloud'],showLink:false,displaylogo:false});

            //gd.onresize = function() {
            //    Plotly.Plots.resize(gd);
            //};
            window.addEventListener('resize', function() { Plotly.Plots.relayout(gd); });

        })();
    }
}

The commented out code shows where I'm not sure what I need to do to make this work. So far all the tinkering I've done has resulted in nothing.

Everything on the page is dynamically created in c# codebehind based on txt files generated by my users.

I found a q/a that seemed relevent Here but to be honest I'm not sure how it might apply to my code.

YakovL
  • 7,557
  • 12
  • 62
  • 102
FrankTheDank
  • 197
  • 1
  • 2
  • 9

3 Answers3

8

Have a look at plotly's resize function.

The graph in the snippet below randomly resizes on hover-over. I hope you can easily modify it for your use.

(function() {
  var d3 = Plotly.d3;

  var WIDTH_IN_PERCENT_OF_PARENT = 60,
    HEIGHT_IN_PERCENT_OF_PARENT = 80;

  var gd3 = d3.select('#myDiv')
    .style({
      width: (Math.random() + Math.random()) * WIDTH_IN_PERCENT_OF_PARENT + '%',
      'margin-left': (100 - WIDTH_IN_PERCENT_OF_PARENT) / 2 + '%',

      height: (Math.random() + Math.random()) * HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
      'margin-top': (100 - HEIGHT_IN_PERCENT_OF_PARENT) / 2 + 'vh'
    });

  var gd = gd3.node();

  a = Plotly.plot(gd, [{
    type: 'bar',
    x: [1, 2, 3, 4],
    y: [5, 10, 2, 8],

  }], {
    title: 'Random resize on hover',
    font: {
      size: 16
    }
  });

  document.getElementById("myDiv").on('plotly_hover', function(data) {
    window.alert("I'm resizing now");
    gd3 = d3.select('#myDiv')
      .style({
        width: (0.5 + Math.random() + Math.random()) * WIDTH_IN_PERCENT_OF_PARENT + '%',
        height: (0.5 + Math.random() + Math.random()) * HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
      });
    gd = gd3.node()
    Plotly.Plots.resize(gd);;
  });


})();
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='myDiv'></div>

(function() {
  var d3 = Plotly.d3;

  var WIDTH_IN_PERCENT_OF_PARENT = 60,
    HEIGHT_IN_PERCENT_OF_PARENT = 80;

  var gd3 = d3.select('#myDiv')
    .style({
      width: WIDTH_IN_PERCENT_OF_PARENT + '%',
      'margin-left': (100 - WIDTH_IN_PERCENT_OF_PARENT) / 2 + '%',

      height: HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
      'margin-top': (100 - HEIGHT_IN_PERCENT_OF_PARENT) / 2 + 'vh'
    });

  var gd = gd3.node();

  a = Plotly.plot(gd, [{
    type: 'bar',
    x: [1, 2, 3, 4],
    y: [5, 10, 2, 8],

  }], {
    title: 'Double on hover, normal on unhover',
    font: {
      size: 16
    }
  });

  document.getElementById("myDiv").on('plotly_hover', function(data) {
    gd3.style({
        width: 2 * WIDTH_IN_PERCENT_OF_PARENT + '%',
        height: 2 * HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
      });
    gd = gd3.node()
    Plotly.Plots.resize(gd);;
  });

  document.getElementById("myDiv").on('plotly_unhover', function(data) {
    gd3.style({
        width: WIDTH_IN_PERCENT_OF_PARENT + '%',
        height: HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
      });
    gd = gd3.node()
    Plotly.Plots.resize(gd);;
  });


})();
<script src="https://cdn.plot.ly/plotly-1.2.0.min.js"></script>
<div id='myDiv'></div>
Maximilian Peters
  • 30,348
  • 12
  • 86
  • 99
  • 2
    Thanks, I think this is the right answer and I can rework my code now cause I solved it with that: `var update = { width: divWidth, height: divHeight }; Plotly.relayout(chartDivId,update);` – phil Nov 15 '16 at 08:59
  • This is close to working for me. It's not as smooth as the CSS transitions but it's ok for now. Only change I really made was to not reselect the gd since we already did it above. Seems to work but is that a mistake? My other follow up question is if there is a 'plotly_hover_off' or something I can use for when my mouse moves away. Either way this has been the best solution I've found so far! – FrankTheDank Nov 16 '16 at 18:04
  • `var updateL = { width: 800, height: 600 }; var updateS = { width: 400, height: 300 }; document.getElementById(divArr[index]).on('plotly_hover', function(data) { Plotly.relayout(gd,updateL); }).on('plotly_unhover', function(data){ Plotly.relayout(gd,updateS); });` Here is what I'm using and it MOSTLY works except it seems to sometimes flicker very quickly. – FrankTheDank Nov 16 '16 at 18:15
  • 1
    @Guernica88: you are looking for `plotly_unhover`, I added another example which uses this event as well. If you want to prevent flickering, store the time of the last event and once the event is triggered check if the last event was at least #n seconds ago and if not, just leave the function before the actual resize. – Maximilian Peters Nov 16 '16 at 21:52
3

A div can be resized, when adding the style properties resize:both; overflow: auto. Since plotly seems to reacts only for window resize, when the configuration responsive: true is passed, one can trigger such a window resize upon div resize. Detection of div resizing is explained in https://stackoverflow.com/a/44807059/11769765. Putting all together (https://jsfiddle.net/3cvnua0q/)

<html>
<head>
  <script type="text/javascript" src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>

<div id='myDiv' style="resize:both; overflow: auto; border: 1px solid; height:250px">
</div>

<script>

let observer = new MutationObserver(function(mutations) {
  window.dispatchEvent(new Event('resize'));
});

let child = document.getElementById('myDiv');
observer.observe(child, {attributes: true})

var trace1 = {
  type: 'bar',
  x: [1, 2, 3, 4],
  y: [5, 10, 2, 8],
}

var data = [trace1]
var layout = {
  margin: {l: 20, r: 10, b: 20, t: 10}
}
var config = {responsive: true}

Plotly.newPlot('myDiv', data, layout, config);
</script>

</body>
</html>
1

According to resize, responsive is passed as a configuration:

var config = {responsive: true}

Plotly.newPlot('myDiv', data, layout, config );