Ширина и высота холста в HTML5

126

Можно ли исправить ширину и высоту элемента HTML5 canvas?

Обычный способ заключается в следующем:

<canvas id="canvas" width="300" height="300"></canvas>
Теги:
canvas

3 ответа

287
Лучший ответ

Элемент canvas DOM имеет свойства .height и .width, которые соответствуют атрибутам height="…" и width="…". Установите их в числовые значения в JavaScript-коде, чтобы изменить размер вашего холста. Например:

var canvas = document.getElementsByTagName('canvas')[0];
canvas.width  = 800;
canvas.height = 600;

Обратите внимание, что это очищает холст, хотя вы должны следовать с ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height); для обработки тех браузеров, которые не полностью очищают холст. После изменения размера вам нужно будет перерисовать любой контент, который вы хотите отобразить.

Обратите внимание, что высота и ширина - это размеры логического холста, используемые для рисования, и отличаются от атрибутов CSS style.height и style.width. Если вы не устанавливаете атрибуты CSS, внутренний размер холста будет использоваться в качестве размера его отображения; если вы установите атрибуты CSS, и они отличаются от размеров холста, ваш контент будет масштабироваться в браузере. Например:

// Make a canvas that has a blurry pixelated zoom-in
// with each canvas pixel drawn showing as roughly 2x2 on screen
canvas.width  = 400;
canvas.height = 300; 
canvas.style.width  = '800px';
canvas.style.height = '600px';

Смотрите этот живой пример холста, увеличенного на 4 раза.

var c = document.getElementsByTagName('canvas')[0];
var ctx = c.getContext('2d');
ctx.lineWidth   = 1;
ctx.strokeStyle = '#f00';
ctx.fillStyle   = '#eff';

ctx.fillRect(  10.5, 10.5, 20, 20 );
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.fillRect(   40, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.fillRect(   70, 10, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );

ctx.strokeStyle = '#fff';
ctx.strokeRect( 10.5, 10.5, 20, 20 );
ctx.strokeRect( 40, 10.5, 20, 20 );
ctx.strokeRect( 70, 10, 20, 20 );
body { background:#eee; margin:1em; text-align:center }
canvas { background:#fff; border:1px solid #ccc; width:400px; height:160px }
<canvas width="100" height="40"></canvas>
<p>Showing that re-drawing the same antialiased lines does not obliterate old antialiased lines.</p>
  • 1
    @Hazaart Если вы хотите установить их по-другому: $('#mycanvas').attr({width:400,height:300}).css({width:'800px',height:'600px'}); Если вы хотите, чтобы визуальный размер соответствовал размеру пикселя, никогда не устанавливайте стили, только атрибуты.
  • 1
    «Если вы хотите, чтобы визуальный размер соответствовал размеру пикселя, никогда не устанавливайте стили, только атрибуты», есть ли причина для этого предпочтения? Если у меня много объектов на холсте и я хочу увеличить / уменьшить масштаб, было бы намного быстрее просто сбросить css, нет? (Вместо того, чтобы перебирать все объекты) ...
Показать ещё 4 комментария
19

Большое спасибо! Наконец, я решил проблему с размытыми пикселями с помощью этого кода:

<canvas id="graph" width=326 height=240 style='width:326px;height:240px'></canvas>

плюс трюк "полупикселя" для размывания строк.

  • 1
    Можете ли вы остановиться на полпиксельном трюке?
  • 25
    @UpTheCreek Если вы рисуете линию на холсте, она выглядит медленнее, чем если бы она была размытой. Поместив линии на половину пикселей (скажем, 50,5 вместо 50), вы получите красивую, чистую линию. Это часто делается с помощью ctx.translate (0.5, 0.5) в самом начале вашего кода, чтобы вы могли забыть об этом потом
12

Холст имеет 2 размера, размер пикселей в холсте (это backingstore или drawingBuffer) и размер дисплея. Количество пикселей задается с использованием атрибутов canvas. В HTML

<canvas width="400" height="300"></canvas>

Или в JavaScript

someCanvasElement.width = 400;
someCanvasElement.height = 300;

Отделяется от ширины и высоты стиля холста CSS

В CSS

canvas {  /* or some other selector */
   width: 500px;
   height: 400px;
}

Или в JavaScript

canvas.style.width = "500px";
canvas.style.height = "400px";

Возможно, лучший способ сделать холст размером 1x1 пикселей - ВСЕГДА ИСПОЛЬЗОВАТЬ CSS, чтобы выбрать размер, а затем напишите маленький бит JavaScript, чтобы количество пикселей соответствовало этому размеру.

function resizeCanvasToDisplaySize(canvas) {
   // look up the size the canvas is being displayed
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;

   // If it resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}

Почему это лучший способ? Потому что он работает в большинстве случаев без необходимости менять код.

Здесь полный холст окна:

const ctx = document.querySelector("#c").getContext("2d");

function render(time) {
  time *= 0.001;
  resizeCanvasToDisplaySize(ctx.canvas);
 
  ctx.fillStyle = "#DDE";
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();
 
  const spacing = 64;
  const size = 48;
  const across = ctx.canvas.width / spacing + 1;
  const down = ctx.canvas.height / spacing + 1;
  const s = Math.sin(time);
  const c = Math.cos(time);
  for (let y = 0; y < down; ++y) {
    for (let x = 0; x < across; ++x) {
      ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
      ctx.strokeRect(-size / 2, -size / 2, size, size);
    }
  }
  
  ctx.restore();
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function resizeCanvasToDisplaySize(canvas) {
   // look up the size the canvas is being displayed
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;

   // If it resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
body { margin: 0; }
canvas { display: block; width: 100vw; height: 100vh; }
<canvas id="c"></canvas>

И здесь холст как плавающий в абзаце

const ctx = document.querySelector("#c").getContext("2d");

function render(time) {
  time *= 0.001;
  resizeCanvasToDisplaySize(ctx.canvas);
 
  ctx.fillStyle = "#DDE";
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();
 
  const spacing = 64;
  const size = 48;
  const across = ctx.canvas.width  / spacing + 1;
  const down   = ctx.canvas.height / spacing + 1;
  const s = Math.sin(time);
  const c = Math.cos(time);
  for (let y = 0; y <= down; ++y) {
    for (let x = 0; x <= across; ++x) {
      ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
      ctx.strokeRect(-size / 2, -size / 2, size, size);
    }
  }
  
  ctx.restore();
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function resizeCanvasToDisplaySize(canvas) {
   // look up the size the canvas is being displayed
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;

   // If it resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
span { 
   width: 250px; 
   height: 100px; 
   float: left; 
   padding: 1em 1em 1em 0;
   display: inline-block;
}
canvas {
   width: 100%;
   height: 100%;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim <span class="diagram"><canvas id="c"></canvas></span>
vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
<br/><br/>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>

Здесь холст в значительной панели управления

const ctx = document.querySelector("#c").getContext("2d");

function render(time) {
  time *= 0.001;
  resizeCanvasToDisplaySize(ctx.canvas);

  ctx.fillStyle = "#DDE";
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();
 
  const spacing = 64;
  const size = 48;
  const across = ctx.canvas.width / spacing + 1;
  const down = ctx.canvas.height / spacing + 1;
  const s = Math.sin(time);
  const c = Math.cos(time);
  for (let y = 0; y < down; ++y) {
    for (let x = 0; x < across; ++x) {
      ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
      ctx.strokeRect(-size / 2, -size / 2, size, size);
    }
  }
  
  ctx.restore();
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function resizeCanvasToDisplaySize(canvas) {
   // look up the size the canvas is being displayed
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;

   // If it resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}

// ----- the code above related to the canvas does not change ----
// ---- the code below is related to the slider ----
const $ = document.querySelector.bind(document);
const left = $(".left");
const slider = $(".slider");
let dragging;
let lastX;
let startWidth;

slider.addEventListener('mousedown', e => {
 lastX = e.pageX;
 dragging = true;
});

window.addEventListener('mouseup', e => {
 dragging = false;
});

window.addEventListener('mousemove', e => {
  if (dragging) {
    const deltaX = e.pageX - lastX;
    left.style.width = left.clientWidth + deltaX + "px";
    lastX = e.pageX;
  }
});
body { 
  margin: 0;
}
.frame {
  display: flex;
  align-items: space-between;
  height: 100vh;
}
.left {
  width: 70%;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}  
canvas {
  width: 100%;
  height: 100%;
}
pre {
  padding: 1em;
}
.slider {
  width: 10px;
  background: #000;
}
.right {
  flex 1 1 auto;
}
<div class="frame">
  <div class="left">
     <canvas id="c"></canvas>
  </div>
  <div class="slider">
  
  </div>
  <div class="right">
     <pre>
* controls
* go 
* here

&lt;- drag this
     </pre>
  </div>
</div>

здесь холст в качестве фона

const ctx = document.querySelector("#c").getContext("2d");

function render(time) {
  time *= 0.001;
  resizeCanvasToDisplaySize(ctx.canvas);
 
  ctx.fillStyle = "#DDE";
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();
 
  const spacing = 64;
  const size = 48;
  const across = ctx.canvas.width / spacing + 1;
  const down = ctx.canvas.height / spacing + 1;
  const s = Math.sin(time);
  const c = Math.cos(time);
  for (let y = 0; y < down; ++y) {
    for (let x = 0; x < across; ++x) {
      ctx.setTransform(c, -s, s, c, x * spacing, y * spacing);
      ctx.strokeRect(-size / 2, -size / 2, size, size);
    }
  }
  
  ctx.restore();
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function resizeCanvasToDisplaySize(canvas) {
   // look up the size the canvas is being displayed
   const width = canvas.clientWidth;
   const height = canvas.clientHeight;

   // If it resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
body { margin: 0; }
canvas { 
  display: block; 
  width: 100vw; 
  height: 100vh;  
  position: fixed;
}
#content {
  position: absolute;
  margin: 0 1em;
  font-size: xx-large;
  font-family: sans-serif;
  font-weight: bold;
  text-shadow: 2px  2px 0 #FFF, 
              -2px -2px 0 #FFF,
              -2px  2px 0 #FFF,
               2px -2px 0 #FFF;
}
<canvas id="c"></canvas>
<div id="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent cursus venenatis metus. Mauris ac nibh at odio scelerisque scelerisque. Donec ut enim vel urna gravida imperdiet id ac odio. Aenean congue hendrerit eros id facilisis. In vitae leo ullamcorper, aliquet leo a, vehicula magna. Proin sollicitudin vestibulum aliquet. Sed et varius justo.
</p>
<p>
Quisque tempor metus in porttitor placerat. Nulla vehicula sem nec ipsum commodo, at tincidunt orci porttitor. Duis porttitor egestas dui eu viverra. Sed et ipsum eget odio pharetra semper. Integer tempor orci quam, eget aliquet velit consectetur sit amet. Maecenas maximus placerat arcu in varius. Morbi semper, quam a ullamcorper interdum, augue nisl sagittis urna, sed pharetra lectus ex nec elit. Nullam viverra lacinia tellus, bibendum maximus nisl dictum id. Phasellus mauris quam, rutrum ut congue non, hendrerit sollicitudin urna.
</p>
</div>

Поскольку я не устанавливал атрибуты, единственное, что изменилось в каждом примере, это CSS (насколько это касается холста)

Примечания:

  • Не помещайте границы или отступы в элемент холста. Вычисление размера для вычитания из числа измерений элемента затруднено

Ещё вопросы

Сообщество Overcoder
Наверх
Меню