JavaScript: 一张图片中的多重裁剪选择?

JavaScript: Multiple cropping selection in one image?

PS:这不是研究型的问题吗!很长一段时间以来,我一直在尝试这样做。

我正在尝试制作 基于 Web 的图像编辑器,用户可以在其中 select 多裁剪区域,然后 selection save/download 所有图像区域。 如下所示。

到目前为止我发现了两个库

1.Cropper.JS 其中只有单个 selection 特征可用。

2.Jcrop where only single selection area restrictions.

目前正在使用cropper.Js,但我似乎不可能进行多次select离子裁剪。 appreciated.if JavaScript、Angular 或 PHP 中可用的任何其他 method/library 或 reactJS 对多个图像区域 selection 和裁剪以及如下图一口气下载

As per @Keyhan Answer I am Updating my Jcrop library Code

 <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>

我试着用注释来解释代码:

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();
        }
    }
};

编辑:正如您所说,如果我们有本地图像加载器会更好,我们可以将文件输入添加到我们的 html

<img id="target" />
<br/>
<input type="file" id="imageLoader" name="imageLoader"/><!-- add this for file picker -->
<button id="save">save</button>

以及我们的 js 函数来处理它

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});
});

是的,@keyhan 是对的 <input type="file"> 是另一个问题,但是,我仍然让您了解如何实现上面 Kayhan 的代码。

<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>

现在您可以在 JavaScript 下方放置 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>