canvas使用ttf字体的正确方法

一、问题描述

最近在写前端项目,有一个页面是背景图+文字格式的,其中,背景图是用canvas里的ctx.drawImage实现的,大概如下:

//这个找的是当前vue页面同级的img文件夹里的png图片
import Ver1 from './img/certificate1@1.5x.png'

const img = new Image()
img.src = Ver1

……
//其它省略,总之是先用这个方法画了背景图
ctx.drawImage(img, 0, 0, 1125, 1530)

然后,图片上层的文字,也是用canvas画上去的,大概如下:

//获得canvas对象
const cvs = document.querySelector('canvas')
const ctx = cvs.getContext('2d')

//设置字体
ctx.font = 'bold 50px 楷体'
//设置文字居中
ctx.textAlign = 'center'
//把文字画上去,这个是文字坐标
ctx.fillText('小明', 300, 600)

这种方法可以实现动态设置背景图以及背景图上面的文字。

其中,遇到了几个问题:

1.canvas里设置了字体是bold 50px 楷体,这个设置在pc端用chrome自测时,是没有问题的;但是在app上访问这个页面,发现楷体设置没有生效,默认显示为了黑体

2.应该是app上没有这个字体库,于是,准备使用ttf字体文件;但是百度发现,大部分教程都是css中使用ttf字体,没有canvas使用ttf字体的方法。

3.找了半天,终于找到了canvas中使用ttf的方法,在此总结下。

二、canvas使用ttf字体的方法

1.先下载一个ttf字体,例如楷体_GB2312.ttf
2.写一个css文件,例如font.css

@font-face{
    font-family:"楷体_GB2312";
    src: url("./楷体_GB2312.ttf");
}

3.把这2个文件放到某个位置,例如:

项目名\src\components\certificate\font\font.css
项目名\src\components\certificate\font\楷体_GB2312.ttf

4.准备修改使用canvas的vue文件certificate.vue,本人的vue文件位置为:

项目名\src\components\certificate\certificate.vue

其中,使用canvas的代码可以这样写:

            //创建一个FontFace对象,参数是字体名称和字体位置
            const myFont = new FontFace('myFont', 'url(./static/fonts/楷体_GB2312.8a1e9fe.ttf)')
            myFont.load().then(font => {
               document.fonts.add(font) 
            }).then(() => {
                //获得canvas对象
                const cvs = document.querySelector('canvas')
                const ctx = cvs.getContext('2d')

                //设置字体,这个就是FontFace方法中写的名字
                ctx.font = 'bold 50px myFont'
                //设置文字居中
                ctx.textAlign = 'center'
                //把文字画上去,这个是文字坐标
                ctx.fillText('小明', 300, 600)
            })

5.还需要在vue的style里加一个:(这样打包才会打进去这个字体文件)

<style lang="stylus" scoped>
@import url('./font/font.css');
</style>

6.这样,canvas就可以使用ttf文件给文字设置字体了。

7.需要注意, new FontFace('myFont', 'url(./static/fonts/楷体_GB2312.8a1e9fe.ttf)')这个方法中,如果写成new FontFace('myFont', 'url(./font/楷体_GB2312.ttf)')是不可以的、会报错404(不知道为什么相对路径不能用);

因此,本人是先把前端项目打包,然后发现楷体_GB2312.ttf文件的真实路径是项目名/dist/static/fonts/楷体_GB2312.8a1e9fe.ttf于是用new FontFace('myFont', 'url(./static/fonts/楷体_GB2312.8a1e9fe.ttf)'),才可以正常使用的。

三、备注

1.canvas中的new FontFace()方法的url参数,这个还不知道怎么写相对路径,目前是通过打包得到ttf文件的真实路径才写出来的。

1.5也许可以用这个方法实现使用相对路径:

import myfont from './font/楷体_GB2312.ttf'

new FontFace('myFont', 'url('+myfont+')')

【已测试,这个方法可以用,其实用这个方法合理些,是相对路径。】

2.css中使用ttf字体的方法简要总结:
(1)下载一个ttf字体,放到项目中
(2)创建一个font.css文件,放到项目中,例如与ttf字体同一个路径:

@font-face {
  /* 重命名字体名 */
  font-family: 'myfont';
  /* 引入字体,因为是同级,可以这样写 */
  src: url('./苹方字体.ttf');
  font-weight: normal;
  font-style: normal;
}

(3)页面中引入css文件(这个页面的位置/font/font.css,就可以引入这个css):

<style lang="stylus" scoped>
 @import url('./font/font.css');
 
.myfont
    font-family myfont
 </style>

(4)页面中就可以使用这个字体了,例如:

<div :class="myfont">abc</div>
当你使用 `html2canvas` 时,可能会遇到跨域字体问题。这是因为当网页从其他域名加载字体(例如通过 @font-face 加载的自定义字体)时,默认情况下这些字体不会被渲染到 canvas 上,除非明确设置了正确的 CORS 策略。 以下是几种解决方案: --- ### **1. 设置服务器端允许跨域访问** 如果你有权管理提供字体文件的服务器,可以在服务器配置中启用 Cross-Origin Resource Sharing (CORS),即设置响应头字段 `Access-Control-Allow-Origin` 来指定哪些源可以访问字体资源。 对于 Apache 服务器,可以在 `.htaccess` 文件里加入类似以下内容: ```apache <FilesMatch "\.(ttf|otf|eot|woff|woff2)$"> Header set Access-Control-Allow-Origin "*" </FilesMatch> ``` 这将允许可接受来自任意来源对上述字体类型的请求。(注意生产环境建议替换 `"*"` 指定具体 URL) 而对于 Nginx,则需要修改 nginx.conf 配置如下: ```nginx location ~ \.(ttf|otf|eot|woff|woff2)$ { add_header Access-Control-Allow-Origin *; } ``` --- ### **2. 将字体嵌入 Base64 编码** 另一种方法是直接将字体转为 base64 字符串内联在 CSS 文件中,这种方式避免了传统外链字体所带来的跨域难题。 示例代码片段: ```css @font-face { font-family: 'MyCustomFont'; src: url(data:application/font-woff;charset=utf-8;base64,d09GRk...) format('woff'); /* 替换 ... 为你真实的base64编码字符串 */ } ``` 这种方法虽然解决了跨域问题,但也存在缺点——增大了前端体积并且可能降低页面性能。 --- ### **3. 使用 html2canvas 的 options 参数忽略字体错误** 如果某些字体确实无法解决跨域限制,你可以考虑让 `html2canvas` 忽略那些未成功加载的字体。通过调整它的选项参数如 `ignoreErrors` 和 `useCORS`, 能够减少此类警告带来的干扰效果。 例如下面的例子展示了如何设置这两个重要属性值: ```javascript html2canvas(document.querySelector("#capture"), { useCORS : true, ignoreErrors: true // 这样即使有错误也不会中断程序运行 }).then((canvas) => { document.body.appendChild(canvas); }); ``` 尽管如此,这样做仅适用于非关键性场合下丢失字体的影响较小的情况下采用。 --- 以上就是三种常见的针对 "Html2Canvas" 技术所引发的跨域字体加载失败情况下的应对办法啦!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追逐梦想永不停

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值