canvas转图片中的文字自动换行

概述

最近项目用到了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

原文地址:https://www.cnblogs.com/yangzhou33/p/9521123.html

时间: 2024-10-11 04:09:46

canvas转图片中的文字自动换行的相关文章

canvas文字自动换行、圆角矩形画法、生成图片手机长按保存

canvas的文字自动换行函数封装 // str:要绘制的字符串 // canvas:canvas对象 // initX:绘制字符串起始x坐标 // initY:绘制字符串起始y坐标 // lineHeight:字行高,自己定义个值即可 function canvasTextAutoLine(str,canvas,initX,initY,lineHeight){ var ctx = canvas.getContext("2d"); var lineWidth = 0; var canv

如何识别图片中的文字

相信很多朋友和我一样都有这样的困扰,经常要将图片或者扫描文件中的文字提取出来,保存在我们的文档中去.但是用了很多软件,效果都不是很理想,还是需要自己人工去核对,大大影响了我们的工作效率,有没有一种简单.高效.识别率百分百的方法呢?下面我就来教大家一个方法保证简单.快速.高效! 工具/原料 WPS办公软件 AJViewer文字识别软件 准备工作 1 下载软件 ① 在“百度搜索”中输入这2款软件的软件名进行下载. ② 在“百度网盘”下载,地址是:http://pan.baidu.com/share/

Azure 认知服务 (4) 计算机视觉API - 读取图片中的文字 (OCR)

<Windows Azure Platform 系列文章目录> 微软Azure认知服务的计算机视觉API,还提供读取图片中的文字功能 在海外的Windows Azure认知服务的读取图片功能,已经集成了用户界面,可以直接读取图片功能. 具体的链接是:https://azure.microsoft.com/zh-cn/services/cognitive-services/computer-vision/ 请注意不要在生产环境中使用这个URL地址,因为服务器是在海外Azure数据中心.网络传输会

Android app开发中用户协议(使用条款)文字自动换行

用户协议(使用条款)文字自动换行处理 转载请注明出处:http://blog.csdn.net/u012301841/article/details/46648821 我们在开发app的时候,经常在关于这一模块,会涉及到用户协议或者使用条款这一类的,纯文本界面,但是需要自动换行和拖动.通常,PM会给你一大段文本,让你自己去处理.IOS可以直接复制文本进去,就会自动换行,不用处理,完全ok.为什么Android不行?我们只能一行行的去复制,去加换行符\r\n之类去处理.下面给大家介绍一种好用的方法

WPF控件TextBlock中文字自动换行

原文:WPF控件TextBlock中文字自动换行 在很多的WPF项目中,往往为了追求界面的美观,需要控制控件中文字的换行显示,现对TextBlock控件换行的实现方式进行总结,希望大家多多拍砖!!! 1.使用转义字符 在XAML文件中,实现方式如下: <TextBlock x:Name="textBlock" Text="Jack Tom" Height="150" HorizontalAlignment="Center"

如何将图片中的文字翻译成英文

有的时候,因为某种需要,会将图片中的文字翻译成英文,这时候你会在浏览器中将文字一个一个字的输进去 进行翻译吗?这种方法太麻烦了,下面就教大家一种在简单的方法. 步骤一.打开电脑,在浏览器中搜素查找迅捷办公将迅捷OCR文字识别软件下载下来,接下来会使用到,再保存一张需要将文字翻译成英文的图片. 步骤二.下载完成后将软件打开,这时候点击软件上方图片局部识别功能,这里就可以将图片中的文字翻译成英文. 步骤三.点击添加文件按钮,就可以将保存的图片添加进来了. 步骤四.图片添加进来后先不着急识别,可以在这

如何通过迅捷OCR文字识别软件精准识别图片中的文字

怎样精准的将图片中的文字识别出来呢?相信这是很多人的烦恼,因为我们经常会遇到文字识别的时候,使用到的方法也有很多,但是很多方法识别出来的效果不是很好,需要对比着原图去改正,这就很令人烦恼了.下面小编将分享一种在图片文字识别软件中精准提取文字的方法,一起来学习下. 步骤一.文字识别的话需要使用到工具,可以打开电脑浏览器通过搜索迅捷OCR文字识别软件将其下载安装到电脑中去. 步骤二.将安装好的软件打开,关闭自动弹窗接着点击软件上上图片局部识别选项. 步骤三.进入图片局部识别选项后,点击添加文件按钮将

iOS开发类似于呱呱卡效果,手指划过的区域形成画笔。适用于取出部分图片(截图),如截取出图片中带文字的区域部分。

HKBrushShots Demo下载地址: 类似于呱呱卡效果,手指划过的路线可以刮出痕迹. ??功能: 用于取出部分图片(截图),如截取出图片中带文字的区域部分. ??效果: 截取出图片中的“你就是我的全世界”文字区域的图片: 截取出图片中那只呆萌的小犀牛??: 更多截图效果: ??使用: 1 - 首先将工程中的“HKScreenShot”文件夹拷贝至项目中. 2 - 在需要使用的类中引入头文件: #import "HKCropView.h" #import "HKLine

如何简单的识别电脑图片中的文字

相信很多人都和小编一样有这样的烦恼,经常需要将电脑中的图片或者扫描件中的文字提取出来应用到别的地方,但是使用了很多种方法效果都不是很理想,这就比较令人头疼了,那如何简单的识别电脑图片中的文字呢?接下来小编就带大家来了解下具体的操作方法. 使用工具:迅捷OCR文字识别软件 操作步骤: 1:打开电脑中的迅捷OCR文字识别软件,在软件左边导航栏中选择图片局部识别板块. 2:进入图片局部识别版块后就可以将所需识别的图片添加进来了,点击添加文件按钮添加. 3:接着鼠标点击框选工具,拖动鼠标在图片将所需识别