Изменение размера холста Chart.js

86

В ( Ошибка холста HTML5 Android WebView ) я разместил вопрос о построении графиков с использованием библиотеки Graph.js. Проблема в том, что если я вызываю функцию для построения графика несколько раз, размер холста меняется каждый раз. Каждый раз, когда график перерисовывается на одном и том же холсте, его размер также изменяется. Я также попытался установить размер холста, но безуспешно.

Что может быть причиной? Почему размер холста меняется каждый раз?

Яка
источник
Теперь их страница посвящена этому на официальном веб-сайте Chart.js, здесь: chartjs.org/docs/latest/general/responsive.html Протестировано решение, и оно работает нормально.
Amine27,

Ответы:

175

У меня было много проблем с этим, потому что после всего этого моя линейная графика выглядела ужасно при наведении курсора мыши, и я нашел более простой способ сделать это, надеюсь, это поможет :)

Используйте эти параметры Chart.js:

// Boolean - whether or not the chart should be responsive and resize when the browser does.

responsive: true,

// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container

maintainAspectRatio: false,
NoFlag
источник
Спасибо @NoFlag за ответ. Для меня атрибуты высоты и ширины не применялись к холсту, на случай, если кто-то окажется здесь, ища решение для попытки изменить размер холста, попробуйте установить отзывчивость на true. * Chart.defaults.global.responsive = false *
sghosh968,
13
Не забывайте, что для правильной работы этого метода вам нужно поместить холст в a <div>и установить высоту и / или ширину на указанном, <div>а не в холсте.
totymedli
2
Эти флаги теперь по умолчанию установлены true, поэтому вам не нужно их трогать: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira
Наряду с этим также установите ширину и высоту холста. Тогда нормально работает. Спасибо
Мажар МИК
63

Что происходит: Chart.js умножает размер холста при его вызове, а затем пытается уменьшить его с помощью CSS с целью предоставить графики с более высоким разрешением для устройств с высоким разрешением.

Проблема в том, что он не понимает, что уже сделал это, поэтому при последовательном вызове он умножает уже (удвоенный или любой другой) размер СНОВА, пока что-то не начнет ломаться. (Что на самом деле происходит, так это то, что он проверяет, следует ли добавлять больше пикселей на холст, изменяя атрибут DOM для ширины и высоты, если нужно, умножая его на некоторый коэффициент, обычно 2, затем меняя это, а затем изменяя стиль css атрибут, чтобы сохранить тот же размер на странице.)

Например, когда вы запускаете его один раз, а ширина и высота холста установлены на 300, он устанавливает их на 600, затем меняет атрибут стиля на 300 ... но если вы запустите его снова, он увидит, что ширина и высота DOM равны 600 (проверьте другой ответ на этот вопрос, чтобы понять, почему), а затем установите его на 1200, а ширину и высоту css на 600.

Не самое элегантное решение, но я решил эту проблему, сохранив повышенное разрешение для устройств Retina, просто задав ширину и высоту холста вручную перед каждым последовательным вызовом Chart.js

var ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 300;
var myDoughnut = new Chart(ctx).Doughnut(doughnutData);
jcmiller11
источник
Я столкнулся с этой ошибкой: Uncaught ReferenceError: doughnutData is not defined
Dulith De Costa
11
Err. да, это просто переменная-заполнитель, поскольку я просто не знаю, какие данные вы пытались отобразить.
jcmiller11
26

Это работает для меня:

<body>
    <form>
        [...]
        <div style="position:absolute; top:60px; left:10px; width:500px; height:500px;">
            <canvas id="cv_values"></canvas>

            <script type="text/javascript">
                var indicatedValueData = {
                    labels: ["1", "2", "3"],
                    datasets: [
                        {
                            [...]
                        };

                var cv_values = document.getElementById("cv_values").getContext("2d");
                var myChart = new Chart(cv_values, { type: "line", data: indicatedValueData });
            </script>
        </div>
    </form>
</body>

Существенный факт заключается в том, что мы должны установить размер холста в теге div.

Патрик Пирзер
источник
дать согласие! просто поместите холст в div, а затем убедитесь, что параметр «адаптивный» НЕ равен false (по умолчанию он истинен). Затем просто примените правило изменения размера к div.
NoelB 08
20

В IOS и Android браузер скрывает панель инструментов при прокрутке, тем самым изменяя размер окна, в которое включается lead chartjs для изменения размера графика. Решение состоит в том, чтобы сохранить соотношение сторон.

var options = { 
    responsive: true,
    maintainAspectRatio: true
}

Это должно решить вашу проблему.

Прадип Раджашекар
источник
6

Как предложил jcmiller11, установка ширины и высоты помогает. Немного более приятное решение - получить ширину и высоту холста перед рисованием диаграммы. Затем используйте эти числа для установки диаграммы при каждом последующем повторном рисовании диаграммы. Это гарантирует, что в коде javascript нет констант.

ctx.canvas.originalwidth = ctx.canvas.width;
ctx.canvas.originalheight = ctx.canvas.height;

function drawchart() {
    ctx.canvas.width = ctx.canvas.originalwidth;
    ctx.canvas.height = ctx.canvas.originalheight;

    var chartctx = new Chart(ctx);
    myNewBarChart = chartctx.Bar(data, chartSettings); 
}
Анон
источник
Извините, не могли бы вы объяснить, как это работает? Например, я открываю страницу, тогда холст имеет один размер, но тогда, если я изменю размер окна, холст будет иметь другой размер (и, предположительно, мне не нужен исходный размер, потому что он был для предыдущего размера окна)?
kiradotee
6

Мне пришлось использовать здесь комбинацию нескольких ответов с некоторыми незначительными изменениями.

Во-первых, необходимо обернуть элемент холста в контейнер уровня блока. Я говорю вам, не позволяйте элементу холста иметь братьев и сестер; пусть это будет одинокий ребенок, ибо он упрямый и испорченный . (Обертка может не нуждаться в каких-либо ограничениях по размеру, но для безопасности может быть полезно применить к ней максимальную высоту.)

Убедившись, что предыдущие условия выполнены, при запуске диаграммы убедитесь, что используются следующие параметры:

var options = { 
    "responsive": true,
    "maintainAspectRatio": false
}

Если вы хотите настроить высоту диаграммы, сделайте это на уровне элемента холста.

<canvas height="500"></canvas>

Не пытайтесь обращаться с ребенком иначе. В результате должна получиться удовлетворительно и правильно составленная таблица, которая мирно лежит в своей кроватке.

истинное слияние
источник
3

У меня была аналогичная проблема, и я нашел ваш ответ .. В конце концов я нашел решение.

Похоже, что источник Chart.js имеет следующее (предположительно потому, что он не должен повторно отображать и совершенно другой график на одном холсте):

    //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
if (window.devicePixelRatio) {
    context.canvas.style.width = width + "px";
    context.canvas.style.height = height + "px";
    context.canvas.height = height * window.devicePixelRatio;
    context.canvas.width = width * window.devicePixelRatio;
    context.scale(window.devicePixelRatio, window.devicePixelRatio);
}

Это нормально, если он вызывается один раз, но когда вы перерисовываете несколько раз, вы в конечном итоге несколько раз меняете размер элемента DOM холста, вызывая изменение размера.

Надеюсь, это поможет!

yahfree
источник
1

Если у кого-то возникают проблемы, я нашел решение, которое не предполагает жертвовать отзывчивостью и т. Д.

Просто оберните свой холст в контейнер div (без стилей) и сбросьте содержимое div на пустой холст с идентификатором перед вызовом конструктора диаграммы.

Пример:

HTML:

<div id="chartContainer">
    <canvas id="myChart"></canvas>
</div>

JS:

$("#chartContainer").html('<canvas id="myChart"></canvas>');
//call new Chart() as usual
fpscolin
источник
1

Я попытался изменить размер холста с помощью jQuery, но это не сработало. Я думаю, что CSS3 - лучший вариант, который вы можете попробовать, если хотите, на определенном уровне масштабирования при наведении курсора.

Следующий вариант наведения из другой ссылки на код:

.style_prevu_kit:hover{
    z-index: 2;
    -webkit-transition: all 200ms ease-in;
    -webkit-transform: scale(1.5);
    -ms-transition: all 200ms ease-in;
    -ms-transform: scale(1.5);   
    -moz-transition: all 200ms ease-in;
    -moz-transform: scale(1.5);
    transition: all 200ms ease-in;
    transform: scale(1.5);
}

Следуйте моей ссылке на код:

https://codepen.io/hitman0775/pen/XZZzqN

Хитен Патель
источник
1

У меня была такая же проблема. Я смог решить эту проблему, установив опцию:

responsive: false,
maintainAspectRatio: true,
showScale: false,

И в css установите ширину контейнера div такой же, как у холста:

    #canvasContainer { 
      width: 300px;
    }
    
    canvas {
      width: 300px;
    }

Нова Цю
источник
0

У меня была такая же проблема масштабирования с использованием Angular CLI. Удалось заставить его работать, удалив эту строку из index.html:

<script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>

а затем в файле angular-cli.json в разделе сценариев, используя это:

"scripts": ["../node_modules/chart.js/dist/Chart.bundle.min.js"]

Источник : mikebarr58

Воутер Ванхерк
источник
-3

Добавьте divи это решит проблему

<div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>
Ришаб Бхардвадж
источник
-5
 let canvasBox = ReactDOM.findDOMNode(this.refs.canvasBox);
 let width = canvasBox.clientWidth;
 let height = canvasBox.clientHeight;
 let charts = ReactDOM.findDOMNode(this.refs.charts);
 let ctx = charts.getContext('2d');
 ctx.canvas.width = width;
 ctx.canvas.height = height;
 this.myChart = new Chart(ctx);
Робин ма
источник