【Canvas】311- 解决 canvas 在高清屏中绘制模糊的问题
点击上方“前端自习课”关注,学习起来~
一、问题分析
使用 canvas 绘制图片或者是文字在 Retina 屏中会非常模糊。如图:
因为 canvas 不是矢量图,而是像图片一样是位图模式的。高 dpi 显示设备意味着每平方英寸有更多的像素。也就是说二倍屏,浏览器就会以 2 个像素点的宽度来渲染一个像素,该 canvas 在 Retina 屏幕下相当于占据了2倍的空间,相当于图片被放大了一倍,因此绘制出来的图片文字等会变模糊。
因此,要做 Retina 屏适配,关键是知道当前屏幕的设备像素比,然后将 canvas 放大到该设备像素比来绘制,然后将 canvas 压缩到一倍来展示。
二、解决思路
在浏览器的 window 对象中有一个 devicePixelRatio 的属性,该属性表示了屏幕的设备像素比,即用几个(通常是 2 个)像素点宽度来渲染 1 个像素。
举例来说,假设 devicePixelRatio 的值为 2 ,一张 100×100 像素大小的图片,在 Retina 屏幕下,会用 2 个像素点的宽度去渲染图片的 1 个像素点,因此该图片在 Retina 屏幕上实际会占据 200×200 像素的空间,相当于图片被放大了一倍,因此图片会变得模糊。
类似的,在 canvas context 中也存在一个 backingStorePixelRatio 的属性,该属性的值决定了浏览器在渲染 canvas 之前会用几个像素来来存储画布信息。 backingStorePixelRatio 属性在各浏览器厂商的获取方式不一样,所以需要加上浏览器前缀来实现兼容。
三、解决问题
1. 首先一样,获取 Canvas 对象:
var myCanvas = document.getElementById("my_canvas");
var context = myCanvas.getContext("2d");
2. 获取像素比,将 Canvas 宽高进行放大,放大比例为: devicePixelRatio/webkitBackingStorePixelRatio , 我们写了一个兼容的方法。
var getPixelRatio = function (context) {
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
};
var ratio = getPixelRatio(context);
3. 按实际渲染倍率来缩放 canvas 。
注意基础知识点:
要设置
canvas的画布大小,使用的是canvas.width和canvas.height;要设置画布的实际渲染大小,使用的
style属性或CSS设置的width和height,只是简单的对画布进行缩放。
2倍屏幕下示例代码:
<canvas
width="640" height="800"
style="width:320px; height:400px"
></canvas>
canvas 的实际大小的 640px×800px,但是实际渲染到页面的大小是 320px×400px,相当于缩小一倍来显示。
那么在3倍屏幕下就是:
<canvas
width="960" height="1200"
style="width:320px; height:400px"
></canvas>
因此,要使 canvas 适配高倍屏,就是要将 canvas 放大到设备像素比来绘制,最后将 canvas 压缩成一倍的物理大小来展示。如下:
myCanvas.style.width = myCanvas.width + 'px';
myCanvas.style.height = myCanvas.height + 'px';
myCanvas.width = myCanvas.width * ratio;
myCanvas.height = myCanvas.height * ratio;
4. 绘制
由于 Canvas 放大后,相应的绘制图片时也要放大,有两种方式:
第一种方法:每一个绘制相应的放大,比如我们绘制文字:
context.font = "36px Georgia";
//一倍屏下18px字体
context.fillStyle = "#999";
context.fillText("我是清晰的文字", 50*ratio, 50*ratio);
// 坐标位置乘以像素比
相对来说这个方法非常繁琐麻烦。
第二种方法:直接使用 scale 方法:
// 放大倍数
context.scale(ratio, ratio);
context.font = "18px Georgia";
context.fillStyle = "#999";
context.fillText("我是清晰的文字", 50, 50);
这样就可以解决 canvas 在高清屏中绘制模糊的问题。
完整的demo:https://www.html.cn/demo/canvas_retina/index.html
▼原创系列推荐▼1.JavaScript 重温系列(22篇全)
2.ECMAScript 重温系列(10篇全)
3.JavaScript设计模式 重温系列(9篇全)
4.正则 / 框架 / 算法等 重温系列(16篇全)5.【汇总】59篇原创系列汇总
你点的每个赞,我都认真当成了喜欢
【Canvas】311- 解决 canvas 在高清屏中绘制模糊的问题的更多相关文章
- 【转】解决 canvas 在高清屏中绘制模糊的问题
来源: http://www.css88.com/archives/9297 使用 canvas 绘制图片或者是文字在 Retina 屏中会非常模糊.如图: 因为 canvas 不是矢量图,而是像图片 ...
- 解决 canvas 在高清屏中绘制模糊的问题
主要代码部分: <canvas id="my_canvas" width="540" heihgt="180"></can ...
- 解决 canvas 绘图在高清屏中的模糊问题
解决 canvas 绘图在高清屏中的模糊问题 为什么模糊 CSS 像素是一个抽象单位(1 px),浏览器根据某种规则将 css 像素转化为屏幕需要的实际像素值. 在高清屏之前,屏幕上显示一个像素点需要 ...
- ArcGIS 在高清屏中主界面界面字体和图标显示过小,如何解决?
作者:安日链接:https://www.zhihu.com/question/40658050/answer/132382971来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 高清屏下canvas重置尺寸引发的问题
我们知道,清空canvas画布内容有以下两个方法. 第一种方法是cearRect函数: context.cearRect(0,0,canvas.width,canvas.height) 第二种方法就是 ...
- Cocos2D瓦块地图高清屏(retina)显示比例问题的解决
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在Cocos2D的游戏编程里,常用到瓦块地图.而cocos2D ...
- 移动端,多屏幕尺寸高清屏retina屏适配的解决方案
移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页 ...
- Cocos2D iOS之旅:如何写一个敲地鼠游戏(一):高清屏显示和UIKit
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- 怎么在高清屏上画一条0.5px的边
怎么在高清屏上画一条0.5px的边呢?0.5px相当于高清屏物理像素的1px.这样的目的是在高清屏上看起来会更细一点,效果会更好一点,例如更细的分隔线. 理论上px的最小单位是1,但是会有几个特例,高 ...
随机推荐
- [深度学习][图像处理][毕设][笔记][安装环境][下载地址]安装VS2013、matconvnet、cuda、cudnn过程中产生的一些记录,2018.5.6号
最近半个多月,被cuda等软件折磨的死去活来,昨天下午,终于安装好了环境,趁着matlab正在,在线下载VOT2016数据集,3点睡眼惺忪被闹醒后,睡不着,爬上来写这份记录. 先记录一下自己电脑的基本 ...
- Linux命令大全(个人整理,如不全面望谅解)
系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...
- pat 1035 Password(20 分)
1035 Password(20 分) To prepare for PAT, the judge sometimes has to generate random passwords for the ...
- Java每日一面(Part1:计算机网络)[19/11/25]
作者:晨钟暮鼓c个人微信公众号:程序猿的月光宝盒 1. HTTP相关[2] 1.1Get请求和Post请求的区别 从三个层面来回答: 1.1.1 从HTTP报文层面: Get请求将请求信息放在UR ...
- PostGIS 查询点在线上
1.缓冲区法:查询数据库fm表里,与坐标(12989691.512 4798962.444)相距0.0001米的数据(3857坐标系) ),),),),geom) ; --如果坐标系统一,不用tran ...
- Java学习笔记 线程池使用及详解
有点笨,参考了好几篇大佬们写的文章才整理出来的笔记.... 字面意思上解释,线程池就是装有线程的池,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程 ...
- 原生JS的移入溢出控制div的显示与隐藏
原生JS的移入溢出控制div的显示与隐藏的写法 上面的写法火狐存在兼容性
- 计蒜客 The Preliminary Contest for ICPC Asia Nanjing 2019
F Greedy Sequence You're given a permutation aa of length nn (1 \le n \le 10^51≤n≤105). For each ...
- 关于C语言中i++和++i的区别以及printf输出的一些问题。
a_pos = a++; //后缀,使用a的值之后,递增a b_pre = ++b; //前缀,使用b的值之前,递增b a--和--b同理,不必赘述.这是几乎每个学习过C语言的同学都会知道的,而我在帮 ...
- 华为云MySQL金融版正式商用,高可靠的金融级数据库来了
摘要:全新三节点架构,基于深度优化的MGR组复制技术,提供金融级的数据一致性. 日前,华为云数据库MySQL 金融版正式商业化发布,MySQL金融版采用MGR技术,基于Paxos协议,采用一主两备三节 ...