千家信息网

如何使用canvas实现分享截图

发表于:2025-02-11 作者:千家信息网编辑
千家信息网最后更新 2025年02月11日,这篇文章主要介绍如何使用canvas实现分享截图,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!实现:一、body部分框架我使用的是react。绘画分享采用原生canvas、js
千家信息网最后更新 2025年02月11日如何使用canvas实现分享截图

这篇文章主要介绍如何使用canvas实现分享截图,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

实现:一、body部分

框架我使用的是react。绘画分享采用原生canvas、js实现。所以不用担心vue、小程序、原生H5也是能够适应。

一、构建canvas

下面展示一些 内联代码片。

//ref是react获取canvas元素的方法。也可以使用id,再通过getElementById() 方法获取canvas//宽高需要转化为而二-四倍图来提高清晰度、否则会导致分享截图模糊,清晰度不足 
//点击分享按钮触发this.shareComponent(this.getUrlImg)方法//非react框架,忽视其余代码。直接触发分享函数              
{ this.setState({ shareModal:true },()=>{ this.shareComponent(this.getUrlImg) })} }>分享活动

实现:二、JS部分:

shareComponent函数:

//函数接受一个回调函数,用于绘画完成后,再将canvas转化为png图片格式。//canvas移动端无法长按保存,必须传为img才能保存。shareComponent = (callback)=>{    let suncode = this.state.suncode //微信小程序太阳码    let activityName = this.state.activityName //活动标题    let backgroundImg = this.state.backgroundImg //背景图    let postShareDesc= this.state.postShareDesc //分享描述字段    let img = new Image()    img.crossOrigin="anonymous"; //关键,处理图片跨域问题!!    let _t = this    //限制活动标题,最多10个字,超过...省略    if(activityName.length>10){        activityName=activityName.slice(0,10)+'...'      }    //由于canvas文字不能自动换行,所以我们这里需要做一个文字换行处理,以及字数的限制,防止超出canvas范围    let arrDescribe = []     let maxLeng = postShareDesc.length/20 //分享描述每行20字,最多8行    if(maxLeng=>8){        maxLeng = 8 //最多8行    }    //postShareDesc为分享描述字段       for(let i = 0;i{            ctx.fillText(item,80,700+index*100);        })        //分享标题        ctx.font="64px Arial";        ctx.fillStyle='#000';        ctx.fillText(activityName,520,1320);  //分享提示        ctx.font="48px Arial";        ctx.fillStyle='#999';        ctx.fillText('长按小程序码查看详情',520,1420);  //分享提示        ctx.font="48px Arial";        ctx.fillStyle='#999';        ctx.fillText('分享自[XXXX]',520,1500);  //分割线        ctx.moveTo(1120,1160);        ctx.lineTo(80,1180);        ctx.strokeStyle="#E8E8E8"        ctx.stroke();        //img1为小程序太阳码        let img1 = new Image()        img1.crossOrigin="anonymous"; //关键,处理太阳码转化为base64格式图片时的跨域问题        img1.onload = function(){        ctx.drawImage(img1,  80, 1200,340,340)        callback(canvas)      }   太阳码赋值给img1      img1.src = suncode   //边框      ctx.strokeStyle="#f5f5f5";      ctx.rect(0,0,1200,1600);      ctx.stroke();          } //timeStamp 事件属性可返回一个时间戳。指示发生事件的日期和时间(从 epoch 开始的毫秒数)。 //URL时间戳的用法:作用:为了防止浏览器缓存。 //URL后面添加随机数或时间戳通常用于防止浏览器(客户端)缓存页面。 浏览器缓存是基于URL进行缓存的, //如果页面允许缓存,则在缓存时效前再次访问相同的URL,浏览器就不会再次发送请求到服务器端,而是直接从缓存中获取指定资源。 //而当URL 的末尾追加了随机数或时间戳,就会保证每次都会实际生成新请求且 Web 服务器不会尝试缓存来自服务器的响应。    const a = `${backgroundImg}?timeStamp=` + (new Date());    img.src = a  }//绘画完成后,必须转化为img,否则移动端将会无法长按保存//必须等绘画完成后,才能够回调。如果直接使用canvas.toDataURL('image/png')转化,会导致出现分享图只有写死的文字,没有请求的图片和文字。会存在异步问题  getUrlImg=(canvas)=>{       let dataImg = new Image()        try {      dataImg.src = canvas.toDataURL('image/png')    } catch (e) {      console.log(e);    }    let urlImg = dataImg.src //urlImg为img路径    this.setState({urlImg},()=>{     })  }

实现:三、canvas更换imgs:

//最后必须将canvas隐藏,再替换为imgs,这样移动端才能长按保存//css中.canvasImg添加display:none隐藏画布//再使用canvas转化的img,并且将img的宽高设置为25%//因为为了提高清晰度,我是采用四倍图再压缩的方式来提高清晰度,所以img需要缩回25%    //display:none    //crossOrigin="Anonymous" 处理图片跨域问题    //width:25%。height:25%    div className={styles.shareTips}>长按保存,可分享至朋友圈

总结与优化

难点在于:
①将canvas转化为base64格式图片,会导致图片跨域问题
②异步问题(图片还未加载,绘画就已经完成)
③背景透明的问题等等

优化:
①清晰度:可以将canvas画成2-4倍图,转化为图片再压缩回50%-25%
②分享图加载速度:小程序二维码太阳码,背景图等页面加载阶段可以先请求,点击分享按钮可以直接绘画,减少请求时间长导致生成绘画慢问题,同时也可以避免二维码、背景图未加载完成,绘画就已经开始,导致画出来的分享图没有背景图、二维码的问题。

以上是"如何使用canvas实现分享截图"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0