1,首先说明一下,我之前遇到一个需求 让我点击一个按钮可以对着当前整个页面进行长截图

这个功能折磨了我一个星期 之后我去问了某宝的人 百分之70说 做不出来,剩下的开会后收我一万元,我就呵呵呵了 于是我苦心钻研 后 借助一个插件(自己修改了些代码)完成了这一个功能,分享给大家----前人栽树 后人乘凉!

---------------------------------------------------------------------------------------------------------------------------------

正式开始

第一步

去uniapp插件市场下载导入到你的项目中(感谢这位插件作者)

tk-view2canvas 页面截屏组件 - DCloud 插件市场

安装完成后 里面的代码需要改写--以下是我的改写后的 你可以直接复制粘贴代替掉他的

<template>
	<view>
	</view>
</template>

<script>
	let promiseIndex = 0
	let promiseArray = []
	let imageArray = []
	let imageIndex = 0
	export default {
		name: "kt-view2canvas",
		data() {
			return {

			};
		},
		props: {
			canvasWidth: {
				type: Number,
				default: 1080
			},
			canvasHeight: {
				type: Number,
				default: 2500
			}
		},
		methods: {

			//rpx转换为px的工具函数
			rpxtopx(rpx) {
				let deviceWidth = wx.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
				let px = (deviceWidth / 750) * Number(rpx)
				return Math.floor(px);
			},

			drawCanvas(arrayInfo) {
				promiseIndex = 0
				promiseArray = []
				imageArray = []
				imageIndex = 0
				uni.showLoading({
					title: '保存中...'
				})
				// 0.创建canvas及ctx,并获取屏幕的dpr
				const canvas = wx.createOffscreenCanvas({
					type: '2d',
					width: this.canvasWidth,
					height: this.canvasHeight
				})
				const ctx = canvas.getContext('2d')

				const dpr = uni.getWindowInfo().pixelRatio

				// 1.根据数组数量创建promise数组
				for (let i = 0; i < arrayInfo.length; i++) {
					promiseArray.push(promiseIndex)
					promiseIndex++
				}

				// 2.根据数组给promise数组赋值
				let that = this
				for (let i = 0; i < arrayInfo.length; i++) {
					promiseArray[i] = new Promise(function(resolve, reject) {
						if (arrayInfo[i].type == 'text') {
							resolve()
						} else if (arrayInfo[i].type == 'view') {
							resolve()
						} else if (arrayInfo[i].type == 'image') {
							let img = canvas.createImage()
							img.src = arrayInfo[i].src
							img.onload = function() {
								imageArray.push(img)
								resolve()
							}
							img.src = arrayInfo[i].src + `?${new Date().getTime()}`
						}
					})
				}

				// 3.异步全部加载完成后,绘制图片
				let p = Promise.all(promiseArray)
				p.then(function() {
					//根据数组顺序绘制图片
					for (let i = 0; i < arrayInfo.length; i++) {
						if (arrayInfo[i].type == 'text') {
							ctx.fillStyle = arrayInfo[i].color
							ctx.font = that.rpxtopx(arrayInfo[i].size) * dpr + 'px sans-serif'
							ctx.textBaseline = 'top'
							ctx.fillText(arrayInfo[i].word, arrayInfo[i].posX * dpr, (arrayInfo[i].posY + that
								.rpxtopx(20)) * dpr)
						} else if (arrayInfo[i].type == 'view') {
							ctx.fillStyle = arrayInfo[i].bgColor
							ctx.fillRect(arrayInfo[i].posX * dpr, arrayInfo[i].posY * dpr, arrayInfo[i].width *
								dpr, arrayInfo[i].height * dpr)
						} else if (arrayInfo[i].type == 'image') {
							ctx.drawImage(imageArray[imageIndex], arrayInfo[i].posX * dpr, arrayInfo[i].posY * dpr,
								arrayInfo[i].width * dpr, arrayInfo[i].height * dpr)
							imageIndex++
						}
					}
					const fileData = canvas.toDataURL()
					const fs = uni.getFileSystemManager()
					const path = `${wx.env.USER_DATA_PATH}/` + new Date().getTime() + `hello.png`
					//数据归零
					promiseIndex = 0
					promiseArray = []
					imageArray = []
					imageIndex = 0
					fs.writeFile({
						filePath: path,
						data: fileData.replace(/^data:image\/\w+;base64,/, ""),
						encoding: 'base64',
						success(res) {
							uni.showShareImageMenu({
								path: path,
								success: res => {
									console.log(res);
								}
							})
						},
						fail(res) {
							console.error(res)
						},
						complete() {
							uni.hideLoading()
						}
					})
				})
			}
		}
	}
</script>

<style>

</style>

第二步

去到你需要截图的页面   引入(如下图)

  * canvasWidth 是你画布的宽度 ----   canvasHeight 是你画布的高度(他们决定着你画出来图片的宽高 后期可以自行调整)

第三步

把canvasWidth     canvasHeight  写进data中

第四步

建立触发事件--我这里就拿点击事件举例子  

view中

<button @click="toCanvas" /> 这是触发 图片生成的事件







JavaScript中

toCanvas() {
        let that = this
        arrayInfo = []
        // 1.先查询要绘制的view,image,text相关属性数据
        uni.createSelectorQuery().selectAll('.queryInfo').boundingClientRect().exec((res) => {
          // console.log('获取到信息:', res[0])
          let resArray = res[0]
          for (let i = 0; i < resArray.length; i++) {
            //1.判断查询到的组件类别,如果是view类,就按照view对应的格式将创建的对象添加到数组中
            if (resArray[i].dataset.type == 'view') {
              // console.log('view')
              let bgColor = resArray[i].dataset.bgcolor
              let width = resArray[i].width
              let height = resArray[i].height
              let posX = resArray[i].left
              let posY = resArray[i].top
              arrayInfo.push({
                type: 'view',
                width: width,
                height: height,
                bgColor: bgColor,
                posX: posX,
                posY: posY
              })
            } //2.判断查询到的组件类别,如果是image类,就按照image对应的格式将创建的对象添加到数组中
            else if (resArray[i].dataset.type == 'image') {
              // console.log('image')
              let type = 'image'
              let src = resArray[i].dataset.src
              let posX = resArray[i].left
              let posY = resArray[i].top
              let width = resArray[i].width
              let height = resArray[i].height
              arrayInfo.push({
                type: 'image',
                src: src,
                width: width,
                height: height,
                posX: posX,
                posY: posY
              })
            } //3.判断查询到的组件类别,如果是text类,就按照text对应的格式将创建的对象添加到数组中
            else if (resArray[i].dataset.type == 'text') {
              // console.log('text')
              let type = 'text'
              let color = resArray[i].dataset.color
              let word = resArray[i].dataset.word
              let size = resArray[i].dataset.size
              let posX = resArray[i].left
              let posY = resArray[i].top
              arrayInfo.push({
                type: 'text',
                color: color,
                word: word,
                size: size,
                posX: posX,
                posY: posY
              })
            }
          }
          //查询完毕后,也就创建好了arrayInfo数组,下面将arrayInfo数组作为参数,传给组件的drawCanvas()方法
          that.$refs.tkCanvas.drawCanvas(arrayInfo)
        })
      },

事件里面的代码你也可以先复制粘贴我的 后面你自己慢慢研究

第五步(最繁琐的一步-加油你快成功了)

开始 设置你要绘制的当前页的内容(需要出现在图片上的内容就 设置  不需要的就不设置,不设置的就不会在图片上出现)

1,只要是view  就在盒子里加上  并且 在class中必须加入 queryInfo

(需要出现在图片上的内容就加 不需要的不加 你之前有的class内容 不动他)

<view class="queryInfo" data-type="view" />---data-type="view" 是他是什么类型的盒子必写

2,颜色设置  -- data-bgcolor="#ffffff"     data-color ="#000" 

<view class="queryInfo" data-type="view" data-bgcolor="#ffffff"     data-color ="#000"  />

3,所有文字必须用text包裹起来 且和上面一样 clas,也是必须加 还有内容要放在data中切记

<text class="queryInfo" data-type="text" :data-word="xuexiaoname" data-font-weight="800" data-margin-top="60"  data-color="#000" data-size="45">{{xuexiaoname}}</text>

---样式前面必须加data-    text盒子 必须加data-type="text"   文字内容必须在data中 要配合:data-word="xuexiaoname"  切记不然没办法画出来

4,图片内容 image

<image class="queryInfo" data-type="image" :data-src="item" :src="item" mode=""></image>

:data-src="这里是图片地址 可以是本地 也可以是 网络(我这里前面遍历了你随意)"

:src="和上面一样"

图片就写 data-type="image"   而且class里面的 queryInfo不能少

到这里就结束了,切记  不需要现实的 就原封不动不管他  需要显示在图片上上的内容 就按上面的操作,生成的图片大小不合适 可以调整data中的 canvasWidth     canvasHeight。

如果您觉得有用 麻烦帮我点个赞收藏一下,还是老话--前人栽树 后人乘凉

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐