html5对图片的支持

以前要想在图片上传前,对图片剪裁下,纯用js的话,很难实现。现在有了html5了,腰也不疼了,腿也不抽筋了。

主要用到html5的2个特性:

 

1、FileReader

FileReader可以把本地文件进行读取并且转化为Base64编码的数据,很便于在html页面里显示。

 

2、canvas

对图片的放大缩小啊,左移右移啊,实现起来很简单。尤其是它还可以对图片的像素进行操作(红、绿、蓝、透明),最后利用toDataURL方法用图片进行剪裁。美中不足的话,目前还不支持gif格式,有点小遗憾。

 

下面是我写的一个简易小例子的片段(完整代码在附件里)

 

选择图片用的是

 

<input id="upload" type="file" />
 

 

选择文件生成Base64及图片加载后初始化canvas的代码:

 

var upload = $('#upload');
upload.change(function (e) {
    e.preventDefault();

    var file = upload[0].files[0],
    reader = new FileReader();
    reader.onload = function (event) {
        img.src = event.target.result;
        var result = img.src.toString().match(/^data:(image\/[a-z+]+);base64,/);
        if (result) {
            imgType = result[1];
        }

    };
    reader.readAsDataURL(file);

    return false;
});

img.onload = function () {
    var min = Math.min(img.width, img.height);
    scale = (bWH - 2 * borderWH) / min;
    $('#range').attr('min', scale * 100);
    // 判断下可放缩的范围
    if (min >= (bWH - 2 * borderWH)) {
        $('#range').attr('max', 100);
    }
    else {
        $('#range').attr('max', scale * 100)
    }
    canvasScale(true, scale);
    $('#range').val(scale * 100);
}

 

 

对图片放缩时,我没有使用canvas的scale方法,因为它会把canvas的大小也一起放缩了,和我想实现的需求不符。我利用的是canvas的drawImage的方法。放大就把dw、dh相应放大,缩小就相应缩小达到类似的效果。

 

function canvasScale(init, num) {
    var w = img.width;
    var h = img.height;
    scale = num;
    dw = w * scale;
    dh = h * scale;
    if (init) {
        dx = 0;
        dy = 0;
        if (bWH > dw) {
            dx = (bWH - dw) / 2;
        }
        if (bWH > dh) {
            dy = (bWH - dh) / 2;
        }
    }
    else {
        if (dx > borderWH) {
            dx = borderWH;
        }
        else if (dx < bWH - borderWH - dw) {
            dx = bWH - borderWH - dw;
        }
        if (dy > borderWH) {
            dy = borderWH;
        }
        else if (dy < bWH - borderWH - dh) {
            dy = bWH - borderWH - dh;
        }
    }
    // 大图
    ctx.clearRect(0, 0, bWH, bWH);
    ctx.drawImage(img, 0, 0, w, h, dx, dy, dw, dh);
    // 大图四周的框
    canvasPadding(ctx, borderWH, bWH);

    // 小图
    ctxSmall.clearRect(0, 0, sWH, sWH);
    ctxSmall.drawImage(img, (15 - dx) / scale, (15 - dy) / scale,
        (bWH - 2 * borderWH) / scale, (bWH - 2 * borderWH) / scale,
        0, 0, sWH, sWH);
}

 

 

最后就剩下一个截取功能了

 

function canvasToDataURL() {
    var canvasTmp = document.createElement('canvas');
    canvasTmp.width = bWH - 2 * borderWH;
    canvasTmp.height = bWH - 2 * borderWH;
    var ctxTmp = canvasTmp.getContext('2d');
    ctxTmp.drawImage(img, (15 - dx) / scale, (15 - dy) / scale,
        (bWH - 2 * borderWH) / scale, (bWH - 2 * borderWH) / scale,
        0, 0, canvasTmp.width, canvasTmp.height);
    // 像素操作
    var imgPixels = ctxTmp.getImageData(0, 0, canvasTmp.width, canvasTmp.height);
    var lenW = imgPixels.width;
    var lenH = imgPixels.height;
    var red = $('#red').val();
    var green = $('#green').val();
    var blue = $('#blue').val();
    var opacity = $('#opacity').val();
    for (var y = 0; y < lenH; y++) {
        for (var x = 0; x < lenW; x++) {
            imgPixels.data[4 * (y * lenW + x) + 0] *= red;
            imgPixels.data[4 * (y * lenW + x) + 1] *= green;
            imgPixels.data[4 * (y * lenW + x) + 2] *= blue;
            imgPixels.data[4 * (y * lenW + x) + 3] = opacity;
        }
    }
    ctxTmp.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
    // 生成对应类型的图片
    return canvasTmp.toDataURL(imgType);
}
 

测试如下:

ff,chrome,mx3都支持FileReader和canvas。

mx3下FileReader还有点问题,估计日后会改好。

chrome本地安全问题,需要放到服务器上才能看效果。

ff目前对<input type="range" />还不支持。

你可能感兴趣的:(html5)