javascript - and - jquery crop image before upload
jCrop(jQuery) a veces no carga la imagen/área de recorte (6)
Aquí mi extraña pero fantástica solución:
if (obj.tagName == ''IMG'') {
var tempImage = new Image();
tempImage.src = $origimg[0].src;
$origimg.width(tempImage.width);
$origimg.height(tempImage.height);
if ($origimg[0].width > 1 && $origimg[0].height > 1) {
$origimg.width($origimg[0].width);
$origimg.height($origimg[0].height);
} else {
var tempImage = new Image();
tempImage.src = $origimg[0].src;
$origimg.width(tempImage.width);
$origimg.height(tempImage.height);
//console.log(''error''+$origimg[0].width + $origimg[0].height);
}
Tengo un problema bastante simple, pero no tengo ni idea de lo que está causando el problema. En una de mis aplicaciones, estoy usando jCrop como un pequeño complemento para recortar imágenes y colocarlas en banners / encabezados, etc. Estos pasos se seguirán:
1) Select an image (using CKFinder for this, CKFinder returns the image path to an input field)
2) Click a button to load the image
3) Crop the image
4) Save the image
en aproximadamente el 75% de los casos, todo va según lo planeado, sin embargo, en el otro 25% de los casos, jCrop no carga el área de recorte y la deja en blanco. Aquí está el código jQuery que estoy usando:
jQuery(''#selectimg'').live(''click'', function(e) {
e.preventDefault();
var newsrc = jQuery(''#img2'').val();
jQuery(''#cropbox'').attr(''src'', newsrc);
var jcrop_api = jQuery.Jcrop(''#cropbox'', {
boxWidth: 700,
boxHeight: 700,
onSelect: updateCoords,
onChange: updateCoords
});
//Some other JS code come''s here for buttons (they work all the time)
});
Noté que cuando dejé la parte donde se transformaba #cropbox en un área recortable, que la imagen se está cargando bien, entonces el error está en la parte var = jcrop_api
, pero lentamente empiezo a pensar que no hay solución para esto...
Esto es lo que he intentado hasta ahora:
Crear un div <div id="cropper-box"></div>
y usar jQuery(''#cropper-box'').append(''<img src="" id="cropbox" />'');
y luego establecer el valor. Intenté lo mismo pero configurando la imagen src en 1 paso en lugar de después.
Intenté colocar un marcador de posición en la página <img src="placeholder.png" id="cropbox" />
y cambiar la fuente al hacer clic en el botón. Esto funciona, pero la zona de cultivo mantiene el tamaño de la imagen (300x180px o algo así) y no se hace más grande como debería.
// Editar:
Al probar un poco más, me mostraron que la fuente de la imagen se está reemplazando correctamente (usando Firefox para mostrar la fuente del texto seleccionado), verifiqué la URL pero esta era una URL correcta y una imagen funcional.
En el lugar donde debería estar el recortador, hay un punto blanco de aproximadamente 10x10 píxeles en el que aparece el ícono del recortador (un signo más) ... pero como se dijo antes: la imagen no se muestra.
// Edición 2:
Así que tomé las fuentes para el primer y el segundo intento de la misma imagen. Como se dijo antes del primer intento, la imagen no se cargará correctamente y el segundo intento lo hace (solo cuando el segundo intento es la misma imagen (!!)).
La fuente de la página seleccionada muestra 1 diferencia, es decir, primero intente:
<img style="position: absolute; width: 0px; height: 0px;" src="http://95.142.175.17/uploads/files/Desert.jpg">
segundo intento:
<img style="position: absolute; width: 700px; height: 525px;" src="http://95.142.175.17/uploads/files/Desert.jpg">
Supongo que esta es la imagen que está siendo reemplazada por jCrop, pero es un completo enigma por el que pone 0 pies / anchos en la primera y la talla correcta la segunda vez.
Bueno chicos, en caso de que alguien más se encuentre con este problema:
jCrop kinda se confunde si las acciones de cargar una imagen y aplicar jCrop a la misma se ponen en cola demasiado rápido una tras otra. Todavía me resulta extraño que un segundo intento funcione a la perfección, pero creo que tiene algo que ver con las dimensiones de las imágenes en caché que son reconocidas por el DOM de la página o algo así.
La solución que se me ocurrió fue crear una función que convierte el #cropbox en un área de jCrop y luego establecer un intervalo de 2 segundos, solo para darle a jCrop algo de tiempo para reconocer la imagen y sus dimensiones y luego convertir el elemento.
Esta es la parte de html que usé (con un precargador):
<div id="cropper-loading" style="display: none;"><img src="images/analytics/ajax-loader.gif" /></div>
<img id="cropbox" src="images/placeholder.png" style="display: none;" />
Como puede ver, tanto la imagen de la caja de recorte como la división de carga del recortador están ocultas ya que no se necesitan al instante. Sin embargo, podría mostrar el marcador de posición si lo desea. Luego se usa este formulario HTML:
<input name="image2" id="img2" type="text" readonly="readonly" onclick="openKCFinder(this)" value="click here to select an image" style="width: 285px;" /> <button class="button button-blue" type="submit" name="load" id="selectimg">Load Image in cropper</button>
En mi caso, he estado utilizando KCFinder para cargar las imágenes (¡es parte de CKEditor, realmente vale la pena verlo!), KCFinder maneja las subidas, el cambio de nombre, etc. y luego de elegirlo devuelve la ruta de la imagen elegida (relativa / absoluta es configurable) al campo de entrada.
Luego, al hacer clic en #selectimg este código se llama:
jQuery(''#selectimg'').click(function(e) {
e.preventDefault();
jQuery(''#cropper-loading'').css(''display'', ''block'');
var newsrc = jQuery(''#img2'').val();
jQuery(''#cropbox'').attr(''src'', newsrc);
jQuery(''#img'').val(newsrc);
function createJcropArea() {
jQuery(''#cropper-loading'').css(''display'', ''none'');
jQuery(''#cropbox'').css(''display'', ''block'');
var jcrop_api = jQuery.Jcrop(''#cropbox'', {
boxWidth: 700,
boxHeight: 700,
onSelect: updateCoords,
onChange: updateCoords
});
clearInterval(interval);
}
var interval = setInterval(createJcropArea, 2000);
});
Al principio, evito que se siga el enlace como lo haría normalmente (o la acción del botón) y luego se muestra el div de carga (esa es mi razón para ocultar la imagen del marcador de posición, de lo contrario se vería desordenado).
Luego, la ubicación de la imagen se carga desde el campo de entrada y se copia en otro (#img), este campo se usa para procesar la imagen posteriormente (PHP usa el valor de #img para cargar esta imagen). También, simultáneamente, el #cropbox src se está configurando para la nueva imagen.
Y aquí viene la parte que resolvió mi problema:
En lugar de activar directamente jCrop, he hecho una función que:
1) hides the loading icon
2) displays the image
3) converts #cropbox into a jCrop area
4) clean the interval (otherwise it would loop un-ending)
Y después de esta función, puede ver que, solo para guardar, tomé 2 segundos de retraso antes de que se convirtiera el área jCrop.
Espero que ayude a alguien en el futuro!
Saludos y gracias por pensar @vector y quien más lo hizo ;-)
La creación de un objeto ''Imagen'' y la configuración del atributo ''src'' no se aplica, se puede tratar la imagen como si ya se hubiera cargado. Además, el hecho de dar un intervalo de tiempo de espera fijo no garantiza que la imagen ya se haya cargado.
En su lugar, debe configurar una devolución de llamada ''onload'' para el objeto de imagen, que luego inicializará el objeto Jcrop:
var src = ''https://example.com/imgs/someimgtocrop.jpg'';
var tmpImg = new Image();
tmpImg.onload = function() {
//This is where you can safely create an image and a Jcrop Object
};
tmpImg.src = src; //Note that the ''src'' attribute is only added to the Image Object after the ''onload'' listener was defined
No llames a esta función en onChange : updateCoords
Pruébalo sin y se ejecutará sin problemas en los móviles.
Puedes crear base64 directamente y mostrarlos como una imagen donde quieras.
Pruebe la biblioteca de borde en el repositorio aquí: https://github.com/tapmodo/Jcrop
Esto debería solucionar tu problema. Las líneas que se cambian para resolver su problema:
// Fix size of crop image.
// Necessary when crop image is within a hidden element when page is loaded.
if ($origimg[0].width != 0 && $origimg[0].height != 0) {
// Obtain dimensions from contained img element.
$origimg.width($origimg[0].width);
$origimg.height($origimg[0].height);
} else {
// Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
var tempImage = new Image();
tempImage.src = $origimg[0].src;
$origimg.width(tempImage.width);
$origimg.height(tempImage.height);
}
Sé que esto es antiguo, pero sucedió al azar en mi instalación recientemente. Se encontró que se debía a que las imágenes no se habían cargado por completo antes de que se inicializara jCrop.
Todo lo que se necesitó para solucionarlo fue envolver el material de inicialización de jCrop dentro de un
$(window).on("load", function () { //jcrop stuff here });
Y ha estado funcionando bien desde entonces.