Canvas中如何画一条清晰的线宽为奇数(如1px逻辑像素)的线?
我在开发中使用canvas
的机会不是很多,但是第一次实际使用中就遇到了问题,“很久很久以前,我自己画了一个雷达图,线宽都是1像素,但是显示效果不如期望,这才发现canvas
中的画线还是有坑的”,对比一下两个图,可以发现下图比较清晰。


我们先画一个线宽为1像素的线,代码和显示效果如下:
const ctx = document.getElementById(canvas).getContext("2d");
ctx.strokeStyle = "red";
ctx.lineWidth =1;
ctx.moveTo(50, 10);
ctx.lineTo(200, 10);
ctx.stroke();

不对呀,这条线咋这么模糊,而且宽度貌似也不是1px
为了画这条线,浏览器首先到达初始起点(50,10)。这条线宽1px,所以两边各留0.5px。所以基本上初始起点是从(50,9.5)延伸到(50,10.5)。现在浏览器不能在屏幕上显示0.5像素——最小阈值是1像素。浏览器别无选择,只能将起点的边界延伸到屏幕上的实际像素边界。它会在两边再加0.5倍的“垃圾”。所以现在,最初的起点是从(50,9)扩展到(50,11),所以看起来有2px宽。情况如下:

下面是真实的2px宽的线,作为对照,可以发现,上面的线宽确实占据了2px,只是边缘显示非常模糊

那如何绘制1像素的线呢?本文总结了三种方法。
- 将划线起始点移动到x.5的位置
既然1px宽的线是向两边各延伸0.5px,那如果我们的起点直接放在x.5的位置,向左右扩展则刚好占据1px,如下图所示:
修改代码
ctx.moveTo(50, 10.5);
ctx.lineTo(200, 10.5);

上面的方法有个坏处是我们要修改现有的计算逻辑,时刻留意要多出0.5px
- 绘制上下文整体移动x.5
这个方法的好处是不扰乱我们的设计尺寸和计算逻辑,操作也很简单,只需要正常画好线后,上下文整体移动。
ctx.translate(0, 0.5);
- 控制
canvas
元素大小与绘制上下文大小的比率
canvas
有两个尺寸,一个是元素本身的css尺寸,一个是绘上下文的尺寸(画布的尺寸),默认情况下,canvas
的画布尺寸和元素尺寸都是300*150.比率为1.画布尺寸是通过直接在元素上添加width
和height
属性设置的,css尺寸则是通过css样式属性设置的,需要注意的是:
1.如果仅在元素上添加width
和height
属性来设置画布尺寸,实际表现则同时设置了画布尺寸和css尺寸为相同的大小;
2.如果仅设置了css尺寸,则画布尺寸还是默认的300*150,并不会改变;
3.如果同时设置了画布尺寸和css尺寸,浏览器会缩放画布尺寸来适应css尺寸;
上面的第三条规则给我们画1px线宽提供了另一种方法,具体方法是设置canvas
的画布尺寸是css尺寸的两倍,这样我们只需要按照两倍的设计尺寸(2px)来画线,这样就不会存在占用半个像素导致模糊的问题,浏览器会自动压缩画布到它的一半大小,原来2px的线宽会压缩显示成1px。
<canvas id="canvas5" width="600" height="300"> </canvas>
<canvas id="canvas6" width="600" height="300"> </canvas>
#canvas5 {
width: 300px;
height: 150px;
}
#canvas6 {
transform-origin: top left;
transform: scale(0.5);
}
如果想画出真实的物理1px的线,可以将画布尺寸继续放大widow.devicePixelRatio
倍
参考
How to Draw 1px Crisp Lines in HTML5 Canvas
Canvas中如何画一条清晰的线宽为奇数(如1px逻辑像素)的线?的更多相关文章
- 有趣html5(两)----使用canvas结合剧本画在画布上的简单图(html5另一个强大)
请珍惜劳动小编成果,这篇文章是原来小编,转载请注明出处. 于html5中能够使用canvas标签在画布上绘图,先直接上代码,这篇文章先简介一下canvas的用法.简单画几个圆,矩形,三角形,写字. 在 ...
- 根据多个点使用canvas贝赛尔曲线画一条平滑的曲线
众所周知想用canvas画一条曲线我们可以使用这些函数: 二次曲线:quadraticCurveTo(cp1x, cp1y, x, y) 贝塞尔曲线:bezierCurveTo(cp1x, cp1y, ...
- HTML5在canvas中绘制复杂形状附效果截图
HTML5在canvas中绘制复杂形状附效果截图 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,绘图环境提供了如下方法来绘制复杂的形状或路径. beginPath() : 开始绘制一个新路 ...
- Html5新特性 <canvas>画板画直线
以下样例为用canvas标签画多条直线 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" & ...
- <canvas>中isPointInPath()方法在不同绘制内容中的效果
<canvas>是HTML5中新增加的一个元素,我们可以使用脚本(通常使用JavaScript)在上面绘制图形,就像个画布一样.我们可以用它来绘制图表.制作一些动画.默认大小为300px ...
- HTML5 在canvas中绘制复杂形状
作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/32942667 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,画图环 ...
- Canvas中的save方法和restore方法
初学者也许会误认为canvas中save方法是用来保存绘图状态的图形,而restore方法是用来还原之前保存的绘图状态的图形,其实不然. save():保存当前的绘图状态. restore():恢复之 ...
- 浅谈HTML5中canvas中的beginPath()和closePath()的重要性
beginPath的作用很简单,就是开始一段新的路径,但在使用canvas绘图的过程中却非常重要 先来看一小段代码: var ctx=document.getElementById("can ...
- Canvas中的非零围绕规则原理
非零围绕规则:对于路径中指定范围区域,从该区域内部画一条足够长的线段.使此线段的全然落在路径范围之外. 非零围绕规则计数器:然后,将计数器初始化为0,每当这个线段与路径上的直线或曲线相交时,就改变计数 ...
随机推荐
- 自动化测试框架【windows版】:JMeter + Ant + Jenkins
前提条件:windows安装了jmeter.ant.jenkins 安装方法参考汇总目录中对应的博文 截图看不清的,可以调大浏览器倍数看 jenkins驱动ant执行,ant驱动jmeter执行 an ...
- Centos下MariaDB操作
MariaDB简介 MariaDB是mysql数据库的一个分支,操作几乎和mysql一样 MariaDB安装.启动.停止 # 安装 yum -y install mariadb mariadb-ser ...
- MongoDB用户权限认证
关于用户的认证及权限 用户是跟着库创建的,在哪个库创建的什么权限的什么用户,只对此库有相应权限(除超级管理员以外). 官网文档:https://docs.mongodb.com/master/refe ...
- 深入理解display属性——前端布局常用重要属性
小注:display属性在网页布局中非常常见,但经常用到的仅仅是block.inline-block.inline和none等寥寥几个属性值,下面本人将详细介绍display属性的各个方面 定义 di ...
- js同步、异步、延时、无阻塞加载
一.同步加载 平常默认用的都是同步加载.如:<script src="http://yourdomain.com/script.js"></script> ...
- 《模式分类(原书第二版)》pdf格式下载电子书免费下载
<模式分类(原书第二版)>pdf格式下载电子书免费下载: https://u253469.ctfile.com/fs/253469-302448505 内容简介 <模式分类>( ...
- ps切图技巧
步骤1: ps打开psd文件 步骤2: 点击移动工具,观察左上角的自动选择是否有勾选 ,如果没有最好勾选,对应的选项有图层和组,善于切换这个功能能够有效快速的找到你要的区域 步骤3: 找到要切图的元素 ...
- 解锁技能:sass + node-sass多页面应用编译(转载)
传送门:https://blog.csdn.net/wx11408115/article/details/78023466
- Python文本编辑器推荐
首推当然是Sublime Text:可以中文化,百度上面有教程,页面比较酷炫,功能也不错 然后就是Notepad++,台湾开发,有中文界面
- sql注入--双查询报错注入
sql注入--双查询报错注入 背景:在sqli-labs第五关时,即使sql语句构造成功页面也没有回显出我们需要的信息,看到了有使用双查询操作造成报错的方式获得数据库信息,于是研究了一下双查询的报错原 ...