• canvas总结:线段宽度与像素边界


    canvas中,我们经常需要绘制线段,主要使用moveTolineTo两个方法,moveTo移动至线段起始点,lineTo将线段绘制至终点。同时,绘制线段时可以指定线段的宽度,使用lineWidth属性,lineWidth默认为1,必须大于0

    moveTo(x, y): 移动至坐标xy

    lineTo(x, y): 线段终点坐标xy

    简单绘制代码如下:

    var context = document.getElementById('canvas').getContext('2d');
    context.lineWidth = 2; //设置线宽
    context.beginPath(); //开始绘制路径
    context.moveTo(0, 50); //移动至起始点
    context.lineTo(50, 50); //移动至终点
    context.stroke(); //绘制
    

    Done, 绘制出了一条线宽为2的线段,就这么简单

    那我们再绘制一条线宽为1的线段

    context.lineWidth = 1;
    context.beginPath();
    context.moveTo(50, 50);
    context.lineTo(100, 50);
    context.stroke();
    

    我勒个去,怎么跟线宽2的宽度是一样的,宽度也是2,只是颜色稍浅。

    那我们换个思路,刚才绘制的Y轴左边为50,我们改成50.5呢,分别再绘制两条线宽分别是21的线段

    context.lineWidth = 2;
    context.beginPath();
    context.moveTo(0, 70.5);
    context.lineTo(50, 70.5);
    context.stroke();
    
    context.lineWidth = 1;
    context.beginPath();
    context.moveTo(0, 80.5);
    context.lineTo(50, 80.5);
    context.stroke();
    

    从上至下分别称为线段1234

    显然,线段312都要宽,实际为3px,线段4实际为1px

    线段1:绘制线宽2, 实际宽度2

    线段2:绘制宽度1, 实际宽度2

    线段3:绘制宽度2, 实际宽度3

    线段4:绘制宽度1: 实际宽度1

    只有14才是我们想要的结果

    为什么呢?

    其实,这跟canvas的绘制逻辑有关,当我们试图绘制一个线段时,canvas会读取lineWidth,,然后尝试将在坐标处两边各绘制一半的lineWidth,比如我们下图:

     

    我们在坐标3处画一条宽为1的横线,canvas会以3为中轴线,在两边各画0.5像素,深蓝色就是我们期望的效果(2.5-3.51个像素),但实际上,浅蓝色也会被绘制出来,因为canvas无法在整个像素宽内只绘制半个像素,所以坐标轴上下两个方向都都会被扩展至整个像素宽度内(2-4,两个像素),但是扩展的像素实际的值并不是原值相同,而是取其一半,所以最直接的视觉感受是:线条比预想的变宽了,但是颜色浅了很多。

     

    还是以宽为1的横线为例,我们如果将其绘制在纵坐标2.5处呢,即以半像素作为中轴线

     

    同样浏览器进行绘制时,在2.5上下各绘制0.5的像素宽度,但与上面的例子不同的是,图像边界正好落在整数像素边界内,合起来正好为1个像素,这个时候,就不需要向两边扩展,而是我们预期的(2-3)的1个像素宽度。

    同理,我们分别使用两种方式绘制宽度为2的线段时,效果恰恰相反,在坐标3处绘制的时候,像素正好扩展至2-4,即2个像素,符合我们的预期;而在坐标2.5处绘制时,像素扩展至1.5-3.5,未到边界,需要补足,就变成了1-4,即3个像素。

    建议

    在实际应用中,如果想得到更好的体验,精确的像素值,如果线段的宽度是奇数像素,绘制时以n.5,即半数像素作为中轴线,如果线段的宽度为偶数像素,绘制时以n.0,即整数像素作为中轴线

  • 相关阅读:
    TortoiseGit 连接oschina不用每次输入用户名和密码的方法
    IIS7 配置SSL 绑定主机头
    二种方法安装卸载Windows服务的命令
    System.Data.SqlClient.SqlException: 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值
    SQL Server 2008 角色
    sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法
    winform窗体间传值
    C#用到的一些代码汇总,后期再整理
    排球计分程序中英文切换
    ASP.NET MVC 排球计分程序 (八)排球计分程序的演示
  • 原文地址:https://www.cnblogs.com/v-rockyli/p/3833845.html
Copyright © 2020-2023  润新知