【问题标题】:2D Graphics and uniform scaling in HTML CanvasHTML Canvas 中的 2D 图形和统一缩放
【发布时间】:2015-02-21 14:08:09
【问题描述】:

我有一个相机对象,它通过一个固定的常量变量放大上下文来“放大”到画布中。这是一个例子:

zoom: function(zoomConstant) {
    this.scaleFactor = this.scaleFactor + zoomConstant;
}

update: function(context) {
    context.scale(this.scaleFactor, this.scaleFactor);
}

在达到非常高的比例值之前,它可以正常工作,此时缩放过渡不再平滑,使用鼠标滚轮进出滚动变得难以忍受。

我正在寻找一个三次缩放函数,它可以在较高的比例值下缩放较少,从而提供视觉上均匀的过渡。不幸的是,我对术语不太了解,我不确定要查找什么。如果您能建议我可以研究的任何资源,并举例说明它如何与 Canvas 一起使用,那就太好了。

【问题讨论】:

    标签: javascript html canvas 2d scaling


    【解决方案1】:

    您正在使用线性函数进行缩放。线性函数仅将缩放量更改为 1,因此从 100 缩放到 10 需要 90 步,但从 10 到 1 只需 9 步,但两种情况下的放大倍率都是 10 倍。您可以尝试按比例因子的 10% 进行缩放:

    this.scaleFactor*=0.9;
    

    因此,如果您的放大倍数为 100,则您将转到 90,然后是 81,等等...但我也会设置最小步长,或者提供对缩放的更大控制(快速与精确)。

    【讨论】:

      【解决方案2】:

      您没有显示太多代码:-/

      所以我想到了至少 2 种可能性:

      • 用户旋转鼠标滚轮的速度太快,以至于画布无法重绘所有请求的绘图。如果是这种情况,您需要使用一种称为“去抖动”的技术来限制鼠标滚轮事件。 Google:去抖动事件

      • 如果您强制画布以增加的大小重新绘制整个原始图像,那么画布会变慢,因为它必须计算画布外的每个像素,以便知道要在画布内绘制哪些像素。您可以通过使用context.drawImage 的剪辑版本来选择原始图像的较小部分并缩放该较小部分而不是整个图像来解决此问题。

      【讨论】:

        【解决方案3】:

        如果您使用累积缩放,如本例所示,较高端将按对数缩放,从而创建较大的步长。

        您可能想要使用绝对比例因子,所以如果您更改此行:

        update: function(context) {
            context.scale(this.scaleFactor, this.scaleFactor);
        }
        

        update: function(context) {
            context.setTransform(this.scaleFactor, 0, 0, this.scaleFactor, 0, 0);
        }
        

        比例将使用绝对方法(如果您需要其他转换,则需要在此处设置它们,并且此方法会覆盖所有转换)。

        插图:

        第一行是累积的,第二行是绝对的。第二个有更多的细粒度控制。您还可以使用两种不同的步进因子,一种用于 scaleFactor 1。

        var canvas = document.querySelector("canvas"),
            ctx = canvas.getContext("2d"),
            scaleFactor = 1,
            step = 1.1,  // 10%
            i = 0,
            dx = 1;
        
        ctx.translate(-100,0);
        
        // accumulative
        for(; i < 20; i++) {
          ctx.fillRect(100, 20, 5, 10);
          scaleFactor *= step;
          ctx.scale(scaleFactor, 1);
        }
        
        // absolute
        ctx.setTransform(1, 0, 0, 1, -100, 0);
        scaleFactor = 1;
        for(i = 0; i < 20; i++) {
          ctx.fillRect(100, 50, 5, 10);
          scaleFactor *= step;
          ctx.setTransform(scaleFactor, 0, 0, 1, -100, 0);
        }
        canvas {border:1px solid #000}
        &lt;canvas width=500&gt;&lt;/canvas&gt;

        【讨论】:

          猜你喜欢
          • 2017-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-07
          • 2017-07-12
          • 1970-01-01
          • 2020-07-24
          相关资源
          最近更新 更多