【问题标题】:Html Canvas at varying pixel densities不同像素密度的 Html 画布
【发布时间】:2015-12-16 10:14:39
【问题描述】:

我希望有人可以帮助解决这个问题,因为我似乎找不到可靠的解决方案。

是否有框架或通用设置可以很好地渲染 html 画布,并且在不同的像素密度下以正确的大小呈现?

我了解问题存在的原因。如果之前多次询问过这个问题,我已经进行了非常彻底的搜索,但我仍然没有看到一个强大的解决方案。

补充:为了澄清,画布渲染在视网膜屏幕上看起来很模糊,我想有一种方法可以让渲染看起来清晰,无论它们在哪里查看。结构框架看起来很棒but their demos still look fuzzy on my retina screen.

【问题讨论】:

  • JavaScript 画布/WebGL 库通常实现某种调整大小的方法。比如在three.js中这个方法是renderer.setSize(w, h)。 (threejs.org/docs/#Reference/Renderers/WebGLRenderer) 也许 vanilla canvas / WebGL 有这样的东西?
  • 如果不使用 CSS,画布像素密度将与文档像素密度相同。所以只需将你的画布widthheight设置为你想要的(例如,如果你想让它占据屏幕的一半:canvas.width = window.innerWidth/2; canvas.innerHeight = window.innerHeight/2;
  • 可能演示在不同版本上运行,尚未添加视网膜缩放,请检查我的链接进行测试。我从视网膜用户那里得到确认,它看起来并不模糊。

标签: javascript html html5-canvas retina-display


【解决方案1】:

fabricjs 实现了一种缩放技巧,以在屏幕上的像素与“逻辑像素”之间的不同比率下很好地在屏幕上渲染画布,

当您将问题标记为视网膜缩放时,我认为您是在问这个问题。

如果您不想使用该框架,这基本上就是它在纯 javascript 中的工作方式(或多或少相同的 fabricjs 实现)

if( window.devicePixelRatio !== 1 ){
          var c = document.getElementById('mycanvas') // your canvas
          var w = c.width, h = c.height;

          // scale the canvas by window.devicePixelRatio
          c.setAttribute('width', w*window.devicePixelRatio);
          c.setAttribute('height', h*window.devicePixelRatio);

          // use css to bring it back to regular size
          c.setAttribute('style', 'width="'+w+'"; height="'+h+'";')

          // set the scale of the context
          c.getContext('2d').scale(window.devicePixelRatio, window.devicePixelRatio);
 }

请注意,浏览器必须启用 Retina。

请检查这些图像在您的视网膜屏幕上是否看起来不同。 首先是启用视网膜,其次不是。 (注意,可怕的图像)

var c = new fabric.StaticCanvas('canvas');
var c2 = new fabric.StaticCanvas('canvas2', {enableRetinaScaling: false});
fabric.Image.fromURL('http://www.free-desktop-backgrounds.net/free-desktop-wallpapers-backgrounds/free-hd-desktop-wallpapers-backgrounds/535693007.jpg', function(img) {
  img.scale(0.5);
  var circle = new fabric.Circle({radius: 40, fill: 'red', stroke: 'blue', top: 2, left: 2});
  
  c.add(img);
  c.add(circle);
  c2.add(img);
  c2.add(circle);
});
<script src="http://www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="canvas" width="800" height="600"></canvas>

<canvas id="canvas2" width="800" height="600"></canvas>

与其他图片的链接: http://www.deltalink.it/andreab/fabric/retina.html

编辑: 添加了一个矢量几何形状,看看是否有更多证据。

【讨论】:

  • 感谢您的回答,澄清一下,画布渲染在视网膜屏幕上看起来很模糊,我想有一种方法可以让渲染看起来清晰,无论在哪里查看。织物框架看起来很棒,但他们的演示在我的视网膜屏幕上仍然看起来很模糊,例如fabricjs.com/static_canvas
  • 我会为您链接一个启用了视网膜的演示。无论如何,这是唯一的解决方案,制作一张大图像,假装它更小,因此视网膜感知浏览器将呈现高分辨率。
【解决方案2】:

如果你看一下,例如three.js source,它会像这样实现调整大小:

this.setSize = function ( width, height, updateStyle ) {

        _width = width;
        _height = height;

        _canvas.width = width * pixelRatio;
        _canvas.height = height * pixelRatio;

        if ( updateStyle !== false ) {

            _canvas.style.width = width + 'px';
            _canvas.style.height = height + 'px';

        }

        this.setViewport( 0, 0, width, height );

    };

this.setViewport = function ( x, y, width, height ) {

        _viewportX = x * pixelRatio;
        _viewportY = y * pixelRatio;

        _viewportWidth = width * pixelRatio;
        _viewportHeight = height * pixelRatio;

        _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );

    };

_gl 似乎是画布上下文。

似乎他们只是采用widthheight(例如屏幕宽度和高度)并将其与pixel ratio 相乘,就我而言,这是1-4 之间的某个整数知道。

【讨论】:

    【解决方案3】:

    这里是使用更高 dpi (devicePixelRatio) 屏幕解决模糊画布问题的技巧。

    缩放画布元素尺寸:dpr x css 尺寸。

    这是 2.0 的 dpr 的样子

    <canvas class="small" width="400" height="400"></canvas> 
    

    CSS

    .small {
        width: 200px;
        height: 200px;
    }
    

    使用 Javascript 检测 dprcanvas 元素尺寸。

    const dpr = window.devicePixelRatio || 1;
    const rect = canvas.getBoundingClientRect(); // css
    

    计算新维度

    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    

    现在您可以使用 CSS 类、@media 规则等来设置相对尺寸。 Javascript 将检测元素大小和 dpr 并返回正确的相对大小。

    【讨论】:

      【解决方案4】:

      创建具有给定分辨率的画布

      function createCanvas (width, height) {
          var canvas = document.createElement("canvas");
          canvas.width = width;
          canvas.height = height;
          return canvas;
      }
      var canvas = createCanvas(1024,1024); // create a canvas that is 1024by1024 pixels
      

      将其添加到元素中

      var element = document.getElementById("uniqueId");
      if(element !== null){
         element.appendChild(canvas);
      }
      

      【讨论】:

      • 感谢您的回答,澄清一下,画布渲染在视网膜屏幕上看起来很模糊,我想有一种方法可以让渲染看起来清晰,无论在哪里查看。织物框架看起来很棒,但他们的演示在我的视网膜屏幕上仍然看起来很模糊,例如fabricjs.com/static_canvas
      • @Brad 您需要将画布分辨率与其显示尺寸相匹配。请参阅stackoverflow.com/q/294250/3877726,了解如何获取元素的显示宽度和高度。因此获取将包含画布的元素的大小,调整任何填充的大小等,然后以计算的分辨率创建画布并将其添加到页面。
      猜你喜欢
      • 1970-01-01
      • 2015-11-24
      • 2018-05-03
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多