第一种,【图文保存为图片并下载到相册】 h5, 微信和 ios 不支持

1,安装html2canvas

npm install html2canvas --save

2,在需要的页面引入

import html2canvas from 'html2canvas'

3,使用

html2canvas(document.body).then((canvas)=> {
    document.body.appendChild(canvas);
});

4,如果要下载的话,可以使用a标签来下载,但是ios和微信不支持

<a href=""
download="你的账单.png"
id="downimg"
style="display:none">保存账单</a>

js:这里我模拟了a标签的点击

let downbtn = document.getElementById('downimg')
html2canvas(document.getElementById('ten')).then((canvas) => {
 downbtn.href = canvas.toDataURL('image/png')
}).then(() => {
 downbtn.click()
})

5,既然微信和ios不支持下载图片,那怎么解决呢,可以显示出图片,然后提示让用户自己去保存

let ele = document.getElementById('ten')
        html2canvas(ele).then((canvas) => {
          var canvimg = document.createElement('img')
          canvimg.src = canvas.toDataURL('image/png')
          canvimg.style.width = '100%'
          canvimg.style.height = '100%'
          document.getElementById('ten').appendChild(canvimg)
          alert('账单已生成\n请长按保存账单')
        })
示例
<template>
	<view class="content" >
		<view ref="imageWrapper" id="poster">
			<view class="viewImg">
				<view class="box">
					<view class="title">
						<text>{{articleMes.title}}</text>
					</view>
					<view class="flex-space author">
						<text>作者:{{articleMes.author}}</text>
						<view class="date">
							<text class="num">{{articleMes.browseNum}}次浏览</text> |
							<text class="num">{{articleMes.createTime}}</text>
						</view>
					</view>
					<view class="stance">
						<!-- {{articleMes.content}} -->
						<view v-html="articleMes.content"></view>
						<image class="img_" :src="articleMes.cover" mode="widthFix"></image>
					</view>
					<view class="codeImg">
							<canvas class="code" canvas-id="couponQrcode"></canvas>
						<!-- <image class="code" src="@/static/code.jpg" mode=""></image> -->
					</view>
				</view>	
				
			</view>	
		</view>
		<view class="saveBtn" @click="capture()">
			<text>保存海报</text>
		</view>
	</view>
</template>

<script>
	import html2canvas from "html2canvas"
	import {
		articleDetail,
	} from '@/api/index/user.js'
	const qrCode = require('@/common//weapp-qrcode.js')
	export default{
		data(){
			return {
				base64:'',
				id:'',
				articleMes:{}
			}
		},
		onLoad(options) {
			let that = this
			that.id = options.id
			that.getArticalDetail()
			setTimeout(() => {
				that.couponQrCode()
			}, 50)
		},
		methods:{
			couponQrCode() {
				new qrCode('couponQrcode', {
					text: "https://www.baidu.com/baidu?tn=monline_3_dg&ie=utf-8&wd=csdn",
					width: 125,
					height: 125,
					colorDark: "#333333",
					colorLight: "#FFFFFF",
					correctLevel: qrCode.CorrectLevel.H,
					src: require('@/pagesA/static/images/rank/qiye.png')
				})
			},
		
			// 获取文章详情
			getArticalDetail(){
				let that = this
				let data = {
					id:that.id,
					userId:uni.getStorageSync('userInfo').id
				}
				articleDetail(data).then(res => {
					that.articleMes = res.data
				})
			},
			capture() {
				// var dom = document.querySelector('#poster')
				html2canvas(this.refs.imageWrapper).then((canvas) => {
					// 将生产的canvas转为base64图片
					this.base64 = canvas.toDataURL('image/png')
					this.saveImg(this.base64)
				});
				
			},
			saveImg(url){
				uni.downloadFile({
					url,
					success: (res) => {
						// 获取到图片本地地址后再保存图片到相册
						uni.saveImageToPhotosAlbum({
							filePath: res.tempFilePath,
							success: () => {
								uni.showToast({
									title: "保存成功!",
								});
							},
							fail: () => {
								uni.showToast({
									title: "保存失败",
								});
							},
						});
					},
				});
			}
		}
	}
</script>

<style lang="scss">
	page{
		background-color: #FB9571;
		
	}
	.content{
		padding-bottom: 100rpx;
		#poster{
			background: url('@/pagesA/static/images/operate/poster-bgc.jpg') no-repeat;
			background-size: 100%;
			padding: 40rpx 20rpx 100rpx;
			.viewImg{
				padding: 20rpx;
				width: 85%;
				margin: 0 auto;
				border-radius: 30rpx;
				background: rgba(255,255,255,.36);
			}
		}
		.box{
			background: #fff;
			border-radius: 30rpx;
			padding: 30rpx;
		}
		.title{
			font-weight: bold;
			color: #333;
			font-size: 38rpx;
			margin-bottom: 20rpx;
		}
		.author{
			font-size: 28rpx;
			border-bottom: 2rpx solid #F8F8F8;
			padding-bottom: 15rpx;
			white-space: nowrap;
		}
		.date{
			color: #AAAAAA;
			font-size: 26rpx;
			.num{
				margin: 0 15rpx;
			}
		}
		.stance{
			padding: 40rpx 0;
			white-space: pre-wrap;
			font-size: 30rpx;
			.img_{
				display: block;
				margin: 20rpx auto 0;
				max-width: 100%;
				// height: auto;
			}
		}
		.codeImg{
			border-top: 2rpx solid #f5f5f5;
			.code{
				width: 250rpx;
				height: 250rpx;
				display: block;
				margin: 30rpx auto;
			}
		}
		
	}	
	.saveBtn{
		background-color: #DD490A;
		color: #fff;
		border-radius: 50rpx;
		display: block;
		text-align: center;
		padding: 26rpx 0;
		font-size: 30rpx;
		width: 85%;
		margin: 0 auto;
		box-shadow: 0 0 8rpx #dd490a;
	}
</style>

**

用uni做 微信小程序

**

示例,页面

<template>
	<view class="">
		<canvas style='width:375px;height:580px' canvas-id="canvasboxid" id="canvasboxid"></canvas>

		<view class="btnbox" @click="savePic">
			保存
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				tempFilePath:''
			}
		},
		onReady() {

			this.capture()

		},

		onload() {
			// this.capture()
		},
		methods: {

			capture() {
				console.log('canvas绘制文本==================================')

				// canvas绘制文本

				const ctx = uni.createCanvasContext('canvasboxid', this)

				// canvas布局

				ctx.setFontSize(20)

				ctx.setTextAlign('center')

				ctx.fillText('缴费凭证', 162, 40)

				ctx.setFillStyle('#f95455')

				ctx.fillText('¥' + 123 + '.00', 162, 75)

				ctx.setFontSize(14)

				ctx.setFillStyle('#999999')

				ctx.fillText('缴费类型', 95, 100)

				ctx.fillText('缴费方式', 230, 100)

				// 绘制矩形,在矩形中添加文本

				ctx.setFillStyle('rgba(225,225,225,0)')

				ctx.setFontSize(11)

				ctx.strokeStyle = "#333333";

				ctx.moveTo(24, 120)

				ctx.lineTo(172, 120)

				ctx.lineTo(172, 150)

				ctx.lineTo(24, 150)

				ctx.lineTo(24, 120)

				ctx.closePath();

				ctx.fill();

				this.drawText(ctx, '文字描述王佳家', 90, 120, 20, 160)

				ctx.setFillStyle('#333333')

				ctx.setFontSize(13)

				ctx.fillText('现金缴费', 230, 120)

				ctx.setFontSize(14)

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('姓名', 25, 165)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('现金缴费啦啦啦啦', 300, 165)

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('手机号', 25, 195)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('15093417544', 300, 195)

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('房号', 25, 225)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('1509341', 300, 225)

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('收费单位', 25, 255)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('国网晋中电力有限公司', 300, 255)

				// 绘制虚线

				ctx.setLineDash([2, 4], 5);

				ctx.beginPath();

				ctx.moveTo(25, 280);

				ctx.lineTo(300, 280);

				ctx.stroke();

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('付款时间', 25, 310)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('支付时间2022', 300, 310)

				ctx.setTextAlign('left')

				ctx.setFillStyle('#999999')

				ctx.fillText('流水号', 25, 340)

				ctx.setTextAlign('right')

				ctx.setFillStyle('#333333')

				ctx.fillText('id123', 300, 340)

				// canvas画布转为图片 ,有时draw调用不成功,写了个定时器
				ctx.draw(setTimeout(() => {
					uni.canvasToTempFilePath({
						x: 0,
						y: 0,
						width: 325,
						height: 375,
						destWidth: 325,
						destHeight: 375,
						fileType: 'jpg',
						canvasId: 'canvasboxid',
						success: (res) => {
							uni.hideLoading()
							// // 保存当前绘制图片
							this.tempFilePath = res.tempFilePath
						},

						fail: function(err) {
							console.log(err, '图片生成失败')
						}
					})

				}, 500))

			},

			// 控制绘制文本换行,百度CV的

			drawText: function(ctx, str, leftWidth, initHeight, titleHeight, canvasWidth) {

				var lineWidth = 0;

				var lastSubStrIndex = 0; //每次开始截取的字符串的索引

				for (let i = 0; i < str.length; i++) {

					lineWidth += ctx.measureText(str[i]).width;

					if (lineWidth > canvasWidth) {

						//因为我这个在矩形中的文本进行的换行,用的ctx.strokeText,不行用在矩形中添加文本的用ctx.fillText

						ctx.strokeText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取部分

						initHeight += 11; //11为字体的高度

						lineWidth = 0;

						lastSubStrIndex = i;

						titleHeight += 30;

					}

					if (i == str.length - 1) { //绘制剩余部分

						ctx.strokeText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight);

					}

				}

				// 标题border-bottom 线距顶部距离

				titleHeight = titleHeight + 10;

				return titleHeight

			},

			// 保存图片到本地,下面保存到手机百度CV的

			savePic() {

				uni.getSetting({

					//获取用户的当前设置

					success: res => {

						if (res.authSetting['scope.writePhotosAlbum']) {

							//验证用户是否授权可以访问相册

							uni.saveImageToPhotosAlbum({

								filePath: this.tempFilePath,

								success: function(res2) {

									uni.hideLoading();

									uni.showToast({

										title: '保存成功,请从相册选择再分享',

										icon: 'none',

										duration: 2000

									});

								},

								fail: function(err) {

									uni.hideLoading();

									uni.showToast({

										title: '保存失败',

										icon: 'none',

										duration: 2000

									});

								}

							});

						} else {

							uni.authorize({

								//如果没有授权,向用户发起请求

								scope: 'scope.writePhotosAlbum',

								success: () => {

									// this.saveImageToPhotosAlbum();
									console.log('发起请求')
									
									uni.showToast({
									
												title: '请打开保存相册权限,再点击保存相册分享1111',
									
												icon: 'none',
									
												duration: 2000
									
											});
									
											setTimeout(() => {
									
												uni.openSetting({
									
													//调起客户端小程序设置界面,让用户开启访问相册
									
													success: res2 => {
									
														// console.log(res2.authSetting)
									
													}
									
												});
									
											}, 2000);
								},

								fail: () => {

									uni.showToast({

										title: '请打开保存相册权限,再点击保存相册分享',

										icon: 'none',

										duration: 2000

									});

									setTimeout(() => {

										uni.openSetting({

											//调起客户端小程序设置界面,让用户开启访问相册

											success: res2 => {

												// console.log(res2.authSetting)

											}

										});

									}, 2000);

								}

							});

						}

					}

				});

			},

		}
	}
</script>

<style>
.btnbox{
	margin: 0 auto;
	width: 80%;
	height: 80rpx;
	line-height: 80rpx;
	text-align: center;
	border: 1rpx solid #ccc;
	border-radius: 10rpx;
	
}
</style>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐