一般场景

我们看下,我们在高清显示屏下,实现这样一个内容,里面填充颜色及文字。第一种是用普通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. Mac 每次都要执行source ~/.bash_profile 配置的环境变量才生效

    自己在 ~/.bash_profile 中配置环境变量, 可是每次重启终端后配置的不生效.需要重新执行 : $source ~/.bash_profile 发现zsh加载的是 ~/.zshrc文件,而 ...

  2. oeasy 教您玩转linux 010304 图形界面 xfce

    我们来回顾一下 上一部分我们都讲了什么? 讲了文件管理器和命令行终端互相交互 用命令nautilus在文件管理器打开某路径 这次我们来看看 图形用户界面(GUI)的情况 图形界面和发行版的关系 一个发 ...

  3. C练习_1005

    题自:题目 1009: [编程入门]数字的处理与判断_C语言网 题目描述 给出一个不多于5位的整数,要求 1.求出它是几位数 2.分别输出每一位数字 3.按逆序输出各位数字,例如原数为321,应输出1 ...

  4. springboot中事务失效的一些场景以及如何应对

    @Transactional是基于AOP的,因此事务发生需要两个条件: 1.添加@Transactional注解 2.使用代理对象 失效场景:同一个类中直接调用的类方法,而被调方法带有@Transac ...

  5. mybatisplus轻松完成一次模糊+分页查询

    之前一直用mybatis+pageinfo完成模糊+分页查询,还需要手写sql语句,之前一直没做尝试,今天试了试mybatisplus一个人完成模糊+分页,挺简单的 有一个小插曲是,我的前端接受的da ...

  6. mysql进阶笔记

    说明:此文章并非原创,参考极客时间文章<MySQL实战45讲>做的一些笔记,方便自己查阅,有兴趣可以自行去极客时间阅读,内容非常给力. mysql引擎  Innodb: Page是Inno ...

  7. matplotlib中渐变颜色条转CSS样式(hex格式)——同mapbox中cog的颜色条拉伸显示

    matplotlib中渐变颜色条转CSS样式(hex格式)--同mapbox中cog的颜色条拉伸显示 应用场景: 1.适用于mapbox中显示cog影像时,colormap_name拉伸颜色条转换 2 ...

  8. 使用PasteSpider实现类似Jenkins的功能,让你的2G服务器也可以飞起

    或许你接触过Jenkins, 在我理解就是拉取源码,然后构建成镜像,最后启动容器! 但是这个功能对于小内存的服务器来说就是奢望了! 今天介绍一个新版本,把你这个遗憾弥补下! 在PasteSpider中 ...

  9. 外形最漂亮的人形机器人——通用机器人Apollo,设计为可以在任何任务和环境中与人类进行协作

    视频地址: https://www.bilibili.com/video/BV11F4m1M7ph/

  10. 灵巧度最高的机械手 —— Clone公司

    地址: https://www.youtube.com/watch?v=ikrDqfnZNLU Clone 公司: 生产通过液压驱动的仿生机器人.