Sample code of how to share screenshots in front-end HTML5

Time:2021-10-16

preface

This article mainly introduces how to share screenshots using canvas,
At first, I thought it was not difficult to share pictures through canvas painting, but in fact, I still encountered a lot of holes during development
For example:
① The background of the picture is transparent
② Share pictures only text, no pictures
③ Picture cross domain problem
Here is an example:
The shared picture, shared content description, title and QR code are dynamically generated through the request interface

Implementation: I. body part

The framework I use is react. Painting sharing is realized by native canvas and JS. So don’t worry, Vue, applet and native H5 can also adapt.

1、 Building canvas

Here are some inline snippets.

//Ref is the method of react to get the canvas element. You can also use ID and get canvas through getelementbyid () method
//The width and height need to be converted into two to four times of the image to improve the definition, otherwise the shared screenshot will be blurred and the definition will be insufficient
 <canvas ref='canvas' width={1200} height={1600} className={styles.canvasImg}/>
//Click the share button to trigger the this. Sharecomponent (this. Geturlimg) method
//Non react framework, ignoring the rest of the code. Direct trigger sharing function
              <div className={styles.luckDraw_viewPrizeBtn} onClick={()=>{
                     this.setState({
                         shareModal:true
                        },()=>{
                            this.shareComponent(this.getUrlImg)
                        })}
                 }>Share activity < / div >

Implementation: II. JS part:

Sharecomponent function

//Function accepts a callback function to convert canvas to PNG image format after painting.
//The canvas mobile terminal cannot be saved by long pressing. It must be transferred to img to save.
shareComponent = (callback)=>{
    Let suncode = this. State. Suncode // wechat applet sun code
    Let activityname = this. State. Activityname // activity title
    Let backgroundimg = this. State. Backgroundimg // background image
    Let postsharedesc = this. State. Postsharedesc // share description field
    let img = new Image()
    img.crossOrigin="anonymous"; // The key is to deal with the cross domain problem of pictures!!
    let _t = this
    //Limit the activity title to 10 words at most, and omit more than
    if(activityName.length>10){
        activityName=activityName.slice(0,10)+'...'
      }
    //Since canvas text cannot wrap automatically, we need to do a word wrap and limit the number of words to prevent exceeding the scope of canvas
    let arrDescribe = [] 
    Let maxleng = postsharedesc.length/20 // each line of sharing description is 20 words, with a maximum of 8 lines
    if(maxLeng=>8){
        Maxleng = 8 // up to 8 lines
    }
    //Postsharedesc is the share description field
   
    for(let i = 0;i<maxLeng;i++){
    //Divide the shared description field into several 20 word lines and store them in the arrdescribe array, with a maximum of 8 lines
        let str = postShareDesc.slice(i*20,i*20+20) 
        arrDescribe.push(str)
    }
    //After the picture is loaded, it is displayed in canvas. The picture must be onload, otherwise it will complete the painting before the picture is loaded
    //IMG is the whole shared picture
    img.onload = function (){
      let canvas = _ t. Refs.canvas // get the canvas element
      let ctx = canvas.getContext('2d')
        //Set the background color, otherwise the background color will be transparent
        ctx.fillStyle='#fff';
        ctx.fillRect(0,0,1196,1596);
        ctx.drawImage(img, 0, 0,1200,600);
  //Shared field description
        ctx.font="52px Arial";
        ctx.fillStyle='#000';
        //For manual line feed, 80 is the X coordinate and 700 + index * 100 is the Y coordinate for dynamic calculation
        arrDescribe.forEach((item,index)=>{
            ctx.fillText(item,80,700+index*100);
        })
        //Share title
        ctx.font="64px Arial";
        ctx.fillStyle='#000';
        ctx.fillText(activityName,520,1320);
  //Share tips
        ctx.font="48px Arial";
        ctx.fillStyle='#999';
        Ctx.filltext ('long press applet code to view details', 5201420);
  //Share tips
        ctx.font="48px Arial";
        ctx.fillStyle='#999';
        CTX. Filltext ('shared from [XXXX] ', 5201500);
  //Split line
        ctx.moveTo(1120,1160);
        ctx.lineTo(80,1180);
        ctx.strokeStyle="#E8E8E8"
        ctx.stroke();
        //Img1 is the sun code of the applet
        let img1 = new Image()
        img1.crossOrigin="anonymous"; // The key is to deal with the cross domain problem when the sun code is converted into Base64 format pictures
        img1.onload = function(){
        ctx.drawImage(img1,  80, 1200,340,340)
        callback(canvas)

      }
   The sun code is assigned to img1
      img1.src = suncode
   //Border
      ctx.strokeStyle="#f5f5f5";
      ctx.rect(0,0,1200,1600);
      ctx.stroke();      

    }
 //The timestamp event property returns a timestamp. Indicates the date and time (in milliseconds from epoch) when the event occurred.
 //Usage of URL timestamp: function: to prevent browser caching.
 //Adding a random number or timestamp after a URL is usually used to prevent the browser (client) from caching the page. Browser caching is based on URL,
 //If the page allows caching, if the same URL is accessed again before the cache expires, the browser will not send the request to the server again, but directly obtain the specified resources from the cache.
 //When a random number or timestamp is appended to the end of the URL, it will ensure that a new request will be actually generated each time, and the web server will not try to cache the response from the server.
    const a = `${backgroundImg}?timeStamp=` + (new Date());
    img.src = a

  }
//After painting, it must be converted to img, otherwise the mobile terminal will not be able to long press to save
//You must wait until the painting is completed before you can call back. If you directly use canvas.todataurl ('image / PNG ') to convert, there will be only dead text in the shared image, but no requested image and text. There will be asynchronous problems
  getUrlImg=(canvas)=>{   
    let dataImg = new Image()    
    try {
      dataImg.src = canvas.toDataURL('image/png')
    } catch (e) {
      console.log(e);
    }
    Let urlimg = dataimg.src // urlimg is the IMG path
    this.setState({urlImg},()=>{ 
    })
  }

Implementation: III. replace IMGs with canvas

//Finally, the canvas must be hidden and replaced with IMGs, so that the mobile terminal can long press to save
//CSS. Canvasimg add display: none to hide canvas
//Then use the IMG converted by canvas, and set the width and height of img to 25%
//In order to improve the definition, I use quadruple image re compression to improve the definition, so img needs to be retracted by 25%
    <canvas ref='canvas' width={1200} height={1600} className={styles.canvasImg}/>//display:none
    //Crossorigin = "anonymous" deal with cross domain problems of pictures
    <img src={this.state.urlImg} crossOrigin="Anonymous"/>//width:25%。height:25%
    Div classname = {styles. Sharetips} > long press to save and share to the circle of friends < / div >

Summary and optimization

The difficulty lies in:
① Converting canvas to Base64 format pictures will lead to cross domain problems
② Asynchronous problem (painting has been completed before the picture is loaded)
③ Background transparency and so on

Optimization:
① Clarity: canvas can be drawn into a 2-4-fold picture, converted into a picture, and then compressed back to 50% – 25%
② Loading speed of sharing map: in the loading stage of applet QR code, sun code, background map and other pages, you can request first. Click the sharing button to draw directly, which can reduce the slow generation of painting due to the long request time. At the same time, it can also avoid the problem that the painting has started before the QR code and background map are loaded, resulting in no background map and QR code in the drawn sharing map.

This is the end of this article about the sample code of how to share screenshots in front-end HTML5. For more information about sharing screenshots in HTML5, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!

Recommended Today

SQL statement of three-level linkage of provinces, cities and counties

The first is the table creation statement Copy codeThe code is as follows: CREATE TABLE `t_address_province` ( `id` INT AUTO_ Increment primary key comment ‘primary key’,`Code ` char (6) not null comment ‘province code’,`Name ` varchar (40) not null comment ‘province name’)Engine = InnoDB default charset = utf8 comment = ‘province information table’; CREATE TABLE […]