Изменение размеров изображений с помощью JavaScript с использованием элементов canvas - PullRequest
0 голосов
/ 27 ноября 2018

Мне трудно понять, как работать с canvas элементами в JavaScript.

Я реализую функцию изменения размера, где пользователь может изменять размер изображения внутри lightbox.lightbox запустится после нажатия на изображение предварительного просмотра.Внутри элемента lightbox, помимо самого изображения, есть два поля ввода для ширины и высоты.

Цель состоит в том, чтобы создать копию исходного изображения в формате base64 и отправить ее на сервер вместе с заданными шириной и высотой в качестве параметров запроса и позволить стороне сервера выполнить операцию изменения размера (яиспользуя PHP для моего бэкенда) или, что еще лучше, позвольте JavaScript выполнить операцию изменения размера во внешнем интерфейсе и вернуть новое изображение с измененным размером, готовое к отправке на сервер через ajax.

Проблема в том, что я точно не знаю, как обращаться с динамически создаваемыми canvas элементами и как я могу использовать его для изменения размера моего изображения в интерфейсе.

Под этим стоит то, чтоЯ пробовал пока что с плохими результатами:

index.html (основные элементы HTML и эффект лайтбокса опущены)

<!-- input fields for width and height -->
<div class="container">
    <div class="form-inline">
        <div class="form-group">
            <input type="number" class="form-control" id="width" placeholder="px">
        </div>
        <div class="form-group">
            <input type="number" class="form-control" id="height" placeholder="px">
        </div>
        <button id="resize" type="button" class="btn btn-primary">Resize</button>
    </div>
</div>

<!-- preview image -->
<div class="container">
    <img src="img/img1.jpg" alt="" class="img-responsive" id="preview">
</div>

<script type="text/javascript">
    button = document.getElementById("resize");

    button.addEventListener("click", function() {
        // get image
        const image = document.getElementById('preview');

        // create a canvas element
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext("2d");

        canvas.width = image.width; // destination canvas size
        canvas.height = canvas.width * image.height / image.width;

        ctx.drawImage(image, 0, 0, image.width, image.height);
        var canvasData = canvas.toDataURL("image/jpeg");


        // ajax call
        var xhr = new XMLHttpRequest();
        var params = "photo=" + encodeURIComponent(canvasData) + "&name=" + encodeURIComponent(name) + "&width="+ encodeURIComponent(width) + "&height=" + encodeURIComponent(height);
        // send request
        xhr.open("POST", "admin.php?" + params);
        xhr.send();
    });
</script>

admin.php (здесь ничего необычного, просто расшифруйте изображение и запишите его в папку)

<?php

if(isset($_POST['photoUpload']) && isset($_POST['name'])) {
// decode base64 formatted image
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $_POST['photoUpload']));

if(isset($_POST['width'] && $_POST['height'])) {
    // resize image here using imagemagick
}

// write file to "img" directory
file_put_contents(dataPath.'img/'.$_POST['name'], $data);

// done
exit('OK|'.dataPath.'img/'.$_POST['name']);
}

Любые советы, рекомендации и советы приветствуются!

1 Ответ

0 голосов
/ 28 ноября 2018

Вы можете изменить размер изображения также на стороне клиента.В приведенном ниже примере кода используется изображение, загруженное из локальной системы пользователя, для запуска примера без необходимости беспокоиться о проблемах CORS.Фрагмент также сохраняет изображение в виде объекта Blob, который при необходимости можно опубликовать на сервере.

// Creates a canvas containing a resized image
function resizeImage(img) {
  var canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d'),
    oWidth = img.naturalWidth,
    oHeight = img.naturalHeight,
    ratio = oWidth / oHeight,
    width = (ratio > 1) ? Math.min(200, oWidth) : Math.min(100, oWidth),
    height = Math.round(width / ratio);
  canvas.width = width;
  canvas.height = height;
  canvas.className = 'temp-cnv';
  document.body.appendChild(canvas);
  ctx.drawImage(img, 0, 0, width, height);
  return canvas;
}

// Define UI elements
var img = document.getElementById('img'),
  loadBut = document.getElementById('load'),
  resizeBut = document.getElementById('resize'),
  resizedImage; // This will be sent to the server

// Creates a blob and attaches it to an image element
resizeBut.addEventListener('click', function() {
  var canvas;
  if (img.src === 'https://stacksnippets.net/js') {
    return; // Quit, no image loaded
  }
  canvas = resizeImage(img);
  canvas.toBlob(function(blob) {
    img.src = URL.createObjectURL(blob);
    resizedImage = blob;
    canvas.parentElement.removeChild(canvas);
  }, 'image/jpeg', 0.99);
});

// Reads an image from the user's local system
loadBut.addEventListener('change', function(e) {
  var file = new FileReader();
  file.addEventListener('load', function() {
    img.src = file.result;
  });
  file.readAsDataURL(e.target.files[0]);
});
.temp-cnv {
  display: none;
}
<input type="file" id="load">
<button id="resize">Resize</button>
<br>
<img src="" id="img">

resizeImage Функция создает временный элемент холста и рассчитывает размеры для этого холста.Здесь изображение всегда сжимается, но вы можете реализовать свои собственные алгоритмы изменения размера.Свойства img.naturalWidth/Height содержат исходный размер изображения.

Когда размер холста был установлен правильно, изображение рисуется на холсте, в этот момент происходит фактическое изменение размера.Затем холст возвращается вызывающей стороне и присваивается локальной переменной canvas.

Затем из вновь созданного холста создается объект Blob.toBlob функция принимает в качестве аргументов функцию обратного вызова, mime-тип и необязательный параметр качества (только для JPEG).Функция обратного вызова присоединяет холст к изображению и сохраняет созданный объект Blob в переменную resizedImage для дальнейшего использования и, наконец, удаляет временный элемент холста.

Хорошо читать в MDN:

метод ctx.drawImage
Объект BLOB
Метод Canvas.toBlob
Изображения с поддержкой CORS

Если вы собираетесь отправить изображение с измененным размером на сервер, вы можете создать объект FormData и добавить изображение к этому объекту.Затем отправьте объект на сервер с помощью AJAX.Примерно так:

var xhr = new XMLHttpRequest(),
    form = new FormData();
form.append('imageBlob', resizedImage); // resizedImage is the Blob object created in the first snippet
form.append('imageName', 'THE_NAME_OF_THE_IMAGE');
xhr.addEventListener('load', function (data) {
    // AJAX response handler code
});
xhr.open('POST', 'THE_URL_TO_POST_TO');
xhr.send(form);

Обратите внимание, что параметры POST (в данном случае объект FormData ) присоединяются в качестве аргумента вызова xhr.send.

...