【满满的全是干货】uniApp——微信小程序分享or图片保存到本地分享 直接拿去用!!!

170 阅读1分钟

1.分享组建的封装

<template>
	<view class="poster">
		<u-popup v-model="shareShow" mode="bottom" border-radius="20" height="420rpx" @close="shareShowFn">
			<view class="shareBox">
				<button class="shareButton" open-type="share" @click="shareLink">
					<u-icon :label="shareList[0].label" label-pos="bottom" margin-top="20" label-color="#282828"
						size="110" :name="shareList[0].icon"></u-icon>
				</button>
				<u-icon @click="posterShowFn" style="width: 50%;justify-content: center;" :label="shareList[1].label"
					label-pos="bottom" margin-top="20" label-color="#282828" size="110" :name="shareList[1].icon">
				</u-icon>
			</view>
			<view class="shareCancel" @click="$emit('posterClose',1)">取消</view>
		</u-popup>

		<u-popup v-model="posterShow" mode="center" width="85%" safe-area-inset-bottom @close="$emit('posterClose',1)">
			<view class="canvasBox">
				<!-- <u-image class="imageBox" border-radius="14" :show-error="false" :src="posterImg" mode="widthFix"
							:fade="false"></u-image> -->
				<canvas canvas-id="shareCanvas" class="canvas"
					:style="{height: canvasHeight+'px',width:canvasWidth+'px'}">
				</canvas>


			</view>
			<u-button class="button" v-show="drawFinish" hover-class="none" type="primary" @click="downImg"
				shape="circle">保存图片
			</u-button>
		</u-popup>

	</view>
</template>
<script>
	import {
		AppModel
	} from '@/models/app.js'
	const appModel = new AppModel();
	export default {
		data() {
			return {
				shareShow: true,
				posterShow: false,
				posterImg: 'https://www.xxxx.com/home/photo/hyq/wechat/weChatShare.png',
				shareList: [{
					label: '微信好友',
					icon: 'https://www.xxxxxx.com/home/photo/hyq/wechat/share_wx.png'
				}, {
					label: '生成海报',
					icon: 'https://www.xxxxxx.com/home/photo/hyq/wechat/share_hb.png'
				}],
				pageData: {
					post_img: '',
					codePng: 'https://www.xxxxxx.com/home/photo/hyq/wechat/qrcodetest.png'
				},
				ctx: null,
				windowObj: {},
				canvasHeight: 0,
				canvasWidth: 0,
				drawFinish: false
			}
		},
		props: {
			posterData: {
				type: Object,
				default: {}
			}
		},
		onReady() {
			// 在自定义组件下,第二个参数传入组件实例this
			this.ctx = wx.createCanvasContext('shareCanvas', this)
		},
		methods: {
			posterShowFn() {
				this.posterShow = true
				this.shareShow = false
				appModel.shareGetCode(this.posterData).then(res => {
					console.log(res, 'shareGetCode');
					this.exportPost(res.data)
				})
			},
			shareShowFn() {
				if (!this.posterShow) {
					this.$emit('posterClose', 1)
				}
			},
			//获取图片的基本信息,即将网络图片转成本地图片,
			getImageInfo(src) {
				console.log(src, "src,src");
				return new Promise((resolve, reject) => {
					wx.getImageInfo({
						src,
						success: (res) => {
							console.log(res)
							resolve(res)
						},
						fail: (res) => {
							uni.hideLoading()
							uni.showToast({
								title: '图片下载失败',
								icon: 'none',
								duration: 3500
							})
							reject(res)
						}
					})
				});
			},
			downImg() {
				let that = this
				uni.showLoading({
					title: '海报下载中',
					mask: true
				})
                //画布。2.9.0 起支持一套新 Canvas 2D 接口(需指定 type 属性)
				wx.canvasToTempFilePath({
					quality: 1,
					canvasId: 'shareCanvas',
					// width: that.canvasWidth,
					// height: that.canvasHeight,
					// destWidth: that.canvasWidth*2,
					// destHeight: that.canvasHeight*2,
					fileType: 'png', //设置导出图片的后缀名
					success: function(res) {
						that.pageData.post_img = res.tempFilePath
						//保存图片到本地
						uni.saveImageToPhotosAlbum({
							filePath: that.pageData.post_img,
							success: function() {
								uni.hideLoading()
								uni.showToast({
									title: '保存成功'
								})
								that.$emit('posterClose', 1)
							},
							fail: (err) => {
								uni.hideLoading()
								uni.showModal({
									title: '提示',
									content: '需要您授权保存相册',
									showCancel: false,
									success(res) {
										if (res.confirm) {
											uni.openSetting({
												success(settingdata) {
													if (settingdata.authSetting[
															'scope.writePhotosAlbum'
														]) {
														uni.showModal({
															title: '提示',
															content: '获取权限成功,再次保存图片即可成功',
															showCancel: false,
														})
													} else {
														uni.showModal({
															title: '提示',
															content: '获取权限失败,无法保存到相册',
															showCancel: false
														})
													}
												}
											})
										}
									}
								})
							}
						})
					},
					fail: (err) => {
						uni.hideLoading()
						console.log(err)
					}
				}, this)
				//uni.canvasToTempFilePath(object, component)在自定义组件下,第二个参数传入自定义组件实例,以操作组件内 <canvas> 组件
			},
			exportPost(codeData) {
				let that = this
				uni.showLoading({
					title: '海报生成中',
					mask: true
				})
				uni.getSystemInfo({
					success: (systemInfo) => {
						console.log(systemInfo, 'systemInfo')
						//获取系统的基本信息,为后期的画布和底图适配宽高
						Promise.all([that.getImageInfo(codeData.posterPath), that.getImageInfo(codeData
							.qrCodePath)]).then(res => {
							//获取底图和二维码图片的基本信息,通常前端导出的二维码是base64格式的,所以要转成图片格式的才可以获取图片的基本信息

							that.canvasWidth = systemInfo.windowWidth * 0.85 //设置画布的宽高
							let ratio = that.canvasWidth / res[0].width
							let codeWidth = res[1].width * 0.27
							that.canvasHeight = res[0].height * ratio + codeWidth + 20
							// 设置背景色


							let x = 0,
								y = 0,
								w = that.canvasWidth,
								h = that.canvasHeight,
								r = 10
							// that.ctx.beginPath()
							// // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
							// // that.ctx.setFillStyle('transparent')
							// that.ctx.setStrokeStyle('transparent')
							// // 左上角
							// that.ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

							// // border-top
							// that.ctx.moveTo(x + r, y)
							// that.ctx.lineTo(x + w - r, y)
							// that.ctx.lineTo(x + w, y + r)
							// // 右上角
							// that.ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

							// // border-right
							// that.ctx.lineTo(x + w, y + h - r)
							// that.ctx.lineTo(x + w - r, y + h)
							// // 右下角
							// that.ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

							// // border-bottom
							// that.ctx.lineTo(x + r, y + h)
							// that.ctx.lineTo(x, y + h - r)
							// // 左下角
							// that.ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

							// // border-left
							// that.ctx.lineTo(x, y + r)
							// that.ctx.lineTo(x + r, y)
							// // that.ctx.fill()
							// that.ctx.stroke()
							// that.ctx.closePath()
							// // 剪切
							// that.ctx.clip()

							that.ctx.setFillStyle('#fff')
							that.ctx.fillRect(0, 0, that.canvasWidth, that.canvasHeight)


							that.ctx.drawImage(res[0].path, 0, 0, that.canvasWidth, res[0].height *
								ratio);
							that.ctx.drawImage(res[1].path, (that.canvasWidth - codeWidth) * 0.5, res[
								0].height * ratio + 10, codeWidth, codeWidth);
							that.ctx.draw()
							that.drawFinish = true
							uni.hideLoading()
						})
					}
				});
			},
			shareLink() {
				appModel.shareLink(this.posterData).then(res => {

				})
			}
		},
	}
</script>

<style lang="scss">
	.shareBox {
		display: flex;
		justify-content: center;
		align-items: center;
		justify-content: space-around;
		height: 300rpx;
	}

	.shareCancel {
		border-top: 1rpx solid #EEEEEE;
		height: 100rpx;
		line-height: 100rpx;
		text-align: center;
		color: #666666;
		font-size: 28rpx;
	}

	.button {
		background-color: transparent;
		line-height: 0;
		padding: 0;
		font-size: 0;

		/deep/button {
			height: 100rpx;
			line-height: 1;
			width: 300rpx;
			margin-top: 60rpx;
			color: #4788e9 !important;
			background: #FFFFFF !important;
			font-weight: bold;
		}
	}

	.shareButton {
		background-color: transparent;
		line-height: 0;
		padding: 0;
		font-size: 0;
		width: 50%;
		margin: 0;

		&::after {
			border: 0;
		}
	}
</style>

2.页面中使用

	<poster v-if="posterShow" @posterClose="posterClose" :posterData="posterData"></poster>

3.参数传递

this.posterData = {
  page: 'pages/service/detail',
	dataCode: this.infoDetail.code,
	dataType: 1,
	userId: userInfo.id,
	scene: userInfo.id
}

4.页面加载通过 onLoad(option)携带参数换取数据

async onLoad(query) {
			console.log(query, 'queryqueryqueryquery');
			let code;
			if (query.scene) {
        // 拿scene在后端换取  传递的参数
				let analysisCodeData = await appModel.analysisCode({
					scene: query.scene,
				})
				console.log(analysisCodeData, 88888);
				code = analysisCodeData.data.dataCode
			} else {
				code = query.code
			}
}

5.解析

  • 扫码进入 onLunch path是小程序码内路径,query.scene是参数唯一标识,获取后传回后端换回详细数据

6. 使用时需要全局注册

Vue.component('poster', poster)//**海报组件**