文章目录
- 前言
- 一、普通二维码生成
- 二、生成海报图片并保存
- 1、引入依赖组件
- 2、生成海报图片
- 2.1 配置painter海报json
- 2.2 引入数据构造函数并在适当时间触发生成海报
- 2.3 弹窗组件中直接使用painter组件
- 三、源码
前言
最近开发的小程序都有分享需求,功能大体为点击分享按钮,或主动生成海报后,用户操作保存对应海报为图片实现分享。以下是具体实现。
最终生成效果如图:
一、普通二维码生成
此处主要是生成工具库来生成普通二维码,如果要生成小程序码,只能通过后台接口调用开放API实现,且需要小程序已上线发布才能通过微信扫一扫进入小程序(废话不多说了。。。。)
- 工具库:weapp.qrcode.min.js
template
<template>
<view class="page">
<canvas
id="canvas"
style="width: 160rpx; height: 160rpx"
canvas-id="canvas"
></canvas>
</view>
</template>
script
// 调用很简单
const drawQrcode = require("@/lib/weapp.qrcode.min.js)
export default {
data(){return {}};
onLoad(){
this.drawCode();
}
methods:{
drawCode(){
drawQrcode({
text: `二维码内容`,
canvasId: "canvas",
width: 80,
height: 80
})
console.log("二维码生成")
}
}
}
二、生成海报图片并保存
生成海报分为两步
一是海报预览弹窗(这个是小程序内页弹窗所以直接代码编写就好)
二是通过painter将元素生成为图片保存到本地。以下代码只描述重点部分,全部代码请查看源码文件。
这里用到了painter这个组件库,这是一个通过配置json就直接生成图片的工具库,开源地址
1、引入依赖组件
这里引用了painter组件来生成(懒人不想造轮子- _ -)。因为是微信原生编写,所以放在根目录下的wxcomponents中
目录如下:
|__ wxcomponents
|__ painter
|__ painter.wxml
|__ painter.wxss
|__painter.json
|__painter.js
|__ ...
page.json中引入微信组件
{
"globalStyle":{
"usingComponents": {
"painter": "/wxcomponents/painter/painter"
}
}
}
2、生成海报图片
这里新建了两个文件,一个share.vue用于在小程序中直接展示海报的样式,一个share.js是配置painter海报的数据源
- share.vue
<template>
<view class="share" v-if="visible">
<view class="share-content">
<view class="share-chart-wrap">
<image
class="share-chart"
@longpress="saveImgNow"
src="http://qiniu.kingdou.fun/kingdou1.jpeg"
mode="widthFix"
/>
<view class="share-title">这是每报标题</view>
</view>
<view class="share-card">
<view class="content-block">
<view class="content-row">
<view class="content-label">海报时间</view>
<view class="content-value">{{ data.time }}</view>
</view>
<view class="content-row">
<view class="content-label">描述</view>
<view class="content-value">{{ data.introduce }}</view>
</view>
<view class="content-row">
<view class="content-label">比赛说明</view>
<view class="content-value">限定时间内根据动作次数记分</view>
</view>
</view>
<view class="qr-block">
<view class="qr-tips">
<view class="tips-title">长按图片进行保存或者转发</view>
<view class="tips-content"
>扫描二维码即可参赛~<br />快去分享吧~
</view>
</view>
<slot name="qrcode" @longpress="init"></slot>
</view>
</view>
</view>
<uni-icons
class="close-btn"
size="50"
type="close"
color="#fff"
@click="close"
/>
<painter
v-show="isSave"
style="position: absolute; top: 79rpx; left: 60rpx"
:palette="template"
@imgOK="onImgOK"
@imgErr="onImgErr"
/>
</view>
</template>
<script>
import Card from "./share";
export default {
props: {
visible: {
type: Boolean,
default: false,
},
data: {
type: Object,
default: () => {
return {
time: "",
introduce: "",
};
},
},
},
data() {
return {
imagePath: "",
template: "",
};
},
methods: {
saveImgNow() {
let data = { ...this.data};
this.template = new Card().palette(data);
},
saveImage() {
if (this.imagePath && typeof this.imagePath === "string") {
// 图片保存到本地
wx.saveImageToPhotosAlbum({
filePath: this.imagePath,
});
// 关闭分享弹窗
setTimeout(() => {
this.$emit("update:visible", false)
}, 500)
}
},
close() {
this.$emit("close");
},
onImgOK(e) {
this.imagePath = e.detail.path;
this.saveImage(this.imagePath);
},
onImgErr() {
console.log("保存图片失败");
},
},
};
</script>
<style lang="scss" scoped>
样式内容省略,详见源码。。。
</style>
- share.js (内容太多,这里就只截部分作为参考,全部内容请参考文末的源码包)PS:这个文件通过工具生成并不需要自己编写
export default class LastMayday {
palette(data) { // 传入动态数据源
return {
width: "320px",
height: "430px",
background: "#f1f1f1",
views: [
{
type: "text",
text: "海报时间",
css: {
color: "#373737",
background: "rgba(0,0,0,0)",
width: "60px",
height: "15.819999999999999px",
top: "202px",
left: "40px",
// 。。。。省略
},
},
{
type: "text",
text: data.time, //这里是动态数据
css: {
color: "#0061D4",
background: "rgba(0,0,0,0)",
width: "181px",
height: "15.819999999999999px",
top: "202px",
// 。。。。省略
},
},
// 。。。。。
}
2.1 配置painter海报json
这里即是对上面的share.js来历进行说明。要生成图片,得有生成图片的规则,也就是painter的绘制数据源。这里也是通过第三方网站来可视化生成的,通过在这个网站中先绘制好海报的样式后,再一键生成json文件,最后放进代码中。
- painter海报json在线绘制生成工具\
- 最终生成内容如上述share.js
2.2 引入数据构造函数并在适当时间触发生成海报
- 在本文示例中是通过长按图片来触发,当然也可以是用户直接点击按钮来触发
import Card from './share.js'
export default {
// 。。。。省略。。。
methods: {
// 这里假设用户长按图片,触发此方法。即上面share.vue中, @longpress="saveImgNow"
saveImgNow() {
let data = { ...this.data};
this.template = new Card().palette(data);
},
// 生成图片事件监听(在调用new Card()后会自动触发
// 图片生成成功时
onImgOK(e) {
this.imagePath = e.detail.path;
this.saveImage(this.imagePath);
},
// 图片生成失败时
onImgErr() {
console.log("保存图片失败");
},
}
2.3 弹窗组件中直接使用painter组件
<painter style="position: absolute; top: -799999rpx; left: -999960rpx" :palette="template" @imgOK="onImgOK"
@imgErr="onImgErr" />
- 这里style中的内容是为了在视觉上隐藏海报(本质上是通过canvas再生成海报,所以需要此元素显示后再在canvas上绘制为图片)
三、源码
地址参见:https://gitee.com/sophie-code-box/share-poster