Foros del Web » Programando para Internet » Javascript » Frameworks JS »

[SOLUCIONADO] Calcular coordenadas sobre imagen redimencionada

Estas en el tema de Calcular coordenadas sobre imagen redimencionada en el foro de Frameworks JS en Foros del Web. Que tal compañeros, vengo a ustedes solicitando su valiosa ayuda, verán, tengo un problema, estoy generando una aplicación donde se subirá imágenes como avatares, pero ...
  #1 (permalink)  
Antiguo 12/06/2015, 14:17
Avatar de Nemutagk
Colaborador
 
Fecha de Ingreso: marzo-2004
Ubicación: México
Mensajes: 2.633
Antigüedad: 20 años
Puntos: 406
Calcular coordenadas sobre imagen redimencionada

Que tal compañeros, vengo a ustedes solicitando su valiosa ayuda, verán, tengo un problema, estoy generando una aplicación donde se subirá imágenes como avatares, pero como debe a ver un limite de tamañano lo que queremos es que si el usuario selecciona una imagen mayor al limite (160x160 pixeles) tengan opción para seleccionar un trozo de la imagen, hasta aquí todo bien, el problema se presenta cuando el usuario selecciona una imagen muy grande, por lo cual debo encajar la etiqueta img dentro del contenedor (un div), por lo cual la imagen esta a escala o x porcentaje mas chica de lo que es originalmente, y eh aquí el problema, intento calcular en base a las coordenadas selecionadas en la imagen mas pequeña para traspasar a la imagen original, pero, siempre obtengo un desface, y entre mas grande es la imagen mas grande el desface...

Todo se maneja en un formulario web y se maneja con Javascript, ajax y php, el formulario es el siguiente:

Código HTML:
Ver original
  1. <form method="post" action="/es/config/avatar" enctype="multipart/form-data" class="form-horizontal" id="avatar-form">
  2.         <div class="form-group">
  3.             <label class="label-control col-xs-10 col-sm-6" for="password">Contraseña actual</label>
  4.             <div class="col-xs-10 col-sm-6">
  5.                 <input type="password" value="" name="password" class="form-control" id="avatar-pass">
  6.             </div>
  7.         </div>
  8.         <div class="form-group">
  9.             <label class="label-control col-xs-10 col-sm-6" for="avatar">Imagen</label>
  10.             <div class="col-xs-10 col-sm-6">
  11.                 <button type="button" class="btn btn-primary" id="btn-avatar">ayanami_rei_neo...</button>
  12.                 <input type="file" name="avatar" class="form-control" id="avatar">
  13.             </div>
  14.         </div>
  15.         <div class="form-group">
  16.             <div class="col-xs-10 col-sm-6 col-sm-offset-6">
  17.                 <input type="submit" value="Cambiar" class="btn btn-primary">
  18.                 <input type="hidden" value="jNQfAJJ9SkGsiA2LLefDEL3W2laWc6T2RI7dDzRB" name="_token">
  19.                 <input type="hidden" value="0|0" id="cropcoordinates" name="cropcoordinates">
  20.                 <input type="hidden" value="160" id="cropsize" name="cropsize">
  21.                 <input type="hidden" value="0|0" id="fix" name="fix">
  22.             </div>
  23.         </div>
  24.     </form>

El contenedor de la imagen
Código HTML:
Ver original
  1. <div class="avatar-block">
  2.     <img class="avatar img-responsive" src="/img/avatars/avatar.png" id="preview">
  3.     <div id="divcut"></div>
  4. </div>

Y este es el código javascript que tengo
Código Javascript:
Ver original
  1. $(document).on('ready',function() {
  2.     $('#btn-avatar').on('click',function() {
  3.         $('#avatar').click();
  4.     });
  5.  
  6.     $('#avatar').on('change',function() {
  7.         var path = $(this).val();
  8.         var fileName = path.match(/[^\/\\]+$/);
  9.         var inputFile = this;
  10.  
  11.         var name = fileName[0].slice(0,15);
  12.         name += '...';
  13.         $('#btn-avatar').text(name);
  14.  
  15.         if (inputFile.files && inputFile.files[0]) {
  16.             var reader = new FileReader();
  17.  
  18.             reader.onload = function(e) {
  19.                 $('#preview').attr('src',e.target.result);
  20.                 setImage();
  21.             };
  22.  
  23.             reader.readAsDataURL(inputFile.files[0]);
  24.         }
  25.     });
  26.  
  27.     $('#avatar-form').on('submit',function() {
  28.         var form = this;
  29.         var fileInput = document.getElementById('avatar');
  30.         var file = fileInput.files[0];
  31.  
  32.         var formData = new FormData(form);
  33.         formData.append('password',$('#avatar-pass').val());
  34.         formData.append('avatar',file);
  35.         formData.append('cropcoordinates',$('#cropcoordinates').val());
  36.         formData.append('cropsize',$('#cropsize').val());
  37.         formData.append('fix',$('#fix').val());
  38.         formData.append('_token',$('input[name=_token]').val());
  39.  
  40.         $.ajax({
  41.             url: $(this).attr('action'),
  42.             data: formData,
  43.             contentType: false,
  44.             processData: false,
  45.             method: 'post',
  46.             cache: false
  47.         }).done(function(data) {
  48.             console.log('Enviado!');
  49.             //$('#preview').attr('src',data);
  50.         });
  51.  
  52.         return false;
  53.     });
  54. });
  55.  
  56. function setImage() {
  57.     $('#divcut').show();
  58.  
  59.     $('#fix').val('0|0');
  60.     $('#cropsize').val(160);
  61.     $('#cropcoordinates').val('0|0');
  62.  
  63.     var position = $('#divcut').position();
  64.  
  65.     var imgWidth = $('#preview').width();
  66.     var imgHeight = $('#preview').height();
  67.     console.log('tamaño imagen x:'+imgWidth+' y:'+imgHeight);
  68.  
  69.     var img = document.getElementById('preview');
  70.     var imgOrgWidth = img.naturalWidth;
  71.     var imgOrgHeight = img.naturalHeight;
  72.     console.log('tamaño original x:'+imgOrgWidth+' y:'+imgOrgHeight);
  73.  
  74.     var tmpFixTop = 0;
  75.     var tmpFixLeft = 0;
  76.     if (imgWidth < imgOrgWidth) {
  77.         var tmpFixTop = (imgWidth  / imgOrgWidth) * 100;
  78.         var tmpFixLeft = (imgHeight / imgOrgHeight) * 100;
  79.     }
  80.  
  81.     if (tmpFixTop > 0 || tmpFixLeft > 0) {
  82.         $('#fix').val(tmpFixTop+'|'+tmpFixLeft);
  83.         console.log('fix: '+tmpFixTop+'|'+tmpFixLeft);
  84.     }
  85.  
  86.     var imgPos = $('#preview').offset();
  87.     console.log('offset x:'+imgPos.left+' y:'+imgPos.top);
  88.     $('#divcut').offset({top:imgPos.top,left:imgPos.left});
  89.     var position = $('#divcut').position();
  90.  
  91.     $('#divcut').draggable({
  92.         containment: $('#preview'),
  93.         stop: function(event, ui) {
  94.             console.log('org coords x:'+ui.position.top+' y:'+ui.position.left);
  95.             var tmpTop = ui.position.top - position.top;
  96.             var tmpLeft = ui.position.left - position.left;
  97.  
  98.             console.log('coords x:'+tmpTop+' y:'+tmpLeft);
  99.             $('#cropcoordinates').val(tmpTop+'|'+tmpLeft);
  100.         }
  101.     }).resizable({
  102.         aspectRatio: true,
  103.         maxWidth: imgWidth,
  104.         maxHeight: imgHeight,
  105.         stop: function(event, ui) {
  106.             console.log('size:'+ui.size.width);
  107.             $('#cropsize').val(ui.size.width);
  108.         }
  109.     });
  110. }

La parte importante es la función setImage() la que calcula las coordenadas pero lo hace de forma erronea

El código PHP que recorta la imagen
Código PHP:
Ver original
  1. $image = Request::file('avatar');
  2.         $size = Request::get('cropsize');
  3.         list($fixLeft,$fixTop) = explode('|',Request::get('fix'));
  4.         list($posLeft,$posTop) = explode('|',Request::get('cropcoordinates'));
  5.  
  6.         if ($image->isValid()) {
  7.             $ext = $image->getClientOriginalExtension();
  8.             $fileName = md5(time().rand(1000,9999)).'.'.$ext;
  9.             $path = $_SERVER['DOCUMENT_ROOT'].'/img/avatars';
  10.             $image->move($path,$fileName);
  11.             $url = $path.'/'.$fileName;
  12.  
  13.             if ($fixTop > 0 || $fixLeft > 0) {
  14.                 if ($fixTop > 0)
  15.                     $posTop = $posTop + (($fixTop * $posTop) / 100);
  16.  
  17.                 if ($fixLeft > 0)
  18.                     $posLeft = $posLeft + (($fixLeft * $posLeft) / 100);
  19.  
  20.                 $size = $size + (($fixLeft * $size) / 100);
  21.             }
  22.            
  23.             $objImage = new Image();
  24.             $objImage->source($url);
  25.             $objImage->crop($posTop,$posLeft,$size,$size);
  26.             $objImage->save($url);

A ver si me pueden ayudar, cualquier información que requieran solo pregunten
__________________
Listo?, tendría que tener 60 puntos menos de IQ para considerarme listo!!!
-- Sheldon Cooper
http://twitter.com/nemutagk
PD: No contestaré temas vía mensaje personal =)
  #2 (permalink)  
Antiguo 13/06/2015, 11:05
Avatar de Nemutagk
Colaborador
 
Fecha de Ingreso: marzo-2004
Ubicación: México
Mensajes: 2.633
Antigüedad: 20 años
Puntos: 406
Respuesta: Calcular coordenadas sobre imagen redimencionada

Después de despejarme y aclarar ideas me di cuenta que estaba completamente mal planteado, no debía obtener el porcentaje de reducción de la imagen reedimencionada con respecto a la original, lo que tenia que hacer es calcular cual es el porcentaje de coordenadas referente a la imagen, por ejemplo, si tengo una posición (top: 10px left:255px) sobre una imagen que mide (width: 1200 height: 650) tendría los siguientes porcentajes (top: 1.538461538461538% left: 21.25%), ojo, que son importantes todos los decimales para tener la mayor precisión posible, entonces tendría que calcular la misma posición en la original usando los porcentajes de la miniatura, para que se entienda mejor dejo el código que generé en un archivo de pruebas

HTML
Código HTML:
Ver original
  1. <!DOCTYPE html>
  2. <html lang="en">
  3.     <meta charset="UTF-8">
  4.     <title>Document</title>
  5.     <link rel="stylesheet" href="jquery-ui.min.css">
  6.     <link rel="stylesheet" href="imagenes.css">
  7.     <script src="jquery-2.1.3.min.js"></script>
  8.     <script src="jquery-ui.min.js"></script>
  9.     <script src="imagen.js"></script>
  10. </head>
  11. <div class="block-preview">
  12.     <img id="img-preview" src="imagen.jpg" alt="">
  13.     <div class="div-cut"></div>
  14. </div>
  15. <div class="block-info">
  16.     <p>coordenadas preview: <input type="text" id="coord-prev"></p>
  17.     <p>coordenadas original: <input type="text" id="coord-org"></p>
  18.     <p>tamaño del recuadro: <input type="text" id="size-cut"></p>
  19. </div>
  20. <div class="block-org">
  21.     <img id="img-org" src="imagen.jpg" alt="">
  22.     <div class="div-cut"></div>
  23. </div>
  24. </body>
  25. </html>

Javascript
Código Java:
Ver original
  1. $(document).on('ready',function() {
  2.  
  3.     //posicionamos el primer bloque
  4.     var offset = $('#img-preview').offset();
  5.     console.log('offset view x:'+offset.top+' y:'+offset.left);
  6.     $('.block-preview .div-cut').offset({"top":offset.top,"left":offset.left});
  7.  
  8.     var position = $('#img-preview').position();
  9.     console.log('position view x:'+position.top+' y:'+position.left);
  10.     $('#coord-prev').val('x:'+position.top+' y:'+position.left);
  11.  
  12.     //posicionamos el segundo bloque
  13.     var offsetOrg = $('#img-org').offset();
  14.     console.log('offset org x:'+offsetOrg.top+' y:'+offsetOrg.left);
  15.     $('.block-org .div-cut').offset({"top":offsetOrg.top,"left":offsetOrg.left});
  16.  
  17.     var positionOrg = $('#img-org').position();
  18.     $('#coord-org').val('x:'+positionOrg.top+' y:'+positionOrg.left);
  19.  
  20.     var posX, posY;
  21.  
  22.     //tamaño de crop
  23.     var porSizeCut = (($('.block-preview .div-cut').width() * 100) / $('#img-preview').width());
  24.     setSizeCrop(porSizeCut);
  25.  
  26.     $('.block-preview .div-cut').draggable({
  27.         containment: $('#img-preview'),
  28.         stop: function(event,ui) {
  29.             posX = ui.position.top - position.top;
  30.             posY =  ui.position.left - position.left;
  31.  
  32.             posX = ui.position.top;
  33.             posY = ui.position.left;
  34.  
  35.             setCoords(posX,posY);
  36.         }
  37.     }).resizable({
  38.         aspectRatio: true,
  39.         maxWidth: $('#img-preview').width(),
  40.         maxHeight: $('#img-preview').height(),
  41.         stop: function(event, ui) {
  42.             console.log('new size cut '+ui.size.width);
  43.             porSizeCut = ((ui.size.width * 100) / $('#img-preview').width());
  44.             setSizeCrop(porSizeCut);
  45.         }
  46.     });
  47. });
  48.  
  49. function setCoords(arriba,derecha) {
  50.     //fix padding
  51.     arriba = arriba - 5;
  52.     derecha = derecha - 5;
  53.     $('#coord-prev').val('arriba: '+arriba+' derecha: '+derecha);
  54.     //porcentajes de view
  55.     var widthView = $('#img-preview').width();
  56.     var heightView = $('#img-preview').height();
  57.     console.log('size ancho: '+widthView+' alto:'+heightView);
  58.  
  59.     var porViewAncho = 100 - (derecha * 100) / widthView;
  60.     var porViewAlto = 100 - (arriba * 100) / heightView;
  61.     console.log('por view ancho:'+porViewAncho+' alto:'+porViewAlto);
  62.  
  63.     //porcentajes orig
  64.     var inputImg = document.getElementById('img-org');
  65.     var widthOrg = inputImg.naturalWidth;
  66.     var heightOrg = inputImg.naturalHeight;
  67.     console.log('size ancho: '+widthOrg+' alto'+heightOrg);
  68.  
  69.     var porOrgAncho = widthOrg - ((widthOrg * porViewAncho) / 100);
  70.     var porOrgAlto = heightOrg - ((heightOrg * porViewAlto) / 100);
  71.     console.log('coord org ancho:'+porOrgAncho+' alto:'+porOrgAlto);
  72.  
  73.     $('#coord-org').val('arriba: '+porOrgAlto+' derecha: '+porOrgAncho);
  74.     $('.block-org .div-cut').css({"top":porOrgAlto,"left":porOrgAncho});
  75. }
  76.  
  77. function setSizeCrop(size) {
  78.     console.log('cut view por '+size);
  79.     var porOrg = 10;
  80.  
  81.     var inputImg = document.getElementById('img-org');
  82.     var widthOrg = inputImg.naturalWidth;
  83.  
  84.     var size = ((widthOrg * size) / 100) + 'px';
  85.     $('#size-cut').val(size);
  86.     $('.block-org .div-cut').css({"width":size,"height":size});
  87. }

CSS
Código CSS:
Ver original
  1. body .block-preview {
  2.     width: 700px;
  3.     border: solid 1px #C2C2C2;
  4.     padding: 5px;
  5.     position: relative;
  6.     overflow: auto;
  7.     float: left;
  8. }
  9.  
  10. body .block-preview img {
  11.     width: 400px;
  12. }
  13.  
  14. body .block-info {
  15.     width: 619px;
  16.     text-align: right;
  17.     border: solid 1px #C2C2C2;
  18.     float: right;
  19. }
  20.  
  21. body .block-info input {
  22.     width: 450px;
  23.     padding: 5px;
  24. }
  25.  
  26. body .block-preview .div-cut {
  27.     width: 160px;
  28.     height: 160px;
  29.     border: solid 1px #FF0000;
  30.     position: absolute;
  31.     top: 0px;
  32.     left: 0px;
  33. }
  34.  
  35. body .block-org {
  36.     border: solid 1px #C2C2C2;
  37.     margin: 10px 0px 0px 0px;
  38.     padding: 5px;
  39.     position: relative;
  40.     clear: both;
  41.     overflow: auto;
  42. }
  43.  
  44. body .block-org .div-cut {
  45.     width: 240px;
  46.     height: 240px;
  47.     border: solid 1px #FF0000;
  48.     position: absolute;
  49.     top: 0px;
  50.     left: 0px;
  51. }

Solo, ojo, la imagen original debe mostrarse en su tamaño original, sin ser redimencionada por css o por el contenedor de la imagen, si no, la posición del recuadro rojo no será correcta

Actualización: eh incluido los cálculos para determinar el tamaño del recuadro rojo coincida en ambas imagenes
__________________
Listo?, tendría que tener 60 puntos menos de IQ para considerarme listo!!!
-- Sheldon Cooper
http://twitter.com/nemutagk
PD: No contestaré temas vía mensaje personal =)

Última edición por Nemutagk; 13/06/2015 a las 12:25 Razón: eh incluido los cálculos para determinar el tamaño del recuadro rojo coincida en ambas imagenes

Etiquetas: ajax, calcular, coordenadas, formulario, input, javascript, 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




La zona horaria es GMT -6. Ahora son las 03:32.