Chartjs-Html canvas element resets width and height to zero after drag/drop

1👍

This is a Chart.js issue of version 3.6.0 and fixed in version 3.6.1. Example below:

var $sourceTile = null;
var charts = [];

$(() => {
  $(".buttons-container a").on("click", btnClickHandler);

  renderChart("canvas1", 'doughnut');
  renderChart("canvas2", "line");

  attachDropHandlers();
});

attachDropHandlers = () => {
  $(".tile").off("dragstart").off("dragover").off("drop");
  $(".tile .report").on("dragstart", dragStartHandler);
  $(".tile.empty").on("dragover", dragOverHandler);
  $(".tile.empty").on("drop", dropHandler);
}

dragStartHandler = (e) => {
  const $target = $(e.target);
  const $report = $target.is(".report") ? $target : $target.parents(".report");
  $sourceTile = $report.parents(".tile");

  e.originalEvent.dataTransfer.setData("application/dashboard", $report[0].id);
  e.originalEvent.dataTransfer.effectAllowed = "move";
  e.originalEvent.dataTransfer.dropEffect = "move";
}

dragOverHandler = (e) => {
  e.preventDefault();
  e.originalEvent.dataTransfer.dropEffect = "move";
}

dropHandler = (e) => {
  e.preventDefault();
  const id = e.originalEvent.dataTransfer.getData("application/dashboard");
  if (id) {
    $("#" + id).appendTo(".tile.empty");
    $(".tile.empty").removeClass("empty");

    if ($sourceTile) {
      $sourceTile.addClass("empty");
      attachDropHandlers();
    }
  }
}

renderChart = (canvasId, type) => {
  const labels = ["Red", "Green", "Blue"];
  const data = [30, 25, 42];
  const colors = ['rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)'];
  const canvas = document.getElementById(canvasId);
  const ctx = canvas.getContext('2d');
  const chart = new Chart(ctx, {
    type: type,
    data: {
      labels: labels,
      datasets: [{
        data: data,
        backgroundColor: colors,
        borderColor: colors,
        borderWidth: 1
      }]
    },
    options: {
      responsive: true,
      maintainAspectRatio: true,
      aspectRatio: 1,
      plugins: {
        legend: {
          display: false
        },
        htmlLegend: {
          tile: this.$tile,
          maxItems: 8
        }
      }
    }
  });

  chart.update();
  charts.push(chart);
}

btnClickHandler = (e) => {
  const button = e.target.id;
  switch (button) {
    case "btn1":
      charts.forEach((chart) => chart.update());
      break;
    case "btn2":
      charts.forEach((chart) => chart.update('resize'));
      break;
    case "btn3":
      charts.forEach((chart) => chart.render());
      break;
    case "btn4":
      charts.forEach((chart) => chart.resize());
      break;
    case "btn5":
      charts.forEach((chart) => chart.resize(120, 120));
      break;
  }
}
html,
body {
  background-color: #eee;
}

h3 {
  margin: 0;
  padding: 10px;
}

.dashboard {}

.dashboard .tile {
  display: inline-block;
  vertical-align: top;
  margin: 5px;
  height: 250px;
  width: 250px;
}

.tile.empty {
  border: 2px dashed #ccc;
}

.report {
  height: 250px;
  width: 250px;
  background-color: #fff;
  border-radius: 3px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}

.buttons-container {
  display: flex;
  justify-content: space-between;
  margin: 20px 0;
}

.buttons-container a {
  background-color: #673AB7;
  color: #EDE7F6;
  cursor: pointer;
  padding: 10px 15px;
  border-radius: 3px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}

.buttons-container a:hover {
  background-color: #7E57C2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.6.1/dist/chart.min.js"></script>
<div class="dashboard">
  <div class="tile">
    <div id="report1" class="report" draggable="true">
      <h3>
        Report 1
      </h3>
      <div style="padding:10px;height:180px;width:180px">
        <canvas id="canvas1"></canvas>
      </div>
    </div>

  </div>
  <div class="tile">
    <div id="report2" class="report" draggable="true">
      <h3>
        Report 2
      </h3>
      <div style="padding:10px;height:180px;width:180px">
        <canvas id="canvas2"></canvas>
      </div>
    </div>

  </div>
  <div class="tile empty">

  </div>
</div>

<div class="buttons-container">
  <a id="btn1">update()</a>
  <a id="btn2">update('resize')</a>
  <a id="btn3">render()</a>
  <a id="btn4">resize()</a>
  <a id="btn5">resize(120,120)</a>
</div>

Leave a comment