Создание уменьшенных квадратов изображений в javascript (без потери соотношения сторон)

#javascript #css #html #base64 #bookmarklet

#javascript #css #HTML #base64 #букмарклет

Вопрос:

Я создаю скрипт загрузки файлов перетаскиванием на стороне клиента в виде букмарклета. Перед загрузкой я использую File API для чтения изображений в формате base64 и отображения их в виде эскизов.

Вот так выглядят мои эскизы. Я хочу, чтобы они выглядели более квадратными, но без потери соотношения сторон. (пожалуйста, игнорируйте индикатор выполнения) широкие миниатюры

Вот как я хочу, чтобы миниатюры были похожи, они центрируются и обрезаются на основе min (высота, ширина). квадратные миниатюры

Могу ли я сделать это, используя только javascript (изменение стилей с помощью скрипта подойдет)? Пожалуйста, постарайтесь убедиться, что ваше решение будет соответствовать изображениям base64 (после того, как изображения будут считаны через file API как URL-адрес ДАННЫХ).

Я загрузил этот точный набор изображений здесь.

Спасибо за помощь.

Ответ №1:

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

Вот мой код для того же:

 function resizeImage(url, width, height, callback, file) {
  console.log("In_resizeImage");
  var sourceImage = new Image();

  sourceImage.onload = (function (f) {
      return function (evt) {
        console.log("In_sourceImage_onload");
        console.log("sourceImage.width:"   sourceImage.width);
        console.log("sourceImage.height:"   sourceImage.height);
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;

        if (sourceImage.width == sourceImage.height) {
          canvas.getContext("2d").drawImage(sourceImage, 0, 0, width, height);
        } else {
          minVal = Math.min(sourceImage.width, sourceImage.height);
          if (sourceImage.width > sourceImage.height) {
            canvas.getContext("2d").drawImage(sourceImage, (sourceImage.width - minVal) / 2, 0, minVal, minVal, 0, 0, width, height);
          } else {
            canvas.getContext("2d").drawImage(sourceImage, 0, (sourceImage.height - minVal) / 2, minVal, minVal, 0, 0, width, height);
          }
        }
        callback(canvas.toDataURL(), f);
      }
    })(file);

  sourceImage.src = url;
}
  

Я имел дело непосредственно с файлами изображений, поэтому смог использовать объект изображения. Для других пользователей может потребоваться небольшая настройка.

Комментарии:

1. можете ли вы привести пример того, как использовать вашу функцию? Спасибо.

Ответ №2:

Создайте экземпляр другого html-элемента (я бы выбрал таблицу, но я старый и устаревший) и выровняйте изображение в качестве фонового изображения с помощью CSS, что-то вроде

таблица { background: url(‘planets.jpg ‘) 0px -150px без повтора; ширина: 60 пикселей; высота 60 пикселей}

Я украл все это отсюда: Как создавать CSS-спрайты

Ответ №3:

Это должно поддерживать как изображение, так и видео. Это создаст миниатюру для мультимедиа, но также сохранит соотношение сторон мультимедиа.

Это также должно очищаться само по себе, поэтому утечки событий не должны сохраняться. Это также сгладит уменьшенное изображение.

 /* example to resize an image to 300px width 
and keep the aspect */ 
resizeMedia('/images/logo.jpg', 300, function(data)
{
    console.log(data); // the new thumbnail data uri 
});  


/* this will create a thumbnail of an image or video 
and keep the aspect. 
@param (string | object) media = the image string or video object 
@param (int) width = the new width to contain the media 
@param (function) callBack = the callBack to handle the 
image data uri */ 
function resizeMedia(media, width, callBack) 
{
    var self = this; 

    /* this will get the type by checking ifthe media 
    is a string (e.g. img src or dataUri) */ 
    var type = typeof media === 'string'? 'image' : 'video'; 

    /* this will get the height and width of the resized 
    media and keep the aspect. 
    @param (int) udateSize = the width the modify 
    @param (int) width = the old width 
    @param (int) height = the old height 
    @return (object) the width and height to modify the 
    media */ 
    var getModifySize = function(updateSize, width, height) 
    { 
        var getModifyAspect = function(max, min, value)
        {
            var ratio = max / min;
            return value * ratio;
        };   

        return { 
            width: updateSize,
            height: getModifyAspect(updateSize, width, height) 
        }; 
    }; 

    /* this will create a canvas and draw the media 
    on the canvas. 
    @param (object) media = the image or video 
    object 
    @param (int) width = the canvas width
    @param (int) height = the canvas height 
    @return (object) the new canvas */ 
    var createCanvas = function(media, width, height)
    { 
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d"); 

        canvas.width = width;
        canvas.height = height;

        ctx.mozImageSmoothingEnabled = true;
        ctx.webkitImageSmoothingEnabled = true;
        ctx.msImageSmoothingEnabled = true;
        ctx.imageSmoothingEnabled = true;

        /* we need to draw on load to make sure
        the image is ready to be used */
        ctx.drawImage(media, 0, 0, width, height);

        /* this will convert the canvas to a data uri
        using jpeg to speed up the process. if you need 
        to keep transparency remove the mime type 
        and it will default to png */ 
        callBack(canvas.toDataURL('image/jpeg'));

        return canvas; 
    }; 

    if(type === 'image') 
    { 
        var img = new window.Image();
        img.crossOrigin = "anonymous";
        img.addEventListener('load', function loadImage() 
        {
            var modify = getModifySize(width, img.width, img.height);

            createCanvas(img, modify.width, modify.height); 
            img.removeEventListener('load', loadImage);
        });

        img.src = media;
    } 
    else if(type === 'video') 
    { 
        var modify = getModifySize(width, media.videoWidth, media.videoHeight);
        createCanvas(media, modify.width, modify.height);
    }
}; 
  

Ответ №4:

Вы также можете «обрезать» непосредственно центрированный квадрат изображения на холсте с помощью drawImage (), вам просто нужно указать эти параметры :

canvas.getContext(«2d»).drawImage(img, sx, sy, ширина, высота, x, y, ширина, высота);

sx необязательно. Координата x, с которой нужно начать обрезку

sy необязательно. Координата y, с которой нужно начать обрезку

swidth необязательно. Ширина обрезанного изображения

высота не является обязательной. Высота обрезанного изображения

x Координата x, где разместить изображение на холсте

y Координата y, где разместить изображение на холсте

ширина необязательна. Ширина используемого изображения (растянуть или уменьшить изображение)

высота необязательна. Высота используемого изображения (растянуть или уменьшить изображение)

С уважением,

Pierrick