chartjs / Chart.js

Simple HTML5 Charts using the <canvas> tag
https://www.chartjs.org/
MIT License
64.33k stars 11.89k forks source link

y axis labels truncated on left side of window #3227

Closed davidmichaelkarr closed 8 years ago

davidmichaelkarr commented 8 years ago

I have a SPA using angular, angular-chart, charts.js, and bootstrap. It just dumps a bunch of bar and line charts to the page in a fluid container (it's an internal application dashboard). In general, it works perfectly fine, but I noticed a minor annoyance in that one chart that gets drawn on the left side of the window is getting the first digit of the y-axis label cut off. In the typical window size that I display this in, there are four charts that get rendered on the left side of the window, and this is the only one that gets a truncated label. There's nothing unusual about the chart that gets truncated, it's very similar to all of the other charts, just using slightly different data.

I've tried doing some small resizing of the window (small meaning doesn't cause charts to be redrawn on a different row, or the number of rows to change), and I see no change to the symptom. If I do major resizing, it appears that either Firefox or the Javascript runtime gets hung up and I have to kill the process.

I see the same symptoms in Firefox and IE.

I don't really know if this is a charts.js problem or a bootstrap problem (angular-chart seems unlikely). I was going to post a similar question in the bootstrap forum.

I'm going to attach five screenshots. One shows an overall view of the page, showing the one truncated chart. The other four are screenshots from Firebug, showing that the resulting "margin-left" property for the bad chart is "-15px", and the other four are "5px". row3col1cssmodified row2col1cssmodified row1col1cssmodified dashboardshowingtruncatedyaxislabelsmodified row4col1cssmodified

The following is my HTML:

<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" data-ng-app="OrdersApp">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet"/>
  <title>Orders</title>
  <style type="text/css">
  </style>
</head>
<body data-ng-controller="OrdersCtrl">
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
  <script src="//cdn.jsdelivr.net/chart.js/2.2.1/Chart.min.js"></script>
  <script src="//cdn.jsdelivr.net/angular.chartjs/1.0.0/angular-chart.min.js"></script>
  <script src="js/ordersMod.js"></script>
  <script src="js/constants.js"></script>
  <script src="js/utilsMod.js"></script>
  <script src="js/ordersApp.js"></script>

  <div class="container-fluid">
    <div ng-if="dataCenterDataList == null || dataCenterDataList.length == 0">
      <h1 class="text-center col-md-4 col-md-offset-4">
        <em>Connection established. Waiting for data ...</em>
      </h1>
    </div>
    <div ng-if="dataCenterDataList != null && dataCenterDataList.length > 0">
      <h3 class="text-center">xxx</h3>
      <div class="row">
        <div ng-repeat="dataCenterData in last30MinutesDataCenterDataList">
          <div class="row col-md-3" style="margin-left: 5px">
            <canvas id="last30Minutes-chart-{{dataCenterData.dataCenter}}"
              class="chart chart-line" chart-data="dataCenterData.data"
              chart-labels="dataCenterData.labels"
              chart-series="dataCenterData.series"
              chart-options="dataCenterData.options"></canvas>
          </div>
        </div>
        <div ng-repeat="dataCenterData in dataCenterDataList">
          <div class="row col-md-3">
            <canvas id="daily-chart-{{dataCenterData.dataCenter}}"
              class="chart chart-bar" chart-data="dataCenterData.data"
              chart-labels="dataCenterData.labels"
              chart-series="dataCenterData.series"
              chart-options="dataCenterData.options"></canvas>
          </div>
        </div>
        <div class="row col-md-3" style="margin-left: 5px">
          <canvas id="aggregate-chart" class="chart chart-bar"
            chart-data="aggregateData.data"
            chart-labels="aggregateData.labels"
            chart-series="aggregateData.series"
            chart-options="aggregateData.options"></canvas>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

Edited code formatting

etimberg commented 8 years ago

@simonbrunel do you think these are related to the sizing issues you've been looking at / investigating?

simonbrunel commented 8 years ago

I don't think so because Chart.js doesn't alter the canvas container margins and apparently the canvas is correctly sized. We don't know what are the charts options, responsive config, etc. and I can't run the given code (missing dependencies). @davidmichaelkarr can you please provide us a link to that page online or an example on one of these websites?

davidmichaelkarr commented 8 years ago

I can't give you an external link to it, and putting together a full example would take some time. In the meantime, it's possible it could help if I just include here a dump of the "data" used to draw that particular errant chart, which is this:

(Sigh. I can't figure out how to include this in github markdown so it looks reasonable.)

dataCenter "Allen" series ["Received", "BE", "OT", "OCE"] labels 0 "00:00" 1 "01:00" 2 "02:00" 3 "03:00" 4 "04:00" 5 "05:00" 6 "06:00" 7 "07:00" 8 "08:00" 9 "09:00" 10 "10:00" 11 "11:00" 12 "12:00" 13 "13:00" data 0 0 7 1 7 2 9 3 10 4 23 5 42 6 93 7 109 8 119 9 129 10 112 11 117 12 87 13 15 1 0 7 1 7 2 9 3 10 4 23 5 42 6 92 7 108 8 120 9 128 10 110 11 117 12 88 13 15 2 0 7 1 7 2 9 3 10 4 23 5 42 6 93 7 109 8 118 9 128 10 111 11 117 12 87 13 15 3 0 7 1 7 2 9 3 9 4 23 5 41 6 92 7 107 8 123 9 127 10 106 11 112 12 97 13 15 options legend display true title display true text "Daily: Allen"

Please ask if there's any part of this that isn't clear.

simonbrunel commented 8 years ago

@davidmichaelkarr we would need to debug the surrounding HTML as a whole to determinate if it's an issue with Chart.js or angular or something else. I can't see why the HTML element margin would be changed by Chart.js, could be a caused by our responsive resizing implementation, maybe. You can try to set a fixed size (width and height) to the canvas and set the responsive config to false in the chart-options and see if the issue still present. You can also try to move that chart somewhere else in the layout to see if the issue is still on the same chart or if it's on the chart at this specific position.

davidmichaelkarr commented 8 years ago

I just did a bit of a head-slap because I realized that I had forgotten that I was already setting "margin-left: 5px" for the other charts. The one with the problem wasn't getting this manually set. I just tried adding the margin to all of them, and also removing it from all of them. When I remove it from all of them, all the charts drawn in the first column are truncated. With it on all of them, everything renders fine. I would think it's not ideal to have to hardcode this margin, but it will be a reasonable workaround for me at this point.

What do you want to do here?

simonbrunel commented 8 years ago

As @etimberg said, it can be our current responsive implementation + your fluid container that doesn't play well together. You can try to set the responsive: false option and a fixed canvas size to see if that changes something to the div margin values.

davidmichaelkarr commented 8 years ago

Wow. Turning off responsive by itself was a big mess. Some charts looked ok, some were squished, it created a big space where no charts were drawn. Pretty chaotic. I then tried adding a fixed width and height to all the canvases, but it just made some of them take up a little more space, but most of them were still mostly messed up. That's not very specific, but I don't think this strategy will end up finding any meaningful comparative results.

simonbrunel commented 8 years ago

IIRC, the only part of Chart.js that changes DOM style attributes is when responsive: true, and it should be only the canvas style width and height. The added iframe could also cause trouble to the fluid layout, but without a live example of the issue, we can't really know. The Chrome style inspector might also help to figure out where comes this negative margin from (i.e. directly set on the element or inherited from a stylesheet rule).

simonbrunel commented 8 years ago

I think the issue is in your code (and related to bootstrap)

image

The row class adds negative left/right margins (-15px) and you have this class for each chart and in the parent div. I would try to remove row from the canvas div wrapper: <div class="row col-md-3"> replaced by <div class="col-md-3">

davidmichaelkarr commented 8 years ago

Yeah, just found that out. Now to figure out why the heck Bootstrap does that.

davidmichaelkarr commented 8 years ago

Ok, I think I've got it more sane now. I'm not sure exactly what was happening, but I had inadvertently applied the "row" class at two different levels in the hierarchy, where the one at the lower level should not have been there. Once I removed the lower "row" reference, I was able to remove the hardcoded margin settings, and everything looks fine. Closing this noise.