关于高清显示屏下canvas绘制模糊问题探索处理
一般场景
我们看下,我们在高清显示屏下,实现这样一个内容,里面填充颜色及文字。第一种是用普通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绘制模糊问题探索处理的更多相关文章
- 高清屏下canvas重置尺寸引发的问题
我们知道,清空canvas画布内容有以下两个方法. 第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height) 第二种方法就是 ...
- vue下canvas绘制矩形
起因:根据项目需求本人写了一个绘制矩形的组件.功能:在图片中绘制矩形,根据图片大小进行自适应展示,获取图片矩形坐标.思路:首先定义一个固定大小的DIV,DIV标签中有监测鼠标变化的四个事件moused ...
- JavaScript Html2canvas 生成高清图片(移动端模糊问题)
最近在做一个移动端的项目,简单记录一下该功能. 需求是这样的: 将带有二维码和一些介绍信息 动态生成一张图片 比如说是 生成这样的图片,文字.主图.价格.二维码都是不固定的. 对于这个需求,看见微信上 ...
- 解决 canvas 绘图在高清屏中的模糊问题
解决 canvas 绘图在高清屏中的模糊问题 为什么模糊 CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值. 在高清屏之前,屏幕上显示一个像素点需要 ...
- 移动端H5页面高清多屏适配方案
背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...
- webapp:移动端高清、多屏适配方案(zz)
来源: http://sentsin.com/web/1212.html 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉 ...
- 解惑好文:移动端H5页面高清多屏适配方案 (转)
转自:http://mobile.51cto.com/web-484304.htm https://github.com/amfe/lib-flexible/blob/master/src/makeg ...
- 移动端高清、多屏适配方案 [来源:http://div.io/topic/1092]
Lovesueee 发布于 8 月前 移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视 ...
- [转]:移动端H5页面高清多屏适配方案
原文链接:http://www.tuicool.com/articles/YJviea 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们 ...
- 解惑好文:移动端H5页面高清多屏适配方案
背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...
随机推荐
- Mac 每次都要执行source ~/.bash_profile 配置的环境变量才生效
自己在 ~/.bash_profile 中配置环境变量, 可是每次重启终端后配置的不生效.需要重新执行 : $source ~/.bash_profile 发现zsh加载的是 ~/.zshrc文件,而 ...
- oeasy 教您玩转linux 010304 图形界面 xfce
我们来回顾一下 上一部分我们都讲了什么? 讲了文件管理器和命令行终端互相交互 用命令nautilus在文件管理器打开某路径 这次我们来看看 图形用户界面(GUI)的情况 图形界面和发行版的关系 一个发 ...
- C练习_1005
题自:题目 1009: [编程入门]数字的处理与判断_C语言网 题目描述 给出一个不多于5位的整数,要求 1.求出它是几位数 2.分别输出每一位数字 3.按逆序输出各位数字,例如原数为321,应输出1 ...
- springboot中事务失效的一些场景以及如何应对
@Transactional是基于AOP的,因此事务发生需要两个条件: 1.添加@Transactional注解 2.使用代理对象 失效场景:同一个类中直接调用的类方法,而被调方法带有@Transac ...
- mybatisplus轻松完成一次模糊+分页查询
之前一直用mybatis+pageinfo完成模糊+分页查询,还需要手写sql语句,之前一直没做尝试,今天试了试mybatisplus一个人完成模糊+分页,挺简单的 有一个小插曲是,我的前端接受的da ...
- mysql进阶笔记
说明:此文章并非原创,参考极客时间文章<MySQL实战45讲>做的一些笔记,方便自己查阅,有兴趣可以自行去极客时间阅读,内容非常给力. mysql引擎 Innodb: Page是Inno ...
- matplotlib中渐变颜色条转CSS样式(hex格式)——同mapbox中cog的颜色条拉伸显示
matplotlib中渐变颜色条转CSS样式(hex格式)--同mapbox中cog的颜色条拉伸显示 应用场景: 1.适用于mapbox中显示cog影像时,colormap_name拉伸颜色条转换 2 ...
- 使用PasteSpider实现类似Jenkins的功能,让你的2G服务器也可以飞起
或许你接触过Jenkins, 在我理解就是拉取源码,然后构建成镜像,最后启动容器! 但是这个功能对于小内存的服务器来说就是奢望了! 今天介绍一个新版本,把你这个遗憾弥补下! 在PasteSpider中 ...
- 外形最漂亮的人形机器人——通用机器人Apollo,设计为可以在任何任务和环境中与人类进行协作
视频地址: https://www.bilibili.com/video/BV11F4m1M7ph/
- 灵巧度最高的机械手 —— Clone公司
地址: https://www.youtube.com/watch?v=ikrDqfnZNLU Clone 公司: 生产通过液压驱动的仿生机器人.