uniapp 生成商品分享通用海报源码详解

本文详细介绍了如何使用uniapp框架创建一个商品分享的通用海报,包括使用canvas生成带有圆角的圆片图片、标题换行显示、兼容H5和小程序等关键步骤。同时展示了组件和海报生成的代码实现,涉及图片处理、文字换行、圆角矩形绘制等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uniapp 生成商品分享通用海报源码,使用canvas生成海报,圆片加圆角,标题换行显示两排 多余点点,兼容H5端和小程序端。

组件显示代码

<template>
		<view>
			<uni-popup ref="popup" type="center" class="poster-alert">
				<view class="poster"><image :src="poster" @longpress="saveImg"></image></view>
				<view class="hm row-center">
					<view class="item" @tap="shareWx">
						<button open-type="share" class="sharebtn">
							<image :src="util.ossimg('button-wechat.png')"></image>
						</button>
						<text>微信</text>
					</view>					
					<!-- #ifdef MP-WEIXIN -->
					<view class="item" @tap="saveImg">
						<view class="sharebtn"><image :src="util.ossimg('button-save.png')"></image></view>
						<text>保存图片</text>
					</view>
					<!-- #endif -->
				</view>			
		 </uni-popup>
	 </view>
</template>

<script>
	export default{
		name:'GoodsPoster', //商品分享海报	
		data(){
			return{
				poster:'',
			}
		},
		methods:{
			 show(){
				 this.$refs.popup.open();
			 },
			 close(){
				 this.$refs.popup.close();
			 },
			 //分享微信好友
			 shareWx(){
				 
			 },
			 //保存图片
			 async saveImg(){
				 // #ifdef MP-WEIXIN
				 let that = this;
				 let imginfo = await uni.getImageInfo({src: that.poster })
				 if(imginfo[1]){
					uni.saveImageToPhotosAlbum({filePath:imginfo[1].path,
						success() { that.tips.toast('保存成功') },
						fail(rej){  that.tips.toast('保存失败'); }
					})
				 }
				 // #endif				 
			 },
			 
		}		
	}
</script>

<style lang="scss" scoped>
	.poster-alert{ width:520rpx;
		.poster{ width:520rpx; height:832rpx; overflow: hidden; background:#fff; border-radius:16rpx;}
		.hm{ margin-top:60rpx; 
			.item{ text-align: center; margin:0 60rpx;
				.sharebtn{ background:none; border:0; padding:0; width:100rpx; height:100rpx; margin:0 auto; margin-bottom:12rpx;
					&:after{display:none;}
					image{ width:100rpx; height:100rpx; display:block; }					
				}
				text{ font-size:24rpx; color:#fff;}
			}
		}
	}	
</style>

 

海报生成代码

<template>
	<view>		
		<!--分享海报-->	
		<goods-poster ref="poster"></goods-poster>
		<canvas canvas-id="mycanvas" class="mycanvas"></canvas>	
	</view>
</template>

<script>
	import GoodsPoster from '@/components/Goods/GoodsPoster.vue'
	export default{
		components:{  GoodsPoster },
		data(){
			return{
			}
		},
		
		async onLoad() {
			 this.create();
		},		
		
		
		
		methods:{		

			//生成圆形填充图片
			//参数:ctx:canvas, img:图片, x:距离X, y:距离Y, r:半径
			circleImg(ctx, img, x, y, r) {
					ctx.save();
					var d =2 * r;
					var cx = x + r;
					var cy = y + r;
					ctx.arc(cx, cy, r, 0, 2 * Math.PI);
					ctx.clip();
					ctx.drawImage(img, x, y, d, d);
					ctx.restore();
			},

			//圆角矩形填充图片
			// 参数:ctx: canvas, img:图片地址, x:距离X,y:距离Y, width:宽, height:高,radius:圆角大小
			drawRoundRectPath(ctx, img, x, y, width, height, radius) {
					ctx.save();
					ctx.translate(x, y);
					ctx.beginPath(0);
					ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
					ctx.lineTo(radius, height);
					ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
					ctx.lineTo(0, radius);
					ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
					ctx.lineTo(width - radius, 0);
					ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
					ctx.lineTo(width, height - radius);
					ctx.closePath();
					ctx.clip();	
					ctx.drawImage(img,0,0,uni.upx2px(460),uni.upx2px(460));
					ctx.restore();
			},

			// 文字自动换行
			// 参数:ctx:canvas, content:文字, drawX:距离X, drawY:距离Y, lineHeight: 行高, lineMaxWidth最大宽度, lineNum: 行数
			textPrewrap(ctx, content, drawX, drawY, lineHeight, lineMaxWidth, lineNum) {
					var drawTxt = ''; // 当前绘制的内容
					var drawLine = 1; // 第几行开始绘制
					var drawIndex = 0; // 当前绘制内容的索引
					// 判断内容是否可以一行绘制完毕
					if(ctx.measureText(content).width <= lineMaxWidth){
						ctx.fillText(content, drawX, drawY);
					} else {
						for (var i = 0; i < content.length; i++) {
							drawTxt += content[i];
							if (ctx.measureText(drawTxt).width >= lineMaxWidth) {
								if (drawLine >= lineNum) {
									ctx.fillText(content.substring(drawIndex, i) + '..', drawX, drawY);
									break;
								} else {
									ctx.fillText(content.substring(drawIndex, i + 1), drawX, drawY);
									drawIndex = i + 1;
									drawLine += 1;
									drawY += lineHeight;
									drawTxt = '';
								}
							} else {
								// 内容绘制完毕,但是剩下的内容宽度不到lineMaxWidth
								if (i === content.length - 1) {
									ctx.fillText(content.substring(drawIndex), drawX, drawY);
								}
							}
						}
					}
				},		 
			 		
			 //获取图片信息
			 //微信:要下载远程图片到本地
			 //H5远程图片时要将图片生成base64位,这个可让后台帮生成base64位,前端生成始终有跨域问题头疼, 另一种是将图片放在static目录
			 async getimgInfo(path){
					// #ifdef MP-WEIXIN
						const info = await uni.downloadFile({url:path})				
						return info;
					// #endif					
					// #ifdef H5
						const info = [{},{tempFilePath:'/static/img/p.png'}]	
						return info;
					// #endif									
			 },

			 //生成海报
			 async create(){
				  uni.showLoading({title:'海报生成中...'})
				  let ctx  = uni.createCanvasContext('mycanvas',this);
					ctx.fillStyle = "#fff"
					ctx.fillRect(0,0,uni.upx2px(520),uni.upx2px(845))
				  //头像
					let head = "https://avatar.csdnimg.cn/8/C/D/0_u012015434.jpg";
				  let headurl = await this.getimgInfo(head);
							headurl = headurl[1].tempFilePath;
					this.circleImg(ctx,headurl,uni.upx2px(30),uni.upx2px(30),uni.upx2px(36))
					//姓名
					ctx.setFontSize(uni.upx2px(28))
					ctx.fillStyle = '#000';
					ctx.fillText("神夜大侠",uni.upx2px(115),uni.upx2px(55))
					//说明
					ctx.setFontSize(uni.upx2px(20))
					ctx.fillStyle = '#000';
					ctx.fillText("这件商品很棒,推荐给你看看",uni.upx2px(115),uni.upx2px(85))
					//logo
					let logo = "https://avatar.csdnimg.cn/8/C/D/0_u012015434.jpg";
					let logourl = await this.getimgInfo(logo);
							logourl = logourl[1].tempFilePath;
					ctx.drawImage(logourl,uni.upx2px(410),uni.upx2px(35),uni.upx2px(80),uni.upx2px(40))
					//商品图
					let img = "https://avatar.csdnimg.cn/8/C/D/0_u012015434.jpg";
					let imgurl = await this.getimgInfo(img);
							imgurl = imgurl[1].tempFilePath;
					this.drawRoundRectPath(ctx,imgurl,uni.upx2px(30),uni.upx2px(120),uni.upx2px(460),uni.upx2px(460),uni.upx2px(16));	
					//商品标题
					ctx.setFontSize(uni.upx2px(24))
					ctx.fillStyle = '#333';
					this.textPrewrap(ctx,"这是商品标题名称商品标题名称",uni.upx2px(30),uni.upx2px(670),uni.upx2px(36),uni.upx2px(250),2);
					//价格
					ctx.setFontSize(uni.upx2px(22))
					ctx.fillStyle = this.config.webColor;
					ctx.fillText("¥",uni.upx2px(30),uni.upx2px(760))
					ctx.setFontSize(uni.upx2px(36))
					ctx.fillStyle = this.config.webColor;
					ctx.fillText("58.00",uni.upx2px(50),uni.upx2px(760))
					//二维码
					let ewm = 'https://avatar.csdnimg.cn/8/C/D/0_u012015434.jpg';
					let ewmurl = await this.getimgInfo(ewm);
							ewmurl = ewmurl[1].tempFilePath;
					ctx.drawImage(ewmurl,uni.upx2px(339),uni.upx2px(620),uni.upx2px(150),uni.upx2px(150))
					//扫码购买
					ctx.setFontSize(uni.upx2px(20))
					ctx.fillStyle = "#333";
					ctx.fillText("-扫码购买商品-",uni.upx2px(347),uni.upx2px(800))										
					ctx.draw();
					setTimeout(()=>{
						uni.canvasToTempFilePath({
							canvasId:'mycanvas',
							success:res=>{
								this.$refs.poster.poster = res.tempFilePath;
								this.$refs.poster.show();
								uni.hideLoading();
							},
							fail:err=>{
								this.tips.toast('海报生成失败')
								uni.hideLoading();
							}
						})
					},500)			 
			 },	 
		}
	}
</script>

<style lang="scss" scoped>	
	.mycanvas{ width:520rpx; height:845rpx; background:#fff; position: fixed; bottom:1000px;  border-radius:16rpx;}
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值