一般场景

我们看下,我们在高清显示屏下,实现这样一个内容,里面填充颜色及文字。第一种是用普通div元素的方式绘制,第二种就是用canvas的方式来绘制,示例效果如下:

从图上我们可以看出,普通div的绘制方式是清晰的,但是用canvas的绘制方式是模糊的。

参考示例代码如下:

css代码:

html,body {
padding: 0;
margin: 0;
}
#normal-parent,#canvas-parent {
width: 150px;
height: 100px;
border: 1px solid #000;
margin: 0 auto 2px;
}
.normal-word {
width: 150px;
height: 100px;
line-height: 0;
padding-top: 50px;
padding-left: 10px;
background-color: green;
font-size: 14px;
color: #999;
font-family: 'Georgia';
box-sizing: border-box;
}

HTML及JS代码:

<div id="normal-parent" style="margin-top: 10px;">
<div class="normal-word">我是清晰的文字</div>
</div> <div id="canvas-parent">
<canvas id="canvas-init" width="150" height="100"></canvas>
</div> <script type="text/javascript">
var canvas = document.getElementById('canvas-init');
var ctx = canvas.getContext('2d'); ctx.fillStyle = 'green';
ctx.fillRect(0,0,150,100);
ctx.font = "14px Georgia";
ctx.fillStyle = "#999";
ctx.fillText("我是清晰的文字", 10, 50);
</script>

为什么canvas画出来的内容会模糊呢?

我们先来看几个常见的概念:

  • 设备像素=物理像素(物理分辨率,比如13寸的macbook pro的分辨率为2560*1600指的是物理分辨率)
  • 设备独立像素=逻辑像素(逻辑分辨率,实际上13寸的macbook pro的屏幕只能显示1440*900的大小,所以1440*900就是它的逻辑分辨率)
  • dpr:设备像素比devicePixelRatio = 物理像素/设备独立像素
  • ppi:即每英寸像素取值,更确切的说法应该是像素密度,也就是衡量单位物理面积内拥有像素值的情况。ppi越高,每英寸像素点越多,图像越清晰。
  • 默认情况下 1css像素=1设备独立像素

注:设备像素比(dpr) 是指在移动开发中1个css像素占用多少设备像素,比如dpr=2就代表1个css像素用2x2个设备像素来绘制。

几个常见的概念说明后,我们在接着标题解释下为什么canvas在高清屏下画出来的内容是模糊的呢?

首先,在一台普通屏幕上的像素(设备独立像素,也即是逻辑像素),可以当成正常的像素(css像素),比如画10px的元素,那么它就是10px的元素。但是如果在高清屏下就会发生变化,有一个属性就做设备像素比devicePixelRatio。在高清屏下,比如我们的设备像素比devicePixelRatio为2,那么在css设置100px(逻辑像素),实际渲染的是200px的物理像素

而不管是否是高清屏,canvas中的单位1(逻辑像素),就是1物理像素。所以在高清屏下,canvas绘制的内容就变得模糊了。

怎样处理变清晰?

canvas标签有一个特性,canvas元素的大小(宽高)会影响canvas的画布的内容

根据上面的一个特性,我们来举个例子,跟上面的示例类似,我们默认设置一个canvas画布,默认画布大小150*100,然后我们改变canvas元素的宽度变成原来的一半,示例代码如下,为了做对比,我们加上了原来的示例代码:

CSS代码:

html,body {
padding: 0;
margin: 0;
}
#normal-parent,#canvas-parent,#canvas-parent2 {
width: 150px;
height: 100px;
border: 1px solid #000;
margin: 0 auto 2px;
}
.normal-word {
width: 150px;
height: 100px;
line-height: 0;
padding-top: 50px;
padding-left: 10px;
background-color: green;
font-size: 14px;
color: #999;
font-family: 'Georgia';
box-sizing: border-box;
}

HTML跟JS代码:

<div id="normal-parent" style="margin-top: 10px;">
<div class="normal-word">我是清晰的文字</div>
</div> <div id="canvas-parent">
<canvas id="canvas-init" width="150" height="100"></canvas>
</div>
<div id="canvas-parent2">
<canvas id="canvas-scale" width="150" height="100"></canvas>
</div> <script type="text/javascript">
var canvas = document.getElementById('canvas-init');
var ctx = canvas.getContext('2d'); ctx.fillStyle = 'green';
ctx.fillRect(0,0,150,100);
ctx.font = "14px Georgia";
ctx.fillStyle = "#999";
ctx.fillText("我是清晰的文字", 10, 50); var canvas2 = document.getElementById('canvas-scale');
var ctx2= canvas2.getContext('2d'); canvas2.style.width = canvas2.width / 2 + 'px'; ctx2.fillStyle = 'green';
ctx2.fillRect(0,0,150,100);
ctx2.font = "14px Georgia";
ctx2.fillStyle = "#999";
ctx2.fillText("我是清晰的文字", 10, 50);
</script>

示例效果:

可以看到最后面一个canvas画布的效果,画布x方向和y方向的内容被缩放到原来的1/2

所以我们利用这个特性,在高清屏下(假设devicePixelRatio的值为2,逻辑像素为100),将canvas画布大小乘以2转换成实际像素(物理像素)大小,然后通过css设置canvas元素大小为逻辑像素100px。缩放后,画布就清晰了。但是这个时候画布内容是缩小的,这个时候可以利用canvas的scale()方法去放大2倍。

注释:canvas 的 scale() 的方法在 放大/缩小 canvas 时,不会改变内容素质,可以理解为清晰度不会变。

那么上例的代码改造下,代码如下:

var canvas = document.getElementById('canvas-init');
var ctx = canvas.getContext('2d');
var ratio = window.devicePixelRatio || 1;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;
ctx.scale(ratio,ratio); ctx.fillStyle = 'green';
ctx.fillRect(0,0,150,100);
ctx.font = "14px Georgia";
ctx.fillStyle = "#999";
ctx.fillText("我是清晰的文字", 10, 50); var canvas2 = document.getElementById('canvas-scale');
var ctx2= canvas2.getContext('2d'); canvas2.style.width = canvas2.width + 'px';
canvas2.style.height = canvas2.height + 'px';
canvas2.width = canvas2.width * ratio;
canvas2.height = canvas2.height * ratio;
ctx2.scale(ratio,ratio); ctx2.fillStyle = 'green';
ctx2.fillRect(0,0,150,100);
ctx2.font = "14px Georgia";
ctx2.fillStyle = "#999";
ctx2.fillText("我是清晰的文字", 10, 50);

效果图:

现在看到的清晰度就完全一样了。

参考地址:

关于高清显示屏下canvas绘制模糊问题探索处理的更多相关文章

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

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

  2. vue下canvas绘制矩形

    起因:根据项目需求本人写了一个绘制矩形的组件.功能:在图片中绘制矩形,根据图片大小进行自适应展示,获取图片矩形坐标.思路:首先定义一个固定大小的DIV,DIV标签中有监测鼠标变化的四个事件moused ...

  3. JavaScript Html2canvas 生成高清图片(移动端模糊问题)

    最近在做一个移动端的项目,简单记录一下该功能. 需求是这样的: 将带有二维码和一些介绍信息 动态生成一张图片 比如说是 生成这样的图片,文字.主图.价格.二维码都是不固定的. 对于这个需求,看见微信上 ...

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

    解决 canvas 绘图在高清屏中的模糊问题 为什么模糊 CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值. 在高清屏之前,屏幕上显示一个像素点需要 ...

  5. 移动端H5页面高清多屏适配方案

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

  6. webapp:移动端高清、多屏适配方案(zz)

    来源: http://sentsin.com/web/1212.html 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉 ...

  7. 解惑好文:移动端H5页面高清多屏适配方案 (转)

    转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...

  8. 移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]

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

  9. [转]:移动端H5页面高清多屏适配方案

    原文链接:http://www.tuicool.com/articles/YJviea 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们 ...

  10. 解惑好文:移动端H5页面高清多屏适配方案

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

随机推荐

  1. [oeasy]python0069_帮助手册_pydoc_manual_document

    帮助手册 回忆上次内容   上次了解了注释 注释是为了让程序更可读 注释不会影响程序运行速度   注释分为两种 单行的 以#开头 不能是字符串当中的#   多行的 三个" 三个'     多 ...

  2. MViTv2:Facebook出品,进一步优化的多尺度ViT | CVPR 2022

    论文将Multiscale Vision Transformers (MViTv2) 作为图像和视频分类以及对象检测的统一架构进行研究,结合分解的相对位置编码和残差池化连接提出了MViT的改进版本 来 ...

  3. 把python中的列表转化为字符串

    怎么把python中的列表转换为字符串: 1,列表中非字符串的元素的转换 方法一: 使用列表推导式进行转换 1 list=['hello',6,9,'beizhi'] 2 list=[str(i) f ...

  4. adb shell 批处理文件

    adb shell 批处理文件 手机截屏,并把图片传到电脑

  5. 【Java】【常用类】LocalDateTime 当前日期时间类 相关

    LocalDate主要的三个API类: java.time.LocalDate; java.time.LocalDateTime; java.time.LocalTime; LocatDate对象获取 ...

  6. 强化学习中的“sample efficiency”应该如何翻译 —— “样本效率”还是“采样效率”

    问题: 强化学习中的"sample efficiency"应该如何翻译 -- "样本效率"还是"采样效率" 答案: 具体看上下文内容.如果是 ...

  7. 带有最小间隔时间的队列读取实现 —— 最小等待时间的队列 —— Python编程(续)

    接前文: 带有最小间隔时间的队列读取实现 -- 最小等待时间的队列 -- Python编程 由于上次的设计多少有些简单,这里对此丰富一下. ============================== ...

  8. 记录一次实验室linux系统的GPU服务器死机故障的排查——Linux系统的Power States

    实验室的ubuntu服务器不知怎么的突然又崩溃了,死机重启,然后查看日志,发现了下面的情况: 由于从其他的日志中知道是显卡的问题引起的死机,而这个显卡的地址正好是D9:00,这部分的日志就不给出了.结 ...

  9. 文本相似度 HanPL汉语言处理

    @ 目录 前言 需求 简介 实操开始 1. 添加pom.xml依赖 2. 文本相似度工具类 3. 案例验证 4. 验证结果 总结 前言 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i. 提示 ...

  10. EF Core连接PostgreSQL数据库

    PostgreSQL数据库介绍 PostgreSQL是一个功能强大的开源对象关系型数据库管理系统(RDBMS).最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生,PostgreSQL以 ...