Масштабування зображення відповідно до полотна


79

У мене є форма, яка дозволяє користувачеві завантажувати зображення.

Після завантаження зображення ми виконуємо його масштабування, щоб зменшити розмір файлу, перш ніж передавати його назад на сервер.

Для цього ми розміщуємо його на полотні і маніпулюємо ним там.

Цей код відображатиме масштабоване зображення на полотні з розміром полотна 320 x 240px:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

... де canvas.width і canvas.height - це коефіцієнт масштабування висоти та ширини зображення xa на основі розміру вихідного зображення.

Але коли я йду використовувати код:

ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height

... Я отримую лише частину зображення на полотні, в даному випадку лівий верхній кут. Мені потрібно, щоб все зображення в масштабі було розміщене на полотні, незважаючи на те, що фактичний розмір зображення перевищує розмір полотна 320x240.

Отже, для коду вище, ширина та висота складають 1142x856, оскільки це кінцевий розмір зображення. Мені потрібно зберегти цей розмір, щоб передавати beck серверу під час подання форми, але хочу лише, щоб його менший вигляд відображався на полотні для користувача.

Чого мені тут не вистачає? Хто-небудь може мені вказати в правильному напрямку, будь ласка?

Заздалегідь велике спасибі.

Відповіді:


136

Введіть розмір вихідного зображення (img) як перший прямокутник:

ctx.drawImage(img, 0, 0, img.width,    img.height,     // source rectangle
                   0, 0, canvas.width, canvas.height); // destination rectangle

Другий прямокутник буде розміром призначення (до якого буде масштабовано вихідний прямокутник).

Оновлення 2016/6 : щодо співвідношення сторін та позиціонування (метод "обкладинки" CSS), ознайомтесь із:
Розмір фону моделювання: обкладинка на полотні


1
Це ідеально, +1. Швидкий пункт - вам не вистачає фіксуючої дужки drawImage()функції. Трохи возитися з моїм ОКР;)
Фрітс

1
Ідеально підходить для моїх потреб. Це позбавило мене від необхідності возитися з розміром / масштабом мого файлу зображення, коли поля форми змінювалися. Дякую;)
Zeek2

145

Ви допустили помилку під час другого виклику, встановивши розмір джерела на розмір цілі.
У будь-якому разі, я впевнений, що для масштабованого зображення потрібно однакове співвідношення сторін, тому вам потрібно його обчислити:

var hRatio = canvas.width / img.width    ;
var vRatio = canvas.height / img.height  ;
var ratio  = Math.min ( hRatio, vRatio );
ctx.drawImage(img, 0,0, img.width, img.height, 0,0,img.width*ratio, img.height*ratio);

я також вважаю, що ви хочете відцентрувати зображення, тому код буде таким:

function drawImageScaled(img, ctx) {
   var canvas = ctx.canvas ;
   var hRatio = canvas.width  / img.width    ;
   var vRatio =  canvas.height / img.height  ;
   var ratio  = Math.min ( hRatio, vRatio );
   var centerShift_x = ( canvas.width - img.width*ratio ) / 2;
   var centerShift_y = ( canvas.height - img.height*ratio ) / 2;  
   ctx.clearRect(0,0,canvas.width, canvas.height);
   ctx.drawImage(img, 0,0, img.width, img.height,
                      centerShift_x,centerShift_y,img.width*ratio, img.height*ratio);  
}

ви можете побачити його в jsbin тут: http://jsbin.com/funewofu/1/edit?js,output


9
Дякую! Я змінив Math.min () на Math.max () для масштабування та обрізання зображення відповідно до полотна. Це було дуже корисно!
Daantje

1
але це генерує розмиття зображення, коли я генерую велике зображення з невеликого розміру. стає розмитим .. будь-яке рішення? будь ласка
saadk

Дуже цінував @gamealchemist. Прочитавши це, я допоміг мені зрозуміти, як дістатися до зменшеного зображення, і мені знадобилося б назавжди, щоб зрозуміти це самостійно. Дякую!
Кріс Шмітц,

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.