小程序分享海报的实现

时间: 2018-08-24阅读: 2151标签: 小程序

需求

小程序分享到朋友圈只能使用小程序码海报来实现,生成小程序码的方式有两种,一种是使用后端方式,一种是使用小程序自带的canvas生成;后端的方式开发难度大,由于生成图片耗用内存比较大对服务端也是不小的压力;所以使用小程序的canvas是一个不错的选择,但由于canvas水比较深,坑比较多,还有不同海报需要重现写渲染流程,导致代码冗余难以维护,加上不同设备版本的情况不一样,因此小程序海报生成组件的需求十分迫切。

在实际开发中,我发现海报中的元素无非一下几种,只要实现这几种,就可以通过一份配置文件生成各种各样的海报了。


海报中的元素分类


要解决的问题

  • 单位问题
  • canvas隐藏问题
  • 圆角矩形、圆角图片
  • 多段文字
  • 超长文字和多行文字缩略问题
  • 矩形包含文字
  • 多个元素间的层级问题
  • 图片尺寸和渲染尺寸不一致问题
  • canvas转图片
  • IOS 6.6.7 clip问题
  • 关于获取canvas实例


单位问题

canvas绘制使用的是px单位,但不同设备的px是需要换算的,所以在组件中统一使用rpx单位,这里就涉及到单位怎么换算问题。

通过wx.getSystemInfoSync获取设备屏幕尺寸,从而得到比例,进而做转换,代码如下:

const sysInfo = wx.getSystemInfoSync();
const screenWidth = sysInfo.screenWidth;
this.factor = screenWidth / 750;    // 获取比例
function toPx(rpx) {    // rpx转px
    return rpx * this.factor;
}
function toRpx(px) {    // px转rpx
    return px / this.factor;
},


canvas隐藏问题

在绘制海报过程时,我们不想让用户看到canvas,所以我们必须把canvas隐藏起来,一开始想到的是使用display:none; 但这样在转化成图片时会空白,所以这个是行不通的,所以只能控制canvas的绝对定位,将其移出可视界面,代码如下:

.canvas.pro {
    position: absolute;
    bottom: 0;
    left: -9999rpx;
}


圆角矩形、圆角图片

由于canvas没有提供现成的圆角api,所以我们只能手工画啦,实际上圆角矩形就是由4条线(黄色)和4个圆弧(红色)组成的,如下:


圆弧可以使用canvasContext.arcTo这个api实现,这个api的入参由两个控制点一个半径组成,对应上图的示例

canvasContext.arcTo(x1, y1, x2, y2, r)

接下来我们就可以非常轻松的写出生成圆角矩形的函数

/**
 * 画圆角矩形
 */
_drawRadiusRect(x, y, w, h, r) {
    const br = r / 2;
    this.ctx.beginPath();
    this.ctx.moveTo(this.toPx(x + br), this.toPx(y));            // 移动到左上角的点
    this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y));        // 画上边的线
    this.ctx.arcTo(this.toPx(x + w), this.toPx(y), this.toPx(x + w), this.toPx(y + br), this.toPx(br));                                                    // 画右上角的弧        
    this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br));    // 画右边的线
    this.ctx.arcTo(this.toPx(x + w), this.toPx(y + h), this.toPx(x + w - br), this.toPx(y + h), this.toPx(br));                                              // 画右下角的弧
    this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h));        // 画下边的线
    this.ctx.arcTo(this.toPx(x), this.toPx(y + h), this.toPx(x), this.toPx(y + h - br), this.toPx(br));                                                    // 画左下角的弧
    this.ctx.lineTo(this.toPx(x), this.toPx(y + br));            // 画左边的线
    this.ctx.arcTo(this.toPx(x), this.toPx(y), this.toPx(x + br), this.toPx(y), this.toPx(br));                                                    // 画左上角的弧
}

如果是画线框就使用this.ctx.stroke();

如果是画色块就使用this.ctx.fill();

如果是圆角图片就使用

this.ctx.clip();
this.ctx.drawImage(***);
clip() 方法从原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)。


多段文字

如果是连续多段不同格式的文字,如果让用户每段文字都指定坐标是不现实的,因为上一段文字的长度是不固定的,这里的解决方案是使用ctx.measureText (基础库 1.9.90 开始支持)Api来计算一段文字的宽度,记住这里返回宽度的单位是px(),从而知道下一段文字的坐标。


超长文字和多行文字缩略问题

设置文字的宽度,通过ctx.measureText知道文字的宽度,如果超出设定的宽度,超出部分使用“...”代替;对于多行文字,经测试发现字体的高度大约等于字体大小,并提供lineHeight参数让用户可以自定义行高,这样我们就可以知道下一行的y轴坐标了。


矩形包含文字

这个同样使用ctx.measureText接口,从而控制矩形的宽度,当然这里用户还可以设置paddingLeft和paddingRight字段;

文字的垂直居中问题可以设置文字的基线对齐方式为middle(this.ctx.setTextBaseline('middle');),设置文字的坐标为矩形的中线就可以了;水平居中this.ctx.setTextAlign('center');;



多个元素间的层级问题

由于canvas没有Api可以设置绘制元素的层级,只能是根据后绘制层级高于前面绘制的方式,所以需要用户传入zIndex字段,利用数组排序(Array.prototype.sort)后再根据顺序绘制。


图片尺寸和渲染尺寸不一致问题

绘制图片我们使用ctx.drawImage()API;

如果使用drawImage(dx, dy, dWidth, dHeight),图片会压缩尺寸以适应绘制的尺寸,图片会变形,如下图:

在基础库1.9.0起支持drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) ,sx和sy是源图像的矩形选择框左上角的坐标,sWidth和sHeight是源图像的矩形选择框的宽度和高度,如下图:


如果绘制尺寸比源图尺寸宽,那么绘制尺寸的宽度就等于源图宽度;反之,绘制尺寸比源图尺寸高,那么绘制尺寸的高度等于源图高度;

我们可以通过wx.getImageInfoApi获取源图的尺寸;


canvas转图片

在canvas绘制完成后调用wx.canvasToTempFilePathApi将canvas转为图片输出,这样需要注意,wx.canvasToTempFilePath需要写在this.ctx.draw的回调中,并且在组件中使用这个接口需要在第二个入参传入this(),如下

this.ctx.draw(false, () => {
    wx.canvasToTempFilePath({
        canvasId: 'canvasid',
        success: (res) => {
            wx.hideLoading();
            this.triggerEvent('success', res.tempFilePath);
        },
        fail: (err) => {
            wx.hideLoading();
            this.triggerEvent('fail', err);
        }
    }, this);
});


IOS 6.6.7 clip问题

在IOS 6.6.7版本中clip方法连续裁剪图片时,只有第一张有效,这是微信的bug,官方也证实了(https://developers.weixin.qq....


关于获取canvas实例

我们可以使用wx.createCanvasContext获取小程序实例,但在组件中使用切记第二个参数需要带上this,如下

this.ctx = wx.createCanvasContext('canvasid', this);


如何使用组件

https://github.com/jasondu/wx...

来源:https://segmentfault.com/a/1190000016121303

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/1031

关闭

小程序保存图片到相册功能实现

先检查用户请求过的权限中是否允许保存到相册权限,如果没有请求过这个权限,应该向用户发起授权请求(弹窗授权),如果请求过这个权限,并且授权了,那就保存图片,显示保存成功;如果请求过,但是是拒绝的,就跳到设置页,重新授权。

小程序开发实践总结

从微信发布小程序以来,各大公司纷纷跟进都想从微信这个流量池里捞一杯羹。前前后后也开发了四五个小程序了。总觉得要留下点什么,既是记录那些年我们踩过的坑,也是希望大家别再掉坑。

微信小程序推广方式_最有效的小程序推广模式

当小程序开发完成后,就需要进行推广操作。当然推广的前提是核心功能是否能够满足用户需求,下面总结一些具体的运作方式。和大多数APP的搜索个性一样,用户搜索小程序名称就能进入小程序界面。我们需要做好关键词优化,通过搜索-微信指数

微信小程序与h5的区别

小程序面世以来,尽管微信团队做了很多关于小程序的普及功课,但是还是有很多人不太理解,最多的误解就是把它等同于H5。小程序由于刚推出来时开放的能力十分有限,所以在功能展示上会让普通用户感觉和H5一样,并没有什么特别之处

腾讯出品的微信小程序有哪些?

腾讯wifi一键连;识花君;企鹅医典;vgo微海报;腾讯AI体验中心;食物健康测评;腾讯地图+;微信辟谣助手;腾讯文档;多媒体AI平台;微云;微信发票助手

小程序组件开发_小程序实现自定义组件的多种方式

在小程序中,目前也支持简单的组件化编程,可以把页面通用功能模块抽象成自定义组件,以以便在不同的页面中复用,提供代码可读性,降低维护成本,这篇文章主要讲解小程序实现组件开发的多种方式

小程序多余文本省略号显示

如何在 wxml 页面中截取数据?取数据想必大家都会,不就是 substring 吗?但是这种方法在 wxml 页面中是无效的。那还有 css 啊,不一样可以做到吗?但是个人觉得 css 复用性太差,暂不考虑。

小程序websocket心跳库——websocket-heartbeat-miniprogram

在16年的时候因为项目接触到websocket,而后对心跳重连做了一次总结,写了篇博客,而后18年对之前github上的demo代码进行了再次开发和开源,最终封装成库。如下:在2020年也就是今年初,同事建议说可以考虑兼容一下小程序,心想也挺好的。

微信小程序商城如何提高成交率

小程序商城早已经是每位商户和消费者广为人知的一类在线网上商城,和别的购物商城相比较,它的操作步骤更为便捷,同时带有好多的数据流量基础,商户还可以省掉引流过来的环节,只需把自已的营销推广业务加强就可以

微信小程序框架推荐_分享好用的小程序前端开发框架

选择优秀的框架,能帮助我们节省开发时间,提高代码重用性,让开发变得更简单。下面就整理关于微信小程序的前端框架,推荐给大家。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!