uniapp 微信小程序 分享海报的实现

时间:2024-04-27 13:13:34

在这里插入图片描述
在这里插入图片描述
主页面

<template>
	<view class="page">
		<!-- 自定义导航栏-->
		<Navbar title="我的海报"></Navbar>
		<view class="container">
			<poster ref="poster" :imageUrl="image" :imageWidth="750" :imageHeight="1000" :drawData="drawData"
				:config="config" :wechatCode="false" @wechatCodeConfig="wechatCodeConfig" @click="createdPoster"
				@loading="onLoading" @success="onSuccess" @fail="onFail" class="poster">
				<!-- <template v-slot:save>
					<view @click="saveToAlbum">保存</view>
				</template> -->
			</poster>
			<u-image width="222rpx" height="222rpx" :src="code" class="container_image"></u-image>
		</view>
		<!-- <view class="bottom"> -->
		<!-- <view class="bottom_item" @click="share('微信好友')">
				<u-image width="74rpx" height="74rpx" 
					src="xxxxxxxxxxxxxxstatic/poster/%E7%BC%96%E7%BB%84%206%402x.png"></u-image>
				<text>微信好友</text>
			</view> -->
		<!-- <view class="bottom_item" @click="share('朋友圈')">
				<u-image width="74rpx" height="74rpx"
					src="xxxxxxxxxxxposter/%E7%BC%96%E7%BB%84%208%402x.png"></u-image>
				<text>朋友圈</text>
			</view> -->
		<!-- <view class="bottom_item" @click="share('保存图片')">
				<u-image width="74rpx" height="74rpx"  
					src="xxxxxxxxxoster/%E7%BC%96%E7%BB%84%2012%402x.png"></u-image>
				<text>保存图片</text>
			</view> -->
		<!-- </view> -->
	</view>
</template>

<script>
	import poster from "@/components/poster/index";
	import {
		saveImageToPhotosAlbum
	} from '@/utils/poster.js';
	export default {
		components: {
			poster
		},
		data() {
			return {
				code: '',
				canvasImages: '',
				image: 'xxxxxxter/static/poster/%E7%BC%96%E7%BB%84%205%402x.png',
				config: {
					imageMode: 'aspectFit',
					posterHeight: '100%',
					// canvasWidth 和 convasHeight使用的是px,防止不同设备Dpr不统一,导致最后图片留白边问题
					canvasWidth: 275,
					convasHeight: 600,
				},
				drawData: [],
				wechatCodeConfig: {
					serverUrl: '',
					scene: '123123',
					config: {
						x: 84.5,
						y: 320,
						w: 100,
						h: 100
					}
				}
			}
		},
		created() {
			this.usercode()
			// 模拟异步请求获得到的数据
			// setTimeout(() => {
			// this.wechatCodeConfig.scene = '456787';
			// this.drawData = [{
			// 		type: 'image',
			// 		config: {
			// 			url: 'https://horifon.oss-cn-shanghai.aliyuncs.com/hongyunartcenter/static/poster/%E7%BC%96%E7%BB%84%205.png',
			// 			x: 0,
			// 			y: 0,
			// 			w: 275,
			// 			h: 490
			// 		},
			// 	},
			// 	{
			// 		type: 'image',
			// 		config: {
			// 			url: this.code,
			// 			x: 40,
			// 			y: 380,
			// 			w: 40,
			// 			h: 40
			// 		},
			// 	},
			// 	{
			// 		type: 'text',
			// 		config: {
			// 			text: '',
			// 			x: 140,
			// 			y: 60,
			// 			color: '#E60012',
			// 			font: 'normal bold 16px 仿宋',
			// 			textAlign: 'center'
			// 		}
			// 	}
			// ];

			// }, 1000)
			// this.createdPoster();
		},
		methods: {
			//二维码
			usercode() {
				let $this = this
				uni.request({
					url: "xxxxxxx/mobile/index.php?m=user&c=indexapi&a=affiliate",
					method: 'POST',
					header: {
						'Content-Type': 'application/x-www-form-urlencoded'
					},
					data: {
						"user_id": parseInt(uni.getStorageSync('USER_ID'))
					},
					success(res) {
						console.log(res.data.data, '数据');
						$this.code = res.data.data
						$this.wechatCodeConfig.serverUrl = res.data.data
					}
				});
			},
			// 保存到相册
			saveToAlbum() {
				this.$refs.poster.saveToAlbum()
			},
			onLoading() {
				console.log('Loading:正在加载静态资源')
			},
			onSuccess(e) {
				console.log('Success:创建海报成功', e)
				this.canvasImages = e
				wx.showShareImageMenu({
					path: this.canvasImages,
					style:"background-color:'black'"
				})
			},
			onFail(e) {
				console.log('Fail:创建海报失败', e)
			},
			createdPoster() {
				console.log('点击')
				// 调用 createImage 开始创建海报
				// this.$refs.poster.createImage()
				this.$refs.poster.cjian()
				// wx.showShareImageMenu({
				// 	path: this.canvasImages
				// })
			},
			share(e) {
				if (e === '微信好友') {
					wx.showShareImageMenu({
						path: this.canvasImages
					})

				} else if (e === '朋友圈') {
					uni.share({
						provider: "weixin",
						scene: "WXSceneTimeline",
						type: 2,
						imageUrl: this.canvasImages,
						success: function(res) {
							console.log("success:" + JSON.stringify(res));
						},
						fail: function(err) {
							console.log("fail:" + JSON.stringify(err));
						}
					});
				} else if (e === '保存图片') {
					saveImageToPhotosAlbum(this.canvasImages).then(res => {
						uni.showToast({
							icon: 'none',
							title: '保存成功'
						})
					}).catch(err => {

					})

				}
			}
		}
	}
</script>

<style scoped lang="scss">
	.container {
		position: relative;
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;

		.poster {
			width: 100%;
			height: 100%;
		}

		.container_image {
			position: absolute;
			bottom: 214rpx;
			left: 76rpx;
		}
	}

	.bottom {
		display: flex;
		justify-content: space-evenly;
		align-items: center;
		position: absolute;
		bottom: 0;
		width: 750rpx;
		height: 218rpx;
		background: #FFFFFF;
		border-radius: 40rpx 40rpx 0rpx 0rpx;
		// border: 2rpx solid #FF583D;
	}
</style>

components/poster/index 组件

<template>
	<view class="poster_wrapper">
		<slot name="header"></slot>
		<!-- 要生成海报的图片 -->
		<image :src="imageUrl" mode="aspectFill" :style="{width:imageWidth + 'rpx'}"  @click="click" class="imagebig"></image>
		<!-- 这里把canvas移到了屏幕外面,如果需要查看canvas的话把定位去掉 -->
		<!-- position:'fixed',left:'9999px',top:'0' -->
		<canvas :style="{width:canvasWidth + 'px',height:canvasHeight + 'px',position:'fixed',left:'9999px',top:'0'}"
		 canvas-id="myCanvas" id="myCanvas" class="canvas"></canvas>
		<!-- 遮罩层 -->
		<!-- <view class="mask" v-if="showMask" @click="hideMask"> -->
			<!-- 生成的海报图 -->
			<!-- <image :style="posterSize" :src="lastPoster" :mode="config.imageMode" @click.stop=""></image> -->
			<!-- <view class="btn_wrapper" @click.stop>
				<slot name="save">
					<button type="primary" @click="saveToAlbum">保存至相册</button>
				</slot>
			</view> -->
		<!-- </view> -->
	</view>
</template>

<script>
	import {
		loadImage,
		createPoster,
		canvasToTempFilePath,
		saveImageToPhotosAlbum
	} from '@/utils/poster.js';
	import {
		getWechatCode
	} from "@/utils/appletCode.js";
	export default {
		props: {
			// 展示图片的宽 单位 rpx
			imageWidth: {
				type: [String, Number],
				default: 550
			},
			// 展示图片的高 单位 rpx
			imageHeight: {
				type: [String, Number],
				default:980
			},
			// 展示图片的url
			imageUrl: {
				type: String,
				default: '',
				required: true
			},
			// 绘制海报的数据参数
			// drawData: {
			// 	type: Array,
			// 	default: () => ([]),
			// 	required: true
			// },
			// 海报的配置参数
			config: {
				type: Object,
				default: () => ({
					imageMode: 'aspectFit',
					posterHeight:1000,
				}),
			},
			// 是否需要小程序二维码
			wechatCode: {
				type: Boolean,
				default: false
			},
			// 小程序二维码的配置参数
			wechatCodeConfig: {
				type: Object,
				default: () => ({
					serverUrl: '',
					scene: '',
					config: {
						x: 0,
						y: 0,
						w: 100,
						h: 100
					}
				}),
			}
		},
		data() {
			return {
				// 资源是否加载成功的标志
				readyed: false,
				// 将网络图片转成静态图片后的绘制参数
				imageMap: [],
				// 最后生成的海报的本地缓存地址
				lastPoster: '',
				// 是否展示遮罩
				showMask: false,
				// 是否加载资源的标志
				loadingShow: false,
				// 是否可以创建海报
				disableCreatePoster:false,
				drawData :[
					{
						type: 'image',
						config: {
							url: '',
							x: 0,
							y: 0,
							w: 275,
							h: 490
						},
					},
					{
						type: 'image',
						config: {
							url: '',
							x: 40,
							y: 380,
							w: 40,
							h: 40
						},
					},
					{
						type: 'text',
						config: {
							text: '',
							x: 140,
							y: 60,
							color: '#E60012',
							font: 'normal bold 16px 仿宋',
							textAlign: 'center'
						}
					}
				],
				
			}
		},
		computed: {
			// 所生成海报图的大小
			posterSize() {
				let str = '';
				this.config.posterWidth && (str += `width:${this.config.posterWidth};`);
				this.config.posterHeight && (str += `height:${this.config.posterHeight};`);
				return str
			},
			// 画布的宽,优先使用配置的宽,如果没用配置默认使用图片的宽
			// 需要主要的是这里canvas和image的单位不同,不过并不影响
			// 我们在绘制时(配置drawData)以px为基准进行绘制就行,用px的原因时防止不同设备Dpr不同导致无法确定画布的具体宽高,使得最后的图片可能会留白边
			canvasWidth(){
				return this.config.canvasWidth ? this.config.canvasWidth : this.imageWidth
			},
			// 画布的高,优先使用配置的高,如果没用配置默认使用图片的高
			canvasHeight(){
				return this.config.convasHeight ? this.config.convasHeight : this.imageHeight
			}
		},
		watch: {
			// 监听外部绘制参数的变化,重新加载资源
			// drawData(newVlaue) {
			// 	this.loadingResources(newVlaue)
			// },
			// 监听readyed变化
			// readyed(newVlaue) {
				
			// 	if (newVlaue == true && this.loadingShow == true) {
			// 		uni.hideLoading()
			// 		this.loadingShow = false;
					
			// 		this.createImage();
			// 	}
			// }
			// 会存在异步问题,还没解决。
			// 目前的解决方法 1.在绘制之前先改变 scene 2.改变scene后手动调用this.loadingResources 函数,但是资源会重新加载
			// "wechatCodeConfig.scene":function (newVlaue){
			// 	console.log('wechatCodeConfig.scene',this.imageMap)
			// 	this.loadingWechatCode(this.imageMap)
			// }
		},
		created() {
			this.usercode()
			// this.$emit('click')
			// this.loadingResources(this.drawData)
		},
		methods: {
			cjian(){
				this.usercode()
			},
			//二维码
			usercode() {
				let $this=this
				uni.request({