preface

Image compression is widely used in many interactive scenarios. Before the popularity of HTML5 standard, image compression is mainly realized by server-side programming. However, with the rapid development of browsers, many advanced attributes are supported so that front-end technology can also achieve the same function. This article takes an in-depth look at how the front-end technology compresses and generates images from a practical perspective.

The example is shown below. Select the file button to open a local image and preview it on the page. Then select the compression rate, the image effect after compression will be displayed below, and finally click Generate to download the compressed image.

Full Demo address

Function implementation

HTML structure

             

UpdateFile method is implemented

When the user clicks the button to upload a local image, the updateFile function is triggered. File is the file object for uploading the image.

 /**
   * 给input绑定事件
   */
  async function updateFile(e) {
    const file = e.target.files[0];

    if (!verify(file)) {
      //参数校验
      return false;
    }

    const base64Code = await getBase64(file); //获取base64编码

    placeImg(base64Code); //放置图片
  }
Copy the code

The verify function obtains the file object to know the type and size of the file, so that it can set some rules for restricting upload behavior.

/** * @param {*} file */ function verify(file) {const {size, type} = file; If (size > 5 * 1024 * 1024) {alert(' upload image size cannot exceed 5M'); return false; } if (! Img_types.includes (type)) {alert(' please upload pictures '); return false; } return true; }Copy the code

The getBase64 function converts the image to base64 encoding using the FileReader AP

  function getBase64(file) {
    return new Promise((resolve) => {
      const fileReader = new FileReader();
      fileReader.onload = (e) => {
        resolve(e.target.result);
      };
      fileReader.readAsDataURL(file);
    });
  }
Copy the code

Code is encoded in Base64,target is the DOM element that is intended to host the preview image, and its width and height are the maximum width and height allowed for the image. The image object image uses naturalWidth and naturalHeight to get the original width and height of the image. First divide the original width of the image by the original height to obtain the aspect ratio radio. If the original width ratio is large, assign the value of the maximum width max_width and the smaller naturalWidth of the image to width, which calculates the height using the aspect ratio radio. If the height is still greater than the maximum height, then the ratio of width to height needs to be reduced one more time. The resulting width and height ensures that the image size will not overflow the outer DOM container, but will be displayed in a true aspect ratio. Target.appendchild (image); The preview image with the set width and height is displayed on the page.

*/ function placeImg(code) {const target = document.getelementById ('original'); const max_width = parseInt(getComputedStyle(target).width); const max_height = parseInt(getComputedStyle(target).height); let width, height; const image = new Image(); image.src = code; image.onload = () => { const naturalWidth = image.naturalWidth; const naturalHeight = image.naturalHeight; const radio = naturalWidth / naturalHeight; If (radio >= 1) {// width = naturalWidth < max_width? naturalWidth : max_width; height = (width * 1) / radio; if (height > max_height) { height = max_height; width = height * radio; } } else { height = naturalHeight < max_height ? naturalHeight : max_height; width = height * radio; if (width > max_width) { width = max_width; height = (width * 1) / radio; } } width = parseInt(width); height = parseInt(height); image.style.width = `${width}px`; image.style.height = `${height}px`; target.innerHTML = ''; target.appendChild(image); img = image; // Assign the preview graph object to the global variable img compress(); }; }Copy the code

The compress function does this. Value is the current value of the select tag, which is the compression ratio of the image to be set. Create a canvas tag in memory, set its width and height to the width and height of the preview image object, and draw the preview image to the canvas, finally through a key API Canvas. toDataURL can generate the base64 encoding after image compression. The second parameter of Canvas. toDataURL is filled in the compression ratio. The compressed Base64 encoding is assigned to the Image object and rendered below the page, so that the compressed Image is displayed smoothly.

/ / function compress() {if (! Img) {//img is the preview image object return false; } const value = Number(document.getElementById('sel').value); const canvas = document.createElement('CANVAS'); const w = img.width, h = img.height; canvas.width = w; canvas.height = h; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, w, h); const code = canvas.toDataURL('image/jpeg', value); const image = new Image(); image.src = code; image.onload = () => { const des = document.getElementById('production'); des.innerHTML = ''; des.appendChild(image); compress_img = image; }; }Copy the code

Generate images

Compress_img is a compressed image object, and generate is triggered when the user clicks generate. It creates an A tag, assigns the base64 encoding of the compressed image to the href attribute, and assigns A value to the Download attribute that corresponds to the downloaded image name. Finally, execute the click of the A tag to trigger the download.

@param {*} */ function generate() {if (! compress_img) { return false; } const a = document.createElement('A'); a.href = compress_img.src; a.download = 'download'; a.click(); }Copy the code

conclusion

The whole process of the case starts from the user uploading pictures. First, the uploaded files are judged to be in accordance with the standards. Then, the pictures are converted into Base64 encoding and the appropriate width and height are set to be displayed on the local web page. Now that the original image has been rendered, it is time to render the compressed image below. Create a canvas object in memory, render the original image to the canvas, compress the image through a key API canvas.toDataURL, which will return the Base64 encoding of the compressed image, and then display the compressed image on the page. Finally, when the user clicks generate, the compressed image can be downloaded to the local smoothly.