首发于那阵东风
迎接没有 Flash 的时代 | 头像裁剪 (A mini web page to crop avatar from local image with canvas)

迎接没有 Flash 的时代 | 头像裁剪 (A mini web page to crop avatar from local image with canvas)

Usually, we use Adobe Flash plugin to implement a web image cropping operation. But with the news that Adobe announced the deadline of Flash, it would be an emergency to find an alternative to perform such a image crop work. So I choose the HTML5 Canvas as my tool.

Here is a demo (also available on Github).


Demo Introduction

After loading the page, click (Aka. tap on mobile devices with touch screen.) upload to select an image from local machine. After less than a second, you will see the image loaded to the very center of the 3rd section.

As you can see, there is an area which is a little bit darker than the others within the image. That is called the “focus”. A focus is something that you may drag or click or move to change its position. And its size (Aka. zoom) will be controlled by the slider on section 4.

With the change of focus, the preview avatar will also change to show how the result image looks like after all the adjustment. Once the preview image is changed, the text in section 5 will change to show the latest image DataURL. This is very useful when we want to cache the image data.

How to make it?

It’s never hard to do something that is already designed in your brain. All we need to do is think, think and code.

What do we want?

We want to:

  1. Display the image we selected.
  2. Map the focus with user mouse position (Aka. event binding).
  3. Crop and display image data and preview every time the focus changes (zoom and position).
  4. Export DataURL as text.

Main steps

First of all, we have to handle event triggered after the file selection operation.

// TypeScript

upload_control.addEventListener('change', (ev) => {
    let files = upload_control.files; // upload_control is an input element with type 'file'
    if (files.length > 0) {
        let reader = new FileReader();
        reader.readAsDataURL(files.item(0));
        reader.onloadend = (ev) => {
            let filevalue = reader.result as string;
            // ... something after loading.
        };
    }
});

Crop and get the image data.

// TypeScript

let imagedata = context.getImageData(X - RADIUS, Y - RADIUS, 2 * RADIUS, 2 * RADIUS);
let tempimage = document.createElement('img');
let tempcanvas = document.createElement('canvas');
tempcanvas.width = 2 * RADIUS;
tempcanvas.height = 2 * RADIUS;
document.body.appendChild(tempcanvas);
document.body.appendChild(tempimage);
let tempcontext = tempcanvas.getContext('2d');
tempcontext.putImageData(imagedata, 0, 0);
let imageuri = tempcanvas.toDataURL();
tempimage.width = 2 * ORI_RADIUS;
tempimage.height = 2 * ORI_RADIUS;
tempimage.src = imageuri;
tempimage.style.opacity = '0';
tempcanvas.remove();
setTimeout(() => {
    context_preview.clearRect(0, 0, 2 * ORI_RADIUS, 2 * ORI_RADIUS);
    context_preview.drawImage(tempimage, 0, 0, 2 * OR7“I_RADIUS, 2 * ORI_RADIUS);
    tempimage.remove();
  }, 50);

Something Important

When you change src property of an image, wait for more 16 milliseconds before next operation. Or you will not get the correct information you want.

This project is also developing. Currently, I support Chrome 60 on all platforms (I didn’t test on other versions). And as I’m not perfect, this repository is not perfect, open issues or write emails to me, THX!


欢迎访问我的博客 devchache.com.

编辑于 2017-08-29 20:56