关于高清显示屏下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文件,称之为视觉稿. 对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范 ...
随机推荐
- CF372C
思路 根据题意可以得到dp转移方程是 \(f_{i,j}=\max\{f_{i-1,k}+b_i-|a_i-j|\}\) 而且 \(j-(t_{i}-t_{i-1})\times d\le k\le ...
- oeasy教您玩转 linux 010212 管道 pipe
上一部分我们都讲了什么? 牛说cowsay 牛可以有各种表情 可以自定义眼睛 可以变成各种别的小动物 可以说也可以想cowthink 我们也想让牛说出字符画的感觉 回顾字符画 下载figlet和toi ...
- Day 4 - 搜索进阶与模拟
启发式搜索 下面将简要介绍启发式搜索及其用法. 定义 启发式搜索(英文:\(\text{heuristic search}\))是一种在普通搜索算法的基础上引入了启发式函数的搜索算法. 启发式函数的作 ...
- C#实现单例模式的6种方法
介绍 单例模式是软件工程学中最富盛名的设计模式之一.从本质上看,单例模式只允许被其自身实例化一次,且向外部提供了一个访问该实例的接口.通常来说,单例对象进行实例化时一般不带参数,因为如果不同的实例化请 ...
- 分享一个idea的文档汉化插件
展示效果: 如何获取:
- 我出一道面试题,看看你能拿 3k 还是 30k!
大家好,我是程序员鱼皮.欢迎屏幕前的各位来到今天的模拟面试现场,接下来我会出一道经典的后端面试题,你只需要进行 4 个简单的选择,就能判断出来你的水平是新手(3k).初级(10k).中级(15k)还是 ...
- stable diffusion 入门教程
sd基础 工作原理&入门 输入提示词后 有文本编码器将提示词编译成特征向量,vae编码器将特征向量传入潜空间内,特征向量在潜空间内不断降噪,最后通过vae解码器将降噪之后的特征向量 解码成一个 ...
- 低代码如何借助 K8s 实现高并发支持?
引言 在当今这个数字化时代,互联网的普及和技术的飞速发展使得应用程序面临着前所未有的挑战,其中最为显著的就是高并发访问的需求.随着用户数量的激增和业务规模的扩大,如何确保应用在高并发场景下依然能够稳定 ...
- WPF MVVM模式简介
WPF是Windows Presentation Foundation的缩写,它是一种用于创建桌面应用程序的用户界面框架.WPF支持多种开发模式,其中一种叫做MVVM(Model-View-ViewM ...
- 【WEB】URL文件
早些年接触电脑的时候就有这个东西,去网站上下载盗版游戏,网站会附加这种URL文件 双击运行之后是打开浏览器跳转到该文件描述的网址 我从来没想过这东西里面写的是什么 百度经验: https://baij ...