技术控

    今日:27| 主题:57810
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] canvas在高倍屏下变模糊的处理办法

[复制链接]
模仿你的呼吸 投递于 2016-10-3 11:46:14
146 4
一. 事起缘由

   最近在用Canvas做社区网站的 技能雷达图 ,如下图所示。
  一倍屏下的显示情况:
   

canvas在高倍屏下变模糊的处理办法

canvas在高倍屏下变模糊的处理办法-1-技术控-canvas,渲染,像素,倍率,实际

  二倍屏下的显示情况:
   

canvas在高倍屏下变模糊的处理办法

canvas在高倍屏下变模糊的处理办法-2-技术控-canvas,渲染,像素,倍率,实际

  正当我很开心的准备发布出去时,用Mac Book 开发的同事跟我说,这简直是糊得不要不要的呀~( ╯□╰ )~。。纳尼可是我的华硕显示十分完美呀,这就十分尴尬了。
  猜想是Canvas毕竟类似于位图,在Retina屏下如果不做多倍屏显示处理的话,图片应该会模糊。Google了一翻,果然如此。
  二. 问题分析

  因为canvas不是矢量图,而是像图片一样是位图模式的。如果不做Retina屏适配的话,例如二倍屏,浏览器就会以2个像素点的宽度来渲染一个像素,该canvas在Retina屏幕下相当于占据了2倍的空间,相当于图片被放大了一倍,因此图片会变模糊。
  因此,要做Retina屏适配,关键是知道当前屏幕的设备像素比,然后将canvas放大到该设备像素比来绘制,然后将canvas压缩到一倍来展示。
  三. 解决办法

  因此,要做Retina屏适配,关键是知道当前canvas的实际渲染倍率,然后将canvas放大到该倍率来绘制,最后将canvas压缩成一倍的物理大小来展示。
  需要注意的是,canvas中的线条大小、文字大小等都需要乘以该倍率来进行绘制。
  3.1 canvas的实际渲染倍率

  在浏览器的window变量中有一个devicePixelRatio的属性,该属性表示了屏幕的设备像素比,即用几个(通常是2个)像素点宽度来渲染1个像素。
  在canvas context中也存在一个 webkitBackingStorePixelRatio 的属性,该属性的值决定了浏览器在渲染canvas之前会用几个像素来来存储画布信息。在iOS6下的safari中的值是2,但是在chrome和iOS7的safari中的值却是1。在iOS6下的safari中,如果有一张100 × 100像素的图片绘制,该图片首先会在内存中生成一张200 × 200的图片,然后再浏览器渲染时会按100 × 100的图片来显示,因此不会出现模糊失真的情况。而在在chrome和iOS7的safari中就会出现模糊。
  但是webkitBackingStorePixelRatio属性在各浏览器厂商的获取方式不一样,所以需要加上浏览器前缀来实现兼容。
  如下:
  1. var canvas = document.getElementById("canvas"),
  2.         context= canvas.getContext("2d");  

  3. // 屏幕的设备像素比
  4. var devicePixelRatio = window.devicePixelRatio || 1;

  5. // 浏览器在渲染canvas之前存储画布信息的像素比
  6. var backingStoreRatio = context.webkitBackingStorePixelRatio ||
  7.                     context.mozBackingStorePixelRatio ||
  8.                     context.msBackingStorePixelRatio ||
  9.                     context.oBackingStorePixelRatio ||
  10.                     context.backingStorePixelRatio || 1;

  11. // canvas的实际渲染倍率
  12. var ratio = devicePixelRatio / backingStoreRatio;
复制代码
3.2 按实际渲染倍率来缩放canvas

  先补充一个基础知识点:
  
       
  • 要设置canvas的画布大小,使用的是 canvas.width 和 canvas.height ;   
  • 要设置画布的实际渲染大小,使用的style或CSS设置的 width 和 height ,只是简单的对画布进行缩放。  
  譬如:
  1. <canvas width="640" height="800" style="width:320px; height:400px"></canvas>
复制代码
canvas的实际大小的640px × 800px,但是实际渲染到页面的大小是320px × 400px,相当于缩小一倍来显示。
  因此,要使canvas适配高倍屏,就是要将canvas放大到设备像素比来绘制,最后将canvas压缩成一倍的物理大小来展示。如下:
  1. canvas.style.width = canvas.width;
  2. canvas.style.height = canvas.height;

  3. canvas.width = canvas.width * ratio;
  4. canvas.height = canvas.height * ratio;
复制代码
3.3 实际渲染效果:

  实际渲染效果如下:
  一倍屏下:

   
  1. <canvas width="200" height="120" style="width: 200px; height: 120px;"></canvas>
复制代码
二倍屏下:

   
  1. <canvas width="400" height="240" style="width: 200px; height: 120px;"></canvas>
复制代码
三倍屏下:

   
  1. <canvas width="600" height="360" style="width: 200px; height: 120px;"></canvas>
复制代码
Perfect!
  3.4 注意事项

  canvas中的线条大小、文字大小等都需要乘以设备像素比来进行绘制,否则高倍屏下的线条会变细几倍。
  四. 应用实例

   该雷达图的实现代码已存放到Github上,地址: https://github.com/dengzhirong/radarChart

canvas在高倍屏下变模糊的处理办法

canvas在高倍屏下变模糊的处理办法-5-技术控-canvas,渲染,像素,倍率,实际

canvas在高倍屏下变模糊的处理办法

canvas在高倍屏下变模糊的处理办法-6-技术控-canvas,渲染,像素,倍率,实际

canvas在高倍屏下变模糊的处理办法

canvas在高倍屏下变模糊的处理办法-7-技术控-canvas,渲染,像素,倍率,实际



上一篇:数学中的极限思想求时间复杂度
下一篇:Using types to unit-test in Haskell
琴灵 投递于 2016-10-4 03:15:36
在神经的人群里呆久了,我发现我正常了。
回复 支持 反对

使用道具 举报

duniang2222 投递于 2016-10-11 10:55:25
我也是坐沙发的
回复 支持 反对

使用道具 举报

远诺家居 投递于 2016-10-11 11:22:14
围观 围观 沙发在哪里!!!
回复 支持 反对

使用道具 举报

tong000 投递于 2016-10-17 13:31:49
模仿你的呼吸是男的还是女的?
回复 支持 反对

使用道具 举报

我要投稿

推荐阅读


回页顶回复上一篇下一篇回列表
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 | 粤公网安备 44010402000842号 )

© 2001-2017 Comsenz Inc.

返回顶部 返回列表