【问题标题】:Scale canvas width and height to be as large as possible but maintain aspect ratio (JS)将画布宽度和高度缩放到尽可能大但保持纵横比(JS)
【发布时间】:2016-12-04 15:07:58
【问题描述】:

如果我有一个特定宽度和高度的画布元素,例如

<canvas id="display" width="900" height="650" tabindex=0></canvas>

并且我想将画布的宽度和高度放大到尽可能大,同时包含在视口中而不更改纵横比或增加要在其中显示的对象的整体区域画布。

这意味着如果一个窗口的宽度为2200,高度为1300,则画布的显示宽度和高度都将加倍(并且不会更大,否则无法包含高度)并且画布将具有新维度 18001300

但是,我放大了画布元素的 CSS 显示高度,而不是画布本身,这意味着 画布内的对象也应该增加它们的尺寸。

canvas {
  width: ...
  height: ...
}

如果在调整窗口大小时画布可以自行调整大小会更好,也许使用事件监听器。

有没有办法在 JS 中做到这一点?

【问题讨论】:

    标签: javascript css html canvas


    【解决方案1】:

    缩放以适应

    您必须定义方面。这可以通过定义一个默认大小来完成。

    const defWidth = 1920;
    const defHeight = 1080;
    

    然后你可以监听窗口调整大小事件并调整画布大小以适应。

    function resizeEventHandler(){
        // get the max size that fits both width and height by finding the min scale
        var canvasScale = Math.min(innerWidth / defWidth, innerHeight / defHeight);
        // or for max size that fills
        // canvasScale = Math.max(innerWidth / defWidth, innerHeight / defHeight);
    
        // now set canvas size and resolution to the new scale
        canvas.style.width = (canvas.width = Math.floor(defWidth * canvasScale)) + "px";
        canvas.style.height = (canvas.height = Math.floor(defHeight * canvasScale)) + "px";
    }
    

    因为画布分辨率必须是整数,所以纵横比可能超出一个像素。但对此无能为力。

    【讨论】:

    • 虽然这确实调整了画布的大小,但它并没有达到我想要的效果,因为它没有改变画布中对象的大小,如果用户将窗口大小调整为更大,则可以看到更多内容。我需要一些可以放大对象的东西,所以尺寸比例仍然相同。
    • @DaemonOfTheWest 只需使用canvasScale 来放大您所做的任何渲染。例如ctx.setTransform(canvasScale,0,0,canvasScale,0,0);
    【解决方案2】:

    最终找到了我自己的解决方案,如果有更优雅的解决方案,请告诉我。

    // get maximum possible size for canvas while maintining aspect ratio
    function resizeEventHandler(){
      var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
      var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
      if(w/canvas.width > h/canvas.height){
        canvas.style.width = "calc("+canvas.width+" / "+canvas.height+" * 100vh)";
        canvas.style.height = "calc(100vh)";
      } else {
        canvas.style.width = "calc(100vw)";
        canvas.style.height = "calc("+canvas.height+" / "+canvas.width+" * 100vw)";
      }
    }
    resizeEventHandler();
    window.addEventListener("resize", resizeEventHandler);
    

    【讨论】:

    • 这将通过 CSS 拉伸您的画布绘图,这可能会导致丑陋的抗锯齿伪影。
    • @Kaiido 抗锯齿效果可以通过 CSS 来控制。 Like this
    • 不是真的哼。首先,您链接到的答案来自 2011 年!而且它根本不使用 CSS。如今(实际上已经很久了),您可以使用ctx.imageSmoothingEnabled = false 而不是这样做可怕的(get/put)ImageData。其次,确实有一个image-rendering CSS 属性,它可以让你说你想要一个最近邻算法而不是抗锯齿,但结果仍然不是你想要的。您必须设置画布的宽度和高度属性,否则 CSS 将尝试填充像素矩阵中的空白。
    猜你喜欢
    • 2016-05-18
    • 2012-05-31
    • 2016-04-01
    • 2014-07-01
    • 2015-01-21
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多