В моем приложении Angular 6 я делаю опцию загрузки файла, и в предварительном просмотре загруженный файл должен отображаться с автоматической обрезкой и автоматическим изменением размера.
Я пробовал следующее,
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)">
Функция выбора файла:
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);
}
}
Выше я пробовал следующее со ссылкой на ссылку 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);
Перед использованием холста исходное изображение выглядит так: https://mdn.mozillademos.org/files/5397/rhino.jpg
А после использования холста это так: https://jsfiddle.net/8jwq3cs7/
Но если я выберу образ из choose file, то после выбора я буду невозможно увидеть изображение ...
Рабочий пример:https://stackblitz.com/edit/angular-file-upload-preview-uwpf8f
Даже решение с одним только чистым JavaScript также было бы заметным, если бы не в Angular ...
Требование:, если я выберу файл, тогда тот же файл необходимо обрезать и автоматически подогнать под размер при предварительном просмотре ...
Пожалуйста, помогите мне добиться результата без jQuery или какой-либо библиотеки ...
@ Rik, извини, я не могу тебя достать .. Пожалуйста, помогите мне обрезать и изменить размер выбранного изображения ..
Вы хотите обрезать его до лица «животные» или только до определенного размера, например background-size: cover?
@undefined Если ваш скрипт будет показывать превью изображений JPEG, они будут неправильно повернуты, если у них есть тег ориентации EXIF (что имеет место, когда изображения сделаны на мобильных телефонах). Поэтому вам нужно будет прочитать тег и соответствующим образом повернуть контекст холста. medium.com/@Orangeeli/oh-my-exif-777335e26213
Возможный дубликат Обрезка изображения и изменение размера



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот функция для получения изображения при загрузке с помощью кнопки выбрать файл
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.info("changed");
myimg.src = e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
}
document.querySelector('#myfile').addEventListener('change', () => {
readURL();
});
И HTML будет
<img src = "" id = "myimg"><br>
<input type = "file" id = "myfile">
Вот такой рабочая рабочий пример
Если вы добавите файл, изображение предварительного просмотра будет обновлено.
Здесь вы действительно получаете URL-адрес данных. Используйте URL-адрес данных, чтобы загрузить изображение на холст, а затем обрезать его. звонок 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;
}
См. Рабочий скрипт: здесь
Я просто использовал jquery, чтобы легко выполнять функцию .change (). В этом нет большого количества jquery. Просто прочтите перед тем, как проголосовать против
Здравствуйте, дорогой, это приложение angular, здесь мы ни в коем случае не будем использовать jquery, даже маленький или большой .. Использование jquery строго ограничено .. Если мне нужен jquery, я бы не стал публиковать этот вопрос ..
@undefined сейчас отредактировал ответ. Вы даже не прочитали ответ должным образом, прежде чем проголосовали против. Код был и продолжает работать. Я использовал jquery только для идентификации события изменения файла. Теперь это полностью ванильный js
Думаю, вы не поняли мой вопрос .. Мне нужно обрезать загруженное изображение .. Прочтите внимательно ..
Ваше заключительное предложение - «Используйте URL-адрес данных для загрузки изображения на холст, а затем обрежьте его» - это вопрос, который, похоже, задает OP; Можете ли вы расширить это, чтобы показать как, что может быть выполнено? Также не забывайте объяснять свои ответы, чтобы люди могли поучиться у вас.
@undefined Вот полная рабочая версия: jsfiddle.net/geongeorgek/8jwq3cs7/14
@undefined К сожалению, изменение не было сохранено. Вот так: jsfiddle.net/geongeorgek/rp0bym1a
Итак, вы хотите, чтобы пользователь выбирал область лица или автоматически определял лица? в любом случае вы неправильно сформулировали вопрос или извините за неверное понимание
Вот как я реализовал это в моем случае:
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.info(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);
}
Рабочая демонстрация stackblitz находится здесь: https://stackblitz.com/edit/angular-file-upload-preview-qrrgx5
Надеюсь, это поможет, и это то, что вы хотите.
Мое требование должно быть таким: если я загружаю свое изображение с высотой 500 пикселей и шириной 500 пикселей, мне нужно изменить его размер, отображая только лицо с автоматическим кадрированием и автоматическим изменением размера. Надеюсь, вы поняли, что я загружаю изображение для изображение профиля, тогда оно автоматически обрезает только область лица и отображает ее .. Я ожидаю, что автоматическая обрезка области лица будет только в загружаемом нами изображении профиля ..
<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.info('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>Пожалуйста, добавьте несколько экспалинаций.
Error: Oops. Something is broken.Я немного опоздал на вечеринку по этому поводу, но вчера я сам столкнулся с очень похожей проблемой, но вместо этого использовал NodeJS.
В конце концов, мое решение состояло в том, чтобы разбить изображение на его значения RGBA и проверить каждую строку и столбец изображения, чтобы найти, где само изображение фактически начинается по сравнению с BG.
В моем случае я работаю с изображениями размером около 1500 пикселей * 500 пикселей, при этом мое решение занимает около 150-250 мс на изображение для чтения в файле, разбивает его пиксели, вычисляет позиции обрезки и записывает обрезанный файл обратно в диск.
Так как я не смог найти в Интернете никаких хороших библиотек для решения этой проблемы, я сделал свою собственную и опубликовал ее в NPM на случай, если кто-то еще столкнется с той же проблемой и ему понадобится помощь! :-)
Не забудьте реализовать коррекцию тега ориентации EXIF, чтобы исправить ориентацию мобильной фотографии.