绘制海报并保存图片到手机相册 v3 uniapp

<template>
	<view class="all">
		<view class="statusBar">
			<view class="top" :style="{marginTop:navTop,height:navHeight}">
				<image :src="$baseImg('title_mywh@2x@1x.png')" mode="heightFix" />
			</view>

		</view>
		<view class="content">
			<view class="title">
				选择图片上传
			</view>
			<!-- <view class="chose">
	
			<view class="weather" :class="{ active: activeGender === '1' }" @click="activeGender = '1'">
				天气
			</view>
			<view class="sunshirle" :class="{ active: activeGender === '2' }" @click="activeGender = '2'">
				心情
			</view>
			<view class="num">
				共计{{imgdata.list.length}}/张图片
			</view>
		</view> -->
			<view class="scbox">
				<scroll-view :scroll-top="scrollTop" scroll-y="true" class="scroll-Y" scroll-top='right'>
					<view class="imgbox">
						<view class="imgitem" v-for="(item, index) in imgdata.list" :key="index">
							<image class="imgs" :src="item.picurl" mode="" @click="toggleChosenStatus(item,index)">
							</image>

							<image class="raiod" v-if="on==index" src="../static/images/okimg.png" mode=""></image>
						</view>
					</view>
				</scroll-view>
			</view>
			<view class="box">
				<view class="title">
					想说点什么.....
				</view>
				<view class="select" @click="open">
					<view class="ll">
						{{duanju}}
					</view>
					<view class="rr">
						<uv-icon name="arrow-down" v-if="!down" color="#fff" size="15" @click="downopen"></uv-icon>
						<uv-icon name="arrow-up" v-if="down" color="#fff" size="15" @click="downopen"></uv-icon>
					</view>
				</view>
			</view>
			<!-- <view class="rawplacard" @click="rawplacard"> -->
			<view class="rawplacard" @click="chaxunstatus">
				生成海报
			</view>
		</view>
		<uv-picker ref="picker" keyName='intro' :columns="columns.list" @confirm="confirm" @cancel='cancel'></uv-picker>
		<uv-popup ref="popup" bgColor='' :closeOnClickOverlay='false' overlayOpacity='0.9' :closeable='true'
			:safeAreaInsetBottom="false" @change='changepopup'>
			<view @click="signtop" class="popupbox">
				<!-- <img class='signtopImgus' src="https://fakeimg.pl/400x200/3c9cff/fff" alt=""> -->
				<canvas canvas-id="myCanvas" style="width: 700rpx; height: 1200rpx;"></canvas>
				<view class="confimbopx" @click="baocun"
					style="color: #fff;width: 600rpx;text-align: center;height: 80rpx;line-height: 80rpx;border-radius: 80rpx;background-color: red;margin: 30rpx auto 0;">
					保存海报
				</view>
			</view>

		</uv-popup>
		<!-- <uv-picker ref="picker" :columns="columns.list" @confirm="confirm" @cancel='cancel'></uv-picker> -->
		<Tabbar class="tabbar" :current="'1'"></Tabbar>
		<complaintButton ref="openmodel"></complaintButton>
	</view>
</template>

<script setup>
	import Tabbar from '@/components/tabbar.vue'
	import complaintButton from '@/components/complaintButton.vue'
	import {
		ref,
		reactive,
		getCurrentInstance
	} from 'vue'
	import {
		onReady,
		onShow,
		onShareAppMessage,
		onShareTimeline
	} from '@dcloudio/uni-app'
	import {
		baseUrl
	} from '@/common';
	const globalProperties = getCurrentInstance().appContext.config.globalProperties;
	const {
		proxy
	} = getCurrentInstance();
	let keywords = ref('')
	let activeGender = ref('1')
	let radioactiveGender = ref('0')
	let scrollTop = ref('0')
	let on = ref(0)
	let onid = ref(0)
	let imgurl = ref('')
	let ischose = ref(false)
	let navHeight = ref('')
	let columns = reactive({
		list: []
	})
	let duanju = ref('选择一段话生成专属海报')
	let duanjuid = ref('')
	let down = ref(false)
	let navTop = ref('')
	const imgdata = reactive({
		list: []
	})
	let isposter = ref('')
	async function getstatus(page = 1) {
		const res = await globalProperties.$api.index({
			page
		});
		console.log(res, 'rrrrrrrr');
		if (res.data.code == 200) {
			isposter = res.data.data.is_poster
			console.log(isposter, 'isposter');
		} else {
			uni.showToast({
				title: res.data.message,
				mask: true,
				icon: 'none'
			})
		}
	}
	async function chaxunstatus(page = 1) {
		if (duanju.value == '选择一段话生成专属海报') {
			return uni.showToast({
				title: '请选择一段话生成海报',
				icon: 'none',
				duration: 1500
			})
		}
		const res = await globalProperties.$api.index({
			page
		});
		console.log(res, 'rrrrrrrr');
		if (res.data.code == 200) {
			isposter = res.data.data.is_poster
			console.log(isposter, 'isposterisposterisposter');
			if (isposter == 0) {
				//可以生成
				console.log('isposternow 状态为', isposter);
				rawplacard()
			} else {
				console.log('机会用尽', isposter);
				//机会用尽 观看广告 挣点元子
				setguanggaomodel()
			}
			console.log(isposter, 'isposter');
		} else {
			uni.showToast({
				title: res.data.message,
				mask: true,
				icon: 'none'
			})
		}
	}

	function setguanggaomodel() {
		console.log('进入');
		uni.showModal({
			title: '请确认',
			content: '再次生成需观看广告',
			success: function(res) {
				if (res.confirm) {
					// 在页面中定义激励视频广告
					let videoAd = null
					// 在页面onLoad回调事件中创建激励视频广告实例
					if (wx.createRewardedVideoAd) {
						videoAd = wx.createRewardedVideoAd({
							adUnitId: 'adunit-16701892963b685f'
						})
						videoAd.onLoad(() => {})
						const isEnded = false
						if (!isEnded) {
							// 用户触发广告后,显示激励视频广告
							if (videoAd) {
								videoAd.show().catch(() => {
									// 失败重试
									videoAd.load()
										.then(() => videoAd.show())
										.catch(err => {
											console.log('激励视频 广告显示失败')
										})
								})
							}
						}
						// 激励广告播放异常回调函数
						videoAd.onError((err) => {})
						// 关闭激励广告回调函数方法
						videoAd.onClose((res) => {
							// isEnded = true 则为观看完整激励广告
							if (res && res.isEnded) {
								//去生成
								rawplacard()
								isEnded = res.isEnded
							} else {
								uni.showToast({
									title: '抱歉!您观看视频中途退出无法获取奖励',
									icon: 'none',
									duration: 1500
								})
							}
						})
					}

				} else if (res.cancel) {
					console.log('用户点击取消');
				}
			}
		});
	}

	function baocun() {
		uni.canvasToTempFilePath({
			canvasId: 'myCanvas',
			width: 350,
			height: 600,
			success(res) {
				var path = res.tempFilePath
				// 获取用户是否开启用户授权相册
				wx.getSetting({
					success(res) {
						// 如果没有则获取授权
						if (!res.authSetting['scope.writePhotosAlbum']) {
							wx.authorize({
								scope: 'scope.writePhotosAlbum',
								success() {
									wx.saveImageToPhotosAlbum({
										filePath: path,
										success() {
											uni.showToast({
												title: '保存成功',
												icon: 'success'
											});
											proxy.$refs.picker.close();
										},
										fail() {
											uni.showToast({
												title: '保存失败',
												icon: 'none'
											});
											proxy.$refs.picker.close();
										}
									})
								},
								fail() {
									wx.showModal({
										title: '提示',
										content: '若点击不授权,将无法使用保存图片功能',
										cancelText: '不授权',
										cancelColor: '#999',
										confirmText: '授权',
										confirmColor: '#f94218',
										success(res) {
											if (res.confirm) {
												wx.openSetting({
													success(res) {
														console.log(res
															.authSetting)
													}
												})
											} else if (res.cancel) {
												console.log('用户点击取消')
											}
										}
									})
								}
							})
						} else {
							// 有则直接保存
							wx.saveImageToPhotosAlbum({
								filePath: path,
								success() {
									uni.showToast({
										title: '保存成功',
										icon: 'success'
									});
									proxy.$refs.picker.close();
								},
								fail() {
									uni.showToast({
										title: '保存失败',
										icon: 'none'
									});
									proxy.$refs.picker.close();
								}
							})
						}
					}
				})
				// console.log(res, '[[[[]]]]');
				// uni.saveImageToPhotosAlbum({
				// 	filePath: res.tempFilePath,
				// 	success() {
				// 		uni.showToast({
				// 			title: '保存成功',
				// 			icon: 'success'
				// 		});
				// 		proxy.$refs.picker.close();
				// 	},
				// 	fail() {
				// 		uni.showToast({
				// 			title: '保存失败',
				// 			icon: 'none'
				// 		});
				// 		proxy.$refs.picker.close();
				// 	}
				// });
			},
			fail(err) {
				console.error(err);
			}
		}, this);
	}

	function rawplacard() {
		if (onid.value == 0) {
			imgurl = imgdata.list[0].picurl
			onid.value = imgdata.list[0].id
		}
		uni.getImageInfo({
			src: imgurl,
			success: (res) => {
				console.log(res, 'res');

				console.log(res, 'getImageInfoerr 返回成功');
				const baseUrl = 'https://mywenhua.cn/interfaces/';
				var imageSrc = res.path //将图片的地址赋值给imageSrc
				uni.uploadFile({ //上传图片
					url: baseUrl + 'Index/upload',
					filePath: imageSrc,
					fileType: 'image',
					name: 'file',
					success: (res) => { //接口调用成功的回调函数
						const img = JSON.parse(res.data)
						const avatar = img.data
						imgurl = avatar
						drawPoster();
					},
					fail: (err) => { //接口调用失败的回调函数	
						console.log('失败返回:', err);
						uni.showModal({ //消息提示框
							content: err.errMsg, //错误信息
							showCancel: false
						});
					}
				});

			},
			fail: (err) => {
				console.error(err, 'getImageInfoerr');
			}
		});

		//
	}

	function drawWrappedText(ctx, text, x, y, maxWidth, lineHeight) {
		var words = text.split(' ');
		var line = '';
		var lines = [];

		words.forEach(function(word) {
			var testLine = line + word + ' ';
			var metrics = ctx.measureText(testLine);
			var testWidth = metrics.width;
			if (testWidth > maxWidth && line.length > 0) {
				lines.push(line);
				line = word + ' ';
			} else {
				line = testLine;
			}
		});
		lines.push(line);

		lines.forEach(function(line, index) {
			ctx.fillText(line, x, y + (index + 1) * lineHeight);
		});
	}

	function drawPoster() {
		const ctx = uni.createCanvasContext('myCanvas', this);
		ctx.width = 375
		ctx.height = 600
		// 绘制图片
		uni.showLoading({
			title: '海报生成中...'
		})
		uni.getImageInfo({
			src: imgurl,
			success: (res) => {
				console.log(res.path, '3所选绘制图片');
				ctx.drawImage(res.path, 0, 0, 375, 600);
				console.log(res.path, '2所选绘制图片');
				// 定义字符串
				// var duanju = "这是一个很长的段落,我们需要在 Canvas 中自动换行显示。这是一个很长的段落,我们需要在 Canvas 中自动换行显示。这是一个很长的段落,我们需要在 Canvas 中自动换行显示。";
				console.log(duanju, '所选文字');
				// 绘制文字
				ctx.setFontSize(15);
				ctx.setFillStyle('#000000');
				ctx.setTextAlign('left');
				var maxWidth = 230; // 最大宽度为 340,可以根据需要调整
				var lineHeight = 15; // 行高为 20,可以根据需要调整
				var words = duanju.split('');
				var line = '';
				var y = 510; // 初始化Y坐标
				console.log(' 初始化Y坐标');
				words.forEach(function(word) {
					console.log(words, ' forEachwords');
					var testLine = line + word + ' ';
					var metrics = ctx.measureText(testLine);
					var testWidth = metrics.width;
					if (testWidth > maxWidth && line.length > 0) {
						ctx.fillText(line, 120, y); // 绘制每行文字
						line = word + ' ';
						y += lineHeight; // 调整Y坐标,进行换行
					} else {
						line = testLine;
					}
				});
				console.log(' forEach结束');
				ctx.fillText(line, 120, y); // 绘制最后一行文字

				// 绘制图片
				ctx.drawImage('../../static/images/ewm.jpg', 10, 490, 100, 100);
				uni.hideLoading()
				console.log('隐藏');
				ctx.draw(true, (() => {

					console.log('ctx.araw');
					upjilu()
					proxy.$refs.popup.open();
					console.log(' z执行结束结束');
				})())

				// ctx.draw(true, (() => {

				// }));
				console.log('隐藏结束');
			},
			fail: (err) => {
				uni.hideLoading()
				console.error(err, 'getImageInfoerr');
			}
		});

	}

	function changepopup(e) {
		if (e.show == false) {
			console.log(e);
			console.log('falses');
			getstatus()
		}
	}
	// function drawPoster() {
	// 	const ctx = uni.createCanvasContext('myCanvas', this);

	// 	// 绘制图片
	// 	ctx.drawImage(imgurl, 0, 0, 350, 650);

	// 	// 绘制文字
	// 	ctx.setFontSize(18);
	// 	ctx.setFillStyle('#000000');
	// 	ctx.setTextAlign('left');
	// 	console.log(duanju);
	// 	var gradient = ctx.createLinearGradient(0, 0, 100, 0);
	// 	gradient.addColorStop("0", "magenta")
	// 	gradient.addColorStop("0.5", "blue")
	// 	gradient.addColorStop("1.0", "red")
	// 	ctx.fillStyle = gradient;
	// 	ctx.fillText(duanju, 0, 470);

	// 	// 绘制图片
	// 	ctx.drawImage('../../static/images/ewm.jpg', 10, 490, 100, 100);

	// 	ctx.draw(false, () => {
	// 		proxy.$refs.popup.open();
	// 		uni.hideLoading();
	// 	});
	// }

	function cancel(e) {
		down.value = !down.value
		console.log('cancel', e);
		proxy.$refs.picker.close();
	}

	function confirm(e) {
		down.value = !down.value
		console.log('confirm', e);
		duanju = e.value[0].intro
		duanjuid = e.value[0].id
		proxy.$refs.picker.close();
	}

	function open() {
		proxy.$refs.picker.open();
		down.value = !down.value
	}

	function downopen() {
		down.value = !down.value
		if (down.value) {
			console.log('打开');
			proxy.$refs.picker.open();
		} else {
			console.log('关闭');

		}
	}

	function toggleChosenStatus(item, index) {
		on.value = index
		onid.value = imgdata.list[index].id
		imgurl = imgdata.list[index].picurl
		console.log(onid, 'onid');
		console.log(index, 'idnex');
		console.log(imgurl, 'imgurl');
	}

	onShareAppMessage((res) => {
		console.log(4444);
		if (res.from === 'button') { // 来自页面内分享按钮
			const user = uni.getStorageSync('user')
			console.log(user.id, 'user.id');
			if (user.id) {
				console.log('有id');
				return {
					title: shareinfo.title,
					imageUrl: shareinfo.picurl,
					path: "/pages/tab/index?uid=" + user.id
				};
			} else {
				console.log('没有id');
				return {
					title: shareinfo.title,
					imageUrl: shareinfo.picurl,
					path: "/pages/tab/index"
				};
			}

		} else {
			const user = uni.getStorageSync('user')
			console.log(user.id, 'user.id');
			if (user.id) {
				console.log('有id三点');
				return {
					title: shareinfo.title,
					imageUrl: shareinfo.picurl,
					path: "/pages/tab/index?uid=" + user.id
				};
			} else {
				console.log('没有id三点');
				return {
					title: shareinfo.title,
					imageUrl: shareinfo.picurl,
					path: "/pages/tab/index"
				};
			}
		}

	})
	async function getfenxiang() {
		const data = await globalProperties.$api.swichview({
			id: 7
		})
		shareinfo = data.data.data

	}
	async function getxuanchuan() {
		const data = await globalProperties.$api.swichview({
			id: 8
		})
		xuanchuan = data.data.data

	}
	async function getswich() {
		const data = await globalProperties.$api.swichviewbox()
		swich.value = data.data.data
	}

	function goMsg() {
		uni.navigateTo({
			url: '/indexOperate/messageCenter'
		})
	}

	function goVideoDetails(id) {
		uni.navigateTo({
			url: '/user/video?id=' + id
		})
	}
	async function getList(page = 1, keywords = '') {
		const res = await globalProperties.$api.listView({
			page,
			keywords,
		});
		console.log(res, '返回')
		if (res.data.code == 200) {
			state.list = res.data.data.data
		} else {
			uni.showToast({
				title: res.data.message,
				mask: true,
				icon: 'none'
			})
		}
	}

	async function gethbimglist() {
		const data = await globalProperties.$api.gethbimg()
		imgdata.list = data.data.data
	}

	async function getpicker() {
		const data = await globalProperties.$api.getduanju()
		columns.list = [data.data.data]
		console.log(columns.list, '-------------------');
	}
	async function upjilu() {
		console.log('up记录接口');
		const params = {
			pid: onid.value,
			tid: duanjuid
		}
		console.log(params, 'params');
		const data = await globalProperties.$api.posterjl(params)
		console.log(data, '返回');
	}

	function goSearch() {
		getList(page.value, keywords.value)
	}
	async function getlogin() {
		const res = await globalProperties.$api.MemberIndex();
		console.log(res, '返回')
		if (res.data.code == 200) {

		} else if (res.data.code == 401) {
			uni.showToast({
				title: '请先登录',
				mask: true,
				icon: 'none'
			})
			setTimeout(function() {
				//登录页
				uni.navigateTo({
					url: '/user/login'
				})
			}, 1200);

		} else {
			uni.showToast({
				title: res.data.message,
				mask: true,
				icon: 'none'
			})
		}
	}
	onShow(() => {
		wx.onUserCaptureScreen(function() {
			openmodel.value.open();
		})
		navTop.value = wx.getMenuButtonBoundingClientRect().top + 'px'
		navHeight.value = wx.getMenuButtonBoundingClientRect().height + 'px'
		uni.createSelectorQuery().select('.search').boundingClientRect(function(rect) {
			console.log(rect, '顶部search')
			gethbimglist()
			getpicker()
			getlogin()
			getstatus()
			uni.createSelectorQuery().select('.top').boundingClientRect(function(rect1) {
				console.log(rect1, '顶部top')
				top.value = rect.top + rect.height + rect1.top + rect1.height + 28 + 'px'
				getList(page.value, keywords.value)
			}).exec();
		}).exec();
	})
</script>

<style lang="less" scoped>
	.all {
		display: flex;
		flex-direction: column;
		// align-items: center;
		background: #f7f7f7;
		min-height: 100vh;

		.statusBar {
			width: 100%;
			height: auto;
			background: #ED422B;
			background-size: 100% 100%;

			.top {
				display: flex;
				padding-left: 27rpx;
				align-items: center;

				image {
					height: 33rpx;
				}
			}

			.search {
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: 16rpx 28rpx 28rpx;
				box-sizing: border-box;
				width: 100%;

				image {
					height: 69rpx;
				}
			}
		}

		.content {
			background-color: #fff;
			width: 710rpx;
			margin: 0rpx auto 0;
			padding: 0 20rpx;
			min-height: 100vh;

			.title {
				margin: 20rpx 0;
				font-size: 30rpx;
				color: #383838;
				font-weight: 500;
				padding: 0 30rpx;
			}

			.chose {
				height: 80rpx;
				// widt0%;
				padding: 0 30rpx;
				display: flex;
				// flex-direction: c;
				flex-wrap: nowrap;
				align-items: center;

				.weather {
					display: flex;
					justify-content: center;
					align-items: center;
					border: 2rpx solid #ccc;
					width: 130rpx;
					height: 60rpx;
					font-weight: 400;
					border-radius: 10rpx;
					font-size: 26rpx;
					color: #333;
					text-align: center;
					margin-right: 10rpx;
				}

				.sunshirle {
					margin-left: 10rpx;
					display: flex;
					justify-content: center;
					align-items: center;
					border: 2rpx solid #ccc;
					width: 130rpx;
					height: 60rpx;
					font-weight: 400;
					border-radius: 10rpx;
					font-size: 26rpx;
					color: #333;
					text-align: center;
				}

				.active {
					background-color: #ed422b;
					color: #fff;
				}

				.num {
					margin-left: 150rpx;
				}
			}

			.scbox {
				border-radius: 30rpx;
				margin: 20rpx auto 0;
				box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 50px -12px inset, rgba(0, 0, 0, 0.3) 0px 18px 26px -18px inset;

				.scroll-Y {
					height: 900rpx
				}

				overflow: hidden;

				.imgbox {
					width: 700rpx;
					height: 900rpx;
					margin: 10rpx auto 0;
					display: flex;
					flex-direction: row;
					flex-wrap: wrap;

					.imgitem {
						width: 46%;
						position: relative;
						margin: 5rpx 10rpx 10rpx;

						.imgs {

							border-radius: 20rpx;
							width: 320rpx;
							height: 500rpx;
						}

						.raiod {
							position: absolute;
							top: 0rpx;
							right: 0rpx;
							width: 30rpx;
							z-index: 999;
							height: 30rpx;
						}

						.raiodactive {}
					}
				}

			}

			.box {
				margin-top: 30rpx;
				width: 710rpx;
				height: 180rpx;
				background: #fff;
				box-shadow: 20px 20px 60px #bebebe,
					-20px -20px 60px #ffffff;
				display: flex;
				border-radius: 20rpx;
				flex-direction: column;

				.title {
					height: 40rpx;
					font-size: 30rpx;
					font-weight: normal;
					color: #333;
				}

				.select {
					width: 700rpx;
					background-color: #ed422b;
					// min-height: 60rpx;
					// padding-left: 10rpx;
					padding: 10rpx 0 10rpx 10rpx;
					// height: 80rpx;
					border-radius: 20rpx;
					display: flex;
					justify-content: space-between;
					align-items: center;

					.ll {
						text-align: left;
						line-height: 40rpx;
						color: #fff;
						overflow: hidden;
					}

					.rr {
						padding-right: 10rpx;
					}
				}
			}

			.popupbox {
				background-color: transparent;
				width: 700rpx;
				height: 1500rpx;
				border-radius: 20rpx;
				// display: flex;
				// justify-content: center;
				// flex-direction: column;

				// align-items: center;
			}

			.confimbopx {
				width: 300rpx;
				height: 80rpx;
				border-radius: 80rpx;
				background-color: #e21918;
				color: #fff;
				line-height: 80rpx;
				text-align: center;
			}

			.rawplacard {
				margin: 60rpx auto 0;
				width: 200rpx;
				height: 80rpx;
				background-color: #ed422b !important;
				line-height: 80rpx;
				text-align: center;
				color: #fff;
				font-size: 30rpx;
				border-radius: 80rpx;
			}
		}



		.tabbar {
			position: fixed;
			width: 100%;
			left: 0;
			bottom: 0;
		}
	}
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值