Foros del Web » Programando para Internet » Javascript »

Crop de imagenes estilo facebook

Estas en el tema de Crop de imagenes estilo facebook en el foro de Javascript en Foros del Web. Estimados amigos, los vecinos del 68 (foro de PHP) estamos trabajando juntos para mejorar una clase para manejo de imagenes del lado del servidor y ...
  #1 (permalink)  
Antiguo 05/08/2011, 14:09
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 7 meses
Puntos: 2237
Crop de imagenes estilo facebook

Estimados amigos, los vecinos del 68 (foro de PHP) estamos trabajando juntos para mejorar una clase para manejo de imagenes del lado del servidor y nos vemos en la necesidad de crear una parte del lado del cliente para poder darle un uso real.

Lo que llevamos?
Aqui la clase con todos sus creditos: http://www.forosdelweb.com/wiki/PHP:...as_al_servidor

Lo que nos falta?
Algun codigo de Javascript para que el usuario pueda seleccionar como recortar la imagen, como lo hace facebook con la imagen del perfil, detectando coordenadas de inicio y tamaño final (ancho y alto), para enviar los datos a este metodo de la clase:

Código PHP:
Ver original
  1. public function crop($x, $y, $width, $height) {
  2.             $newImage = imagecreatetruecolor($width, $height);
  3.  
  4.             imagecopy($newImage, $this->_image, 0, 0, $x, $y, $width, $height);
  5.             $this->_image = $newImage;
  6.         }
  7.     }

La mayoria de los que estamos en PHP tenemos conocimientos muy basicos de Javascript, por lo que preferimos recurrir a los expertos para ver si nos pueden echar la mano con esto y, de ser posible, sin uso de frameworks, asi los novatos aprendemos un poco mas.

Gracias de antemano y disculpen las molestias.
__________________
- León, Guanajuato
- GV-Foto
  #2 (permalink)  
Antiguo 05/08/2011, 14:13
Avatar de abimaelrc
Colaborador
 
Fecha de Ingreso: mayo-2009
Ubicación: En el planeta de Puerto Rico
Mensajes: 14.734
Antigüedad: 14 años, 10 meses
Puntos: 1517
Respuesta: Crop de imagenes estilo facebook

Para el ganador, le tenemos un premio un viaje con gastos pagos en donde se haya sentado para crear el código

De verdad que queremos que la clase crezca con lo mejor

Otra cosa, si se les ocurre otro estilo, también es bienvenido
__________________
Verifica antes de preguntar.
Los verdaderos amigos se hieren con la verdad, para no perderlos con la mentira. - Eugenio Maria de Hostos
  #3 (permalink)  
Antiguo 05/08/2011, 23:20
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 7 meses
Puntos: 2237
Respuesta: Crop de imagenes estilo facebook

Bueno, nuestro primer intento funciona a medias, porque puedo crear un marco y posicionarlo dentro de la imagen, incluso cambiarle tamaño, pero "manualmente" con un par de inputs... seguiremos probando a ver que sale:

Código HTML:
Ver original
  1. <!DOCTYPE html>
  2. <html lang="es" dir="ltr" >
  3.     <title>Crop in Javascript</title>
  4.     <meta http-equiv="content-type" content="text/html; charset=utf8" />
  5.  
  6. <style type="text/css">
  7. #div-js {
  8.     position:relative;
  9.     margin:0;
  10.     padding:0;
  11. }
  12. #click-js {
  13.     margin:0;
  14.     padding:0;
  15. }
  16. #frame-js {
  17.     position:absolute;
  18.     top:0;
  19.     left:0;
  20.     width:98px;
  21.     height:48px;
  22.     border:1px #888 dotted;
  23.     margin:0;
  24.     padding:0;
  25. }
  26.  
  27. <script type="text/javascript">
  28. var divcont = "div-js";
  29. var clickable = "click-js";
  30. var frame = "frame-js";
  31. function $(target) {
  32.     return document.getElementById(target);
  33. }
  34. function clickMe(event) {
  35.     posX = (event.offsetX) ? event.offsetX : event.pageX - $(divcont).offsetLeft;
  36.     posY = (event.offsetY) ? event.offsetY : event.pageY - $(divcont).offsetTop;
  37.     $(frame).style.left = posX + 'px';
  38.     $(frame).style.top = posY + 'px';
  39.     $(frame).style.visibility = "visible" ;
  40.     $("inputx").value = posX;
  41.     $("inputy").value = posY;
  42. }
  43. function changeWidth(width) {
  44.     $(frame).style.width = width + 'px';
  45. }
  46. function changeHeight(height) {
  47.     $(frame).style.height = height + 'px';
  48. }
  49.  
  50. </head>
  51. <div id="div-js">
  52.     <img src="triby.jpg" alt="Imagen de prueba" id="click-js" onclick="clickMe(event);" />
  53.     <div id="frame-js" style="visibility:hidden;"></div>
  54. </div>
  55. <div>
  56.     X: <input type="text" name="inputx" id="inputx" size="5" readonly="readonly" /><br />
  57.     Y: <input type="text" name="inputy" id="inputy" size="5" readonly="readonly" /><br />
  58.     Width: <input type="text" name="width" value="100" onchange="changeWidth(this.value)" /><br />
  59.     Height: <input type="text" name="height" value="100" onchange="changeHeight(this.value)" />
  60. </div>
  61. </body>
  62. </html>
__________________
- León, Guanajuato
- GV-Foto
  #4 (permalink)  
Antiguo 06/08/2011, 15:13
Avatar de Panino5001
Me alejo de Omelas
 
Fecha de Ingreso: mayo-2004
Ubicación: -34.637167,-58.462984
Mensajes: 5.148
Antigüedad: 19 años, 10 meses
Puntos: 834
Respuesta: Crop de imagenes estilo facebook

Fijate si te sirve para implementar o como idea (Aquí un ejemplo online que funciona para navegadores que soportan canvas y por tanto nos ahorramos GD -está indicado en el código el lugar donde debería implementarse la solución del lado del servidor para los navegadores que no soportan canvas-):
Código PHP:
<!DOCTYPE HTML>
<
htmL>
<
head>
<
meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<
title>Documento sin título</title>
<
script type="text/javascript">
/*---- funciones auxiliares---*/
//DOMReady
var DR=function(f){
    if(
document.addEventListener){
        var 
func=function(){f();document.removeEventListener('DOMContentLoaded',func,false);}
        
document.addEventListener('DOMContentLoaded',func,false);
    }else{
        function 
r(f){/in/.test(document.readyState)?setTimeout(function(){r(f);},9):f();};
        
r(f);
    }
}
function 
clearSelection() {
    if(
window.permSel)return;
    var 
sel ;
    if(
document.selection && document.selection.empty){
        try{
document.selection.empty() ;}catch(err){}
    } else if(
window.getSelection) {
        
sel=window.getSelection();
    if(
sel && sel.removeAllRanges)
        
sel.removeAllRanges() ;
    }
}
function 
cancelEvent(e){
    if(
&& e.preventDefault)
        
e.preventDefault();
    else if(
window.event)
        
window.event.returnValue=false;
}
/*---- cropeo---*/
var crop=(
function(){
    var 
cur='';
    var 
coords={x:0,y:0};
    var 
coords2={x:0,y:0};
    var 
origen={x:0,y:0};
    var 
origen2={x:0,y:0};
    var 
renderizar=0;
    var 
recorte=0;
    var 
f=document.createDocumentFragment();
    var 
l=document.createElement('div');
    var 
r=document.createElement('div');
    var 
t=document.createElement('div');
    var 
b=document.createElement('div');
    var 
over=document.createElement('div');
    
l.style.borderLeft=r.style.borderLeft='1px dashed white';
    
t.style.borderBottom=b.style.borderBottom='1px dashed white';
    
over.style.position=l.style.position=r.style.position=t.style.position=b.style.position='absolute';
    
over.style.top='-15000px';
    
over.style.zIndex=100;
    
l.style.width=r.style.width=t.style.width=b.style.width=l.style.height=r.style.height=t.style.height=b.style.height=0;
    
f.appendChild(l);
    
f.appendChild(r);
    
f.appendChild(t);
    
f.appendChild(b);
    
over.appendChild(f);
    
DR(function(){
        
document.body.appendChild(over);            
    });
    var 
mp={
        
iniciar:function(o){
            
crop.target=o;
            var 
pos=this.getElementPosition(o);
            var 
w=o.width || o.offsetWidth || 0;
            var 
h=o.height || o.offsetHeight || 0;
            
over.style.width=w+'px';
            
over.style.height=h+'px';
            
over.style.top=pos.top+'px';
            
over.style.background='url('+o.src+')';
            
over.style.left=pos.left+'px';
            
this.addEvent('mousemove',this.setCoord,over);
            
this.addEvent('mousedown',this.setOrigen,over);
            
this.addEvent('mouseup',function(){renderizar=0;over.style.cursor='default';},over);
            
over.style.cursor='default';
        },
        
render:function(){
            if(
renderizar){
                if((
coords.y-origen.y)<0){
                    
origen2.y=coords.y+3;
                    
coords2.y=origen.y;
                    
cur='n';
                }else{
                    
origen2.y=origen.y;
                    
coords2.y=coords.y-3;
                    
cur='s';
                }
                if((
coords.x-origen.x)<0){
                    
origen2.x=coords.x+3;
                    
coords2.x=origen.x;
                    
cur+='w';
                }else{
                    
origen2.x=origen.x;
                    
coords2.x=coords.x-3;
                    
cur+='e';
                }
                
over.style.cursor=cur+'-resize';
                
l.style.top=t.style.top=r.style.top=origen2.y+'px';
                
l.style.left=t.style.left=b.style.left=origen2.x+'px';
                
r.style.left=coords2.x+'px';
                
b.style.top=coords2.y+'px';
                
l.style.height=r.style.height=Math.abs(coords2.y-origen2.y)+'px';
                
t.style.width=b.style.width=Math.abs(coords2.x-origen2.x)+'px';
                
t.style.height=b.style.height=l.style.width=r.style.width=0;
                if(
parseInt(l.style.height)<|| parseInt(t.style.width)<5){
                    
t.style.visibility=l.style.visibility=r.style.visibility=b.style.visibility='hidden';
                    
recorte=0;
                }else{
                    
t.style.visibility=l.style.visibility=r.style.visibility=b.style.visibility='visible';
                    
recorte=1;
                }
            }
        },
        
setOrigen:function(x){
            
cancelEvent(x);
            var 
ev=|| event;
            var 
o=ev.target || ev.srcElement;
            if(
o!=over)return false;
            
l.style.width=r.style.width=t.style.width=b.style.width=l.style.height=r.style.height=t.style.height=b.style.height=0;
            
l.style.left=r.style.left=b.style.left=t.style.left=coords.x+'px';
            
l.style.top=r.style.top=b.style.top=t.style.top=coords.y+'px';
            
origen={x:coords.x,y:coords.y};
            
renderizar=1;
            
recorte=0;
            
over.style.cursor='default';
            
        },
        
setCoord:function(x){
            
cancelEvent(x);
            
clearSelection();
            var 
ev=|| event;
            var 
o=ev.target || ev.srcElement;
            var 
posX=ev.layerX || ev.offsetX || 0
            var 
posY=ev.layerY || ev.offsetY || 0
            
coords={x:posX,y:posY};
            if(
o==over)
                
mp.render();
            
        },
        
addEvent: function(typefn,) {
            if ( 
o.addEventListener ) {
                
o.addEventListenertypefnfalse );
            } else if(
o.attachEvent){
                var 
O=o;
                var 
f= function(){fn.call(O,window.event);}
                
o.attachEvent'on'+typef);
                
o[fn.toString()+type]=f;
            }else{
                
o['on'+type]=fn;
            }
            var 
ev={_obj:this,_evType:type,_fn:fn};
            
window.EvRegister=window.EvRegister || [];
            
window.EvRegister.push(ev);
        },
        
getElementPosition:function(o) {
            var 
offsetTrail o;
            var 
offsetLeft 0;
            var 
offsetTop 0;
            while (
offsetTrail) {
                
offsetLeft += offsetTrail.offsetLeft;
                
offsetTop += offsetTrail.offsetTop;
                
offsetTrail offsetTrail.offsetParent;
            }
            return {
left:offsetLefttop:offsetTop};
        }
    };
    return {
        
setTarget:function(id){
            if(!
document.getElementById(id)){
                throw new 
Error('El elemento no existe o no posee atributo id');
            }else if(
document.getElementById(id).nodeName.toLowerCase()!='img'){
                throw new 
Error('El elemento no es una imagen');
            }else{
                
mp.iniciar(document.getElementById(id));
            }
        },
        
getCoords:function(){
            if(
recorte)
                return {
xo:origen2.x,yo:origen2.y,xd:coords2.x,yd:coords2.y}
            return 
0;
        }
        
    }
})();
DR(
   function(){
       
crop.setTarget('arw');//seteamos la imagen a cropear indicando su id
    
}
);

function 
cropear(){
    
/*---obtenemos las coordenadas del cropeo:---*/
    
var recorte=crop.getCoords();
    if(!
recorte)return false;
    
/*--- si canvas está soportado le ahorramos trabajo al servidor ---*/
    
if(document.createElement('canvas').getContext){
        var 
canvas=document.createElement('canvas');
        
canvas.width=recorte.xd-recorte.xo;
        
canvas.height=recorte.yd-recorte.yo;
        var 
ctx=canvas.getContext('2d');
        
ctx.drawImage(crop.targetrecorte.xorecorte.yocanvas.widthcanvas.height00canvas.widthcanvas.height);
        var 
src=canvas.toDataURL();
    }else{
        
//recortar en servidor    
    
}
    
/*--- opcional: mostramos la imagen---*/
    
var im=document.createElement('img'); 
    
im.src=src
    
document.body.appendChild(im); 
}

</script>

</head>

<body>
<img id="arw" src="arwen.jpg" width="500" height="350">
<form action="" method="get">
<input onClick="cropear()" id="gc" name="" type="button" value="cropear">
</form>

</body>
</html> 
He agregado alguna mejora

Última edición por Panino5001; 08/08/2011 a las 19:56
  #5 (permalink)  
Antiguo 06/08/2011, 16:23
Avatar de abimaelrc
Colaborador
 
Fecha de Ingreso: mayo-2009
Ubicación: En el planeta de Puerto Rico
Mensajes: 14.734
Antigüedad: 14 años, 10 meses
Puntos: 1517
Respuesta: Crop de imagenes estilo facebook

Ufff, interesantisimo. Como siempre te pasaste, tremenda forma de trabajarlo . Lo que me llamó la atención es el uso del protocolo data. Muy bueno Aunque la idea es grabar esa imagen cropeada en el servidor y también la original. Pero me gustó para aprender
__________________
Verifica antes de preguntar.
Los verdaderos amigos se hieren con la verdad, para no perderlos con la mentira. - Eugenio Maria de Hostos
  #6 (permalink)  
Antiguo 06/08/2011, 17:28
Avatar de Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 15 años, 7 meses
Puntos: 2237
Respuesta: Crop de imagenes estilo facebook

Panino5001, comienzo a probarlo (seguramente Abimael tambien lo hara) para ver de que forma lo usamos en la clase; aunque, por mi parte, primero voy a tratar de entenderlo, de lo contario no llegare a ningun lado.

Gracias por el aporte!
__________________
- León, Guanajuato
- GV-Foto

Etiquetas: crop, estilo, facebook, imagenes, php
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 6 personas




La zona horaria es GMT -6. Ahora son las 20:05.