فهرست منبع

新增分享盲票海报组件

hwb0 3 سال پیش
والد
کامیت
ab0063a300
1فایلهای تغییر یافته به همراه407 افزوده شده و 0 حذف شده
  1. 407 0
      components/share-code/share-code.vue

+ 407 - 0
components/share-code/share-code.vue

@@ -0,0 +1,407 @@
+<!--
+ * @Description: 生成图片组件
+ * @Version: 1.0.0
+ * @Autor: hch
+ * @Date: 2020-08-07 14:48:41
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2021-07-31 18:11:35
+ * 保存图片按钮和关闭按钮 在html代码中写出来 绑定点击方法然后透明 再用canvas 覆盖
+-->
+
+<template>
+	<view class="canvas-content" v-show="canvasShow" :style="'width:' + system.w + 'px; height:' + system.h + 'px;'">
+		<!-- 遮罩层 -->
+		<view class="canvas-mask"></view>
+		<!-- 图片 -->
+		<!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 -->
+		<canvas class="canvas" canvas-id="myCanvas" id="myCanvas"
+			:style="'width:' + system.w + 'px; height:' + system.h + 'px;'" :width="system.w"
+			:height="system.h"></canvas>
+		<view class="button-wrapper">
+			<!-- 保存图片按钮 -->
+			<!-- #ifndef MP-QQ -->
+			<!-- cover-view 标签qq小程序有问题 -->
+			<cover-view class="save-btn" @tap="handleSaveCanvasImage">保存</cover-view>
+			<cover-view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</cover-view>
+			<!-- #endif -->
+			<!-- #ifdef MP-QQ -->
+			<view class="save-btn" @tap="handleSaveCanvasImage">保存</view>
+			<view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</view>
+			<!-- #endif -->
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		drawSquarePic,
+		drawTextReturnH,
+		getSystem
+	} from './utils'
+	export default {
+		data() {
+			return {
+				system: {},
+				canvasShow: false
+			}
+		},
+		props: {
+			posterData: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			}
+		},
+		computed: {
+			/**
+			 * @description: 计算图片背景数据
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			poster() {
+				let data = this.posterData
+				let system = this.system
+				let posterBg = {
+					url: data.poster.url,
+					r: data.poster.r * system.scale,
+					w: data.poster.w * system.scale,
+					h: data.poster.h * system.scale,
+					x: (system.w - data.poster.w * system.scale) / 2,
+					y: (system.h - data.poster.h * system.scale) / 2,
+					p: data.poster.p * system.scale
+				}
+				return posterBg
+			},
+			/**
+			 * @description: 计算图片头部主图
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			mainImg() {
+				let data = this.posterData
+				let system = this.system
+				let posterMain = {
+					url: data.mainImg.url,
+					r: data.mainImg.r * system.scale,
+					w: data.mainImg.w * system.scale,
+					h: data.mainImg.h * system.scale,
+					x: (system.w - data.mainImg.w * system.scale) / 2,
+					y: this.poster.y + data.poster.p + data.mainImg.mt * system.scale
+				}
+				return posterMain
+			},
+			/**
+			 * @description: 计算图片标题
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			title() {
+				let data = this.posterData
+				let system = this.system
+				let posterTitle = data.title
+				posterTitle.x = this.mainImg.x
+				posterTitle.y = this.mainImg.y + this.mainImg.h + data.title.mt * system.scale
+				return posterTitle
+			},
+			/**
+			 * @description: 计算小程序码
+			 * @param {*}
+			 * @return {*}
+			 * @author: hch
+			 */
+			codeImg() {
+				let data = this.posterData
+				let system = this.system
+				let posterCode = {
+					url: data.codeImg.url,
+					r: data.codeImg.r * system.scale,
+					w: data.codeImg.w * system.scale,
+					h: data.codeImg.h * system.scale,
+					x: (system.w - data.codeImg.w * system.scale) / 2,
+					y: data.codeImg.mt * system.scale //y需要加上绘图后文本的y
+				}
+				return posterCode
+			}
+		},
+		created() {
+			// 获取设备信息
+			this.system = getSystem()
+		},
+		methods: {
+			/**
+			 * @description: 展示图片
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			posterShow() {
+				this.canvasShow = true
+				this.creatPoster()
+			},
+			/**
+			 * @description: 生成图片
+			 * @author: hch
+			 */
+			async creatPoster() {
+				uni.showLoading({
+					title: '生成海报中...'
+				})
+				const ctx = uni.createCanvasContext('myCanvas', this)
+				this.ctx = ctx
+				ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的图片
+				ctx.draw() //清空之前的图片
+				// 根据设备屏幕大小和距离屏幕上下左右距离,及圆角绘制背景
+				let poster = this.poster
+				let mainImg = this.mainImg
+				let codeImg = this.codeImg
+				let title = this.title
+				await drawSquarePic(ctx, poster.x, poster.y, poster.w, poster.h, poster.r, poster.url)
+				await drawSquarePic(ctx, mainImg.x, mainImg.y, mainImg.w, mainImg.h, mainImg.r, mainImg.url)
+				// 绘制标题 textY 绘制文本的y位置
+				// console.log('creatPoster -> title.x', title.x)
+				let textY = drawTextReturnH(
+					ctx,
+					title.text,
+					title.x,
+					title.y,
+					title.w,
+					title.fontSize,
+					title.color,
+					title.lineHeight,
+					title.align
+				)
+				// 绘制小程序码
+				await drawSquarePic(
+					ctx,
+					codeImg.x,
+					codeImg.y + textY,
+					codeImg.w,
+					codeImg.h,
+					codeImg.r,
+					codeImg.url
+				)
+				// 小程序的名称
+				// 长按/扫描识别查看商品
+				let y = 0
+				this.posterData.tips.forEach((element, i) => {
+					if (i == 0) {
+						y = codeImg.y + textY + element.mt + codeImg.h
+					} else {
+						y += element.mt
+					}
+					y = drawTextReturnH(
+						ctx,
+						element.text,
+						title.x,
+						y,
+						mainImg.w,
+						element.fontSize,
+						element.color,
+						element.lineHeight,
+						element.align
+					)
+				})
+				uni.hideLoading()
+			},
+			/**
+			 * @description: 保存到系统相册
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			handleSaveCanvasImage() {
+				uni.showLoading({
+					title: '保存中...'
+				})
+				let _this = this
+				// 把画布转化成临时文件
+				// #ifndef MP-ALIPAY
+				// 支付宝小程序外,其他都是用这个方法 canvasToTempFilePath
+				uni.canvasToTempFilePath({
+						x: this.poster.x,
+						y: this.poster.y,
+						width: this.poster.w, // 画布的宽
+						height: this.poster.h, // 画布的高
+						destWidth: this.poster.w * 5,
+						destHeight: this.poster.h * 5,
+						canvasId: 'myCanvas',
+						success(res) {
+							//保存图片至相册
+							// #ifndef H5
+							// 除了h5以外的其他端
+							uni.saveImageToPhotosAlbum({
+								filePath: res.tempFilePath,
+								success(res) {
+									uni.hideLoading()
+									uni.showToast({
+										title: '海报保存成功,可以去分享啦~',
+										duration: 2000,
+										icon: 'none'
+									})
+									_this.handleCanvasCancel()
+								},
+								fail() {
+									uni.showToast({
+										title: '保存失败,稍后再试',
+										duration: 2000,
+										icon: 'none'
+									})
+									uni.hideLoading()
+								}
+							})
+							// #endif
+
+							// #ifdef H5
+							// h5的时候
+							uni.showToast({
+								title: '请长按保存',
+								duration: 3000,
+								icon: 'none'
+							})
+							_this.handleCanvasCancel()
+							_this.$emit('previewImage', res.tempFilePath)
+							// #endif
+						},
+						fail(res) {
+							// console.log('fail -> res', res)
+							uni.showToast({
+								title: '保存失败,稍后再试',
+								duration: 2000,
+								icon: 'none'
+							})
+							uni.hideLoading()
+						}
+					},
+					this
+				)
+				// #endif
+				// #ifdef MP-ALIPAY
+				// 支付宝小程序条件下 toTempFilePath
+				this.ctx.toTempFilePath({
+						x: this.poster.x,
+						y: this.poster.y,
+						width: this.poster.w, // 画布的宽
+						height: this.poster.h, // 画布的高
+						destWidth: this.poster.w * 5,
+						destHeight: this.poster.h * 5,
+						success(res) {
+							//保存图片至相册
+							my.saveImage({
+								url: res.apFilePath,
+								showActionSheet: true,
+								success(res) {
+									uni.hideLoading()
+									uni.showToast({
+										title: '图片保存成功,可以去分享啦~',
+										duration: 2000,
+										icon: 'none'
+									})
+									_this.handleCanvasCancel()
+								},
+								fail() {
+									uni.showToast({
+										title: '保存失败,稍后再试',
+										duration: 2000,
+										icon: 'none'
+									})
+									uni.hideLoading()
+								}
+							})
+						},
+						fail(res) {
+							// console.log('fail -> res', res)
+							uni.showToast({
+								title: '保存失败,稍后再试',
+								duration: 2000,
+								icon: 'none'
+							})
+							uni.hideLoading()
+						}
+					},
+					this
+				)
+				// #endif
+			},
+			/**
+			 * @description: 取消图片
+			 * @param {type}
+			 * @return {type}
+			 * @author: hch
+			 */
+			handleCanvasCancel() {
+				this.canvasShow = false
+				this.$emit('cancel', true)
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.content {
+		height: 100%;
+		text-align: center;
+	}
+
+	.canvas-content {
+		position: absolute;
+		top: 0;
+
+		.canvas-mask {
+			position: fixed;
+			top: 0;
+			right: 0;
+			bottom: 0;
+			left: 0;
+			z-index: 9;
+			width: 100%;
+			height: 100%;
+			background: rgba(0, 0, 0, 0.5);
+		}
+
+		.canvas {
+			z-index: 10;
+		}
+
+		.button-wrapper {
+			position: fixed;
+			bottom: 80rpx;
+			z-index: 16;
+			display: flex;
+			width: 100%;
+			height: 72rpx;
+			justify-content: space-around;
+		}
+
+		.save-btn {
+			z-index: 16;
+			width: 40%;
+			height: 100%;
+			font-size: 30rpx;
+			line-height: 72rpx;
+			color: #fff;
+			text-align: center;
+			background: $uni-btn-color;
+			border-radius: 45rpx;
+			border-radius: 36rpx;
+		}
+
+		.cancel-btn {
+			color: $uni-btn-color;
+			background: #fff;
+		}
+
+		.canvas-close-btn {
+			position: fixed;
+			top: 30rpx;
+			right: 0;
+			z-index: 12;
+			width: 60rpx;
+			height: 60rpx;
+			padding: 20rpx;
+		}
+	}
+</style>