He recibido varias solicitudes para explicaros cómo implementar la funcionalidad de subir imágenes y recortarlas en una ventana modal. La subida de imágenes y el recortado es una función muy importante de cualquier proyecto web que se precie. Proporciona una experiencia para los usuarios alucinante para que puedan subir sus propias imágenes y recortarlas, todo en una misma ventana modal. Por lo tanto, en este artÃculo, te mostraremos cómo implementar una subida de imágenes y una función de recorte dentro de una ventana modal utilizando PHP y jQuery.
LibrerÃas que utilizaremos
- LibrerÃa jQuery: LibrerÃa base necesaria para utilizar los plugins de jQuery
- Bootstrap: La utilizaremos para crear el diseño de la página
- Imgareaselect: Plugin ideal para recortar imágenes
- Ajax form: Plugin de jQuery que utilizaremos para gestionar el envÃo del formulario sin recargar la página
Estructura de ficheros
- index.php
- change_pic.php
- functions.js
Habiendo dicho todo esto, vamos a empezar con el tutorial.
Antes que nada, tenemos que incluir todas las librerÃas necesarias en el head de index.php.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="dist_files/jquery.imgareaselect.js" type="text/javascript"></script> <script src="dist_files/jquery.form.js"></script> <link rel="stylesheet" href="dist_files/imgareaselect.css"> <script src="functions.js"></script>
Ahora creamos nuestro formulario HTML en index.php para mostrar el botón Change Profile Picture y la preview de la imagen para informar al usuario de cómo quedarÃa la imagen.
<div> <img class="img-circle" id="profile_picture" height="128" data-src="default.jpg" data-holder-rendered="true" style="width: 140px; height: 140px;" src="default.jpg"/> <br><br> <a type="button" class="btn btn-primary" id="change-profile-pic">Change Profile Picture</a> </div>
Ahora creamos la ventana modal en index.php para la subida de la imagen y la funcionalidad de recorte.
<div id="profile_pic_modal" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h3>Change Profile Picture</h3> </div> <div class="modal-body"> <form id="cropimage" method="post" enctype="multipart/form-data" action="change_pic.php"> <strong>Upload Image:</strong> <br><br> <input type="file" name="profile-pic" id="profile-pic" /> <input type="hidden" name="hdn-profile-id" id="hdn-profile-id" value="1" /> <input type="hidden" name="hdn-x1-axis" id="hdn-x1-axis" value="" /> <input type="hidden" name="hdn-y1-axis" id="hdn-y1-axis" value="" /> <input type="hidden" name="hdn-x2-axis" value="" id="hdn-x2-axis" /> <input type="hidden" name="hdn-y2-axis" value="" id="hdn-y2-axis" /> <input type="hidden" name="hdn-thumb-width" id="hdn-thumb-width" value="" /> <input type="hidden" name="hdn-thumb-height" id="hdn-thumb-height" value="" /> <input type="hidden" name="action" value="" id="action" /> <input type="hidden" name="image_name" value="" id="image_name" /> <div id='preview-profile-pic'></div> <div id="thumbs" style="padding:5px; width:600p"></div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" id="save_crop" class="btn btn-primary">Crop & Save</button> </div> </div> </div> </div>
Después, mostraremos la ventana modal utilizando jQuery cuando el usuario haga clic en el botón Change Profile Picture.
jQuery('#change-profile-pic').on('click', function(e){ jQuery('#profile_pic_modal').modal({show:true}); });
Una vez hecho eso, mostraremos la imagen para el proceso de recorte en nuestra ventana modal de Bootstrap y gestionaremos el envÃo del formulario utilizando el plugin jQuery Form.
jQuery('#profile-pic').on('change', function() { jQuery("#preview-profile-pic").html(''); jQuery("#preview-profile-pic").html('Uploading....'); jQuery("#cropimage").ajaxForm( { target: '#preview-profile-pic', success: function() { jQuery('img#photo').imgAreaSelect({ aspectRatio: '1:1', onSelectEnd: getSizes, }); jQuery('#image_name').val(jQuery('#photo').attr('file-name')); } }).submit(); });
Después realizaremos el recorte de la imagen llamando al método ajax saveCropImage() para guardar la imagen en el disco duro cuando se haga clic en el botón Crop & Save.
jQuery('#save_crop').on('click', function(e){ e.preventDefault(); params = { targetUrl: 'change_pic.php?action=save', action: 'save', x_axis: jQuery('#hdn-x1-axis').val(), y_axis : jQuery('#hdn-y1-axis').val(), x2_axis: jQuery('#hdn-x2-axis').val(), y2_axis : jQuery('#hdn-y2-axis').val(), thumb_width : jQuery('#hdn-thumb-width').val(), thumb_height:jQuery('#hdn-thumb-height').val() }; saveCropImage(params); });
Esta serÃa la función saveCropImage() que guardarÃa la imagen
function saveCropImage(params) { jQuery.ajax({ url: params['targetUrl'], cache: false, dataType: "html", data: { action: params['action'], id: jQuery('#hdn-profile-id').val(), t: 'ajax', w1:params['thumb_width'], x1:params['x_axis'], h1:params['thumb_height'], y1:params['y_axis'], x2:params['x2_axis'], y2:params['y2_axis'], image_name :jQuery('#image_name').val() }, type: 'Post', success: function (response) { jQuery('#profile_pic_modal').modal('hide'); jQuery(".imgareaselect-border1,.imgareaselect-border2,.imgareaselect-border3,.imgareaselect-border4,.imgareaselect-border2,.imgareaselect-outer").css('display', 'none'); jQuery("#profile_picture").attr('src', response); jQuery("#preview-profile-pic").html(''); jQuery("#profile-pic").val(); }, error: function (xhr, ajaxOptions, thrownError) { alert('status Code:' + xhr.status + 'Error Message :' + thrownError); } }); }
Ahora implementaremos la subida de la imagen al servidor y guardaremos la imagen que acaba de cambiar el usuario en la tabla MySQL en el fichero change_pic.php
<?php /* Get post details */ $post = isset($_POST) ? $_POST: array(); switch($post['action']) { case 'save' : saveProfilePic(); saveProfilePicTmp(); break; default: changeProfilePic(); } /* Function to change profile picture */ function changeProfilePic() { $post = isset($_POST) ? $_POST: array(); $max_width = "500"; $userId = isset($post['hdn-profile-id']) ? intval($post['hdn-profile-id']) : 0; $path = 'images/tmp'; $valid_formats = array("jpg", "png", "gif", "jpeg"); $name = $_FILES['profile-pic']['name']; $size = $_FILES['profile-pic']['size']; if(strlen($name)) { list($txt, $ext) = explode(".", $name); if(in_array($ext,$valid_formats)) { if($size < (1024*1024)) { $actual_image_name = 'avatar' .'_'.$userId .'.'.$ext; $filePath = $path .'/'.$actual_image_name; $tmp = $_FILES['profile-pic']['tmp_name']; if(move_uploaded_file($tmp, $filePath)) { $width = getWidth($filePath); $height = getHeight($filePath); //Scale the image if it is greater than the width set above if ($width > $max_width){ $scale = $max_width/$width; $uploaded = resizeImage($filePath,$width,$height,$scale, $ext); } else { $scale = 1; $uploaded = resizeImage($filePath,$width,$height,$scale, $ext); } echo "<img id='photo' file-name='".$actual_image_name."' class='' src='".$filePath.'?'.time()."' class='preview'/>"; } else echo "failed"; } else echo "Image file size max 1 MB"; } else echo "Invalid file format.."; } else echo "Please select image..!"; exit; } /* Function to update image */ function saveProfilePicTmp() { $post = isset($_POST) ? $_POST: array(); $userId = isset($post['id']) ? intval($post['id']) : 0; $path ='imagestmp'; $t_width = 300; // Maximum thumbnail width $t_height = 300; // Maximum thumbnail height if(isset($_POST['t']) and $_POST['t'] == "ajax") { extract($_POST); $imagePath = 'images/tmp/'.$_POST['image_name']; $ratio = ($t_width/$w1); $nw = ceil($w1 * $ratio); $nh = ceil($h1 * $ratio); $nimg = imagecreatetruecolor($nw,$nh); $im_src = imagecreatefromjpeg($imagePath); imagecopyresampled($nimg,$im_src,0,0,$x1,$y1,$nw,$nh,$w1,$h1); imagejpeg($nimg,$imagePath,90); } echo $imagePath.'?'.time();; exit(0); } /* Function to resize image */ function resizeImage($image,$width,$height,$scale) { $newImageWidth = ceil($width * $scale); $newImageHeight = ceil($height * $scale); $newImage = imagecreatetruecolor($newImageWidth,$newImageHeight); switch ($ext) { case 'jpg': case 'jpeg': $source = imagecreatefromjpeg($image); break; case 'gif': $source = imagecreatefromgif($image); break; case 'png': $source = imagecreatefrompng($image); break; default: $source = false; break; } imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height); imagejpeg($newImage,$image,90); chmod($image, 0777); return $image; } /* Function to get image height. */ function getHeight($image) { $sizes = getimagesize($image); $height = $sizes[1]; return $height; } /* Function to get image width */ function getWidth($image) { $sizes = getimagesize($image); $width = $sizes[0]; return $width; } ?>
Por último, guardamos la ruta de la imagen guardada en nuestra base de datos MySQL mediante la función saveProfilePic().
/* Function to handle profile pic update*/ function saveProfilePic(){ include_once("db_connect.php"); $post = isset($_POST) ? $_POST: array(); //Handle profile picture update with MySQL update Query using $options array if($post['id']){ $sql_query = "SELECT * FROM users WHERE uid = '".mysqli_escape_string($conn, $post['id'])."'"; $resultset = mysqli_query($conn, $sql_query) or die("database error:". mysqli_error($conn)); if(mysqli_num_rows($resultset)) { $sql_update = "UPDATE users set profile_photo='".mysqli_escape_string($conn,$post['image_name'])."' WHERE uid = '".mysqli_escape_string($conn, $post['id'])."'"; mysqli_query($conn, $sql_update) or die("database error:". mysqli_error($conn)); } } }
Fuente: phpzag.com