canvas如何绘制标签,在知识的海洋狗刨(下)

简介: 下面总结了一些canvas绘制标签的心得体会,希望能够对你有所帮助。

接下来只需要设定参数调用即可


var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  ctx.font = "16px PingFangSC-Regular";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillStyle = "#fff";
  var config = {
    paddingLeft: 20, // 文本左内边距
    paddingRight: 20, // 文本右内边距
    labelHeight: 50, // 标签高度
    labelRadius: 5, // 圆角
    labelBackgroundColor: "#ff6a61" // 标签背景色
  };
  var x = 100;
  var y = 100;
  var str = "快狗打车";
  var textWidth = ctx.measureText(str).width;
  drawRoundRect( ctx, x, y, textWidth + config.paddingLeft + config.paddingRight, config.labelHeight, config.labelRadius, config.labelBackgroundColor);
  ctx.fillText( str, x + config.paddingLeft + textWidth / 2, y + config.labelHeight / 2 );
  var x = 100;
  var y = 200;
  var str = "快狗打车-前端团队";
  var textWidth = ctx.measureText(str).width;
  drawRoundRect( ctx, x, y, textWidth + config.paddingLeft + config.paddingRight, config.labelHeight, config.labelRadius, config.labelBackgroundColor);
  ctx.fillText( str, x + config.paddingLeft + textWidth / 2, y + config.labelHeight / 2 );


运行结果:



measureText() 方法返回包含一个对象,该对象包含以像素计的指定字体宽度。


多标签自动换行



如何实现绘制多标签自动换行?


标签的实际占用空间宽度 = 文本宽度 + 左右内边距 + 左右外边距


遍历所有标签文本,根据限定空间宽度与标签的实际占用空间宽度计算出每一个标签的具体坐标值。


配置参数:


var labelList = [
  { "id": 1, "name": "小型面包" },
  { "id": 2, "name": "金杯" },
  { "id": 3, "name": "依维柯" },
  { "id": 4, "name": "商务车" },
  { "id": 5, "name": "皮卡" },
  { "id": 6, "name": "冷藏车" },
  { "id": 7, "name": "平板货车" },
  { "id": 8, "name": "高栏货车" },
  { "id": 9, "name": "宽体尾板" },
  { "id": 10, "name": "厢式货车" },
  { "id": 11, "name": "其它" }
]
var config = {
  // 标签范围参数
  spaceX: 0, // x坐标
  spaceY: 0, // y坐标
  spaceWidth: 300, // 宽度
  spaceHeight: 300, // 高度
  // 标签参数
  paddingRight: 10, // 文本至左边框距离
  paddingLeft: 10, // 文本至右边框距离
  marginTop: 0, // 上外边界
  marginRight: 10, // 右外边界
  marginBottom: 10, // 下外边界
  marginLeft: 0, // 左外边界
  labelHeight: 30, // 高度
  labelRadius: 5, // 圆角
  labelBackgroundColor: '#ff6a61', // 背景色
  // 字体参数
  fontSize: 12, // 字体大小
  fontColor: '#fff', // 字体颜色
  fontFamily: 'PingFangSC-Regular', // 字体类型
}


遍历标签列表计算出每一个标签具体参数:


function formatLine(ctx, list, config) {
  let labelLine = [];
  let lineIndex = 0;
  let usedWidth = 0;
  list.forEach(item => {
    item.textWidth = ctx.measureText(item.name).width; // 文字占据空间
    let labelSpace = item.textWidth + config.paddingLeft + config.paddingRight + config.marginLeft + config.marginRight; // 标签实际占据宽度
    if(usedWidth + labelSpace > config.spaceWidth) {
      usedWidth = 0;
      lineIndex = lineIndex + 1;
    }
    item.x = config.spaceX + usedWidth + config.marginLeft;
    item.y = config.spaceY + lineIndex * (config.labelHeight + config.marginTop + config.marginBottom) + config.marginTop;
    labelLine.push(item);
    usedWidth = usedWidth + labelSpace;
  });
  return labelLine
}


接下来就是遍历标签进行绘制了:


let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// 填充背景色,以便于观察边界
ctx.fillStyle = "#ccc";  
ctx.fillRect(config.spaceX, config.spaceY, config.spaceWidth, config.spaceHeight);
let labelLine = formatLine(ctx, labelList, config);
drawLabel(ctx, labelLine, config);
function drawLabel(ctx, labelLine, config) {
  ctx.font = `${config.fontSize}px ${config.fontFamily}`;
  ctx.textAlign = "center";
  ctx.textBaseline = 'middle';
  ctx.fillStyle = config.fontColor;
  labelLine.map((item)=>{
    drawRoundRect(ctx, item.x, item.y, item.textWidth + config.paddingLeft + config.paddingRight , config.labelHeight , config.labelRadius , config.labelBackgroundColor);
    ctx.fillText(item.name, item.x + config.paddingLeft + item.textWidth/2, item.y + config.labelHeight/2);
  })
}


运行结果:



延伸



那么到这里标签的绘制已经结束。鬼机灵的小伙伴可能会想到既然ctx.measureText(text).width可以获得文本实际占据宽度,那ctx.measureText(text).height肯定就是获取文本实际占据高度了呗(俺也一样),很遗憾并不是_(°:з」∠)_)


canvas并没有提供获取文本高度的接口,需要通过其他方式间接获取。所幸,我还是百度到了一种解决方案(百度打钱_(°:з」∠)_)——通过获取指定范围内的所有像素数据,计算非白色像素点之间的最大高度差值即为文本实际像素高度。说人话就是找出第一个与最后一个非白色像素点,两者所在像素行之间的差值即为文本实际高度。


核心代码如下


function measureTextHeight(ctx, x, y, width, height) {
  // 从画布获取像素数据
  var data = ctx.getImageData(x, y, width, height).data,
    first = false,
    last = false,
    r = height,
    c = 0;
  // 找到最后一行非白色像素
  while (!last && r) {
    r--;
    for (c = 0; c < width; c++) {
      if (data[r * width * 4 + c * 4 + 3]) {
        last = r;
        break;
      }
    }
  }
  // 找到第一行非白色像素
  while (r) {
    r--;
    for (c = 0; c < width; c++) {
      if (data[r * width * 4 + c * 4 + 3]) {
        first = r;
        break;
      }
    }
    if (first != r) return last - first;
  }
  return 0;
}


getImageData()属性:复制画布上指定矩形的像素数据


这种方法简单粗暴,但是局限性也非常明显,先绘制后获取数据等于耍流氓。小伙伴们还有除此之外的方法不妨在评论区探讨一下。


相关文章
|
JSON JavaScript 数据可视化
D3 不到20行代码就能实现世界地图的绘制
每到农历年末,相信很多小伙伴和本作者一样,都忍不住会去看江苏卫视的一档脑力比拼节目《最强大脑》,尽管上一季最强大脑喷点确实很多,但依旧没有减弱"追剧"的热情。今年最强大脑(第5季)的赛制有很大的变化,挑战的人数从百人大战,到最强30脑,再到现从第三场的一对一PK,确实与以往有了很大的不同。此外,今年更加强调了选手在生活中的光环,例如本文要引用的一场比赛就是最近一期来自清华的孙勇与北京的陈泽坤的一场以地图投影为背景的比赛,孙勇就是顶着2016安徽省高考理科状元的光环来的。今年没了叨叨魏,节目的流程显得自然了很多。好了,不扯了,来、来、来来来!我们开始说本文要讲的主题--地图。
1444 0
D3 不到20行代码就能实现世界地图的绘制
|
2月前
ThreeJs绘制线
这篇文章详细说明了如何使用Three.js来绘制线条,包括创建线几何体、设置材质以及将线条添加到3D场景中的具体步骤。
26 1
|
6月前
|
移动开发 前端开发 HTML5
HTML5 Canvas中实现绘制一个像素宽的细线
HTML5 Canvas中实现绘制一个像素宽的细线
63 3
|
5月前
|
前端开发
Canvas绘画之多边形画板,绘制多边形,携带背景图和绘画功能,带有全部清除的功能,用这个
Canvas绘画之多边形画板,绘制多边形,携带背景图和绘画功能,带有全部清除的功能,用这个
|
6月前
|
移动开发 前端开发 JavaScript
HTML5 Canvas组件绘制太极图案
HTML5 Canvas组件绘制太极图案
28 0
|
7月前
|
前端开发
canvas详解04-绘制文字
canvas详解04-绘制文字
93 2
canvas详解04-绘制文字
|
定位技术
Echarts实战案例代码(39):地理坐标整体地图背景色渐变效果和字体随地图缩放的解决方案
Echarts实战案例代码(39):地理坐标整体地图背景色渐变效果和字体随地图缩放的解决方案
317 0
|
前端开发 JavaScript
教你如何利用canvas画布绘制哆啦A梦
订阅专栏 教你如何利用canvas画布绘制哆啦A梦 最近一直在练习使用canvas画布标签,今天教大家如何使用canvas画布绘制哆啦A梦。如图: HTML代码: <canvas id="my_canvas"></canvas> 1 CSS代码: canvas { display:block; margin:0 auto; background: pink } 1 2 3 4 5 JavaScript代码: var oCanvas = document.getEleme
教你如何利用canvas画布绘制哆啦A梦
|
前端开发 JavaScript
教你如何用Canvas绘制整身的哆啦A梦
教你如何用Canvas绘制整身的哆啦A梦 上牌你文章我们说到了如何使用canvas绘制哆啦A梦,但当时只是绘制了哆啦A梦的头部,之后有学员留言说可不可以教大家绘制整身的哆啦A梦,想了想,决定安排一下。如图: 在这里插入图片描述 HTML代码: &lt;canvas id=&quot;my_canvas&quot;&gt;&lt;/canvas&gt; &lt;canvas id=&quot;my_canvas2&quot;&gt;&lt;/canvas&gt; 1 2 CSS代码: * { margin: 0; } #my_canvas {
教你如何用Canvas绘制整身的哆啦A梦
|
JSON 前端开发 JavaScript
Threejs引入字体,实现3D文字,Canvas画布作为纹理贴图实现滚动字幕
Threejs引入字体,实现3D文字,Canvas画布作为纹理贴图实现滚动字幕
947 0
Threejs引入字体,实现3D文字,Canvas画布作为纹理贴图实现滚动字幕