关于高清显示屏下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文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...
随机推荐
- 敏捷开发(Scrum)
一.敏捷的背景与动机 1.1 软件危机及软件工程的出现 速度是企业竞争致胜的关键因素,软件项目的最大挑战在于,一方面要应付变动中的需求,一方面要在紧缩的时程内完成项目,传统的软件工程难以满足这些要 ...
- Java-文件下载案例
文件下载需求 1.页面显示超链接 2.点击超链接后弹出下载框 3.完成图片文件下载 分析 1.超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框.不满足需求 2.任 ...
- 玄机-第一章 应急响应-Linux日志分析
目录 前言 简介 应急开始 准备工作 查看auth.log文件 grep -a 步骤 1 步骤 2 步骤 3 步骤 4 步骤 5 总结 前言 又花了一块rmb玩玄机...啥时候才能5金币拿下一个应急靶 ...
- 基于Java+SpringBoot+vue+element助农平台设计和实现
\n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 随着互联网大趋势的到来,社会的方方面面,各行各业都在考虑利用互联网作为媒介将自 ...
- 前端太卷了,不玩了,写写node.js全栈涨工资,赶紧学起来吧!!!!!
首先聊下node.js的优缺点和应用场景 Node.js的优点和应用场景 Node.js作为后端开发的选择具有许多优点,以下是其中一些: 高性能: Node.js采用了事件驱动.非阻塞I/O模型,使得 ...
- 第六节 JMeter基础-中级登录【用户自定义变量】
1.认识JMeter (1)配置元件:配置对应的一些数据 (例如:HTTP请求默认值.用户定义的变量) (2)[HTTP请求默认值]:HTTP请求默认值是设置的Web服务器部分信息,可以贯穿多个接口. ...
- windows server dhcp与AD域
创建两台windows server 2016 同一个网络适配器 windows1 配置window1手动网络 安装域 设置密码下一步下一步 重启 完成域安装后创建用户 配置windows1 dhcp ...
- 【Mybatis】08 ResultMap、Association、分步查询、懒加载
ResultMap自定义结果集 可以把查询返回的结果集封装成复杂的JavaBean对象 原来的ResultType属性,只能把查询到的结果集转换为简单的JavaBean 什么是简单的JavaBean对 ...
- 【Docker】06 部署挂载本地目录的Nginx
1.拉取Nginx镜像: docker pull nginx:1.19 2.生成一个测试的Nginx容器: docker run --rm --name nginx-test -p 8080:80 - ...
- Rust项目的代码组织
学习一种编程语言时,常常优先关注在语言的语法和标准库上,希望能够尽快用上新语言来开发,我自己学习新的开发语言时也是这样. 不过,想用一种新的语言去开发实际的项目,或者自己做点小工具的话,除了语言本身之 ...