Resize HTML5 canvas to fit window

前端 未结 16 1152
遥遥无期
遥遥无期 2020-11-22 12:03

How can I automatically scale the HTML5 element to fit the page?

For example, I can get a

to scale by setting th
16条回答
  •  名媛妹妹
    2020-11-22 12:15

    Here's a tiny, complete Code Snippet that combines all the answers. Press: "Run Code Snippet" then press "Full Page" and resize the window to see it in action:

    function refresh(referenceWidth, referenceHeight, drawFunction) {
      const myCanvas = document.getElementById("myCanvas");
      myCanvas.width = myCanvas.clientWidth;
      myCanvas.height = myCanvas.clientHeight;
    
      const ratio = Math.min(
        myCanvas.width / referenceWidth,
        myCanvas.height / referenceHeight
      );
      const ctx = myCanvas.getContext("2d");
      ctx.scale(ratio, ratio);
    
      drawFunction(ctx, ratio);
      window.requestAnimationFrame(() => {
        refresh(referenceWidth, referenceHeight, drawFunction);
      });
    }
    
    //100, 100 is the "reference" size. Choose whatever you want.
    refresh(100, 100, (ctx, ratio) => {
      //Custom drawing code! Draw whatever you want here.
      const referenceLineWidth = 1;
      ctx.lineWidth = referenceLineWidth / ratio;
      ctx.beginPath();
      ctx.strokeStyle = "blue";
      ctx.arc(50, 50, 49, 0, 2 * Math.PI);
      ctx.stroke();
    });
    div {
      width: 90vw;
      height: 90vh;
    }
    
    canvas {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }

    This snippet uses canvas.clientWidth and canvas.clientHeight rather than window.innerWidth and window.innerHeight to make the snippet run inside a complex layout correctly. However, it works for full window too if you just put it in a div that uses full window. It's more flexible this way.

    The snippet uses the newish window.requestAnimationFrame to repeatedly resize the canvas every frame. If you can't use this, use setTimeout instead. Also, this is inefficient. To make it more efficient, store the clientWidth and clientHeight and only recalculate and redraw when clientWidth and clientHeight change.

    The idea of a "reference" resolution lets you write all of your draw commands using one resolution... and it will automatically adjust to the client size without you having to change the drawing code.

    The snippet is self explanatory, but if you prefer it explained in English: https://medium.com/@doomgoober/resizing-canvas-vector-graphics-without-aliasing-7a1f9e684e4d

提交回复
热议问题