How to implement compression

Check MDN and find this API:

The htmlCanvasElement.toblob () method creates Blob objects that display images on the canvas; This image file can be cached or saved locally at the discretion of the user agent. The default image type is image/ PNG and the resolution is 96dpi unless otherwise specified.

// Callback processing blob main, type image type, encoderOptions image compression ratio 0-1
canvas.toBlob(callback, type, encoderOptions); 

Copy the code

# rendering

Demo

# implementation code


      
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            padding: 20px 0;
        }
        #fileSelect{
            margin-top: 10px;
            padding: 10px 5px;
            border: 1px solid chartreuse;
            border-radius: 5px;
            background: green;
            color: white;
            text-decoration: none;
        }
        #fileSelect:hover{
            opacity: 0.8;
        }

    </style>
</head>

<body>
    <input type="file" id="fileElem" multiple accept="image/*" style="display:none"
        onchange="handleFiles(event,this.files)">
    <a href="#" id="fileSelect">Click on the upload</a>
</body>
<script>
    window.onload = function () {
        var fileSelect = document.getElementById("fileSelect"),
            fileElem = document.getElementById("fileElem");
        fileSelect.addEventListener("click".function (e) {
            if (fileElem) {
                fileElem.click(); // input File upload
            }
            e.preventDefault(); 
        }, false);
    }
    function handleFiles(e, files) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var imageType = /^image\//;
            if(! imageType.test(file.type)) {continue;
            }
            console.log(file);

            const width = 500;
            const height = 300;
            const fileName = file.name;
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = event= > {
                const img = new Image();
                img.src = reader.result;
                img.onload = (a)= > {
                    const elem = document.createElement('canvas');
                    elem.width = width;
                    elem.height = height;
                    const ctx = elem.getContext('2d');
                    Canvas size Settings
                    ctx.drawImage(img, 0.0, width, height);
                    // Embed content
                    document.body.append(elem);
                    //--------- if you do not need to upload the resource, just display it, the following code can not be removed ------
                    ctx.canvas.toBlob((blob) = > {
                        const file = new File([blob], fileName, {
                            type: 'image/jpeg'.lastModified: Date.now()
                        });
                        console.log(file); // file is the compressed image
                    }, 'image/jpeg'.10e-9);
                    // ----------------------
                    
                },
                reader.onerror = error= > console.log(error); }; }}</script>

</html>
Copy the code

# process

1.new FileReader()

The first thing you need to do is use the API to read the file, instantiate it and use readAsDataURL to read the resource path of the image. This is compatible with almost all browser versions and platforms.Copy the code

reader.readAsDataURL(file); // We can do multiple operations in the above example, so we loopCopy the code

2. Create images in the reader.onload callback

// Create the image content
 const img = new Image();
// If you want to bind the image address to base64, there is a problem with event. Target. Result
 img.src = reader.result;

Copy the code

3. Create canvas and draw picture content

 // Create canvas canvas
 const elem = document.createElement('canvas');
 // Set the canvas size
 elem.width = width; 
 elem.height = height;
 / / get 🖌 ️
 const ctx = elem.getContext('2d')
 / / to draw
 ctx.drawImage(img, 0.0, width, height); // drawImage
 // Populate the page
 document.body.append(elem);

Copy the code

4. Focus on compression and convert canvas compression size into image object

ctx.canvas.toBlob((blob) = > {
    const file = new File([blob], fileName, {
        type: 'image/jpeg'.// The format can be JPG, PNG, GIF, PNG etc
        lastModified: Date.now()
    });
    console.log(file);
}, 'image/jpeg'.10e-9); // 10E-9 here is very small limit 0-1 0 is the maximum compression ratio, 1 is a little bit metaphysically bigger than 1 or less than 0 it's about 60% compressed
Copy the code

# added

Here we see a compatibility issue, the main consideration is Sarari IOS, who calls the customer to use it?

// MDN adds toBlob functions to the Object prototype in addition to compatible code
if(! HTMLCanvasElement.prototype.toBlob) {Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {
      var dataURL = this.toDataURL(type, quality).split(', ') [1];
      setTimeout(function() {

        var binStr = atob( dataURL ),
            len = binStr.length,
            arr = new Uint8Array(len);

        for (var i = 0; i < len; i++ ) {
          arr[i] = binStr.charCodeAt(i);
        }

        callback( new Blob( [arr], {type: type || 'image/jpeg'})); }); }}); }Copy the code

# epilogue

The information on the net is very much, did not find once can run, check search to realize the function, still can use, it is true. — No one was around on March 25, 2019

# References

  • The MIME type

  • HTMLCanvasElement.toBlob()

  • FileReader

  • Canvas API

  • CanvasRenderingContext2D.drawImage()