组件目录 /share-canvas.vue

<template>
	<u-popup :show="visiable" closeable @close="hiddenCanvas" zIndex="999999">
		<view class="shareModel" @touchstart="" @touchmove="" @touchend="">
			<view class="title">分享店铺</view>
			<template v-if="visiable">
				<canvas canvas-id="posterid" :style="{width:screen_width*375+'px',height:screen_height*0.65+'px'}"
					class="myCanvas" disable-scroll="true" @touchstart="" @touchmove="" @touchend=""></canvas>
			</template>
			<view class="share-bot" @click.stop>
				<view class="share-btns">
					<!-- <view class="btns-list" @click="handleCopyLink">
						<u--image :showLoading="true" :src="copyLink" width="72rpx" height="72rpx" />
						<text>复制链接</text>
					</view> -->
					<view class="btns-list">
						<button class="btns-box" open-type="share">
							<u--image :showLoading="true" :src="copyLink" width="72rpx" height="72rpx" />
							<text>分享链接</text>
						</button>
					</view>
					<view class="btns-list" @click="savePoster(100)">
						<u--image :showLoading="true" :src="saveIcon" width="72rpx" height="72rpx" />
						<text>保存二维码</text>
					</view>
					<view class="btns-list" @click="savePoster(200)">
						<u--image :showLoading="true" :src="saveIcon" width="72rpx" height="72rpx" />
						<text>保存海报</text>
					</view>
				</view>
			</view>
		</view>
	</u-popup>
</template>

<script>
	import {
		mapState
	} from 'vuex'
	import {
		createQrCode
	} from '@/common/api.js'
	export default {
		props: {
			storeInfo: {
				type: Object,
				default: () => {}
			}
		},
		data() {
			return {
				saveIcon: require('../../static/download.png'),
				copyLink: require('../../static/copyLink.png'),
				goodsIcon: require('../../static/goodsIcon.png'),
				qrCode: "",
				visiable: false,
				screen_height: 0,
				screen_width: 0
			}
		},
		computed: {
			...mapState(['$userInfo'])
		},
		created() {
			this.screen_height = uni.getSystemInfoSync().windowHeight;
			this.screen_width = uni.getSystemInfoSync().windowWidth / 375;
			
			console.log(this.screen_height,'screen_height');
		},
		methods: {
			// 店铺二维码分享
			createQrCodeFun() {
				uni.showLoading({
					title: '二维码加载中...',
					mask: true
				})
				createQrCode({
					path: 'pages/home/storePage/index?userGroupAuthId=' + this.storeInfo.userGroupAuthId,
					width: 500
				}).then(res => {
					const {
						filePath
					} = res.data || {} 
                    // 二维码图片,接口可使用网络地址模拟       
					this.qrCode = filePath
					// 得到二维码绘画
					this.setStopter();
				}).finally(() => {
					uni.hideLoading();
				})
			},
			// 复制链接
			handleCopyLink() {
				// #ifdef MP-WEIXIN
				var shareText = '【' + this.storeInfo.merchantName + '】' + '店铺欢迎您##长按复制此条消息,打开亿联乐购小程序首页即可跳转##' + this
					.storeInfo.userGroupAuthId
				uni.setClipboardData({
					data: shareText,
					showToast: false,
					success(res) {
						console.log("success:" + JSON.stringify(res));
						uni.showToast({
							title: '复制成功',
							icon: 'success'
						})
					},
					fail: () => {
						uni.showToast({
							title: '复制失败',
							icon: 'error'
						})
					},
					complete: () => {}
				})
				// #endif
			},
			//显示
			showCanvas() {
				this.visiable = true
				// 得到二维码绘画
				this.createQrCodeFun()
			},
			// 点击关闭
			hiddenCanvas() {
				this.visiable = false
			},
			// 绘制海报
			async setStopter() {
				uni.showLoading({
					title: '加载中...',
					mask: true
				})
				var _this = this
				var ctx = uni.createCanvasContext('posterid', _this) //创建画笔
// 自适应屏幕关键
				let rpx = this.screen_width
				ctx.drawImage('/static/share/share.png', 20 * rpx, 0, 330 * rpx, 380 * rpx);
				this.canvasFont(ctx, 16 * rpx, '#2D2D2D', this.storeInfo.merchantName, 100 * rpx, 50 * rpx)
				this.drawRoundRect(ctx, 90 * rpx, 70 * rpx, 192 * rpx, 192 * rpx, 12 * rpx, '#F5F5F5')
				let banerQrCode = await this.downloadImage(this.qrCode)
				if (banerQrCode.tempFilePath) {
					ctx.save()
					ctx.drawImage(banerQrCode.tempFilePath, 100 * rpx, 80 * rpx, 172 * rpx, 172 * rpx);
					ctx.restore()
				}
				this.canvasFont(ctx, 14 * rpx, '#999999', '(微信扫描二维码即可进入)', 100 * rpx, 280 * rpx)
				ctx.drawImage('../../static/goodsIcon.png', 265 * rpx, 290 * rpx, 50 * rpx, 50 * rpx);
				const {
					portraitFile,
					userName = "亿联乐购用户"
				} = this.$userInfo
				if (portraitFile && portraitFile.staticPath) {
					let userPortraitFile = await this.downloadImage(portraitFile.staticPath)
					ctx.save()
					ctx.drawImage(userPortraitFile.tempFilePath, 50 * rpx, 300 * rpx, 32 * rpx, 32 * rpx);
					ctx.restore()
				} else {
					ctx.drawImage('/static/share/user.png', 50 * rpx, 300 * rpx, 32 * rpx, 32 * rpx)
				}
				this.canvasFont(ctx, 12 * rpx, '#2D2D2D', userName, 90 * rpx, 320 * rpx)

				// ctx.draw()
				ctx.draw(true, () => {
					uni.hideLoading()
				})
				console.log('绘画完成')
			},
			canvasFont(ctx, fs, color, txt, x, y) { //绘制文字
				ctx.setFontSize(fs)
				ctx.setFillStyle(color)
				ctx.fillText(txt, x, y)
			},
			//圆角矩形
			drawRoundRect(ctx, x, y, width, height, radius, color) {
				ctx.save();
				ctx.beginPath();
				ctx.setFillStyle(color);
				ctx.setStrokeStyle(color)
				ctx.setLineJoin('round'); //交点设置成圆角
				ctx.setLineWidth(radius);
				ctx.strokeRect(x + radius / 2, y + radius / 2, width - radius, height - radius);
				ctx.fillRect(x + radius, y + radius, width - radius * 2, height - radius * 2);
				ctx.stroke();
				ctx.closePath();
			},
			downloadImage(url) { //绘制网络图片,网络图片需要先缓存到本地再绘制
				return new Promise((resolve, reject) => {
					uni.downloadFile({ // 还可以使用 uni.getImageInfo 方法
						url: url,
						success: (res) => {
							return resolve(res)
						},
						fail: (err) => {
							return reject(err)
						}
					})
				})
			},
			// 保存图片手机本地(二维码)
			saveImageToPhotosQrCode() {
				uni.showLoading({
					title: '二维码下载中'
				});
				const that = this;
				uni.downloadFile({
					url: that.qrCode, //二维码的地址
					success: function(res) {
						const tempFilePath = res.tempFilePath //通过res中的tempFilePath 得到需要下载的图片地址
						uni.saveImageToPhotosAlbum({
							filePath: tempFilePath,
							success: () => {
								uni.hideLoading();
								uni.showToast({
									title: '二维码已存入相册'
								});
							},
							fail: () => {
								uni.hideLoading();
								uni.showToast({
									title: '下载失败',
									icon: 'error'
								});
							},
							complete: () => {}
						});
					}
				})
			},
			// 保存海报
			saveImageToPhotosPoster() {
				uni.showLoading({
					title: '海报下载中...'
				});
				uni.canvasToTempFilePath({
					canvasId: 'posterid',
					success: function(res) {
						uni.saveImageToPhotosAlbum({
							filePath: res.tempFilePath,
							success(result) {
								uni.hideLoading()
								uni.showToast({
									title: '海报已存入相册',
									icon: 'success',
									duration: 2000
								})
							},
							fail: () => {
								uni.hideLoading()
							}
						})
					},
					complete(res) { //不管成功或者失败都会执行
						console.log('canvas转成图片结果', res)
					}
				}, this);
			},
			//保存海报和二维码
			saveImageToPhotosAlbumFun(flag) {
				if (flag === 100) {
					// 保存二维码
					this.saveImageToPhotosQrCode()
				} else {
					// 保存海报
					this.saveImageToPhotosPoster()
				}
			},
			//保存图片到相册
			savePoster(flag) {
				const that = this;
				// #ifdef MP-WEIXIN
				uni.getSetting({
					success: res => {
						if (res.authSetting['scope.writePhotosAlbum']) {
							that.saveImageToPhotosAlbumFun(flag)
						} else {
							uni.authorize({
								scope: 'scope.writePhotosAlbum',
								success: () => {
									that.saveImageToPhotosAlbumFun(flag)
								},
								fail: () => {
									uni.showModal({
										title: '提示',
										content: '请先在设置页面打开“保存相册”使用权限',
										confirmText: '去设置',
										cancelText: '算了',
										success: data => {
											if (data.confirm) {
												uni.openSetting();
											}
										}
									});
								},
								complete: res => {}
							});
						}
					}
				});
				// #endif
			}
		}
	}
</script>

<style lang="scss" scoped>
	// 边框样式
	button::after {
		border: 0;
	}

	.shareModel {
		width: 100%;
		background-color: #F5F5F5;
		color: #2D2D2D;

		.title {
			padding: 32rpx;
			text-align: center;
			font-size: 32rpx;
			font-weight: bold;
		}

		.share-container {
			margin: 0 80rpx 24rpx;
			padding: 32rpx;
			height: 100%;
			background: rgba(255, 255, 255, 0.39);
			box-shadow: 0 6rpx 20rpx rgba(110, 108, 108, 0.1);
			border-radius: 24rpx;

			.merchant-info {
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;

				.merchantName {
					margin-bottom: 48rpx;
					font-weight: bold;
					font-size: 32rpx;
				}

				.tip {
					padding: 24rpx 0 48rpx;
					color: #999999;
					font-size: 24rpx;
				}

				.store-img {
					padding: 20rpx;
					background-color: #F5F5F5;

					.img {
						width: 380rpx;
						height: 380rpx;
					}
				}
			}

			.user-info {
				display: flex;
				align-items: center;
				justify-content: space-between;

				.header-name {
					display: flex;
					align-items: center;

					text {
						margin-left: 12rpx;
					}
				}
			}
		}

		.share-bot {
			width: 100%;
			background: #FFFFFF;

			.share-btns {
				display: flex;
				justify-content: space-around;
				align-items: center;
				width: 100%;
				padding: 30rpx 0;

				.btns-list,
				.btns-share,
				.btns-box {
					display: flex;
					flex-direction: column;
					justify-content: center;
					align-items: center;
					background-color: #FFFFFF;

					text {
						color: #2D2D2D;
						font-size: 28rpx;
						margin-top: 8rpx;
					}
				}
			}
		}
	}
</style>

父组件使用

父组件引入
<share-model-canvas ref="poster" :storeInfo="merchantInfo"></share-model-canvas>

<script>
import ShareModelCanvas from './shareModel/share-canvas.vue'

 //显示绘制店铺海报
sharePoster() {
	// canvas操作
	this.$refs.poster.showCanvas()
}
</script>

效果图

Logo

前往低代码交流专区

更多推荐