使用canvas绘制海报

想要绘制这样的海报

1.结构

<!-- 生成海报的canvas -->
<view class="my-canvas-box" @touchmove.stop.prevent :class="posterInfo.status ? 'show' : 'hide'" @click="posterInfo.status = false">
	<canvas class="my-canvas" canvas-id="mycanvas" :style="{ width: canvasW + 'px', height: canvasH + 'px' }"></canvas>
	<button class="btn" @tap="save" >保存图片</button>
</view>

//对于微信公众号,可以使用html2canvas将html转成图片然后设置一个图片蒙层,src是转成的图片地址。然后长按保存

	<uni-popup ref="poster" type="center" v-if="isweixin">
		<view class="poster-pop">
			<view class="my-canvas" >
				<view class="canvas-top flex">
					<image :src="logo" mode=""></image>
					<view class=" flex column justify-content-center">
						<view class="font-size-28 font-600">鱿鱼圈</view>
						<view class="grey font-size-22">SquidTrade</view>
					</view>
				</view>
				<view class="poster-centent">
					<view class="goodsimg">
						<image :src="goodsDetail.images[0]" mode="aspectFill"></image>
						<!-- 拍卖 -->
						<image src="../../static/img/paimaijiao.png" mode="" v-if="goodsDetail.type==2"  class="goods-type"></image>
						<!-- 盲拍 -->
						<image src="../../static/img/mangpaijiao.png" mode="" v-else-if="goodsDetail.type==3" class="goods-type"></image>
						<!-- 估价 -->
						<image src="../../static/img/gujiajiao.png" mode="" v-else class="goods-type"></image>
					</view>
					<view class="goodsmessage flex justify-content-between">
						<view class="flex column justify-content-between">
							<view class="font-size-32 font-600">{{goodsDetail.title}}</view>
							<view class="font-size-24"><text class="grey">当前价</text> <text class="font-size-30 red font-600 startprice">{{goodsDetail.now_price}}</text><text>鱿鱼圈</text></view>
						</view>
						<view class="">
							<image :src="posterInfo.usercode" mode="aspectFit"></image>
						</view>
					</view>
				</view>
			</view>
			<!-- 生成图片后的蒙层 -->
			<image :src="img" mode="" class="img-box"></image>
			<button class="btn">长按图片保存</button>
		</view>
	</uni-popup>

import html2canvas from '@/common/html2canvas.min.js'

 2.数据

// 用来控制canvas遮罩层的显示与隐藏
posterInfo: {
	status: false,
	type:0,
	usercode:''
},
img:''   //保存到本地的海报地址
canvasW:0,
canvasH:0,

3.绘制

	generatePoster(){
		// #ifdef H5
		if(this.isweixin){
			let that = this
			this.$refs.poster.open()
			uni.showLoading({
				title:'海报生成中。。。'
			})
			setTimeout(() => {
				const dom = document.querySelector('.my-canvas') // 需要生成图片内容的 dom 节点
				html2canvas(dom, {
				  width: dom.clientWidth, //dom 原始宽度
				  height: dom.clientHeight,
				  scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0
				  scrollX: 0,
				  useCORS: true, //支持跨域
				  scale: 2, // 设置生成图片的像素比例,默认是1,如果生成的图片模糊的话可以开启该配置项
				}).then((canvas) => {
				  // 生成成功
				  // html2canvas 生成成功的图片链接需要转成 base64位的url
				  // ownerFun.callMethod('receiveRenderData', canvas.toDataURL('image/png'))
				   that.img = canvas.toDataURL('image/png')
				   uni.hideLoading()
				   console.log(that.img,'图片生成成功')
				   console.log(canvas,'canvas')
				}).catch(err=>{
				  // 生成失败 弹出提示弹窗
				  // ownerFun.callMethod('_errAlert',`【生成图片失败,请重试】${err}`)
				  uni.hideLoading()
				  console.log(err,'图片生成失败')
				})
			  }, 300)
		}else{
			this.getPoster()
		}
		// #endif
		// #ifndef H5
		this.getPoster()
		// #endif
	},


// 生成海报
	async getPoster(){
		uni.showLoading({
			title: '海报生成中'
		});
		let that = this
		// 获取设备信息,主要获取宽度,赋值给canvasW 也就是宽度:100%
		this.SystemInfo = await this.getSystemInfo();
		this.canvasW = this.SystemInfo.windowWidth*0.8; // 画布宽度
		this.canvasH = this.SystemInfo.windowHeight*0.7; 
		this.posterInfo.status = true
		let logo = await this.downloadFile(this.logo)
		let imgUrl = !!this.goodsDetail.images[0]?this.goodsDetail.images[0]:this.imgUrl
		this.goodsImg = await this.downloadFile(imgUrl);
		this.ewmImg = await this.downloadFile(this.posterInfo.usercode);
		let typeUrl = this.type==1?"":''
		var context = uni.createCanvasContext('mycanvas',this)
		context.setFillStyle('#fff')
		context.fillRect(0,0,this.canvasW,this.canvasH)
		context.font = 'normal 400 12px PingFang SC-Bold, PingFang SC'
		context.setFillStyle('#999999');
		context.fillText('SquidTrade',80,60)
		context.setFontSize(12)
		context.setFillStyle('#999');
		context.fillText('当前价',20,that.canvasH-30)
		let priceWidth = context.measureText(this.goodsDetail.now_price).width + 80; //计算昵称宽度,绘制间隔距离
		context.setFontSize(12)
		context.setFillStyle('#333');
		context.fillText('鱿鱼圈',priceWidth,that.canvasH-30)
		
		// 绘制鱿鱼圈
		context.setFillStyle('#333')
		context.font = 'normal bold 16px PingFang SC-Bold, PingFang SC'
		context.fillText('鱿鱼圈', 80, 40);
		
		// 绘制商品名称
		// context.setFontSize(16);
		context.setFillStyle('#333');
		context.font = 'normal bold 16px PingFang SC-Bold, PingFang SC'
		context.fillText(this.goodsDetail.title,20,that.canvasH-54)
		// 绘制商品价格
			
		context.setFontSize(20)
		context.setFillStyle('#D50000');
		context.fillText(this.goodsDetail.now_price,60,that.canvasH-30)
		
		//绘制头像
		context.save()
		context.beginPath();
		context.arc(44, 44, 22, 0, 2 * Math.PI)
		context.clip();
		context.drawImage(logo.tempFilePath, 22, 22, 44, 44);
		context.restore();
		context.draw(true);
		// 商品图片
		context.drawImage(this.goodsImg.tempFilePath, 20, 80, that.canvasW-40, that.canvasH-170);
		context.draw(true);
		// 二维码
		context.drawImage(this.ewmImg.tempFilePath, that.canvasW-80, that.canvasH-80, 70, 70);
		context.draw(true);
		uni.hideLoading()
	},

	// 获取设备信息
	getSystemInfo(){
		return new Promise((req, rej) => {
			uni.getSystemInfo({
				success: function (res) {
					req(res)
				}
			});
		})
	},

	downloadFile(image) {
		return new Promise((req, rej) => {
			uni.downloadFile({
				url: image,
				success: function(res) {
					req(res)
				},
			});
		})
	},

4.点击保存按钮保存海报

    save(){
		let that = this
		uni.canvasToTempFilePath({
			fileType: 'jpg',
			canvasId: 'mycanvas',
			quality: 1,
			success: (res) => {
				that.img = res.tempFilePath
				console.log(res.tempFilePath,'海报地址')
				that.download()
				
			},
			fail: function(err) {
				console.log(err)
				// reject(err)
			}
		},this)
	},

	download(){
		let that = this
		console.log(this.img,'图片img')
		// 先下载图片
		uni.downloadFile({
			url:this.img,
			success: (res) => {
				console.log(res.tempFilePath,'下载后的图片地址')
				// #ifdef H5
				const imgUrl = res.tempFilePath;
				if(that.isweixin){
					uni.showToast({
						icon:'none',
						title:'请长按图片保存'
					})
					// that.preview(res.tempFilePath)
					// let canvas = document.querySelector('.my-canvas');
					// Canvas2Image.saveAsImage(canvas, this.canvasW, this.canvasH, 'png','商品分享');
				}else{
					var oA = document.createElement("a");
					oA.download = '下载图片'; // 设置下载的文件名,默认是'下载'
					oA.href = imgUrl;
					console.log(oA ,'按钮a')
					document.body.appendChild(oA);
					oA.click();
					oA.remove(); // 下载之后把创建的元素删除
				}
				// #endif
				// #ifdef MP-WEIXIN
				// 获取到图片本地地址后再保存图片到相册(因为此方法不支持远程地址)
				// that.preview()
				uni.saveImageToPhotosAlbum({
					filePath: res.tempFilePath,
					success: () => {
					uni.showToast({
							title: "保存成功!",
						});
					},
					fail: () => {
						uni.showToast({
							title: "保存失败",
						});
					},
				});
				// #endif
			},
		});
	},

css:

.my-canvas-box {
	width: 750rpx;
	height: 100%;
	position: fixed;
	left: 0;
	top: 0;
	background-color: rgba(0, 0, 0, 0.6);
	z-index: 99;
	&.hide {
		display: none;
	}
	&.show {
		display: block;
	}
	.canvas-tip {
		color: #ffffff;
		font-size: 24rpx;
		margin-top: 30rpx;
		text-align: center;
	}
	.my-canvas {
		width: 614rpx;
		height: 907rpx;
		background: #FFFFFF;
		border-radius: 24rpx;
		margin: 155rpx auto 0;
	}
	.btn{
		margin: 30rpx auto 0;
		width: 614rpx;
		height: 87rpx;
		line-height: 87rpx;
		background: #FFD14A;
		border-radius: 44rpx;
	}
}

.poster-pop{
	position: relative;
	.my-canvas{
		width: 614rpx;
		height: 907rpx;
		background: #FFFFFF;
		border-radius: 24rpx;
		.canvas-top{
			padding: 20rpx;
			image{
				width: 88rpx;
				height: 88rpx;
				border-radius: 50%;
				margin-right: 7rpx;
			}
		}
		.poster-centent{
			padding: 0 30rpx 30rpx;
		}
		.goodsimg{
			width: 555rpx;
			height: 555rpx;
			position: relative;
			image{
				width: 100%;
				height: 100%;
			}
			.goods-type{
				width: 97rpx;
				height: 97rpx;
				position: absolute;
				top:0;
				left:0
			}
		}
		.goodsmessage{
			margin-top: 38rpx;
			image{
				width: 140rpx;
				height: 140rpx;
			}
			.startprice{
				margin: 0 8rpx 0 14rpx;
			}
		}
	}
	.img-box{
		width: 614rpx;
		height: 907rpx; 
		border-radius: 24rpx;
		position: absolute;
		top: 0;
		left: 0;
	}
	.btn{
		margin: 30rpx auto 0;
		width: 614rpx;
		height: 87rpx;
		line-height: 87rpx;
		background: #FFD14A;
		border-radius: 44rpx;
		text-align: center;
	}
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
微信小程序通过 Canvas 2D 绘制海报可以用于商品展示、广告宣传等场景。下面介绍一下实现流程: 1. 页面结构 在页面中添加一个 Canvas 标签,设置 id 和宽高: ```html <canvas id="poster" style="width: 750rpx; height: 1334rpx;"></canvas> ``` 2. 获取 Canvas 上下文 在页面的 onLoad 函数中获取 Canvas 上下文: ```javascript let ctx = wx.createCanvasContext('poster'); ``` 3. 绘制背景 使用 Canvas 2D 绘制背景,可以使用 fillRect 方法绘制一个填充矩形: ```javascript ctx.setFillStyle('#ffffff'); ctx.fillRect(0, 0, 750, 1334); ``` 4. 绘制图片 使用 drawImage 方法绘制图片,需要先将图片下载到本地: ```javascript wx.getImageInfo({ src: 'https://example.com/image.png', success: function(res) { ctx.drawImage(res.path, 0, 0, 750, 500); } }); ``` 5. 绘制文本 使用 fillText 或者 strokeText 方法绘制文本,需要设置字体样式和对齐方式: ```javascript ctx.setFontSize(32); ctx.setTextAlign('center'); ctx.fillText('这是一段文本', 375, 600); ``` 6. 保存海报 使用 Canvas 2D 的 toTempFilePath 方法将绘制海报保存到本地: ```javascript ctx.draw(false, function() { wx.canvasToTempFilePath({ x: 0, y: 0, width: 750, height: 1334, canvasId: 'poster', success: function(res) { console.log(res.tempFilePath); } }); }); ``` 完整代码: ```javascript Page({ onLoad: function() { let ctx = wx.createCanvasContext('poster'); ctx.setFillStyle('#ffffff'); ctx.fillRect(0, 0, 750, 1334); wx.getImageInfo({ src: 'https://example.com/image.png', success: function(res) { ctx.drawImage(res.path, 0, 0, 750, 500); } }); ctx.setFontSize(32); ctx.setTextAlign('center'); ctx.fillText('这是一段文本', 375, 600); ctx.draw(false, function() { wx.canvasToTempFilePath({ x: 0, y: 0, width: 750, height: 1334, canvasId: 'poster', success: function(res) { console.log(res.tempFilePath); } }); }); } }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值