简体   繁体   English

使用 JavaScript 裁剪图像

[英]Crop the image using JavaScript

In my Angular 6 application I am making a file upload option and in preview the uploaded file needs to be displayed with auto cropping and auto resizing.在我的 Angular 6 应用程序中,我正在制作一个文件上传选项,并且在预览中上传的文件需要显示为自动裁剪和自动调整大小。

I have tried the following,我试过以下,

HTML: HTML:

<canvas id="canvas"></canvas>
<div style="display:none;">
  <img id="source" [src]="url" width="300" height="227">
</div>
<input type='file' (change)="onSelectFile($event)">

File select functtion:文件选择功能:

  onSelectFile(event) {
    if (event.target.files && event.target.files[0]) {
      var reader = new FileReader();

      reader.readAsDataURL(event.target.files[0]); // read file as data url

      reader.onload = (event) => { // called once readAsDataURL is completed
        this.url = event.target.result;
      }

      const canvas : any =  document.getElementById('canvas');
      const ctx = canvas.getContext('2d');
      const image = document.getElementById('source');

      ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
    }
  }

In the above I have tried the following with the reference of link https://jsfiddle.net/8jwq3cs7/在上面,我尝试了以下参考链接https://jsfiddle.net/8jwq3cs7/

      const canvas : any =  document.getElementById('canvas');
      const ctx = canvas.getContext('2d');
      const image = document.getElementById('source');

      ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);

Before using the canvas the original image looks like this: https://mdn.mozillademos.org/files/5397/rhino.jpg在使用画布之前,原始图像如下所示: https ://mdn.mozillademos.org/files/5397/rhino.jpg

Whereas after using canvas it's like this: https://jsfiddle.net/8jwq3cs7/而在使用画布之后它是这样的: https ://jsfiddle.net/8jwq3cs7/

But if I choose the image from choose file then I am unable to see the image after choosing...但是,如果我从choose file中选择图像,那么在选择后我将无法看到图像...

Working example: https://stackblitz.com/edit/angular-file-upload-preview-uwpf8f工作示例: https ://stackblitz.com/edit/angular-file-upload-preview-uwpf8f

Even the solution with pure JavaScript alone would also be appreciable if not in the Angular way...如果不是以 Angular 方式,即使是仅使用纯 JavaScript 的解决方案也将是可观的......

The requirement is, if I choose a file then the same file needs to be cropped and fit the size automatically in preview...要求是,如果我选择一个文件,则需要裁剪同一个文件并在预览中自动适应大小...

Kindly help me to achieve the result without jQuery or any library ...请帮助我在没有 jQuery 或任何库的情况下实现结果......

Here is a function to get the image as you are uploading using the choose file button这是使用选择文件按钮上传时获取图像的功能

function readURL() {
    const myimg = document.getElementById("myimg");
    const input = document.getElementById("myfile");
    if(input.files && input.files[0]) {
        const reader = new FileReader();
        reader.onload = e => {
            console.log("changed");
            myimg.src = e.target.result;
        };
        reader.readAsDataURL(input.files[0]);
    }
}
document.querySelector('#myfile').addEventListener('change', () => {
    readURL();
});

And the HTML will be HTML 将是

<img src="" id="myimg"><br>
<input type="file" id="myfile">

Here is a working fiddle这是一个工作小提琴

If you add a file the preview image will be updated.如果您添加文件,预览图像将被更新。 You actually get a data url here.你实际上在这里得到了一个数据 url。 Use the data url to the load the image to the canvas then crop it.使用数据 url 将图像加载到画布,然后裁剪它。 calling drawimg(e.target.result)调用drawimg(e.target.result)

function drawimg(idata) {
    const img = new Image();
    img.onload = () => {
        ctx.drawImage(img, 33, 71, 104, 124, 21, 20, 87, 104);
    };
    img.src = idata;
}

See working Fiddle: here请参阅工作小提琴:此处

Here is how I implemented it in my case:以下是我在我的案例中的实现方式:

  onSelectFile(event) {
    if (event.target.files && event.target.files[0]) {
      var reader = new FileReader();

      reader.readAsDataURL(event.target.files[0]); // read file as data url

      reader.onload = (event) => { // called once readAsDataURL is completed
       console.log(event);
        this.url = event.target.result;
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        const image = new Image();
        image.src = this.url;

        ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);

      }

The working stackblitz demo is here: https://stackblitz.com/edit/angular-file-upload-preview-qrrgx5工作 stackblitz 演示在这里: https ://stackblitz.com/edit/angular-file-upload-preview-qrrgx5

Hope it helps and this is what you want.希望它有所帮助,这就是你想要的。

I'm a bit late to the party on this one, but I was facing a very similar issue myself yesterday, but instead using NodeJS.我参加这个聚会有点晚了,但昨天我自己也遇到了一个非常相似的问题,但我使用的是 NodeJS。

My solution in the end was to break down the image into its RGBA values and check each row and column of the image to find where the image itself actually starts in comparison to the BG.我最后的解决方案是将图像分解成它的 RGBA 值,并检查图像的每一行和每一列,以找到与 BG 相比图像本身实际开始的位置。

In my case, I'm working with images that are around 1500px*500px, with my solution taking around 150-250ms per image to read in the file, break down its pixels, calculate the cropping positions and to write the cropped file back to disk.在我的例子中,我正在处理大约 1500px*500px 的图像,我的解决方案每张图像需要大约 150-250ms 来读取文件、分解其像素、计算裁剪位置并将裁剪后的文件写回磁盘。

Since I couldn't find any nice libraries online to handle this, I've made my own and published it to NPM in case anyone else comes across the same issue and needs some help: :-)由于我在网上找不到任何不错的库来处理这个问题,所以我自己制作了它并将其发布到 NPM,以防其他人遇到同样的问题并需要一些帮助::-)

https://www.npmjs.com/package/developyn-autocrop https://www.npmjs.com/package/developyn-autocrop

So if you want to just crop it to a position whatever image it is then have a look at @black-mamba answer or make use of css crop to don't oversize your js. 因此,如果您想将其裁剪到任何图像位置,请查看@ black-mamba答案或使用CSS裁剪来不要放大js。 Here you can read more about css crop: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Attribute/crop 在这里您可以阅读有关CSS裁剪的更多信息: https : //developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Attribute/crop

But if you want to crop an image to the face of its user (or animal) use a library like jquery.facedetection or service like imgix (paid). 但是,如果您想将图像裁剪为用户(或动物)的脸,请使用jquery.facedetection之类的库或imgix (付费)之类的服务。

<html>
    <head>
    <style>
    #preview {
    background: red;
    border: 1px solid green;
    }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="http://jcrop-cdn.tapmodo.com/v0.9.12/js/jquery.Jcrop.min.js"></script>
    <link rel="stylesheet" href="http://jcrop-cdn.tapmodo.com/v0.9.12/css/jquery.Jcrop.css" type="text/css" />

    <script type="text/javascript">
         $(document).delegate(':file', 'change', function() {
            picture(this);
            console.log('running');
        });

         //$(document).delegate(':form', 'change', function() {

        var picture_width;
        var picture_height;
        var crop_max_width = 300;
        var crop_max_height = 300;
        function picture(input) {
            if (input.files && input.files[0]) {
                var reader = new FileReader();
                reader.onload = function (e) {
                    $("#jcrop, #preview").html("").append("<img src=\""+e.target.result+"\" alt=\"\" />");
                    picture_width = $("#preview img").width();
                    picture_height = $("#preview img").height();
                    $("#jcrop  img").Jcrop({
                        onChange: canvas,
                        onSelect: canvas,
                        boxWidth: crop_max_width,
                        boxHeight: crop_max_height
                    });
                }
                reader.readAsDataURL(input.files[0]);
            }
        }
        function canvas(coords){
            var imageObj = $("#jcrop img")[0];
            var canvas = $("#canvas")[0];
            canvas.width  = coords.w;
            canvas.height = coords.h;
            var context = canvas.getContext("2d");
            context.drawImage(imageObj, coords.x, coords.y, coords.w, coords.h, 0, 0, canvas.width, canvas.height);
            png();
        }
        function png() {
            var png = $("#canvas")[0].toDataURL('image/png');
            $("#png").val(png);
        }
        function dataURLtoBlob(dataURL) {
            var BASE64_MARKER = ';base64,';
            if(dataURL.indexOf(BASE64_MARKER) == -1) {
                var parts = dataURL.split(',');
                var contentType = parts[0].split(':')[1];
                var raw = decodeURIComponent(parts[1]);

                return new Blob([raw], {type: contentType});
            }
            var parts = dataURL.split(BASE64_MARKER);
            var contentType = parts[0].split(':')[1];
            var raw = window.atob(parts[1]);
            var rawLength = raw.length;
            var uInt8Array = new Uint8Array(rawLength);
            for(var i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
            }

            return new Blob([uInt8Array], {type: contentType});
        }
    </script>
    </head>
    <body>
       <form id="form">
        <h2>Image file select</h2>
        <input id="file" type="file" onchange="imageLoad()" />
        <h2>Uploaded Image</h2>
        <div id="jcrop"></div>
        <h2>Cropped Image</h2>
        <canvas id="canvas"></canvas>
        <input id="png" type="hidden" />
        <h2>Submit form</h2>
        <input type="submit" value="Upload form data and image" />
       </form>
    </body>
</html>

 // Set constraints for the video stream var constraints = { video: { facingMode: "user" }, audio: false }; // Define constants const cameraView = document.querySelector("#camera--view"), cameraOutput = document.querySelector("#camera--output"), cameraSensor = document.querySelector("#camera--sensor"), cameraTrigger = document.querySelector("#camera--trigger") // Access the device camera and stream to cameraView function cameraStart() { navigator.mediaDevices.getUserMedia(constraints).then(function(stream) { track = stream.getTracks()[0]; cameraView.srcObject = stream; }).catch(function(error) { console.error("Oops. Something is broken.", error); }); } // Take a picture when cameraTrigger is tapped cameraTrigger.onclick = function() { cameraSensor.width = cameraView.videoWidth; cameraSensor.height = cameraView.videoHeight; cameraSensor.getContext("2d").drawImage(cameraView, 0, 0); cameraOutput.src = cameraSensor.toDataURL("image/webp"); cameraOutput.classList.add("taken"); }; // Start the video stream when the window loads window.addEventListener("load", cameraStart, false);
 html, body{ margin: 0; padding: 0; height: 100%; width: 100%; } #camera, #camera--view, #camera--sensor, #camera--output{ position: fixed; height: 100%; width: 100%; object-fit: cover; } #camera--view, #camera--sensor, #camera--output{ transform: scaleX(-1); filter: FlipH; } #camera--trigger{ width: 200px; background-color: black; color: white; font-size: 16px; border-radius: 30px; border: none; padding: 15px 20px; text-align: center; box-shadow: 0 5px 10px 0 rgba(0,0,0,0.2); position: fixed; bottom: 30px; left: calc(50% - 100px); }.taken{ height: 100px;important: width; 100px:important. transition; all 0:5s ease-in; border: solid 3px white, box-shadow, 0 5px 10px 0 rgba(0,0.0;0:2); top: 20px; right: 20px; z-index: 2; }
 <html lang=”en”> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <.-- Name of your awesome camera app --> <title>Camera App</title> <:-- Link to your main style sheet--> <link rel="stylesheet" href="style.css"> </head> <body> <!-- Camera --> <main id="camera"> <!-- Camera sensor --> <canvas id="camera--sensor"></canvas> <!-- Camera view --> <video id="camera--view" autoplay playsinline></video> <!-- Camera output --> <img src="//:0" alt="" id="camera--output"> <!-- Camera trigger --> <button id="camera--trigger">Take a picture</button> </main> <!-- Reference to your JavaScript file --> <script src="app.js"></script> </body> </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM