热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

小程序用canvas绘制海报的做法

微信小程序用canvas绘制海报的做法
2020年第一篇文章,年初忙着复习刷题一直没空去写东西,书看的越多感觉越技不如人,始终徘徊在小菜鸡的行列中,最近项目里正好有一个canvas的业务,突然又燃起了我一个UI前端的火种,记下了踩坑和思考。

踩坑

问题1:为什么在canvas上画图片模糊?

在canvas上绘制图片/文字的时候,我们设定canvas:375*667的宽高,会发现绘制出来的图片很模糊,感觉像是一张分辨率很差的图片,文字看起来也会有叠影。

解决: 将canvas-width和canvas-height都放大2倍,在通过style将canvas的显示width,height缩小2 倍.

例如:

问题2:如何处理px和rpx的转换?

rpx是小程序里特有的尺寸单位,可以根据屏幕的宽度进行自适应,而在iphone6/iphonex上,1rpx等于不同的px。所以很可能会导致在不同手机下,你的canvas展示不一致。

在绘制海报的之前,我们拿到的设计稿一般都是基于iphone6的2倍图。而且从上一个问题的解决,我们知道canvas的大小也是2倍的,所以我们可以直接量取2倍图的设计稿直接绘制canvas,而尺寸需要注意一下rpxtoPx.

/**
   * 
   * @param {*} rpx 
   * @param {*} int  //是否变成整数
   factor => 0.5 //iphone6
   pixelRatio => 2 像素比
   */
toPx(rpx, int) {
    if (int) {
      return parseInt(rpx * this.factor * this.pixelRatio)
    }
    return rpx * this.factor * this.pixelRatio
  }

问题3:关于canvasContext.measureText计算纯数字的时候手机上为0

在小程序中提供this.ctx.measureText(text).width去计算文本的长度,但是如果你全数字 的话,你会发现该API永远都计算成0.所以,最后采用模拟measureText方法去计算文本长度。

measureText(text, fOntSize= 10) {
    text = String(text)
    text = text.split('')
    let width = 0
    text.forEach(function(item) {
      if (/[a-zA-Z]/.test(item)) {
        width += 7
      } else if (/[0-9]/.test(item)) {
        width += 5.5
      } else if (/\./.test(item)) {
        width += 2.7
      } else if (/-/.test(item)) {
        width += 3.25
      } else if (/[\u4e00-\u9fa5]/.test(item)) { // 中文匹配
        width += 10
      } else if (/\(|\)/.test(item)) {
        width += 3.73
      } else if (/\s/.test(item)) {
        width += 2.5
      } else if (/%/.test(item)) {
        width += 8
      } else {
        width += 10
      }
    })
    return width * fontSize / 10
  }

问题4:如何保证一行字体的居中展示?多行呢?

字体的如果过长,会超出canvas画布,造成绘制难看,这个时候我们就应该让超出的部分变成...你可以设置一个width并且循环计算计算出文本的宽度,如果超出则利用substring截取后补充...即可。

let fillText=''
let width = 350
for (let i = 0; i <= text.length - 1; i++) { // 将文字转为数组,一行文字一个元素
        fillText = fillText + text[i]
        // 判断截断的位置
        if (this.measureText(fillText, this.toPx(fontSize, true)) >= width) {
          if (line === lineNum) {
            if (i !== text.length - 1) {
              fillText = fillText.substring(0, fillText.length - 1) + &#39;...&#39;
            }
          }
          if (line <= lineNum) {
            textArr.push(fillText)
          }
          fillText = &#39;&#39;
          line++
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText)
            }
          }
        }
      }

文字剧中展示计算公式:

居中在canvas中可以用(canvas的宽度-文字宽度)/2 + x (x为字体的x轴的推移)

let w = this.measureText(text, this.toPx(fontSize, true))
this.ctx.fillText(text, this.toPx((this.canvas.width - w) / 2 + x), this.toPx(y + (lineHeight || fontSize) * index))

问题5:在小程序中如何处理网络图?

关于在小程序里使用网络图片,比如cdn上的图片,是需要down到微信本地进行 LRU 管理,让后续绘制同样图片时,节省下载时间。所以首先需要你在微信小程序的后台配置downloadFile合法域名,其次你可以在canvas绘制之前,最好提前去down图片,等待图片下载好了,再开始绘制,以避免一些绘制失败的问题。

问题6:在 IDE 中可设置 base64 的图片数据进行绘制,但真机上无用?

先把 base64 转成 Uint8ClampedArray 格式。然后再通过 wx.canvasPutImageData(OBJECT, this) 绘制到画布上,然后把画布导出为图片。

问题6:如何画一个圆角图片?

问题7:关于wx.canvasToTempFilePath

使用 Canvas 绘图成功后,直接调用该方法生成图片,在IDE上没有问题,但在真机上会出现生成的图片不完整的情况,可以使用一个setTimeout来解决这个问题。

this.ctx.draw(false, () => {
        setTimeout(() => {
            Taro.canvasToTempFilePath({
              canvasId: &#39;canvasid&#39;,
              success: async(res) => {
                this.props.onSavePoster(res.tempFilePath)//回调事件
                // 清空画布
                this.ctx.clearRect(0, 0, canvas_width, canvas_height)
              },
              fail: (err) => {
                console.log(err)
              }
            }, this.$scope)
          }, time)
    })

问题8:关于canvasContext.font

fontsize 不能使用小数 如果设置 font 中字体大小部分包含小数,则会导致整个 font 设置无效。

问题9:安卓下字体渲染错位?

利用canvas绘制一个简单的折线图,只需要利用lineTomoveTo俩个API将点连接即可。利用createLinearGradient绘制阴影。

思考

思考1:用json配置表生成海报的局限

现在的海报生成只需要按照设计稿去量取尺寸就可以,但是量取的过程还是很繁琐的,在设计稿量不到的地方还需要手动微调一下。 后续还可以做一个web端使用拖拽的方式去完成设计稿的事情,自动生成json应用到小程序的海报上。

思考2:后端生成海报的局限

海报一开始是后端同学生成的,优点是不需要前端绘制时间,也不需要去踩微信API的坑,接口返回拿到url即可展示,但是在后端生成出来的效果不佳,毕竟这种工作更加前端一些。

思考3:前端生成海报的局限

前端生成海报的时候我发现耗时更长,包括图片的下载本地而且还需要给安卓一个特意写一个setTimeout去确保绘制正常。各种兼容性问题、手机的dpr、安卓和ios等不间断彩蛋踩到你头秃~ 哈哈哈哈~

彩蛋

采用了最新的canvas-2d背景图确无法绘制全部?

在canvas开发的过程中,小程序里一直有一束微光提醒我。

推荐教程:《JS教程》

以上就是小程序用canvas绘制海报的做法的详细内容,更多请关注其它相关文章!


推荐阅读
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 今天周六,原则上要休息,但想到下周还有一堆任务,还是先做一部分工作吧,就把之前做的票面设计器改了改,增加了上传图片和更换背景底图的功能。现在打算整理下这个设计器,也算对齐一个总结。不过这属于我们部门的 ... [详细]
  • python实现内容写在图片上的方法
    这篇文章主要介绍python实现内容写在图片上的方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体代码内容如下:#-*-co ... [详细]
  • 从C#Byte数组加载图像,并使用AngularJS将图像放在html标记中我正在使用ByteArrayforms的Image,因为我正在使用以下C#方法转换字节数组publicH ... [详细]
author-avatar
忆--______100
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有