【问题标题】:Prevent y-axis labels from being cut off防止y轴标签被切断
【发布时间】:2022-01-31 12:00:36
【问题描述】:

我的图表 y 标签被切断,通过尝试在 stackoverflow 上找到的不同解决方案(例如在标签中添加空格或设置布局填充)并没有解决问题。

代码

const optionsTotali = {
  maintainAspectRatio: false,
  responsive: true,
  plugins: {
    legend: {
      display: false
    },
    tooltip: {
      displayColors: false,
      mode: "index",
      intersect: 0,
      callbacks: {
        label: function(context) {
          return "€" + context.parsed.y.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,').replace(/[,.]/g, m => (m === ',' ? '.' : ','));
        }
      }
    },
  },
  scales: {
    y: {
      grid: {
        display: false
      },
      ticks: {
        min: 0,
        beginAtZero: true,
        sampleSize: 1,
        callback: function(value, index, values) {
          return "€" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
        }
      }
    }
  }
};

const ctx = document.getElementById("chartTotali").getContext('2d');
const chartTotali = new Chart(ctx, {
  type: 'line',
  data: {
    labels: [
      "08:00",
      "09:00",
      "10:00",
      "11:00",
      "12:00",
      "13:00",
      "14:00",
      "15:00",
      "16:00",
      "17:00",
      "18:00",
      "19:00",
      "20:00"
    ],
    datasets: [{
      label: "Totale €",
      fill: true,
      backgroundColor: '#0084ff',
      borderColor: '#0084ff',
      borderWidth: 2,
      pointBackgroundColor: '#0084ff',
      data: [
        "17089.36",
        "394279.52",
        "514863.02",
        "540198.74",
        "379222.06",
        "8793.42",
        "79.58",
        "116379.41",
        "444580.43",
        "506663.36",
        "457947.28",
        "138158.94",
        "398.46"
      ],
    }]
  },
  options: optionsTotali
});
.card-chart {
  overflow: hidden;
}

.card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  word-wrap: break-word;
  background-color: #fff;
  background-clip: border-box;
  border: 0.0625rem solid rgba(34, 42, 66, .05);
  border-radius: 0.2857rem;
}

.card {
  background: #27293d;
  border: 0;
  position: relative;
  width: 100%;
  margin-bottom: 30px;
  box-shadow: 0 1px 20px 0 rgb(0 0 0 / 10%);
}

.card .card-body {
  padding: 15px 15px 15px 15px;
}

.card-body {
  flex: 1 1 auto;
  padding: 1.5rem;
}

.card-chart .chart-area {
  height: 220px;
  width: calc(100% + 30px);
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js"></script>
<div class="card card-chart">
  <div class="card-header">
    <div class="row">
      <div class="col-sm-6 text-left">
        <h5 class="card-category">Totale vendite</h5>
        <h2 class="card-title">Totali</h2>
      </div>
    </div>
  </div>
  <div class="card-body">
    <div class="chart-area">
      <canvas id="chartTotali" width="1563" height="220" style="display: block; box-sizing: border-box; height: 220px; width: 1563px;"></canvas>
    </div>
  </div>
</div>

【问题讨论】:

    标签: javascript chart.js


    【解决方案1】:

    y 轴配置中的sampleSize 属性是罪魁祸首,因为你把它放在1 中,它只查看第一个刻度以了解它可以使用的长度。但是您数组中的其他数据要大得多,因此不适合。删除此属性或将其设置为更大的数字以便采样更多的刻度将解决您的行为(删除将产生最一致的结果)。

    const optionsTotali = {
      maintainAspectRatio: false,
      responsive: true,
      plugins: {
        legend: {
          display: false
        },
        tooltip: {
          displayColors: false,
          mode: "index",
          intersect: 0,
          callbacks: {
            label: function(context) {
              return "€" + context.parsed.y.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,').replace(/[,.]/g, m => (m === ',' ? '.' : ','));
            }
          }
        },
      },
      scales: {
        y: {
          grid: {
            display: false
          },
          ticks: {
            min: 0,
            beginAtZero: true,
            callback: function(value, index, values) {
              return "€" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
            }
          }
        }
      }
    };
    
    const ctx = document.getElementById("chartTotali").getContext('2d');
    const chartTotali = new Chart(ctx, {
      type: 'line',
      data: {
        labels: [
          "08:00",
          "09:00",
          "10:00",
          "11:00",
          "12:00",
          "13:00",
          "14:00",
          "15:00",
          "16:00",
          "17:00",
          "18:00",
          "19:00",
          "20:00"
        ],
        datasets: [{
          label: "Totale €",
          fill: true,
          backgroundColor: '#0084ff',
          borderColor: '#0084ff',
          borderWidth: 2,
          pointBackgroundColor: '#0084ff',
          data: [
            "17089.36",
            "394279.52",
            "514863.02",
            "540198.74",
            "379222.06",
            "8793.42",
            "79.58",
            "116379.41",
            "444580.43",
            "506663.36",
            "457947.28",
            "138158.94",
            "398.46"
          ],
        }]
      },
      options: optionsTotali
    });
    .card-chart {
      overflow: hidden;
    }
    
    .card {
      display: flex;
      flex-direction: column;
      min-width: 0;
      word-wrap: break-word;
      background-color: #fff;
      background-clip: border-box;
      border: 0.0625rem solid rgba(34, 42, 66, .05);
      border-radius: 0.2857rem;
    }
    
    .card {
      background: #27293d;
      border: 0;
      position: relative;
      width: 100%;
      margin-bottom: 30px;
      box-shadow: 0 1px 20px 0 rgb(0 0 0 / 10%);
    }
    
    .card .card-body {
      padding: 15px 15px 15px 15px;
    }
    
    .card-body {
      flex: 1 1 auto;
      padding: 1.5rem;
    }
    
    .card-chart .chart-area {
      height: 220px;
      width: calc(100% + 30px);
    }
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js"></script>
    <div class="card card-chart">
      <div class="card-header">
        <div class="row">
          <div class="col-sm-6 text-left">
            <h5 class="card-category">Totale vendite</h5>
            <h2 class="card-title">Totali</h2>
          </div>
        </div>
      </div>
      <div class="card-body">
        <div class="chart-area">
          <canvas id="chartTotali" width="1563" height="220" style="display: block; box-sizing: border-box; height: 220px; width: 1563px;"></canvas>
        </div>
      </div>
    </div>

    【讨论】:

    • 该死的,我在同一页面中有很多其他图表没有这个问题,但只是没有注意到该属性
    【解决方案2】:

    您可以使用sampleSize: x, 属性来处理它。您可以删除,然后 y 轴将正确显示。非常感谢@LeeLenalee!

    const optionsTotali = {
      maintainAspectRatio: false,
      responsive: true,
      plugins: {
        legend: {
          display: false
        },
        tooltip: {
          displayColors: false,
          mode: "index",
          intersect: 0,
          callbacks: {
            label: function(context) {
              return "€" + context.parsed.y.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,').replace(/[,.]/g, m => (m === ',' ? '.' : ','));
            }
          }
        },
      },
      scales: {
        y: {
          grid: {
            display: false
          },
          ticks: {
            min: 0,
            beginAtZero: true,
            callback: function(value, index, values) {
              return "€" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
            }
          }
        }
      }
    };
    
    const ctx = document.getElementById("chartTotali").getContext('2d');
    const chartTotali = new Chart(ctx, {
      type: 'line',
      data: {
        labels: [
          "08:00",
          "09:00",
          "10:00",
          "11:00",
          "12:00",
          "13:00",
          "14:00",
          "15:00",
          "16:00",
          "17:00",
          "18:00",
          "19:00",
          "20:00"
        ],
        datasets: [{
          label: "Totale €",
          fill: true,
          backgroundColor: '#0084ff',
          borderColor: '#0084ff',
          borderWidth: 2,
          pointBackgroundColor: '#0084ff',
          data: [
            "17089.36",
            "394279.52",
            "514863.02",
            "540198.74",
            "379222.06",
            "8793.42",
            "79.58",
            "116379.41",
            "444580.43",
            "506663.36",
            "457947.28",
            "138158.94",
            "398.46"
          ],
        }]
      },
      options: optionsTotali
    });
    .card-chart {
      overflow: hidden;
    }
    
    .card {
      display: flex;
      flex-direction: column;
      min-width: 0;
      word-wrap: break-word;
      background-color: #fff;
      background-clip: border-box;
      border: 0.0625rem solid rgba(34, 42, 66, .05);
      border-radius: 0.2857rem;
    }
    
    .card {
      background: #27293d;
      border: 0;
      position: relative;
      width: 100%;
      margin-bottom: 30px;
      box-shadow: 0 1px 20px 0 rgb(0 0 0 / 10%);
    }
    
    .card .card-body {
      padding: 15px 15px 15px 15px;
    }
    
    .card-body {
      flex: 1 1 auto;
      padding: 1.5rem;
      background: ;
    }
    
    .card-chart .chart-area {
      height: 220px;
      width: calc(100% + 30px);
    }
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js"></script>
    <div class="card card-chart">
      <div class="card-header">
        <div class="row">
          <div class="col-sm-6 text-left">
            <h5 class="card-category">Totale vendite</h5>
            <h2 class="card-title">Totali</h2>
          </div>
        </div>
      </div>
      <div class="card-body">
        <div class="chart-area">
          <canvas id="chartTotali"  style=""></canvas>
        </div>
      </div>
    </div>

    【讨论】:

    • 这只有在第 10 个属性之后没有非常大的值时才能解决问题,最好的解决方案是不使用它
    • @LeeLenalee 非常感谢您提供重要且正确的建议。我真的不知道,我刚刚学到了一些新东西。谢谢!我已经删除了sampleSize 并调整了我的答案。
    【解决方案3】:

    测试您的代码后,问题似乎来自这部分:

        callback: function(value, index, values) {
          return "€" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
        }
    

    我的猜测是:由于您在异步回调中更改标签,chart.js 不再知道要应用哪个宽度,而是使用第一个标签的宽度...

    你可以通过这样设置宽度来解决这个问题:

      afterFit: function(scaleInstance) {
        scaleInstance.width = 100; // sets the width to 100px
      }
    

    来源:How to set fixed width for labels in chartjs

    【讨论】:

    • 虽然这解决了问题,但它不是一个可扩展的解决方案,您要么放弃现在浪费的大量空间,要么如果数字变得非常大并且您的宽度需要增加。
    • @LeeLenalee 我猜你可以事先根据 min-max 值估计宽度
    【解决方案4】:

    您可以使用 sampleSize 属性

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多