HTML5中的画布宽度和高度

Dus*_*tin 167 html5 canvas

是否可以修复HTML5 canvas元素的宽度和高度?

通常的方法如下:

<canvas id="canvas" width="300" height="300"></canvas>
Run Code Online (Sandbox Code Playgroud)

Phr*_*ogz 354

canvasDOM元素具有.height.width对应于属性height="…"width="…"属性.在JavaScript代码中将它们设置为数值以调整画布大小.例如:

var canvas = document.getElementsByTagName('canvas')[0];
canvas.width  = 800;
canvas.height = 600;
Run Code Online (Sandbox Code Playgroud)

请注意,这会清除画布,但您应该使用它ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height);来处理那些不完全清除画布的浏览器.您需要重新绘制尺寸更改后想要显示的任何内容.

进一步注意的是,高度和宽度是用于绘图的逻辑帆布尺寸和是不同的距离style.heightstyle.widthCSS属性.如果未设置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';
Run Code Online (Sandbox Code Playgroud)

查看以4x放大的画布的实时示例.

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 );
Run Code Online (Sandbox Code Playgroud)
body { background:#eee; margin:1em; text-align:center }
canvas { background:#fff; border:1px solid #ccc; width:400px; height:160px }
Run Code Online (Sandbox Code Playgroud)
<canvas width="100" height="40"></canvas>
<p>Showing that re-drawing the same antialiased lines does not obliterate old antialiased lines.</p>
Run Code Online (Sandbox Code Playgroud)

  • @Gamemorize:通过CSS缩放使其模糊.但是,您可以通过上下文缩放和重绘之间的转换进行缩放,而不是更改每个对象的"大小". (3认同)
  • 此外,您现在可以使用画布上的"图像渲染:像素化"样式,至少在Chrome上"清除像素化放大"而不是"模糊的像素化放大".我摆弄你的小提琴以显示差异:http://jsfiddle.net/donhatch/9bheb/1663/ (3认同)
  • @Hazaart 如果你想以不同的方式设置它们:`$('#mycanvas').attr({width:400,height:300}).css({width:'800px',height:'600px'});`如果您希望视觉尺寸与像素尺寸相同,请不要设置样式,只需设置属性。 (2认同)

gma*_*man 49

画布有2种尺寸,画布中像素的尺寸(它是backingstore或drawingBuffer)和显示尺寸.使用画布属性设置像素数.在HTML中

<canvas width="400" height="300"></canvas>
Run Code Online (Sandbox Code Playgroud)

或者在JavaScript中

someCanvasElement.width = 400;
someCanvasElement.height = 300;
Run Code Online (Sandbox Code Playgroud)

与此分开的是画布的CSS样式宽度和高度

在CSS中

canvas {  /* or some other selector */
   width: 500px;
   height: 400px;
}
Run Code Online (Sandbox Code Playgroud)

或者在JavaScript中

canvas.style.width = "500px";
canvas.style.height = "400px";
Run Code Online (Sandbox Code Playgroud)

制作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's resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
Run Code Online (Sandbox Code Playgroud)

为什么这是最好的方式?因为它适用于大多数情况而无需更改任何代码.

这是一个完整的窗口画布:

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's resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
Run Code Online (Sandbox Code Playgroud)
body { margin: 0; }
canvas { display: block; width: 100vw; height: 100vh; }
Run Code Online (Sandbox Code Playgroud)
<canvas id="c"></canvas>
Run Code Online (Sandbox Code Playgroud)

这是一个画布作为段落中的浮动

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's resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
Run Code Online (Sandbox Code Playgroud)
span { 
   width: 250px; 
   height: 100px; 
   float: left; 
   padding: 1em 1em 1em 0;
   display: inline-block;
}
canvas {
   width: 100%;
   height: 100%;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这是一个相当大的控制面板中的画布

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's 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;
  }
});
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

这是画布作为背景

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's resolution does not match change it
   if (canvas.width !== width || canvas.height !== height) {
     canvas.width = width;
     canvas.height = height;
     return true;
   }

   return false;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

因为我没有设置属性,所以每个样本中唯一改变的是CSS(就画布而言)

笔记:

  • 不要在canvas元素上放置边框或填充.计算尺寸以从元件的尺寸数减去是很麻烦的

  • 最佳答案,这个片段应该是一个标准的 DOM 画布方法。 (2认同)

小智 22

非常感谢你!最后我用这段代码解决了模糊像素问题:

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

添加"半像素"可以解开线条.

  • @UpTheCreek如果你在画布上画一条线,它看起来应该是它应该的,好像它是模糊的.通过将线条放在半像素(例如,50.5而不是50)上,您将获得一条漂亮,干净的线条.这通常是在代码的最开始使用ctx.translate(0.5,0.5)完成的,所以你可以在之后忘记它 (26认同)