jCrop 在更改图像时使用正确的坐标调整大小
jCrop resize with correct coords when changing image
希望这不会被标记为重复,因为 SO 上的另一个 q/as 的 none 帮助我解决了这个问题,我想我需要更具体的帮助。
我的网站上有一个个人资料页面,允许用户更改他们的个人资料图片而无需重新加载页面(通过 AJAX / jQuery)。
一切正常。用户打开 "Change Profile Picture" 模式,选择要上传的文件并按 "Crop this image"。按下此按钮时,它会使用发送文件和 formData(我将文件数据附加到其中)的典型方式将文件上传到网站。
它通过以下 jQuery 发送到后端:
// Upload the image for cropping (Crop this Image!)
$("#image-upload").click(function(){
// File data
var fileData = $("#image-select").prop("files")[0];
// Set up a form
var formData = new FormData();
// Append the file to the new form for submission
formData.append("file", fileData);
// Send the file to be uploaded
$.ajax({
// Set the params
cache: false,
contentType: false,
processData: false,
// Page & file information
url: "index.php?action=uploadimage",
dataType: "text",
type: "POST",
// The data to send
data: formData,
// On success...
success: function(data){
// If no image was returned
// "not-image" is returned from the PHP script if we return it in case of an error
if(data == "not-image"){
alert("That's not an image, please upload an image file.");
return false;
}
// Else, load the image on to the page so we don't need to reload
$(profileImage).attr("src", data);
// If the API is already set, then we should apply a new image
if(jCropAPI){
jCropAPI.setImage(data + "?" + new Date().getTime());
}
// Initialise jCrop
setJCrop();
//$("#image-profile").show();
$("#send-coords").show();
}
})
});
setJcrop 执行以下操作
function setJCrop(){
// Get width / height of the image
var width = profileImage.width();
var height = profileImage.height();
// Var containing the source image
var imgSource = profileImage.attr("src");
// New image object to work on
var image = new Image();
image.src = imgSource;
// The SOURCE (ORIGINAL) width / height
var origWidth = image.width;
var origHeight = image.height;
// Set up the option to jCrop it
$(profileImage).Jcrop({
onSelect: setCoords,
onChange: setCoords,
setSelect: [0, 0, 51, 51],
aspectRatio: 1, // This locks it to a square image, so it fits the site better
boxWidth: width,
boxHeight: height, // Fixes the size permanently so that we can load new images
}, function(){jCropAPI = this});
setOthers(width, height, origWidth, origHeight);
}
一旦后端,它会执行以下操作:
public function uploadImage($file){
// See if there is already an error
if(0 < $file["file"]["error"]){
return $file["file"]["error"] . " (error)";
}else{
// Set up the image
$image = $file["file"];
$imageSizes = getimagesize($image["tmp_name"]);
// If there are no image sizes, return the not-image error
if(!$imageSizes){
return "not-image";
}
// SIZE LIMIT HERE SOON (TBI)
// Set a name for the image
$username = $_SESSION["user"]->getUsername();
$fileName = "images/profile/$username-profile-original.jpg";
// Move the image which is guaranteed a unique name (unless it is due to overwrite), to the profile pictures folder
move_uploaded_file($image["tmp_name"], $fileName);
// Return the new filename
return $fileName;
}
}
然后,用户使用选择器在图像上选择他们的区域并按下 "Change Profile Picture",这将执行以下操作
// Send the Coords and upload the new image
$("#send-coords").click(function(){
$.ajax({
type: "POST",
url: "index.php?action=uploadprofilepicture",
data: {
coordString: $("#coords").text() + $("#coords2").text(),
imgSrc: $("#image-profile").attr("src")
},
success: function(data){
if(data == "no-word"){
alert("Can not work with this image type, please try with another image");
}else{
// Append a date to make sure it reloads the image without using a cached version
var dateNow = new Date();
var newImageLink = data + "?" + dateNow.getTime();
$("#profile-picture").attr("src", newImageLink);
// Hide the modal
$("#profile-picture-modal").modal("hide");
}
}
});
})
后端是:
public function uploadProfilePicture($coordString, $imgSrc){
// Target dimensions
$tarWidth = $tarHeight = 150;
// Split the coords in to an array (sent by a string that was created by JS)
$coordsArray = explode(",", $coordString);
//Set them all from the array
$x = $coordsArray[0];
$y = $coordsArray[1];
$width = $coordsArray[2];
$height = $coordsArray[3];
$newWidth = $coordsArray[4];
$newHeight = $coordsArray[5];
$origWidth = $coordsArray[6];
$origHeight = $coordsArray[7];
// Validate the image and decide which image type to create the original resource from
$imgDetails = getimagesize($imgSrc);
$imgMime = $imgDetails["mime"];
switch($imgMime){
case "image/jpeg":
$originalImage = imagecreatefromjpeg($imgSrc);
break;
case "image/png":
$originalImage = imagecreatefrompng($imgSrc);
break;
default:
return "no-work";
}
// Target image resource
$imgTarget = imagecreatetruecolor($tarWidth, $tarHeight);
$img = imagecreatetruecolor($newWidth, $newHeight);
// Resize the original image to work with our coords
imagecopyresampled($img, $originalImage, 0, 0, 0, 0,
$newWidth, $newHeight, $origWidth, $origHeight);
// Now copy the CROPPED image in to the TARGET resource
imagecopyresampled(
$imgTarget, // Target resource
$img, // Target image
0, 0, // X / Y Coords of the target image; this will always be 0, 0 as we do not want any black nothingness
$x, $y, // X / Y Coords (top left) of the target area
$tarWidth,
$tarHeight, // width / height of the target
$width,
$height // Width / height of the source image crop
);
$username = $_SESSION["user"]->getUsername();
$newPath = "images/profile/$username-profile-cropped.jpg";
// Create that shit!
imagejpeg($imgTarget, $newPath);
// Return the path
return $newPath;
}
所以基本上这是 returns 新文件的路径,它会更改为用户的个人资料图片(每次都使用相同的名称)并在 ?
之后附加时间进行实时上传以刷新图片正确(无缓存)。
这一切都很好,但是如果用户选择另一张图片上传,在已经上传一张之后,坐标会变得一团糟(例如,它们从 50 变为 250)并且他们最终裁剪了完全不同的部分图像,留下大部分黑色虚无。
对于这个问题中的大量代码,我深表歉意,但如果之前可能解决过这个问题的人提供任何帮助,我将不胜感激。
有些代码可能看起来不合适,但这只是我在调试它。
谢谢,再一次,对于这个问题的大小感到抱歉。
-编辑-
我的 setCoords()
和 setOthers()
函数如下所示:
//Set the coords with this method, that is called every time the user makes / changes a selection on the crop panel
function setCoords(c){
$("#coords").text(c.x + "," + c.y + "," + c.w + "," + c.h + ",");
}
//This one adds the other parts to the second div; they will be concatenated in to the POST string
function setOthers(width, height, origWidth, origHeight){
$("#coords2").text(width + "," + height + "," + origWidth + "," + origHeight);
}
我使用了 jcrop,我认为这发生在我身上。当有新图像时,您必须"reset" jcrop。尝试这样的事情:
function resetJCrop()
{
if (jCropAPI) {
jCropAPI.disable();
jCropAPI.release();
jCropAPI.destroy();
}
}
$("#image-upload").click(function(){
success: function(data){
...
resetJCrop(); // RESETTING HERE
// If the API is already set, then we should apply a new image
if(jCropAPI){
jCropAPI.setImage(data + "?" + new Date().getTime());
}
// Initialise jCrop
setJCrop();
...
}
});
我不记得为什么我必须在特定情况下使用 disable() AND release() AND destroy() 的详细信息。可能你只能使用其中一个。试试吧,看看是否适合您!
我现在已经解决了这个问题。
我的问题是在使用 setJCrop() 时; - 它没有重新加载图像。原因是每次上传然后加载到 JCrop window 的图像都具有相同的名称(用户名作为前缀,然后是配置文件-cropped.jpg)。
因此,为了尝试解决这个问题,我使用了 setImage 方法来加载全尺寸图像。
我通过设置 boxWidth / boxHeight 参数解决了这个问题,但每次我加载新图像时它们都会给我留下坐标不正确的问题。
事实证明,它每次都从缓存中加载图像,即使我在 jQuery.
中使用 new Image();
也是如此
为了解决这个问题,我现在使用了 destroy();在 jCropAPI 上,然后每次都重新初始化它,不使用 setImage();
我在图像本身的 CSS 中设置了最大宽度,这阻止了它被锁定到特定宽度。
下一个问题是,每次我第二次加载图像时,旧图像的宽度/高度都留在那里,这使得图像看起来完全倾斜和错误。
为了解决这个问题,我将使用 jCrop 的图像的宽度和高度重置为 ""
和 $(profileImage).css("width", ""); $(profileImage).css("height", "");
,然后再从新上传的图像重新设置图像源.
但我仍然遇到在图像上使用相同名称,然后每次都从缓存中加载它的问题。
我的解决方案是在数据库中添加一个 "avatar" 列,每次都将图像名称保存在数据库中。该图像被命名为 $username-$time.jpg
和 $username-$time.jpg-cropped.jpg
,其中 $username 是用户的用户名 (derp),$time 只是 PHP.
中的 time();
这意味着每次我上传一张图片时,它都有一个新名称,所以当对该图片进行任何调用时,没有它的缓存。
像 imageName + ".jpg?" + new Date.getTime();
这样的追加对某些事情有用,但是当发送图像名称后端时,它不能正常工作,决定何时追加/不追加它很痛苦,然后一件事要求附加它以强制重新加载,但是当附加它时它不能正常工作,所以我不得不重新处理它。
所以关键是:(TL;DR)
如果您要加载新图像,请不要使用与 jCrop 相同的图像名称;上传具有不同名称的图像,然后引用该图像。缓存问题很痛苦,如果不每次都使用一个新名称,就无法真正解决它们,因为这可以确保绝对不会再出现问题(只要名称始终是唯一的)。
然后在初始化jCrop的时候,如果有之前的就先销毁掉。在图像上使用 max-width
而不是 width
以阻止它锁定宽度,如果您要将新图像加载到相同的 [=19] 中,请重新设置图像的宽度/高度=] 或 <div>
希望这对某人有所帮助!
希望这不会被标记为重复,因为 SO 上的另一个 q/as 的 none 帮助我解决了这个问题,我想我需要更具体的帮助。
我的网站上有一个个人资料页面,允许用户更改他们的个人资料图片而无需重新加载页面(通过 AJAX / jQuery)。
一切正常。用户打开 "Change Profile Picture" 模式,选择要上传的文件并按 "Crop this image"。按下此按钮时,它会使用发送文件和 formData(我将文件数据附加到其中)的典型方式将文件上传到网站。
它通过以下 jQuery 发送到后端:
// Upload the image for cropping (Crop this Image!)
$("#image-upload").click(function(){
// File data
var fileData = $("#image-select").prop("files")[0];
// Set up a form
var formData = new FormData();
// Append the file to the new form for submission
formData.append("file", fileData);
// Send the file to be uploaded
$.ajax({
// Set the params
cache: false,
contentType: false,
processData: false,
// Page & file information
url: "index.php?action=uploadimage",
dataType: "text",
type: "POST",
// The data to send
data: formData,
// On success...
success: function(data){
// If no image was returned
// "not-image" is returned from the PHP script if we return it in case of an error
if(data == "not-image"){
alert("That's not an image, please upload an image file.");
return false;
}
// Else, load the image on to the page so we don't need to reload
$(profileImage).attr("src", data);
// If the API is already set, then we should apply a new image
if(jCropAPI){
jCropAPI.setImage(data + "?" + new Date().getTime());
}
// Initialise jCrop
setJCrop();
//$("#image-profile").show();
$("#send-coords").show();
}
})
});
setJcrop 执行以下操作
function setJCrop(){
// Get width / height of the image
var width = profileImage.width();
var height = profileImage.height();
// Var containing the source image
var imgSource = profileImage.attr("src");
// New image object to work on
var image = new Image();
image.src = imgSource;
// The SOURCE (ORIGINAL) width / height
var origWidth = image.width;
var origHeight = image.height;
// Set up the option to jCrop it
$(profileImage).Jcrop({
onSelect: setCoords,
onChange: setCoords,
setSelect: [0, 0, 51, 51],
aspectRatio: 1, // This locks it to a square image, so it fits the site better
boxWidth: width,
boxHeight: height, // Fixes the size permanently so that we can load new images
}, function(){jCropAPI = this});
setOthers(width, height, origWidth, origHeight);
}
一旦后端,它会执行以下操作:
public function uploadImage($file){
// See if there is already an error
if(0 < $file["file"]["error"]){
return $file["file"]["error"] . " (error)";
}else{
// Set up the image
$image = $file["file"];
$imageSizes = getimagesize($image["tmp_name"]);
// If there are no image sizes, return the not-image error
if(!$imageSizes){
return "not-image";
}
// SIZE LIMIT HERE SOON (TBI)
// Set a name for the image
$username = $_SESSION["user"]->getUsername();
$fileName = "images/profile/$username-profile-original.jpg";
// Move the image which is guaranteed a unique name (unless it is due to overwrite), to the profile pictures folder
move_uploaded_file($image["tmp_name"], $fileName);
// Return the new filename
return $fileName;
}
}
然后,用户使用选择器在图像上选择他们的区域并按下 "Change Profile Picture",这将执行以下操作
// Send the Coords and upload the new image
$("#send-coords").click(function(){
$.ajax({
type: "POST",
url: "index.php?action=uploadprofilepicture",
data: {
coordString: $("#coords").text() + $("#coords2").text(),
imgSrc: $("#image-profile").attr("src")
},
success: function(data){
if(data == "no-word"){
alert("Can not work with this image type, please try with another image");
}else{
// Append a date to make sure it reloads the image without using a cached version
var dateNow = new Date();
var newImageLink = data + "?" + dateNow.getTime();
$("#profile-picture").attr("src", newImageLink);
// Hide the modal
$("#profile-picture-modal").modal("hide");
}
}
});
})
后端是:
public function uploadProfilePicture($coordString, $imgSrc){
// Target dimensions
$tarWidth = $tarHeight = 150;
// Split the coords in to an array (sent by a string that was created by JS)
$coordsArray = explode(",", $coordString);
//Set them all from the array
$x = $coordsArray[0];
$y = $coordsArray[1];
$width = $coordsArray[2];
$height = $coordsArray[3];
$newWidth = $coordsArray[4];
$newHeight = $coordsArray[5];
$origWidth = $coordsArray[6];
$origHeight = $coordsArray[7];
// Validate the image and decide which image type to create the original resource from
$imgDetails = getimagesize($imgSrc);
$imgMime = $imgDetails["mime"];
switch($imgMime){
case "image/jpeg":
$originalImage = imagecreatefromjpeg($imgSrc);
break;
case "image/png":
$originalImage = imagecreatefrompng($imgSrc);
break;
default:
return "no-work";
}
// Target image resource
$imgTarget = imagecreatetruecolor($tarWidth, $tarHeight);
$img = imagecreatetruecolor($newWidth, $newHeight);
// Resize the original image to work with our coords
imagecopyresampled($img, $originalImage, 0, 0, 0, 0,
$newWidth, $newHeight, $origWidth, $origHeight);
// Now copy the CROPPED image in to the TARGET resource
imagecopyresampled(
$imgTarget, // Target resource
$img, // Target image
0, 0, // X / Y Coords of the target image; this will always be 0, 0 as we do not want any black nothingness
$x, $y, // X / Y Coords (top left) of the target area
$tarWidth,
$tarHeight, // width / height of the target
$width,
$height // Width / height of the source image crop
);
$username = $_SESSION["user"]->getUsername();
$newPath = "images/profile/$username-profile-cropped.jpg";
// Create that shit!
imagejpeg($imgTarget, $newPath);
// Return the path
return $newPath;
}
所以基本上这是 returns 新文件的路径,它会更改为用户的个人资料图片(每次都使用相同的名称)并在 ?
之后附加时间进行实时上传以刷新图片正确(无缓存)。
这一切都很好,但是如果用户选择另一张图片上传,在已经上传一张之后,坐标会变得一团糟(例如,它们从 50 变为 250)并且他们最终裁剪了完全不同的部分图像,留下大部分黑色虚无。
对于这个问题中的大量代码,我深表歉意,但如果之前可能解决过这个问题的人提供任何帮助,我将不胜感激。
有些代码可能看起来不合适,但这只是我在调试它。
谢谢,再一次,对于这个问题的大小感到抱歉。
-编辑-
我的 setCoords()
和 setOthers()
函数如下所示:
//Set the coords with this method, that is called every time the user makes / changes a selection on the crop panel
function setCoords(c){
$("#coords").text(c.x + "," + c.y + "," + c.w + "," + c.h + ",");
}
//This one adds the other parts to the second div; they will be concatenated in to the POST string
function setOthers(width, height, origWidth, origHeight){
$("#coords2").text(width + "," + height + "," + origWidth + "," + origHeight);
}
我使用了 jcrop,我认为这发生在我身上。当有新图像时,您必须"reset" jcrop。尝试这样的事情:
function resetJCrop()
{
if (jCropAPI) {
jCropAPI.disable();
jCropAPI.release();
jCropAPI.destroy();
}
}
$("#image-upload").click(function(){
success: function(data){
...
resetJCrop(); // RESETTING HERE
// If the API is already set, then we should apply a new image
if(jCropAPI){
jCropAPI.setImage(data + "?" + new Date().getTime());
}
// Initialise jCrop
setJCrop();
...
}
});
我不记得为什么我必须在特定情况下使用 disable() AND release() AND destroy() 的详细信息。可能你只能使用其中一个。试试吧,看看是否适合您!
我现在已经解决了这个问题。
我的问题是在使用 setJCrop() 时; - 它没有重新加载图像。原因是每次上传然后加载到 JCrop window 的图像都具有相同的名称(用户名作为前缀,然后是配置文件-cropped.jpg)。
因此,为了尝试解决这个问题,我使用了 setImage 方法来加载全尺寸图像。
我通过设置 boxWidth / boxHeight 参数解决了这个问题,但每次我加载新图像时它们都会给我留下坐标不正确的问题。
事实证明,它每次都从缓存中加载图像,即使我在 jQuery.
中使用new Image();
也是如此
为了解决这个问题,我现在使用了 destroy();在 jCropAPI 上,然后每次都重新初始化它,不使用 setImage();
我在图像本身的 CSS 中设置了最大宽度,这阻止了它被锁定到特定宽度。
下一个问题是,每次我第二次加载图像时,旧图像的宽度/高度都留在那里,这使得图像看起来完全倾斜和错误。
为了解决这个问题,我将使用 jCrop 的图像的宽度和高度重置为 ""
和 $(profileImage).css("width", ""); $(profileImage).css("height", "");
,然后再从新上传的图像重新设置图像源.
但我仍然遇到在图像上使用相同名称,然后每次都从缓存中加载它的问题。
我的解决方案是在数据库中添加一个 "avatar" 列,每次都将图像名称保存在数据库中。该图像被命名为 $username-$time.jpg
和 $username-$time.jpg-cropped.jpg
,其中 $username 是用户的用户名 (derp),$time 只是 PHP.
time();
这意味着每次我上传一张图片时,它都有一个新名称,所以当对该图片进行任何调用时,没有它的缓存。
像 imageName + ".jpg?" + new Date.getTime();
这样的追加对某些事情有用,但是当发送图像名称后端时,它不能正常工作,决定何时追加/不追加它很痛苦,然后一件事要求附加它以强制重新加载,但是当附加它时它不能正常工作,所以我不得不重新处理它。
所以关键是:(TL;DR)
如果您要加载新图像,请不要使用与 jCrop 相同的图像名称;上传具有不同名称的图像,然后引用该图像。缓存问题很痛苦,如果不每次都使用一个新名称,就无法真正解决它们,因为这可以确保绝对不会再出现问题(只要名称始终是唯一的)。
然后在初始化jCrop的时候,如果有之前的就先销毁掉。在图像上使用 max-width
而不是 width
以阻止它锁定宽度,如果您要将新图像加载到相同的 [=19] 中,请重新设置图像的宽度/高度=] 或 <div>
希望这对某人有所帮助!