PD: ¿No es un tipo de pregunta de investigación? He estado tratando de hacer esto desde hace mucho tiempo.
Estoy tratando de hacer un editor de imágenes basado en la web donde el usuario puede seleccionar múltiples áreas de recorte y después de la selección guardar/descargar toda el área de la imagen. como abajo.
A partir de ahora descubrí dos bibliotecas.
1. Cropper.JS donde solo está disponible la función de selección única.
2. Jcrop donde solo hay restricciones de área de selección única.
Actualmente estoy usando cropper.Js pero me parece imposible hacer un recorte de selección múltiple. Cualquier ayuda es muy apreciada. Si hay algún otro método/biblioteca disponible en JavaScript, Angular o PHP o reactJS para la selección de múltiples áreas de imagen y recortar y descargar de una sola vez como en la imagen a continuación.
Según la respuesta de @Keyhan, estoy actualizando el código de mi biblioteca Jcrop
<div style="padding:0 5%;"> <img id="target" src="https://d3o1694hluedf9.cloudfront.net/market-750.jpg"> </div> <button id="save">Crop it!</button> <link rel="stylesheet" href="https://unpkg.com/jcrop/dist/jcrop.css"> <script src="https://unpkg.com/jcrop"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>JavaScript
<script> setImage(); var jcp; var jcp; Jcrop.load('target').then(img => { //You can enable multiple cropping with this line: jcp = Jcrop.attach(img, { multi: true }); }); // to fix security issue when trying to convert to Data URI function setImage() { document.getElementById('target').setAttribute('crossOrigin', 'anonymous'); document.getElementById('target').src = 'https://d3o1694hluedf9.cloudfront.net/market-750.jpg'; } var link = document.getElementById('save'); link.onclick = function () { //we check if at least one crop is available if (jcp.active) { var i = 0; var fullImg = document.getElementById("target"); //we are looping cropped areas for (area of jcp.crops) { i++; //creating temp canvas and drawing cropped area on it canvas = document.createElement("canvas"); canvas.setAttribute('width', area.pos.w); canvas.setAttribute('height', area.pos.h); ctx = canvas.getContext("2d"); ctx.drawImage(fullImg, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h); //creating temp link for saving/serving new image temp = document.createElement('a'); temp.setAttribute('download', 'area' + i + '.jpg'); temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream")); temp.click(); } } }; </script>Traté de explicar el código con comentarios:
var jcp; Jcrop.load('target').then(img => { //You can enable multiple cropping with this line: jcp = Jcrop.attach(img,{multi:true}); }); //assuming you have a button with id="save" for exporting cropped areas var link=document.getElementById('save'); link.onclick = function(){ //we check if at least one crop is available if(jcp.active){ var i=0; var fullImg = document.getElementById("target"); //we are looping cropped areas for(area of jcp.crops){ i++; //creating temp canvas and drawing cropped area on it canvas = document.createElement("canvas"); canvas.setAttribute('width',area.pos.w); canvas.setAttribute('height',area.pos.h); ctx = canvas.getContext("2d"); ctx.drawImage(fullImg, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h); //creating temp link for saving/serving new image temp = document.createElement('a'); temp.setAttribute('download', 'area'+i+'.jpg'); temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream")); temp.click(); } } };EDITAR: como comentó, sería mejor si tuviéramos un cargador de imágenes local, podemos agregar una entrada de archivo a nuestro html
<img id="target" /> <br/> <input type="file" id="imageLoader" name="imageLoader"/><!-- add this for file picker --> <button id="save">save</button>y una función a nuestro js para manejarlo
var jcp; var save=document.getElementById('save'); var imageLoader = document.getElementById('imageLoader'); var img = document.getElementById("target"); imageLoader.onchange=function handleImage(e){//handling our image picker <input>: var reader = new FileReader(); reader.onload = function(event){ img.src = event.target.result; } reader.readAsDataURL(e.target.files[0]); } save.onclick = function(){ if(jcp&&jcp.active){ var i=0; for(area of jcp.crops){ i++; canvas = document.createElement("canvas"); canvas.setAttribute('width',area.pos.w); canvas.setAttribute('height',area.pos.h); ctx = canvas.getContext("2d"); ctx.drawImage(img, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h); temp = document.createElement('a'); temp.setAttribute('download', 'area'+i+'.jpg'); temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream")); temp.click(); } } }; Jcrop.load('target').then(img => { jcp = Jcrop.attach(img,{multi:true}); });Sí, @keyhan tenía razón <input type="file"> es otra pregunta, pero aun así, les estoy dando una idea de cómo implementar el código de Kayhan anterior.
<div> <input type="file" id="image-input" accept="image/*"> <!-- img id name should be "target" as it is also using by Jcrop --> <img id="target"></img> </div> y ahora puede poner debajo del código JavaScript justo encima de setImage()
<script> let imgInput = document.getElementById('image-input'); imgInput.addEventListener('change', function (e) { if (e.target.files) { let imageFile = e.target.files[0]; var reader = new FileReader(); reader.onload = function (e) { var img = document.createElement("img"); img.onload = function (event) { var MAX_WIDTH = 1600; var MAX_HEIGHT = 800; var width = img.width; var height = img.height; // Change the resizing logic if (width > height) { if (width > MAX_WIDTH) { height = height * (MAX_WIDTH / width); width = MAX_WIDTH; } } else { if (height > MAX_HEIGHT) { width = width * (MAX_HEIGHT / height); height = MAX_HEIGHT; } } // Dynamically create a canvas element var canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; // var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // Actual resizing ctx.drawImage(img, 0, 0, width, height); // Show resized image in preview element var dataurl = canvas.toDataURL(imageFile.type); document.getElementById("target").src = dataurl; } img.src = e.target.result; } reader.readAsDataURL(imageFile); } }); </script>