上传前在浏览器中裁剪图像
我发现的许多库,例如 Jcrop,实际上并没有进行裁剪,它只创建了一个图像裁剪 UI.然后,它取决于进行实际裁剪的服务器.
Many libraries I have found, like Jcrop, do not actually do the cropping, it only creates an image cropping UI. It then depends on the server doing the actual cropping.
如何在不使用任何服务器端代码的情况下使用一些HTML5 功能 来使图像裁剪客户端.
How can I make the image cropping client-side by using some HTML5 feature without using any server-side code.
如果有,是否有一些例子或提示?
If yes, are there some examples or hints?
推荐答案
可以的.
它基于锚标签的新 html5下载"属性.
流程应该是这样的:
Yes, it can be done.
It is based on the new html5 "download" attribute of anchor tags.
The flow should be something like this :
- 加载图片
- 将图像绘制到指定裁剪边界的画布中
- 从画布中获取图像数据并使其成为 dom 中锚标记的
href
属性 - 将下载属性 (
download="desired-file-name"
) 添加到该a
元素而已.用户所要做的就是单击您的下载链接",图像将被下载到他的电脑上.
- load the image
- draw the image into a canvas with the crop boundaries specified
- get the image data from the canvas and make it a
href
attribute for an anchor tag in the dom - add the download attribute (
download="desired-file-name"
) to thata
element That's it. all the user has to do is click your "download link" and the image will be downloaded to his pc.
有机会我会回来做一个演示的.
I'll come back with a demo when I get the chance.
更新
这是我承诺的现场演示.它采用 jsfiddle 徽标 并裁剪每个边距的 5px.
代码如下所示:
Update
Here's the live demo as I promised. It takes the jsfiddle logo and crops 5px of each margin.
The code looks like this :
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
).
因此,您仍然需要一个服务器端代理来为您的图像提供服务,就好像它托管在您的域上一样.
Update II
Forgot to mention : of course there is a downside :(.
Because of the same-origin policy that is applied to images too, if you want to access an image's data (through the canvas method toDataUrl
).
So you would still need a server-side proxy that would serve your image as if it were hosted on your domain.
更新 III虽然我不能为此提供现场演示(出于安全原因),但这里有一个解决同源策略的 php 示例代码:
Update III Although I can't provide a live demo for this (for security reasons), here is a php sample code that solves the same-origin policy :
文件proxy.php
:
$imgData = getimagesize($_GET['img']);
header("Content-type: " . $imgData['mime']);
echo file_get_contents($_GET['img']);
这种方式,而不是直接从它的原点加载外部图像:
This way, instead of loading the external image direct from it's origin :
img.src = 'http://some-domain.com/imagefile.png';
您可以通过代理加载它:
You can load it through your proxy :
img.src = 'proxy.php?img=' + encodeURIComponent('http://some-domain.com/imagefile.png');
这是一个将图像数据(base64)保存到实际图像中的示例 php 代码:
And here's a sample php code for saving the image data (base64) into an actual image :
文件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;
然后您所要做的就是将图像数据发布到此文件,它会将图像保存到光盘并返回现有图像文件名.
All you have to do then is post the image data to this file and it will save the image to disc and return you the existing image filename.
当然,这一切可能感觉有点复杂,但我想告诉你,你想要达到的目标是可能的.
Of course all this might feel a bit complicated, but I wanted to show you that what you're trying to achieve is possible.
相关文章