【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)

可在系列教程的基础上继续开发,也可以单独使用

【微信小程序-原生开发】系列教程

效果预览

在这里插入图片描述

代码实现

点击触发生成海报

在活动详情页,指定点击某图标/按钮,触发跳转到生成海报的页面

pages\components\party\detail\index.js

  getPoster() {let detail = this.data.detailwx.navigateTo({url: '/pages/components/poster/index',success: function (res) {// 跳转页面时,将活动详情传递过去res.eventChannel.emit('sendData', {data: detail})}})},

海报页加载时接收参数,开始生成海报

pages\components\poster\index.js

  onLoad() {let that = this// 接收列表页传入的复杂数据--对象(详情)const eventChannel = this.getOpenerEventChannel()eventChannel.on('sendData', function (res) {that.setData({detail: res.data})wx.showLoading({title: '生成中',})//开始生成海报that.getPoster()})},

海报的绘制过程

海报通过Canvas进行绘制

1. 获取系统屏幕宽高,确定画布的宽高

  // 生成海报getPoster() {let that = this// 获取屏幕宽高wx.getSystemInfo({success(res) {that.drawCanvas(res.windowWidth, res.windowHeight)}})},

2. 创建Canvas对象,进行绘制,并生成图片

详见代码中的注释

<canvas class="canvasClass" id="mycanvas" type="2d" />
Page {background-color: black;
}.canvasClass {width: 80%;height: 80vh;margin: 40rpx auto
}
  // 绘制海报drawCanvas(windowWidth, windowHeight) {let that = this;let detail = this.data.detail// 根据id查找到页面中的 canvas 标签,生成 Canvas 对象wx.createSelectorQuery()// # 后为页面中的 canvas 标签的 id 属性.select('#mycanvas').fields({node: true,size: true}).exec(async (res) => {// 获取到 Canvas 对象const canvas = res[0].node// 渲染上下文const ctx = canvas.getContext('2d')// Canvas 画布的实际绘制宽高const width = windowWidthconst height = windowHeight// 获取设备像素比const dpr = wx.getWindowInfo().pixelRatio// 清空画布ctx.clearRect(0, 0, width, height)// 初始化画布大小canvas.width = width * dprcanvas.height = height * dprctx.scale(dpr, dpr)// 绘制画布底色ctx.fillStyle = "white";ctx.fillRect(0, 0, canvas.width, canvas.height);// 解析活动封面图片let posterImgURL = detail.poster// 获取源图片宽高let posterImgInfo = await that.getImgInfo(posterImgURL)// 计算源图片的宽高比let posterImgRate = posterImgInfo.width / posterImgInfo.height// 计算出新的图片宽高(此处以宽为基准,按80%的宽等比例缩放图片)let newWidth = 0.8 * widthlet newHeight = 0.8 * width / posterImgRate// 绘制文本 -- 水平居中(活动名称)let text1 = detail.title;ctx.fillStyle = "black";ctx.font = "bold 25px 微软雅黑";let y1 = width / 10 + newHeight + 50ctx.fillText(text1, that.getTextxPosition(ctx, width, text1), y1);// 绘制文本 -- 水平居中(活动时间)let text2 = detail.date + ' ' + detail.week + ' ' + detail.timectx.font = "15px 微软雅黑";let y2 = y1 + 30ctx.fillText(text2, that.getTextxPosition(ctx, width, text2), y2);// 绘制文本 -- 水平居中(活动地点)let text3 = detail.placeMark || detail.placeInfo.titlectx.font = "15px 微软雅黑";let y3 = y2 + 30ctx.fillText(text3, that.getTextxPosition(ctx, width, text3), y3);// 绘制文本 -- 水平居中let codeTips = "长按识别二维码报名";ctx.font = "20px bold";ctx.fillStyle = "green";let y4 = y3 + 40ctx.fillText(codeTips, that.getTextxPosition(ctx, width, codeTips), y4);// 绘制图片--活动封面图片let posterImg = canvas.createImage()posterImg.src = posterImgURLposterImg.onload = async () => {ctx.drawImage(posterImg, (width - newWidth) / 2, width / 10, newWidth, newHeight)// 绘制图片--小程序二维码const codeImg = canvas.createImage()// 异步生成小程序二维码codeImg.src = await that.initCodeImg()codeImg.onload = () => {let y5 = y4 + 20ctx.drawImage(codeImg, width / 3, y5, width / 3, width / 3)// 生成图片wx.canvasToTempFilePath({canvas,success: res => {wx.hideLoading()that.setData({// 生成的图片临时文件路径tempFilePath: res.tempFilePath})},})}}})},

技术要点一:画布的最终大小需要按设备像素比进行转换

        // Canvas 画布的实际绘制宽高const width = windowWidthconst height = windowHeight// 获取设备像素比const dpr = wx.getWindowInfo().pixelRatio// 初始化画布大小canvas.width = width * dprcanvas.height = height * dprctx.scale(dpr, dpr)

技术要点二:需先清空画布后绘制底色

  • 为避免多次渲染导致累积层叠绘制,每次都需清空画布
  • 若未绘制底色,则最终保存的海报会是透明的(若想生成背景透明的海报,请删除绘制画布底色的代码)
        // 清空画布ctx.clearRect(0, 0, width, height)// 绘制画布底色ctx.fillStyle = "white";ctx.fillRect(0, 0, canvas.width, canvas.height);

技术要点三:保持图片的宽高比

        // 解析活动封面图片let posterImgURL = detail.poster// 获取源图片宽高let posterImgInfo = await that.getImgInfo(posterImgURL)// 计算源图片的宽高比let posterImgRate = posterImgInfo.width / posterImgInfo.height// 计算出新的图片宽高(此处以宽为基准,按80%的宽等比例缩放图片)let newWidth = 0.8 * widthlet newHeight = 0.8 * width / posterImgRate

此处需要异步解析图片,获取源图片的宽高,来计算宽高比

  // 获取图片信息getImgInfo(imgURL) {return new Promise((reslove) => {wx.getImageInfo({src: imgURL,success(res) {reslove(res);}})})},

通过返回 Promise ,方便借助 async和 await 将异步变同步,避免过多的代码嵌套。

技术要点四:绘制水平居中的文字

        // 绘制文本 -- 水平居中(活动名称)let text1 = detail.title;ctx.fillStyle = "black";ctx.font = "bold 25px 微软雅黑";let y1 = width / 10 + newHeight + 50ctx.fillText(text1, that.getTextxPosition(ctx, width, text1), y1);
  • fillText 的参数依次为:文本内容、文本的 x 坐标,文本的 y 坐标
  • 水平居中的 x 坐标计算方法为:(画布宽度-文本宽度)/ 2
  // 获取居中文本的x坐标getTextxPosition(ctx, ctxWidth, text) {let textWidth = ctx.measureText(text).width;let xPosition = ctxWidth / 2 - textWidth / 2;return xPosition},

技术要点五:绘制图片

        // 绘制图片--活动封面图片let posterImg = canvas.createImage()posterImg.src = posterImgURLposterImg.onload = () => {ctx.drawImage(posterImg, (width - newWidth) / 2, width / 10, newWidth, newHeight)}
  • 图片若是网络图片,则需等其异步加载完成后再绘制,所以后续生成图片等操作,都需在图片的 onload 函数中执行

技术要点六:生成小程序二维码

  // 生成小程序二维码async initCodeImg() {let {codeImgURL} = this.dataif (!codeImgURL) {// 生成小程序二维码let codeImgID = await this.getCodeImg()// 云存储的图片,需要通过云id去换取外网访问链接let result = await wx.cloud.getTempFileURL({fileList: [codeImgID]})codeImgURL = result.fileList[0].tempFileURL}return codeImgURL},
  // 通过云函数,生成小程序二维码getCodeImg() {let detail = this.data.detaillet params = detail._idreturn new Promise((resolve) => {wx.cloud.callFunction({name: 'get_codeImg', // 云函数的名称data: {// 页面路径path: 'pages/components/party/detail/index',// 参数params: params}}).then(res => {// 从云函数返回的结果中提取出目标数据resolve(res.result.fileID);})})},

云函数–生成小程序二维码

此处自定义的云函数名称为 get_codeImg

cloudfunctions\get_codeImg\index.js

// 云函数入口文件
const cloud = require('wx-server-sdk')cloud.init({env: cloud.DYNAMIC_CURRENT_ENV
}) // 使用当前云环境// 云函数入口函数
exports.main = async (event, context) => {const wxacodeResult = await cloud.openapi.wxacode.getUnlimited({// 页面路径page: event.path,// 参数scene: event.params,})let suffix = event.path.replace(/\//g, '_') + '_' + event.params// 在云存储生成图片const uploadResult = await cloud.uploadFile({// 图片存储路径cloudPath: `codeImgs/wxacode_${suffix}.jpg`,fileContent: wxacodeResult.buffer,})return uploadResult
}
  • 此处需注意,因参数通过 scene 场景值传递(且scene限定了长度,刚好和默认的 _id 值等长),在目标页面需添加代码识别该参数
  onLoad(options) {// 通过id获取详情(扫描小程序二维码时,id在scene里 )let id = options.id || options.sceneif (id) {this.setData({id: id})this.getDetail()return}
}

技术要点七:将canvas转换为图片

此步可在 canvas 绘制后执行,也可以在点击保存海报时在执行

            // 生成图片wx.canvasToTempFilePath({canvas,success: res => {that.setData({// 生成的图片临时文件路径tempFilePath: res.tempFilePath})},})

保存图片到手机

点击保存按钮时执行

在这里插入图片描述

<view class="btnBanner"><t-button style="margin-right: 40rpx;" block theme="light" capture-bind:tap="cancel" size="medium">取消</t-button><t-button block capture-bind:tap="saveImg" theme="primary" size="medium">保存</t-button>
</view>
.btnBanner {padding-top: 20rpx;display: flex;justify-content: space-evenly;margin: 0rpx 10%;
}
  //保存到手机相册saveImg() {wx.saveImageToPhotosAlbum({filePath: this.data.tempFilePath,success(res) {wx.showToast({title: '已保存到相册',icon: 'success',duration: 3000})}})},
  // 取消cancel() {wx.navigateBack()},

注意事项

  • 不同的海报,内容和布局不同,需要修改对应的 canvas 绘制代码

更多技巧

canvas 系列教程

微信小程序的 canvas 绘制已与 web 中 canvas 的绘制统一,相关的绘制技术,可参考

  • 01——直线、三角形、多边形、矩形、调色板_canvas调色板
    https://blog.csdn.net/weixin_41192489/article/details/124333306

  • 02——圆、弧线、圆角矩形、曲线(气泡、心形、N叶草)、扇形_canvas 半圆矩形
    https://blog.csdn.net/weixin_41192489/article/details/124339528

  • 03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)_canvas putimagedata 缩放
    https://blog.csdn.net/weixin_41192489/article/details/124347589

  • 04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式_canvas strokerect
    https://blog.csdn.net/weixin_41192489/article/details/124375153

  • 05 ——交互、动画_canvas 交互
    https://blog.csdn.net/weixin_41192489/article/details/124388436

  • 06 ——边界检测、碰撞检测_canvas碰撞检测
    https://blog.csdn.net/weixin_41192489/article/details/124407221

  • 07 ——捕获、拖拽、抛掷、缓动动画、弹性动画_canvas管道动画
    https://blog.csdn.net/weixin_41192489/article/details/124415085

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/72183.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2020赚钱机会总结,拾元富另附10个副业赚钱必备的工具与平台,看看你到底错过了多少钱!

赚钱不努力&#xff0c;努力不赚钱&#xff01;你会发现一个现象&#xff0c;自己很辛苦也很努力地去工作&#xff0c;甚至连假节日都不敢休息&#xff0c;平时也很节俭&#xff0c;也没买什么奢侈品&#xff0c;每个月也都有存钱。但是就是不知道为什么&#xff0c;钱存得很慢…

单日直播GMV破亿,爆品热销628w+,8月榜单有哪些看点?

今年的“抖音818发现好物节”&#xff0c;再次引爆了用户们在夏日的消费热情。 截止8月18日24时&#xff0c;大促成交额破百万直播间达3894个&#xff0c;挂购物车短视频投稿量达1621条&#xff0c;交易额破百万品牌达5560个&#xff0c;泛商城交易额破百万单品个数达400。 而纵…

微信重磅更新,视频号狂放大招:直播连麦打赏美颜齐上线,新增巨大流量入口

本文转载自 新榜 12月23日晚&#xff0c;微信迎来重大改版&#xff01;在最新7.0.20版本的微信中&#xff0c;视频号大招不断&#xff0c;不仅上线了连麦功能&#xff0c;支持美颜瘦脸、打赏等功能。 此外&#xff0c;微信还给视频号开放了两个重大入口&#xff0c;包括微信个…

谷歌开放生成式AI Bard,百度文心一言《唐伯虎点秋香》出圈

雷递网 雷建平 3月22日 谷歌今日正式开放类ChatGPT产品Bard的访问。谷歌称&#xff0c;这是一项早期实验&#xff0c;可让用户与生成AI协作。 Bard的服务从美国和英国开始&#xff0c;随着时间的推移将扩展到更多国家和语言。 谷歌称&#xff0c;用户可使用Bard来提高工作效率、…

文心ERNIE 3.0 Zeus千亿参数大模型,一键生成“学术范儿”论文标题

文章整理自哔哩哔哩科技区UP主“同济子豪兄”&#xff08;张子豪&#xff09;的主题分享「文心雕龙&#xff0c;一键生成学术灵感」。 文心ERNIE 3.0 Zeus作为基于知识增强的千亿模型&#xff0c;在各类真实场景的生成准确性、流畅性、相关性上全面领先业界其他大模型&#xff…

飞浆AI studio人工智能课程学习(3)-在具体场景下优化Prompt

文章目录 在具体场景下优化Prompt营销场景办公效率场景日常生活场景海报背景图生成办公效率场景预设Prompt 生活场景中日常学习Prompt: 给写完的代码做文档 将优质Prompt模板化Prompt 1:Prompt 1:Prompt 2步骤文本过长而导致遗失信息的示例 步骤三:归纳输入情况&#xff0c;确定…

聊聊软件登录界面的设计与交互

前面说了一堆废话&#xff0c;想看代码的可直接看第二章。 版本记录 日期备注2020-06-13初稿 零、前言 这个登录界面提取自最近正在做的一个项目&#xff0c;此项目曾被我自豪地称为是公司数采软件的颜值担当&#xff0c;虽然这里面有不少夸大的成分&#xff0c;但也并非担不…

交互设计介绍

交互设计是一门需要结合用户体验和设计思维的复杂学科。作为Ul设计师&#xff0c;我们需要通过了解用户需求和市场趋势&#xff0c;以及深入了解产品的特点和功能&#xff0c;来设计出符合用户需求的交互方式&#xff0c;以提高产品的用户体验和用户满意度。以下是一些交互设计…

Midjourney助力交互设计师设计网站主页

Midjourney的一大核心优势是提供创意设计&#xff0c;这个功能也可以用在网站主页设计上&#xff0c;使用Midjourney prompt 应尽量简单&#xff0c;只需要以"web design for..." or "modern web design for..."开头即可 比如设计一个通用SAAS服务的初创企…

诚意满满的奉上2000套Axure原型图设计源文件UI UX交互设计案例

网络上的Axure教程看了很多&#xff0c;大多数都是讲软件如何操作&#xff0c;讲交互逻辑和用户体验的却寥寥无几&#xff0c;而实际项目中却非常重交互逻辑和用户体验。把这2000套原型文件一一拆解&#xff0c;慢慢分析作者的设计思路&#xff0c;会发现&#xff0c;互联网产品…

11个优秀的交互设计作品集

本文转自墨刀编译自Vanschneider的10 inspiring ux portfolios and why they work。 不管你做什么样的设计&#xff0c;一个在线交互设计作品集都是必备的。在大多数情况下&#xff0c;公司和客户根本不会考虑你是做什么工作的。虽然很多交互设计师可能认为自己的工作不能很好…

Websocket的基本认识、使用与封装

目录 一、Websocket是什么 二、Websocket的基本使用 使用介绍 第一步 第二步 第三步 第四步 常用API介绍 WebSocket(url[, protocols]) WebSocket.readyState WebSocket.send(data) WebSocket.close([code[, reason]]) WebSocket.bufferedAmount WebSocket.exten…

asp.net paypal信用卡支付功能

前段时间有个客户网站需要用到信用卡支付功能&#xff0c;客户有个Website Payments Pro的帐号&#xff0c;第一次做这东西花了很多时间在上面&#xff0c;已做好运行了一段日子&#xff0c; 现在总结一下&#xff1a; 1. 先注册一个paypal开发者帐号&#xff0c;这个主要用于s…

通义听悟诞生背后,AI大模型打响应用第一枪

配图来自Canva可画 2023年伊始&#xff0c;ChatGPT的爆火出圈&#xff0c;迅速引发了业界对于生成式AI应用的关注&#xff0c;AI大模型的竞争更是愈演愈烈。 作为参与其中的重要玩家&#xff0c;阿里云先是在4月11日举行的阿里云峰会上&#xff0c;推出了通义千问大模型。紧接…

开发私有chatGPT(二)openai前景展望

使用 OpenAI 的强大模型构建下一代应用程序。 GPT-3可以执行各种自然语言任务、Codex 可以将自然语言转换为代码的 &#xff0c;DALLE&#xff0c;用于创建和编辑原始图像。 DALLE 开发人员现在可以开始使用&#xff0c;已经有超过3万人已经在使用DALLE来扩展他们的创造力并加…

快给你的对象做一个微信公众号播报吧-java版

一、前期准备 1.注册微信测试公众号 使用微信扫码登录此网站https://mp.weixin.qq.com/debug/cgi-bin/sandbox?tsandbox/login就能得到一个微信公众号测试号 推送消息需要用到的信息 用户扫码关注得到用户的id 编辑消息模板 此步骤的模板id、用户微信号id、以及自己的appID、…

2013年10月微软MVP当选名单揭晓!

微软公司于2001年8月起开始在亚洲与各大主要的第三方网站上的微软技术相关论坛合作&#xff0c;微软称之为“亚洲社区支持”计划。 为了鼓励大家在论坛中更好地互相帮助&#xff0c;共同提高&#xff0c;微软在全亚洲的微软论坛参与者中评选出那些技术水平高&#xff0c;积…

八大排序·希尔排序

大家好&#xff0c;我是安然无虞。 文章目录 希尔排序1.基本思想预排序 2.算法实现3.时间复杂度 遇见安然遇见你&#xff0c;不负代码不负卿。 插入排序分为两种&#xff1a;直接插入排序&希尔排序 希尔排序 1.基本思想 希尔排序是在直接插入排序基础上的优化&#xff0c…

十大排序之希尔排序

希尔排序 希尔排序(Shell Sort)是插入排序的一种算法&#xff0c;是对直接插入排序的一个优化&#xff0c;也称缩小增量排序。 希尔排序是非稳定排序算法。 希尔排序因DL&#xff0e;Shell于1959年提出而得名。 希尔排序是将待排序的数组元素按下标的一定增量分组 &#xff…

NBA球员出手位置分布图

小白一只&#xff0c;想转行互联网行业的数据分析&#xff0c;通过寒假的佛系学习对python有了一定的了解。记录一下第一个小玩意儿。 在刷crossin论坛的时候突然看到一篇关于NBA的数据分析&#xff0c;因为本身自己也非常喜欢打球&#xff0c;顿时就有了兴趣。 由于对python…