首页 文章

HTML5中的画布宽度和高度

提问于
浏览
144

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

通常的方法如下:

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

3 回答

  • 319

    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); 来处理那些在尺寸更改后不需要重绘任何内容的浏览器 .

    另请注意,高度和宽度是用于绘制的逻辑画布尺寸,与 style.heightstyle.width CSS属性不同 . 如果未设置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';
    

    请参阅以16x放大的画布的this live example .

    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>
    
  • 30

    画布有2种尺寸,画布中像素的尺寸(它是backingstore或drawingBuffer)和显示尺寸 . 使用画布属性设置像素数 . 在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像素画布的最佳方法是 ALWAYS USE 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;
    }
    

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

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

    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;
    }
    
    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's 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.
    

    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'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;
      }
    });
    
    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's 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(就画布而言)

    笔记:

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

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

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

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

相关问题