Search code examples
javascriptjqueryhtmlcsscanvasjs

CanvasJS graphs skewed until zoom level changed?


window.onload = function() {
  var chart = new CanvasJS.Chart("chartContainer", {
    zoomEnabled: false,
    animationEnabled: true,
    title: {
      text: "Mobile Phone Subscriptions"
    },
    axisY2: {
      valueFormatString: "0.0 bn",

      maximum: 1.2,
      interval: .2,
      interlacedColor: "#F5F5F5",
      gridColor: "#D7D7D7",
      tickColor: "#D7D7D7"
    },
    theme: "theme2",
    toolTip: {
      shared: true
    },
    legend: {
      verticalAlign: "bottom",
      horizontalAlign: "center",
      fontSize: 15,
      fontFamily: "Lucida Sans Unicode"

    },
    data: [{
        type: "line",
        lineThickness: 3,
        axisYType: "secondary",
        showInLegend: true,
        name: "India",
        dataPoints: [{
            x: new Date(2001, 0),
            y: 0
          }, {
            x: new Date(2002, 0),
            y: 0.001
          }, {
            x: new Date(2003, 0),
            y: 0.01
          }, {
            x: new Date(2004, 0),
            y: 0.05
          }, {
            x: new Date(2005, 0),
            y: 0.1
          }, {
            x: new Date(2006, 0),
            y: 0.15
          }, {
            x: new Date(2007, 0),
            y: 0.22
          }, {
            x: new Date(2008, 0),
            y: 0.38
          }, {
            x: new Date(2009, 0),
            y: 0.56
          }, {
            x: new Date(2010, 0),
            y: 0.77
          }, {
            x: new Date(2011, 0),
            y: 0.91
          }, {
            x: new Date(2012, 0),
            y: 0.94
          }


        ]
      }, {
        type: "line",
        lineThickness: 3,
        showInLegend: true,
        name: "China",
        axisYType: "secondary",
        dataPoints: [{
            x: new Date(2001, 00),
            y: 0.18
          }, {
            x: new Date(2002, 00),
            y: 0.2
          }, {
            x: new Date(2003, 0),
            y: 0.25
          }, {
            x: new Date(2004, 0),
            y: 0.35
          }, {
            x: new Date(2005, 0),
            y: 0.42
          }, {
            x: new Date(2006, 0),
            y: 0.5
          }, {
            x: new Date(2007, 0),
            y: 0.58
          }, {
            x: new Date(2008, 0),
            y: 0.67
          }, {
            x: new Date(2009, 0),
            y: 0.78
          }, {
            x: new Date(2010, 0),
            y: 0.88
          }, {
            x: new Date(2011, 0),
            y: 0.98
          }, {
            x: new Date(2012, 0),
            y: 1.04
          }


        ]
      }, {
        type: "line",
        lineThickness: 3,
        showInLegend: true,
        name: "USA",
        axisYType: "secondary",
        dataPoints: [{
            x: new Date(2001, 00),
            y: 0.16
          }, {
            x: new Date(2002, 0),
            y: 0.17
          }, {
            x: new Date(2003, 0),
            y: 0.18
          }, {
            x: new Date(2004, 0),
            y: 0.19
          }, {
            x: new Date(2005, 0),
            y: 0.20
          }, {
            x: new Date(2006, 0),
            y: 0.23
          }, {
            x: new Date(2007, 0),
            y: 0.261
          }, {
            x: new Date(2008, 0),
            y: 0.289
          }, {
            x: new Date(2009, 0),
            y: 0.3
          }, {
            x: new Date(2010, 0),
            y: 0.31
          }, {
            x: new Date(2011, 0),
            y: 0.32
          }, {
            x: new Date(2012, 0),
            y: 0.33
          }


        ]
      }



    ],
    legend: {
      cursor: "pointer",
      itemclick: function(e) {
        if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
          e.dataSeries.visible = false;
        } else {
          e.dataSeries.visible = true;
        }
        chart.render();
      }
    }
  });

  chart.render();
}
#control_panel_container {
  text-align: center;
}
.cp_content_container {
  padding-top: 12px;
  text-align: left;
  color: #373737;
}
.cp_content_container > div {
  display: none;
}
input.control_panel_tabs {
  display: none;
}
label.control_panel_tabs {
  font-family: Verdana, Tahoma, sans-serif;
  font-weight: 600;
  background-color: #C0B9C7;
  color: white;
  display: inline-block;
  padding: 15px 25px;
  text-align: center;
  border: 2px solid black;
  border-radius: 15px;
}
label.control_panel_tabs:hover {
  background-color: #AA95B9;
  color: #fff;
  cursor: pointer;
}
input:checked + label.control_panel_tabs {
  background: #9471AB;
  color: #fff;
}
#cp_tab1:checked ~ .cp_content_container #cp_content1,
#cp_tab2:checked ~ .cp_content_container #cp_content2 {
  display: block;
}
<script src="http://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="control_panel_container">
  <input class="control_panel_tabs" id="cp_tab1" type="radio" name="cp_tabs" checked>
  <label class="control_panel_tabs" for="cp_tab1">tab 1</label>
  <input class="control_panel_tabs" id="cp_tab2" type="radio" name="cp_tabs">
  <label class="control_panel_tabs" for="cp_tab2">tab 2</label>
  <div class="cp_content_container">
    <div id="cp_content1"></div>
    <div id="cp_content2">
      <div id="chartContainer" style="height: 300px; width: 100%;"></div>
    </div>
  </div>
</div>

I have a chart in a tab that's by default hidden. When a user clicks on that tab, they appear. However, they're skewed a bit, smooshed horizontally and stretched vertically. See the Fiddle for what I mean, it's under "tab 2".

Changing the browser's zoom level (in Firefox at least) seems to make it correct itself.

I noticed if I put it inside tab 1, however, on page load it displays correctly. It's only when it's not the default tab does it warp around and requires zoom change to display correctly.

What's going on here? It looks like the graph is only rendered when I open the tab (judging by the animation). I was thinking maybe it's because of the display property in CSS but maybe it's because it needs to be rendered at page load?

Here's an editable fiddle: http://jsfiddle.net/ryfy8j9s/1/


Solution

  • The problem is that the chart's default width is set to 500, and even though you are calling chart.render() in window.onload, since its container is not visible it creates the chart at the default width and it's stuck there until chart.render() is called again (e.g., for a window resize). This isn't the only issue. For example, if you resize the window to fix the chart, but then click back on tab1, resize the window again, and click back to tab2, once again the chart is the wrong size.

    You could set an explicit width when the chart is created, but that would make the chart non-responsive to resize, which probably isn't what you want.

    I would suggest a click handler on tab2 to check for this exact situation and call chart.render() only if the chart is visible and not the same size as its container:

    window.onload = function () {
        $("#cp_tab2").on("click", function() {
            if ($("#chartContainer").is(":visible") && $("#chartContainer canvas").width() !== $("#chartContainer").width()) {
                chart.render();
            }
        });
    
        var chart = new CanvasJS.Chart("chartContainer", {
            zoomEnabled: false,
    // etc.
    

    I tried this on your fiddle and it fixes the issue. See my fork of your jsFiddle. with this working.