解决 canvas 绘图在高清屏中的模糊问题

时间:2022-09-05 19:17:11

解决 canvas 绘图在高清屏中的模糊问题

为什么模糊

CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值。

在高清屏之前,屏幕上显示一个像素点需要 1 x 1 个 css 像素。在高清屏,同样大小的屏幕上要显示一个点,就需要 n x 1 个 css 像素。这里的 n 就是设备像素比 devicePixelRatio >= 2.

也就是说,同样大小的区域,高清屏需要更多的 css 像素:css 像素不够,则会放大内容——变得模糊;css 像素足够,则会缩小内容——变得清晰。放大、缩小的比例由 devicePixelRatio 决定。

比如说 iPhone 4s,它的 devicePixelRatio 为 2,假设屏幕上有块区域大小为 100px x 100px,上面有张 100px x 100px大小的图片,那么这张图片会被放大 2 倍后再渲染到这块区域,所以看起来就模糊了。

canvas 绘图在高清屏中模糊

canvas 属于位图,绘制在它上面的文字、图片、线条也属于位图,经放大后就失真、显得模糊了。要解决这个问题,我们就需要 canvas 拥有更多的 css 像素,即让 canvas 足够大。多大才够呢?太大会不会浪费资源/性能?我们需要因地制宜,根据 devicePixelRatio 来决定画布的大小。

function setupCanvas(canvas) {
var dpr = window.devicePixelRatio || 1
var rect = canvas.getBoundingClientRect() canvas.width = rect.width * dpr
canvas.height = rect.height * dpr var ctx = canvas.getContext('2d')
ctx.scale(dpr, dpr) return ctx
} // 现在我们只需要根据 UI 设计图绘制需要的内容
// 由于使用了 setupCanvas,绘制的内容在各种高清屏中表现清晰、一致
var ctx = setupCanvas(document.querySelector('.my-canvas'));
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.stroke();

在 setupCanvas 函数中,我们根据屏幕的 devicePixelRatio 对 canvas 画布本身进行放大,然后使用 ctx.scale() 放大 canvas 单位,这样在 ctx 上下文绘制的内容就会被放大,使得最后生成的图片清晰的显示在对应的屏幕上。

实际上,我们还要兼顾不同大小、不同分辨率的屏幕。一般设计师会给我们宽度为 375px 的设计图,这需要我们根据屏幕大小进行缩放:

function setupCanvas(canvas) {
const UI_WIDTH = 375
const DOC_WIDTH = document.documentElement.clientWidth
const DPR = window.devicePixelRatio || 1
let scale = (DPR * DOC_WIDTH / UI_WIDTH).toFIxed(2)
//let rect = canvas.getBoundingClientRect() canvas.width = canvas.width * scale
canvas.height = canvas.height * scale let ctx = canvas.getContext('2d')
ctx.scale(scale, scale) return ctx
}

术语

device pixel

设备像素(又称物理像素、屏幕像素)是显示屏的最小物理单元,是我们在屏幕上能看到的最小点。

device-independent pixel

设备无关像素(又称密度无关像素,DIP)是一个抽象单位,表示计算机中的一个虚拟点,由系统转为一个设备像素点。

devicePixelRatio

设备像素比,它的值等于设备像素/设备无关像素,devicePixelRatio = DP/DIP

css pixel

css 像素是浏览器使用的抽象单位,属于设备无关像素(DIP)。我们看到的内容,是浏览器将 css 像素转化为设备像素后的结果。

矢量图

矢量图是根据几何特性来绘制图形,矢量可以是一个点或一条线,矢量图只能靠软件生成,文件占用内在空间较小,因为这种类型的图像文件包含独立的分离图像,可以*无限制的重新组合。它的特点是放大后图像不会失真。

位图

位图图像(bitmap),亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。当放大位图时,图像就失真、模糊了。

引用

解决 canvas 绘图在高清屏中的模糊问题的更多相关文章

  1. 【转】解决 canvas 在高清屏中绘制模糊的问题

    来源: http://www.css88.com/archives/9297 使用 canvas 绘制图片或者是文字在 Retina 屏中会非常模糊.如图: 因为 canvas 不是矢量图,而是像图片 ...

  2. 【Canvas】311- 解决 canvas 在高清屏中绘制模糊的问题

    点击上方"前端自习课"关注,学习起来~ 一.问题分析 使用 canvas 绘制图片或者是文字在 Retina 屏中会非常模糊.如图: 因为 canvas 不是矢量图,而是像图片一样 ...

  3. 解决 canvas 在高清屏中绘制模糊的问题

    主要代码部分: <canvas id="my_canvas" width="540" heihgt="180"></can ...

  4. ArcGIS 在高清屏中主界面界面字体和图标显示过小,如何解决?

    作者:安日链接:https://www.zhihu.com/question/40658050/answer/132382971来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  5. 高清屏下canvas重置尺寸引发的问题

    我们知道,清空canvas画布内容有以下两个方法. 第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height) 第二种方法就是 ...

  6. Cocos2D瓦块地图高清屏&lpar;retina&rpar;显示比例问题的解决

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在Cocos2D的游戏编程里,常用到瓦块地图.而cocos2D ...

  7. 移动端,多屏幕尺寸高清屏retina屏适配的解决方案

    移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页 ...

  8. Cocos2D iOS之旅&colon;如何写一个敲地鼠游戏&lpar;一&rpar;&colon;高清屏显示和UIKit

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  9. 怎么在高清屏上画一条0&period;5px的边

    怎么在高清屏上画一条0.5px的边呢?0.5px相当于高清屏物理像素的1px.这样的目的是在高清屏上看起来会更细一点,效果会更好一点,例如更细的分隔线. 理论上px的最小单位是1,但是会有几个特例,高 ...

随机推荐

  1. 一个Java文件至多包含一个公共类

    编写一个java源文件时,该源文件又称为编译单元.一个java文件可以包含多个类,但至多包含一个公共类,作为编译时该java文件的公用接口,公共类的名字和源文件的名字要相同,源文件名字的格式为[公共类 ...

  2. C&num;在Dictionary中使用枚举作为键

    Enum类型没有实现IEquatable接口,Dictionary中使用Enum作为键时,将发生装箱,使效率降低. 此时可用Dictionary中一个接收IEqualityComparer<T& ...

  3. 【py网页】sitecopy代码

    001 #coding:utf-8 002 import re,os,shutil,sys 003 import urllib2,socket,cookielib 004 from threading ...

  4. angularjs应用骨架

    使用典型的类库时,你可以选择并使用你所喜欢的功能:而对于angularjs框架来说,必须把它看成一个完整的套件来使用,框架中的所有的东西都包含在里面,接下来将会介绍angular的基础模块,这样你就可 ...

  5. PHP安全编程:留心后门URL 直接可以通过URL访问(转)

    后门URL是指虽然无需直接调用的资源能直接通过URL访问.例如,下面WEB应用可能向登入用户显示敏感信息: <?php $authenticated = FALSE; $authenticate ...

  6. 三种Dataase Mapping的系统架构

    ORM - O/R M - Object/Relational Mapping: A technique/idea used to map objects and thier individual r ...

  7. ArcGIS制图表达Representation实战篇2-河流渐变与符号旋转

    ArcGIS制图表达Representation实战篇2-河流渐变与符号旋转 by 李远祥 上一章节主要是从实战中使用规则和几何效果,如何分解制图规则.本章主要还是通过一些特殊要求如河流线宽渐变和符号 ...

  8. python---01&period;名片管理系统

    这是第一篇文章,也是完整编写的第一份代码,,,,希望大神们多多指导,提出更好的想法. 第一部分-----提供选项的菜单栏 第二部分:根据用户输入的选择,提供功能 总体需要一个while True: 其 ...

  9. C&num; 对象池的实现&lpar;能限制最大实例数量,类似于WCF的MaxInstanceCount功能&rpar;

    对象池服务可以减少从头创建每个对象的系统开销.在激活对象时,它从池中提取.在停用对象时,它放回池中,等待下一个请求.我们来看下主线程中,如何与对象池打交道: static void Main(stri ...

  10. iText7生成pdf

    1 官网 http://developers.itextpdf.com/itext-java 2 form中加入表格 http://developers.itextpdf.com/content/be ...