使用 JavaScript 裁剪图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/53810434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Crop the image using JavaScript
提问by Maniraj Murugan
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 filethen I am unable to see the imageafter 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 或任何库的情况下实现结果......
回答by Geon George
Here is a function to get the image as you are uploading using the choose filebutton
这是使用选择文件按钮在上传时获取图像的功能
function readURL() {
var myimg = document.getElementById("myimg");
var input = document.getElementById("myfile");
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
console.log("changed");
myimg.src = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}
document.querySelector('#myfile').addEventListener('change',function(){
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. Use the data url to the load image to canvas then crop it. calling drawimg(e.target.result)
如果您添加文件,预览图像将被更新。你实际上在这里得到了一个数据 url。使用数据 url 将图像加载到画布,然后裁剪它。打电话drawimg(e.target.result)
function drawimg(idata) {
var img = new Image();
img.onload = function(){
ctx.drawImage(img, 33, 71, 104, 124, 21, 20, 87, 104);
};
img.src = idata;
}
See working Fiddle: here
见工作小提琴:在这里
回答by Black Mamba
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.
希望它有帮助,这就是你想要的。
回答by muuvmuuv
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. Here you can read more about css crop: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Attribute/crop
因此,如果您只想将其裁剪到任何图像的位置,那么请查看@black-mamba 的答案或使用 css 裁剪不要使您的 js 过大。在这里您可以阅读有关 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.facedetectionor service like imgix(paid).
但是,如果您想将图像裁剪为其用户(或动物)的脸部,请使用像jquery.facedetection这样的库或像imgix(付费)这样的服务。
回答by ganesh
// 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>
回答by Akshay Kumar
// 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>
回答by ganesh
<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>

