canvas转图片中的文字自动换行(代码片段)

yangzhou33 yangzhou33     2022-12-24     485

关键词:

概述

最近项目用到了canvas转图片,但是由于canvas对文字排版的支持非常弱,一般我们在canvas上画不同排版的文字(比如竖排文字)都是利用js计算横纵坐标,然后一个字一个字地画出来,今天无意中看到一个使用svg的方法,记录下来,供以后开发时参考,相信对其他人也有用。

参考资料:

SVG 简介与截图等应用

svg和canvas介绍

svg和canvas都支持图形渲染,它们各有侧重:

  • svg:更适用于高保真文档,静态图像,可交互图表图形,2D游戏等。
  • canvas:更适用于屏幕截图,视频操作,很多对象的复杂场景,web广告等。

foreignObject元素

foreignObject元素是个非常强大的元素,它可以在其中使用具有其它XML命名空间的XML元素,简单来说,就是我们可以利用foreignObject元素把html“画在”svg里面!

示例如下。其中xmlns表示XML命名空间,标记它是一个svg或者一个xhtml。注意:svg和xhtml都属于XML。

<svg xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="120" height="50">
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>文字。</p>
      </body>
    </foreignObject>
</svg>

另外,所有的svg都必须加上这个svg的命名空间标识,否则它就会以XML文档树的形式渲染。示例如下:

//渲染出来的是数字
<svg width="12" height="12" viewBox="0 0 12 12"><path d="M10.263 10.874L6 6.61l-4.264 4.264a.431.431 0 0 1-.61-.61L5.39 6.001 1.128 1.736a.431.431 0 0 1 .61-.61L6 5.391l4.264-4.263a.431.431 0 0 1 .61.61L6.61 6l4.262 4.264a.43.43 0 1 1-.61.609z" stroke="#979797" fill="#999"/></svg>

//渲染出来的是图形
<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="M10.263 10.874L6 6.61l-4.264 4.264a.431.431 0 0 1-.61-.61L5.39 6.001 1.128 1.736a.431.431 0 0 1 .61-.61L6 5.391l4.264-4.263a.431.431 0 0 1 .61.61L6.61 6l4.262 4.264a.43.43 0 1 1-.61.609z" stroke="#979797" fill="#999"/></svg>

canvas中文本换行

由于我们可以利用foreignObject把html转化为SVG,然后我们可以把svg画在canvas里面,最后用canvas把它转化为图形

示例如下:

//首先初始化canvas
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');

//获取文字的长度
context.font = "20px 微软雅黑";
var textLength = context.measureText(text).width;

//画一个svg图片
var img = new Image();

//对文字长度做判断,一行的文字字要大些,二行的文字字要小些
if(textLength <= 135) 
    img.src = 'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><foreignObject width="270" height="45"><body xmlns="http://www.w3.org/1999/xhtml" style="margin:0;color:#e7793f;text-align:center;font-size:40px;line-height:45px;font:微软雅黑;">'+ text +'</body></foreignObject></svg>';
 else 
    img.src = 'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg"><foreignObject width="270" height="60"><body xmlns="http://www.w3.org/1999/xhtml" style="margin:0;color:#e7793f;text-align:left;font-size:25px;line-height:30px;font:微软雅黑;overflow: hidden;display: -webkit-box;text-overflow: ellipsis;--webkit-box-orient: vertical;--webkit-line-clamp: 2;word-break: break-all;">'+ text +'</body></foreignObject></svg>';


//把图片绘制上去,并利用canvas生成图片
img.onload = function() 
    context.drawImage(img, 72, 1080);
    document.querySelector('#ticket').src = canvas.toDataURL('image/png');

canvas文字竖排

理论上有三种方法来解决:
1.利用js逐个字符逐行绘制,但是这样对英文要做特殊处理,不能单个字符绘制,而应该旋转90度。相关参考代码如下:

fillTextVertical: function(context, text, x, y) 
  var canvas = context.canvas;

  var arrText = text.split('');
  var arrWidth = arrText.map(function (letter) 
    return context.measureText(letter).width;
  );

  var align = context.textAlign;
  var baseline = context.textBaseline;

  //emoji的位置
  var emoji_arr = fn.findEmoji(text);

  //emoji第一位的缓存
  var emoji_first = '';

  if (align == 'left') 
    x = x + Math.max.apply(null, arrWidth) / 2;
   else if (align == 'right') 
    x = x - Math.max.apply(null, arrWidth) / 2;
  
  if (baseline == 'bottom' || baseline == 'alphabetic' || baseline == 'ideographic') 
    y = y - arrWidth[0] / 2;
   else if (baseline == 'top' || baseline == 'hanging') 
    y = y + arrWidth[0] / 2;
  

  context.textAlign = 'center';
  context.textBaseline = 'middle';

  // 开始逐字绘制
  arrText.forEach(function (letter, index) 
    // 确定下一个字符的纵坐标位置
    var letterWidth = arrWidth[index];
    // 是否需要旋转判断
    var code = letter.charCodeAt(0);

    //是否是emoji的第二位
    if(emoji_arr.indexOf(index) != -1) 
      emoji_first = letter;
      return;
    
    //是否是emoji
    if(emoji_arr.indexOf(index - 1) != -1) 
      letter = emoji_first + letter;
      emoji_first = '';
     else 
      if (code <= 256) 
          context.translate(x, y);
          // 英文字符,旋转90°
          context.rotate(90 * Math.PI / 180);
          context.translate(-x, -y);
       else if (index > 0 && text.charCodeAt(index - 1) < 256) 
          // y修正
          y = y + arrWidth[index - 1] / 2;
      
    

    context.fillText(letter, x, y);
    // 旋转坐标系还原成初始态
    context.setTransform(1, 0, 0, 1, 0, 0);
    // 确定下一个字符的纵坐标位置
    var letterWidth = arrWidth[index];
    y = y + letterWidth;
  );
  // 水平垂直对齐方式还原
  context.textAlign = align;
  context.textBaseline = baseline;
,

上面方法的缺点是,对emoji符号使用正则匹配的,但仍然会有部分emoji符号匹配不到导致乱码。

2.使用foreignObject绘制。但是有一些bug,就是在安卓机上emoji表情会错位,而且在ios上会被莫名截断。

3.使用html2canvas库。还是有一个bug,就是对英文的竖排支持不是很理想,英文会横排显示。

总之上面的方法各有各的优缺点,完美的竖排兼容emoji的实现是不可能的,这辈子都不可能的!0.0

canvas文字换行(代码片段)

引子近期的工作中,遇到的功能需求,需要控制文字显示行数,超过就省略号显示。OriginMyGitHub文字换行一般文字行数控制用css就可以实现,但在canvas中不行。在网站查询资料,就可以发现需要程序控制文字换行,主要使用到的... 查看详情

python实现文字转图片(代码片段)

文章目录一、需求二、实现文字转单个图片代码三、实现文字转配对图片代码一、需求目前想要将输入的文字,转为指定风格的图片,比如宋体、草体二、实现文字转单个图片代码importosimportpdbimportPILimportnumpyasnpfromPILimpor... 查看详情

excel中如何让文字自动换行?

...操作。比如,下图中的表格,不能自动换行。请点击输入图片描述请点击输入图片描述2先选中表格;这个时候,文档上方的菜单栏中显出了“布局”选项卡;请点击输入图片描述请点击输入图片描述3在“对齐方式”组这里,我... 查看详情

[canvas,js,fileapi]图片转文字

语言:javascriptAPI及元素:canvas,fileAPI读取图片像素值,变化为灰度,根据画面设定,替换为文字显示---效果图【福字】:猜猜下面是什么:【金鸡】原图:继续猜猜:源码非常简单:1<html>2<head>3<title>pic2Str</title>4... 查看详情

python实现文字转图片(代码片段)

文章目录一、需求二、实现文字转单个图片代码三、实现文字转配对图片代码一、需求目前想要将输入的文字,转为指定风格的图片,比如宋体、草体二、实现文字转单个图片代码importosimportpdbimportPILimportnumpyasnpfromPILimpor... 查看详情

vue+canvas图片加水印(代码片段)

思路:将两张图片绘制为一张目标:输入的文字,绘制到图片上,简单实现图片水印效果:输入的文字1:‘你猜猜’+图片2=图片3(不要看清除水印的按钮,本人垃圾没实现)   选择图片html  <inputtype="file"id="... 查看详情

html文本自动换行(代码片段)

...进来了哈哈(啊别打我)1.今天拿到老师出的题,素材里有个图片是饱经沧桑の牛皮纸,上面有画好的几条线我要做的就是允许用户往横线上写入文字.其实前一天半夜就开始想,感觉弄个文本框就行了所 查看详情

canvas将图片转成base64格式以及验证图片是否透明(代码片段)

...mg=newImage();img.src=e.target.result;self.isAlphaBackground=false;//缩放图片需要的canvasvarcanvas=document.createElement(‘canvas‘);varcontext=canvas.getContext(‘2d‘);//base64地址图片加载完毕后img.onload=function()//图片原始尺寸varoriginWidth=this.width;varoriginHeight=... 查看详情

canvas文本自动换行

在用canvas中写刮奖结果的时候发现canvas中的文本不会自动折行,要进行截断另起一行来写。在此参考文章html5-canvas的绘制文本自动换行来做改写。根据canvas宽度来做折行在此根据项目的情况让文本占canvas的八分之五,具体可以根... 查看详情

文字换行(代码片段)

...宽为行内元素设置width是无效的,但块级元素可以,所以文字不会超出span(即便出现横向滚动条),但会超出div让div内的文字自动换行的三条CSS代码white-space:normal;word-break:break-all;word-space:normal; 查看详情

解决用h5canvas绘制的图片或文字在高清屏下模糊的问题(代码片段)

...点都有不同的指标数值,而且很多点根据分类还用不同的图片作为背景。因此考虑用H5Canvas加载图标png并把数值画上去,然后把canvas导出图片url并应用到点标记上。1、常规绘制:代码:varimage=newImage();image.src=‘../../assets/img/polluti... 查看详情

uniapp弹出窗显示协议内容-解决文字自动换行的问题-view标签忽略等换行符(代码片段)

效果图实现方法uniapp项目中,在多行文字外面套一个<text></text>标签即可,自动换行<!--弹出框--><view> <uni-popupref="agreementBox"@change="change"> <viewclass&# 查看详情

使用echart的雷达图的时候,如果文字越界的解决办法记录,标签文字自动换行(代码片段)

使用echart的雷达图的时候,如果文字越界的解决办法记录,标签文字自动换行前几天项目中有一个图表的是用echart生成的,遇到一个问题,就是在手机端显示的售时候,如果文字太长就会超出div,之前的效果如图所示:后来查资料,发现这... 查看详情

java根据文字旋转图片方法

1、java本身肯定有这样的api来实现基本的文字转图片功能,果不其然,经过一番简单搜索,发现java.awt.Graphics类有一个方法,如下2、经过简单测试,发现上述方法果然只能实现基本的文字转图片功能,无法换行,然后搜到一篇博... 查看详情

canvas踩坑记录(代码片段)

一、绘制一个带有多张图片和文字的canvas。要求将一张矩形的图片,放置进去显示为圆角矩形的图片  解决方案,先把图片处理成圆角矩形的样子,再放进去就可以了  绘制圆角矩形图片的解决方案<imgsrc="http://pics.sc.chinaz... 查看详情

怎样让excel表格中的文字自动换行

参考技术A材料/工具:Excel20101、打开自己电脑上的excel2010软件。2、右击一个你想设置自动换行的单元格。3、然后选择“设置单元格格式”选项。4、接着点击弹出窗口上方的“对齐”选项卡。5、然后勾选“文本控制”下的“自... 查看详情

textview设置文字包含中英文时自动换行问题的终极解决方案(代码片段)

情景,正常TextView中设置文本内容中包含中英文时会造成自动换行的问题,影响界面显示效果,如图:网上很多解决途径,甚至有多三方框架处理,但是效果并不能达到,最终是要如下代码完美解决,效果图如下:具体实现过程... 查看详情

canvas合并两张图片(代码片段)

...原理是一样的  画多张图需要一张一张画  也就是等图片onload成功后处理  这里代码写的比较随意  实际用的时候可以小粉转一下也非常简单。我懒~~  么么、、        newImage(text)//生成图片varimageBox=document.... 查看详情