Canvas растягивается при использовании CSS, но обычно со свойствами «width» / «height»

195

У меня есть 2 холста, один использует атрибуты HTML widthи heightего размер, другой использует CSS:

<canvas id="compteur1" width="300" height="300" onmousedown="compteurClick(this.id);"></canvas>
<canvas id="compteur2" style="width: 300px; height: 300px;" onmousedown="compteurClick(this.id);"></canvas>

Compteur1 отображается так, как должно, но не compteur2. Контент рисуется с использованием JavaScript на холсте размером 300x300.

Почему разница в отображении?

альтернативный текст

Sirber
источник

Ответы:

216

Кажется , что widthи heightатрибуты определяют ширину и высоту холста систему координат, в то время как свойства CSS просто определить размер окна , в котором будет показано.

Это объясняется по адресу http://www.whatwg.org/html#attr-canvas-width (требуется JS) или http://www.whatwg.org/c#attr-canvas-width (вероятно, будет есть ваш компьютер) :

canvasЭлемент имеет два атрибута для управления размером растрового элемента: widthа height. Эти атрибуты, если они указаны, должны иметь значения, которые являются действительными неотрицательными целыми числами . В правилах для разбора неотрицательных целых чисел должны быть использованы для получения их числовых значений. Если атрибут отсутствует или анализ его значения возвращает ошибку, то вместо этого должно использоваться значение по умолчанию. В widthатрибутах по умолчанию 300, и heightатрибут по умолчанию 150.

Самба
источник
11
на самом деле .. Я всегда думал, что прямые атрибуты, такие как "ширина" и "высота", были объявлены устаревшими в последних версиях HTML ..
Сирбер
4
О, по-видимому, на самом деле это довольно хорошо описано в whatwg.org/specs/web-apps/current-work/multipage/… (раздел #attr-canvas-width). Беда в том, что я нажал не на ту кнопку widthи #dom-canvas-widthвместо этого пошел в раздел. Подал w3.org/Bugs/Public/show_bug.cgi?id=9469 об этом.
SamB
3
Наличие API, который выглядит как, но принципиально отличается от другого (ширина CSS, высота). Вот это да.
Бен Астон
1
Важно различать их в тех случаях, когда вы хотите, чтобы внутренняя система координат была другой. (то есть для дисплеев сетчатки или 8-
битной
1
Это действительно сбивало с толку. Мы пытались установить ширину и высоту в CSS. Нам потребовалось 2 дня для того, чтобы узнать об этих двух различных интерпретациях ширины и роста. Просто вау ...
NME New Media Entertainment
39

Чтобы установить widthи heightвам нужно, вы можете использовать

canvasObject.setAttribute('width', '475');
fermar
источник
6
+1 el.setAttribute('width', parseInt($el.css('width')))сделал
свое дело
9
Что если я хочу, чтобы мой холст имел относительный размер? То есть, как имитировать width: 100%;свойство CSS?
Максбестер
1
Отличный ответ, но не забудьте также добавить canvasObject.setAttribute ('height', '123')!
Том Уэллс
Я не думаю, что вам нужно использовать .setAttribute () Я всегда использовал свойства .width и .height
Zorgatone
4
Plain JavaScript (без JQuery) версии с помощью getComputedStyle : canvas.setAttribute('width', window.getComputedStyle(canvas, null).getPropertyValue("width"));. Повторите для высоты.
Бен Дж
25

Для <canvas>элементов правила CSS widthи heightустановите фактический размер элемента canvas, который будет отображаться на странице. С другой стороны, атрибуты HTML widthи heightустанавливают размер системы координат или «сетки», которые будет использовать API холста.

Например, рассмотрим это ( jsfiddle ):

var ctx = document.getElementById('canvas1').getContext('2d');
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 30, 30);

var ctx2 = document.getElementById('canvas2').getContext('2d');
ctx2.fillStyle = "red";
ctx2.fillRect(10, 10, 30, 30);
canvas {
  border: 1px solid black;
}
<canvas id="canvas1" style="width: 50px; height: 100px;" height="50" width="100"></canvas>
<canvas id="canvas2" style="width: 100px; height: 100px;" height="50" width="100"></canvas>

На обоих были нарисованы одинаковые элементы относительно внутренних координат элемента canvas. Но на втором холсте красный прямоугольник будет в два раза шире, потому что холст в целом растягивается по большей площади по правилам CSS.

Примечание. Если правила CSS для widthи / или heightне указаны, то браузер будет использовать атрибуты HTML для определения размера элемента таким образом, чтобы 1 единица этих значений равнялась 1 пикселю на странице. Если эти атрибуты не указаны , то они будут по умолчанию к widthо 300и heightо 150.

Бен Джексон
источник
16

Холст будет растянут, если вы установите ширину и высоту в вашем CSS. Если вы хотите динамически манипулировать размером холста, вы должны использовать JavaScript следующим образом:

canvas = document.getElementById('canv');
canvas.setAttribute('width', '438');
canvas.setAttribute('height', '462');
Синий дождь
источник
1
Большой! Спасибо за этот ответ. Я должен был поставить canvas.setAttributeперед тем, canvas.getContext('2d')чтобы избежать растяжения изображения.
чч
6

Браузер использует ширину и высоту CSS, но элемент холста масштабируется в зависимости от ширины и высоты холста. В JavaScript прочитайте ширину и высоту CSS и установите ширину и высоту холста.

var myCanvas = $('#TheMainCanvas');
myCanvas[0].width = myCanvas.width();
myCanvas[0].height = myCanvas.height();
Рассел Харкинс
источник
2

Шеннимальная коррекция

var el = $('#mycanvas');
el.attr('width', parseInt(el.css('width')))
el.attr('height', parseInt(el.css('height')))
XaviGuardia
источник
0

CSS устанавливает ширину и высоту элемента canvas, так что он влияет на пространство координат, оставляя все нарисованное перекошенным

Вот мой способ, как установить ширину и высоту с помощью Vanilla JavaScript

canvas.width = numberForWidth

canvas.height = numberForHeight
Энтони Гедеон
источник
-1

Если вы хотите динамическое поведение, основанное, например, на медиазапросах CSS, не используйте атрибуты width и height. Используйте правила CSS, а затем, прежде чем получить контекст визуализации холста, присвойте атрибутам width и height стили CSS width и height:

var elem = document.getElementById("mycanvas");

elem.width = elem.style.width;
elem.height = elem.style.height;

var ctx1 = elem.getContext("2d");
...
Маноло
источник
Понятно, что холст получит размер координат по умолчанию (300 x 150), если размер указан только в CSS. Тем не менее, это предложение не работает для меня, но решение ниже работает.
за Линдберга
@PerLindberg - это решение работает, если вы определили ширину и высоту CSS в пикселях для элемента canvas.
Маноло