61

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

如何在不使用任何服务器端代码的情况下使用一些HTML5 功能在客户端进行图像裁剪。

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

4

4 回答 4

45

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

  1. 加载图像
  2. 将图像绘制到指定裁剪边界的画布中
  3. 从画布中获取图像数据并使其成为hrefdom 中锚标记的属性
  4. 将下载属性 ( download="desired-file-name") 添加到该a元素就是这样。用户所要做的就是单击您的“下载链接”,图像将被下载到他的电脑上。

当我有机会时,我会带着演示回来。

更新
这是我承诺的现场演示。它采用jsfiddle 徽标并裁剪每个边距的 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';

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

更新三 虽然我不能为此提供现场演示(出于安全原因),但这里有一个解决同源策略的 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;

您所要做的就是将图像数据发布到该文件中,它会将图像保存到光盘并返回现有的图像文件名。

当然,这一切可能感觉有点复杂,但我想向您展示您想要实现的目标是可能的。

于 2012-10-04T14:52:35.007 回答
7

Pixastic库完全符合您的要求。但是,它仅适用于支持画布的浏览器。对于那些较旧的浏览器,您需要:

  1. 提供服务器端回退,或
  2. 告诉用户你很抱歉,但他需要一个更现代的浏览器。

当然,选项#2 对用户不是很友好。但是,如果您的意图是提供纯客户端工具和/或您不支持后备后端裁剪器(例如,您可能正在编写浏览器扩展程序或离线 Chrome 应用程序,或者您负担不起一个提供图像处理库的体面的托管服务提供商),那么将您的用户群限制在现代浏览器中可能是公平的。

编辑:如果你不想学习 Pixastic,我在这里的 jsFiddle 上添加了一个非常简单的裁剪器。应该可以修改和集成和使用drawCroppedImageJcrop的功能。

于 2012-10-04T14:41:05.233 回答
3

#change-avatar-file是一个文件输入 #change-avatar-file是一个img标签(jcrop的目标)“关键”是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;
                });
            }
        }
    });
于 2014-04-23T11:09:35.793 回答
-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;
}
于 2012-10-04T15:04:13.263 回答