当前位置: 代码网 > it编程>编程语言>Javascript > 微信小程序海报绘制示例讲解

微信小程序海报绘制示例讲解

2024年05月26日 Javascript 我要评论
前言海报分享功能在许多应用中应该是很常见的,因为它作为一种常用的应用推广和拉新的方式。接下来看个实际的案例,如下:把任务拆解下:如何绘制海报如何把绘制后的海报保存到相册绘制海报用 canvas 来绘制

前言

海报分享功能在许多应用中应该是很常见的,因为它作为一种常用的应用推广和拉新的方式。

接下来看个实际的案例,如下:

把任务拆解下:

  • 如何绘制海报
  • 如何把绘制后的海报保存到相册

绘制海报

canvas 来绘制海报。 这里需要了解基本的 canvas api,不熟悉可以先去了解下相关 canvas api

定义 canvas 元素

<template>
  <view class="poster-container">
    <canvas class="poster" canvas-id="posterid"></canvas>
    <button class="btn" @click="onsave">保存至相册</button>
  </view>
</template>

获取 canvas 上下文对象

const context = uni.createcanvascontext('posterid');

绘制背景图片

图片支持远程图片和本地图片,网络图片要通过 getimageinfo / downloadfile 先下载。

context.drawimage('/static/poster.png', 0, 0, 320, 410); // 绘制背景图片

绘制头像和昵称

const avatarleft = 185;
const avatartop = 18;
const avatarwidth = 16;
const avatarheight = 16;
context.drawimage(
  '/static/avatar.png',
  avatarleft,
  avatartop,
  avatarwidth,
  avatarheight
);

从设计上来看头像和昵称是对齐的。

直接按照设计稿距离来设定看看效果

const nickname = '墙头草中的顶尖的';
const nameleft = avatarleft + avatarwidth + 7;
context.setfillstyle('#ffffff');
context.setfontsize(12);
context.filltext(nickname, nameleft, 21, 96);

实际效果如下:

发现与预期效果对应不上,思考下这是为什么? 文字设置距离偏移的参考基线不是文字的顶部。

怎么验证我的说法呢?可以 x 值设置为 0

const nickname = '墙头草中的顶尖的';
const nameleft = avatarleft + avatarwidth + 7;
context.setfillstyle('#ffffff');
context.setfontsize(12);
context.filltext(nickname, nameleft, 0, 96); // 修改为 0

再看看效果:

发现参考点几乎是文字的底部,这就验证了上面的结论。

怎么解决这个问题呢?

  • 获取文本行的高度
  • 更改偏移的参考点

通常知道文本行实际占用的高度,需要知道其 line-height,上面并不知道其 line-height 值。canvas 本身并不直接支持line-height属性,显然没办法获得相对准确的行高。

只能采用第二种方式,从 canvas 提供 api 来看,可以更改文本相行对齐的点。

const nickname = '墙头草中的顶尖的';
const nameleft = avatarleft + avatarwidth + 7;
context.setfillstyle('#ffffff');
context.setfontsize(12);
context.settextbaseline('top'); // 更改基线对齐点
context.filltext(nickname, nameleft, 21, 96);

再来看看效果如下:

接下来实现二维码区域,主要白色背景 + 二维码 + 文案

白色背景区域

const rectwidth = 300;
const rectheight = 89;
const rectleft = 10;
const recttop = 311;
context.setfillstyle('#ffffff');
context.fillrect(rectleft, recttop, rectwidth, rectheight);

效果如下:

绘制二维码

const qrcodeleft = 20;
const qrcodetop = recttop + 10;
const qrcodewidth = 68;
const qrcodeheight = 68;
context.drawimage(
  '/static/qrcode.png',
  qrcodeleft,
  qrcodetop,
  qrcodewidth,
  qrcodeheight
);

二维码这里直接采用现成图片。实际上前端可以通过 weapp.qrcode.esm.js 在前端生成二维码,再把它绘制上去。

绘制多行文本

const startx = qrcodeleft + qrcodewidth + 15;
const text1 = '与志同道合的,他们一起成长';
context.setfillstyle('#161413');
context.setfontsize(14);
context.settextbaseline('top');
context.filltext(text1, startx, recttop + 29);
const text2 = '扫码即可进入“get一下”社区';
context.font = 'bold 14px arial';
context.filltext(text2, startx, recttop + 51);

看看最后的效果:

左上角的部分没有绘制,思路同头像和昵称一样。 接下来只要把图片保存到相册即可。

保存到相册

在小程序中,提供方法支持如下:

const onsave = () => {
  // 转换为临时路径
  uni.canvastotempfilepath({
    canvasid: 'posterid',
    success: (res) => {
      // 保存图片到相册
      uni.saveimagetophotosalbum({
        filepath: res.tempfilepath,
        success: () => {
          uni.showtoast({
            title: '保存成功',
            icon: 'none',
          });
        },
        fail: () => {
          uni.showtoast({
            title: '保存失败',
            icon: 'none',
          });
        },
      });
    },
  });
};

这里基本上把一个海报绘制

扩展

在绘制名称时,用户名称长短不一至,如果名字过长时会出现什么效果呢

const nickname = '墙头草中的顶尖的墙头草中的顶尖的';
const nameleft = avatarleft + avatarwidth + 7;
context.setfillstyle('#ffffff');
context.setfontsize(12);
context.filltext(nickname, nameleft, 21, 96);

从效果来看,发现文字直接重叠。如果希望超出的部分能够通过省略号来省略,是可以的

const nickname = '墙头草中的顶尖的墙头草中的顶尖的';
const nameleft = avatarleft + avatarwidth + 7;
context.setfillstyle('#ffffff');
context.setfontsize(12);
context.filltext(nickname, nameleft, 21, 96);
let text = '';
const textarr = nickname.split('');
const ellipsiswidth = context.measuretext('...').width; // 省略号的宽度
for (let i = 0; i < textarr.length; i++) {
  const temp = text + textarr[i];
  const metrics = context.measuretext(temp);
  if (metrics.width + ellipsiswidth > 96) {
    text = text + '...';
    break;
  }
  text = temp;
}
context.filltext(text, nameleft, 21, 96);

上面主要是通过 measuretext 方法获得文字对应宽度,针对超出的部分采用省略号替代。当然,如果希望完整地显示名字,也可以使用换行的方式。具体的实现方式,就留给大家自己思考和实现了。

处理后效果如下:

头像实现圆角

默认采用圆角头像,如果用户上传的头像没有进行裁剪处理,导致图片出现非圆角情况,那么在海报上呈现的效果可能会有所差异。

先使用一个非圆角的图片,代码修改如下:

const avatarleft = 185;
const avatartop = 18;
const avatarwidth = 16;
const avatarheight = 16;
context.drawimage(
  '/static/avatar-rect.png',
  avatarleft,
  avatartop,
  avatarwidth,
  avatarheight
);

效果如下:

现在对图片处理一下:

const avatarleft = 185;
const avatartop = 18;
const avatarwidth = 16;
const avatarheight = 16;
context.beginpath();
context.arc(
  avatarleft + avatarwidth / 2,
  avatartop + avatarheight / 2,
  avatarwidth / 2,
  0,
  2 * math.pi
);
context.closepath();
context.clip();
// 绘制圆形头像
context.drawimage(
  '/static/avatar-rect.png',
  avatarleft,
  avatartop,
  avatarwidth,
  avatarheight
);

效果如下:

圆角是实现了,发现其他区域内容都被裁剪了。 这是为什么? clip()改变了绘画环境。ctx()调用后,所裁剪的区域就是 clip ()后的绘制环境,clip()之后的绘画只能在裁剪区域中渲染,不能访问画布上的其他区域。

怎么处理这个问题呢 ? 通过 save()restore().

context.save(); // 暂存
context.beginpath();
context.arc(
  avatarleft + avatarwidth / 2,
  avatartop + avatarheight / 2,
  avatarwidth / 2,
  0,
  2 * math.pi
);
context.closepath();
context.clip();
// 绘制圆形头像
context.drawimage(
  '/static/avatar-rect.png',
  avatarleft,
  avatartop,
  avatarwidth,
  avatarheight
);
context.restore(); // 恢复

效果如下:

总结

  • 通过 canvas + 小程序提供 api 实现海报绘制、保存海报到相册
  • 优化特殊情况下名称和头像的展示方式。

以上就是微信小程序海报绘制示例讲解的详细内容,更多关于小程序海报绘制的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com