在上传之前在浏览器中裁剪图像

时间:2012-10-04 13:18:24

标签: javascript html5 html5-canvas

我发现的许多库,如Jcrop,实际上并没有进行裁剪,只会创建一个图像裁剪UI。然后它取决于服务器进行实际裁剪。

如何使用某些 HTML5功能使图像裁剪客户端,而不使用任何服务器端代码。

如果是,是否有一些示例或提示?

4 个答案:

答案 0 :(得分:42)

是的,可以做到。
它基于锚标签的新html5“下载”属性 流程应该是这样的:

  1. 加载图片
  2. 将图像绘制到指定了裁剪边界的画布
  3. 从画布中获取图像数据,并使其成为dom中锚标记的href属性
  4. 将下载属性(download="desired-file-name")添加到该a元素 而已。用户只需点击“下载链接”,图像就会下载到他的电脑上。
  5. 当我有机会的时候,我会带回演示。

    <强>更新
    这是我承诺的the live demo。每个边距需要jsfiddle logo和庄稼5px 代码如下所示:

    var img = new Image();
    img.onload = function(){
        var cropMarginWidth = 5,
            canvas = $('<canvas/>')
                        .attr({
                             width: img.width - 2 * cropMarginWidth,
                             height: img.height - 2 * cropMarginWidth
                         })
                        .hide()
                        .appendTo('body'),
            ctx = canvas.get(0).getContext('2d'),
            a = $('<a download="cropped-image" title="click to download the image" />'),
            cropCoords = {
                topLeft : {
                    x : cropMarginWidth,
                    y : cropMarginWidth 
                },
                bottomRight :{
                    x : img.width - cropMarginWidth,
                    y : img.height - cropMarginWidth
                }
            };
    
        ctx.drawImage(img, cropCoords.topLeft.x, cropCoords.topLeft.y, cropCoords.bottomRight.x, cropCoords.bottomRight.y, 0, 0, img.width, img.height);
        var base64ImageData = canvas.get(0).toDataURL();
    
    
        a
            .attr('href', base64ImageData)
            .text('cropped image')
            .appendTo('body');
    
        a
            .clone()
            .attr('href', img.src)
            .text('original image')
            .attr('download','original-image')
            .appendTo('body');
    
        canvas.remove();
    }
    img.src = 'some-image-src';
    

    更新II
    忘了提:当然有一个缺点:(。 由于也适用于图像的同源策略,如果要访问图像的数据(通过画布方法toDataUrl)。
    因此,您仍然需要一个服务器端代理来为您的映像提供服务,就好像它是在您的域上托管一样。

    更新III 虽然我无法为此提供实时演示(出于安全原因),但这里有一个解决同源策略的php示例代码:

    档案proxy.php

    $imgData = getimagesize($_GET['img']);
    header("Content-type: " . $imgData['mime']);
    echo file_get_contents($_GET['img']);  
    

    这样,不是直接从它的原点加载外部图像:

    img.src = 'http://some-domain.com/imagefile.png';
    

    您可以通过代理加载它:

    img.src = 'proxy.php?img=' + encodeURIComponent('http://some-domain.com/imagefile.png');  
    

    这是一个示例php代码,用于将图像数据(base64)保存到实际图像中:

    档案save-image.php

    $data = preg_replace('/data:image\/(png|jpg|jpeg|gif|bmp);base64/','',$_POST['data']);
    $data = base64_decode($data);
    $img = imagecreatefromstring($data);
    
    $path = 'path-to-saved-images/';
    // generate random name
    $name  = substr(md5(time()),10);
    $ext = 'png';
    $imageName = $path.$name.'.'.$ext;
    
    // write the image to disk
    imagepng($img,  $imageName);
    imagedestroy($img);
    // return the image path
    echo $imageName;
    

    然后,您只需将图像数据发布到此文件,它就会将图像保存到光盘并返回现有的图像文件名。

    当然这一切可能都有点复杂,但我想告诉你,你想要实现的目标是可能的。

答案 1 :(得分:7)

Pixastic库执行exactly what you want。但是,它仅适用于具有画布支持的浏览器。对于那些旧版浏览器,您需要:

  1. 提供服务器端后备或
  2. 告诉用户你很抱歉,但他需要一个更现代的浏览器。
  3. 当然,选项#2不是非常用户友好。但是,如果您的目的是提供纯粹的仅限客户端的工具和/或您无法支持后备后端裁剪器(例如,您可能正在编写浏览器扩展程序或离线Chrome应用程序,或者您可能负担不起一个体面的托管服务提供商,提供图像处理库),然后将您的用户群限制在现代浏览器可能是公平的。

    编辑:如果您不想学习Pixastic,我在jsFiddle here上添加了一个非常简单的裁剪器。应该可以修改和集成并使用drawCroppedImage函数和Jcrop。

答案 2 :(得分:3)

#change-avatar-file是文件输入 #change-avatar-file是一个img标签(jcrop的目标) &#34;键&#34;是FR.onloadend事件 https://developer.mozilla.org/en-US/docs/Web/API/FileReader

$('#change-avatar-file').change(function(){
        var currentImg;
        if ( this.files && this.files[0] ) {
            var FR= new FileReader();
            FR.onload = function(e) {
                $('#avatar-change-img').attr( "src", e.target.result );
                currentImg = e.target.result;
            };
            FR.readAsDataURL( this.files[0] );
            FR.onloadend = function(e){
                //console.log( $('#avatar-change-img').attr( "src"));
                var jcrop_api;

                $('#avatar-change-img').Jcrop({
                    bgFade:     true,
                    bgOpacity: .2,
                    setSelect: [ 60, 70, 540, 330 ]
                },function(){
                    jcrop_api = this;
                });
            }
        }
    });

答案 3 :(得分:-1)

如果你仍然使用JCrop,你只需要这个php函数来裁剪文件:

$img_src = imagecreatefromjpeg($src);
$img_dest = imagecreatetruecolor($new_w,$new_h);
imagecopyresampled($img_dest,$img_src,0,0,$x,$y,$new_w,$new_h,$w,$h);
imagejpeg($img_dest,$dest);

客户方:

jQuery(function($){

    $('#target').Jcrop({
    onChange:   showCoords,
    onSelect:   showCoords,
    onRelease:  clearCoords
    });

});

var x,y,w,h; //these variables are necessary to crop
function showCoords(c)
{
    x = c.x;
    y = c.y;
    w = c.w;
    h = c.h;
};
function clearCoords()
{
    x=y=w=h=0;
}