【问题标题】:Scale down a Konvajs stage without losing quality在不损失质量的情况下缩小 Konvajs 舞台
【发布时间】:2019-09-02 16:33:43
【问题描述】:

考虑有一个大型 (2000x1000) 舞台,其中包含一些文字。舞台缩小到 1000x500,使文本无法阅读。然后我们尝试通过放大来放大文本。

预期:文本应该在某个时候再次变得可读。

实际:无论我们放大多少,文本仍然不可读(模糊)。

运行 sn-p 后尝试放大页面(在桌面上使用原生浏览器缩放):

const stage = new Konva.Stage({
   container: 'container',
   width: 2000,
   height: 1000,
});

const layer = new Konva.Layer();
stage.add(layer);

const rect = new Konva.Text({
   x : 50, y : 50, width: 100, height: 100,
   fontSize: 12,   
   text: "This text should be readable when the viewport gets downscaled"
});

layer.add(rect).draw();

stage.scale({x: 0.5, y: 0.5});
stage.setAttrs({width: 1000,  height: 500});
stage.draw();
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.js"></script>
<div id="container"></div>

仅使用 CSS 缩小可以避免质量损失,如下所示:

const stage = new Konva.Stage({
   container: 'container',
   width: 2000,
   height: 1000,
});

const layer = new Konva.Layer();
stage.add(layer);

const rect = new Konva.Text({
   x : 50, y : 50, width: 100, height: 100,
   fontSize: 12,   
   text: "This text should be readable when the viewport gets downscaled"
});

layer.add(rect).draw();

stage.getChildren().forEach(function(layer) {
    layer.canvas._canvas.style.width = "1000px";
    layer.canvas._canvas.style.height = "500px";

    layer.hitCanvas.setSize(1000, 500);
    layer.hitCanvas.context.scale(0.5, 0.5);
});    

stage.draw();
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.js"></script>
<div id="container"></div>

注意文本在特定缩放级别如何变得可读。

解决方法破坏了 Konvajs 抽象。它可能会导致什么问题?有没有更好的方法,只使用 Konvajs 公开的公共方法?

在 fabric.js 中可以这样做 (complete example here):

canvas.setDimensions({width: '1000px', height: '500px'}, {cssOnly: true});

【问题讨论】:

  • 如何缩放?在移动设备上触摸原生缩放?
  • 本机浏览器缩放。我刚刚注意到 StackOverflow 没有在我的手机上运行 sn-ps。请使用桌面浏览器。

标签: javascript css konvajs


【解决方案1】:

Konva 是一个画布框架。与 SVG 等矢量元素不同,Canvas 是位图图像。所以应该预料到“模糊”。从技术上讲,要解决此问题,您可以在缩放事件中使用更高的 pixelRatio 重绘舞台:

Konva.pixelRatio = 4
stage.draw();

该代码将为画布元素生成更多像素。但在这种情况下,页面在 RAM 中可能非常重,因为 Konva 必须生成非常大的画布。在大多数移动应用程序中,您不需要原生缩放,您可以使用响应式设计。对于缩放舞台,您可以使用 Konva 方法。

【讨论】:

  • 在图层缩小后增加 pixelRatio 是行不通的,因为所有额外的像素数据都已经丢失了。防止数据丢失的唯一方法是使用 CSS 缩放(但仅在缩小时)。我们基本上保留了原始图像,所以当我们稍后再次放大时,像素仍然存在。这是一种可行的方法,我所有的测试都通过了。然而,它破坏了框架抽象,这可能会在未来导致奇怪的错误。对这种方法可能出现什么问题有什么想法吗?
  • “数据丢失”是什么意思?使用 CSS 进行缩放会破坏 Konva 的命中检测。所以不推荐。
  • 缩小画布后,画布质量会降低,因为画布后面的位图实际上发生了变化。如果我们随后将画布放大(通过放大或其他方式),我们将无法获得原始画布。我注意到命中检测问题并更新了问题中的代码。我仍然不确定可能的缓存问题,但到目前为止它似乎有效。
  • 我已经尝试过使用这种方法,因为我有一个可缩放的画布容器,它改变了它的缩放属性,并且在每个滚轮事件中我都设置了缩放比例和像素比率。后者设置在从 konva 导入的类上,而我的舞台是 react-konva 组件。但是,在其上调用 draw 不会导致任何会导致图像不模糊的重绘。还有其他方法可以防止父缩放时画布模糊吗?
  • 不了解 konva,但屏幕外的东西不应该引起问题或者 konva 不处理剔除吗?
猜你喜欢
  • 2019-12-13
  • 2014-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多