html5 canvas在img标签的图片上绘制矩形框、矩形框为1px时线条模糊问题

需求

前端需要在后端返回的图片集合里,根据提供的对角线坐标绘制矩形。矩形可能是多个。效果达到如下:


image.png
思路:

1、根据后端返回的图片list,生成canvas画布,
2、把图片画到canvas里面,再根据后端返回的坐标,在canvas里画矩形框。
此项目中,后端返回的坐标是基于缩略图的,但是前端渲染在页面上的图片,会按宽为788px来显示,所以坐标应该要按照比例来算。
真实的左上x点的计算方式为:真实宽 / 压缩宽 * 压缩x点

关于改变画布大小

https://blog.csdn.net/qq_29594393/article/details/52849339
https://www.runoob.com/w3cnote/html5-canvas-intro.html

符合我的思维

https://www.imooc.com/wenda/detail/551496

推荐阅读

https://blog.csdn.net/qq_44907926/article/details/114907056?spm=1001.2014.3001.5501

完整实例:
html
           <template v-if="text_img_pos.length">
              <div v-for="(item, index) in text_img_pos" :key="index">
                <canvas
                  :id="'myCanvas' + index"
                  width="940"
                  height="570"
                ></canvas>
              </div>
            </template>
            <div v-else style="padding-top:50px">
              暂无内容
            </div>
后端返回数据
//图片集合
       this.text_img_pos = [
            {           
              image_path: "http://192.168.1.90:8081/img/achives1.png", //图片路径
              width: "719", //图宽
              height: "819", //图高
              coordinate: [
                //坐标
                { x1: "6", y1: "248", x2: "710", y2: "350" },
                { x1: "6", y1: "430", x2: "710", y2: "510" },
                { x1: "6", y1: "690", x2: "710", y2: "790" }
              ]
            },
            {            
              width: "719",
              height: "819",
              image_path: "http://192.168.1.90:8081/img/achives1.png"
            },
          ];
//在canvas里添加图片和矩形
    drawLight() {
      for (let i = 0; i < this.text_img_pos.length; i++) {
        if (this.text_img_pos[i].image_path) {
          this.draw(this.text_img_pos[i], i);
        }
      }
    },
    draw(obj, index) {
      let canvasHeight = Math.round(
        (788 * Number(obj.height)) / Number(obj.width)
      );
      var myCanvas = document.getElementById("myCanvas" + index);
      var ctx = myCanvas.getContext("2d");
      var img = new Image();
      img.src = obj.image_path;
      img.onload = () => {
        myCanvas.setAttribute("width", 788);
        myCanvas.setAttribute("height", canvasHeight); //重新设置画布的大小
        ctx.drawImage(img, 0, 0, 788, canvasHeight);
        //矩形高亮
        if (obj.coordinate && obj.coordinate.length) {
          for (let i = 0; i < obj.coordinate.length; i++) {
            let zipCoor = obj.coordinate[i];
            let realX1 = Math.round((788 / obj.width) * zipCoor.x1); //画布坐标x1
            let realY1 = Math.round((canvasHeight / obj.height) * zipCoor.y1);
            let realX2 = Math.round((788 / obj.width) * zipCoor.x2);
            let realY2 = Math.round((canvasHeight / obj.height) * zipCoor.y2);
            //选中区域的宽高
            let width = realX2 - realX1;
            let height = realY2 - realY1;
            ctx.lineWidth = "1";// 线条的粗细
            ctx.strokeStyle = "red"; // 线条的颜色
            ctx.rect(realX1, realY1, width, height);
            ctx.stroke();// 最后,画线条,作用是描边————这句才是真正的画线!
          }
        }
      };
    },
踩坑记录:

①画矩形时,如果里面的参数有不是整数的话,容易导致边框粗细不一等问题。
②当矩形的边框lineWidth设置为1px时候,会出现线条模糊的问题。
关于第②个问题的延申:
这是测试提给我的bug:

image.png

我的思路存在的问题:
首先,同样是矩形的边框我同样设置的都是1px,不应该有的线条颜色深,有的颜色淡啊,排除了参数没有取整的问题后,我怀疑了颜色red在画布上的渲染问题,换成十六进制的同样有问题。就在我一筹莫展的时候,我叫来了小伙伴,我说你看这线条颜色是不是不一样,我开始怀疑我的眼神有问题。小伙伴说,你给线条整粗点看看这问题明显吗。我把边框线条设置了2px,发现和1px的粗细是一样的,并且颜色一样了线条不模糊了。换成别的宽度,只要不是1px都没有问题了。
思维的问题在于,我百度问题的描述有问题,我之前一直搜canvas绘制矩形线条深浅不一,我应该搜canvas矩形线条模糊。我排查问题的时候,固定思维模式觉得1px写的没错,却没有尝试排查。

关于这个问题的详细解答与解决办法:
canvas1px线条模糊

我的理解
canvas的线条画法不一样,canvas的每条线都有一条无限细的“中线”,线条的宽度是从中线向两侧延伸的,也就是说canvas绘制1px的时候,是中线向左右两边延申各取0.5,并不是向某一边延申(如果只是往右延申就不再是问题了),此时问题出现了,计算机不允许出现小于1px的图形,所以他做了一个折中的事:把这两个像素都绘制了。所以,如此一来,本来1px的线条,就成了看起来2px宽的线条。

延申:
HTML 5 Canvas详细讲解 ———— 第二篇(清除canvas画布上指定区域+橡皮擦功能实现;在画布上平铺指定图片;在画布上绘制文本;总结案例之刮刮乐功能实现)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容