Нарисовать изображение на весь Canvas

380
14 января 2017, 14:19

Я работаю с загрузкой фотографий, пытаюсь отображать миниатюры этих фото. Для изменения размера фотографий использую canvas. Проблема в том, что canvas рисует фотографии меньшего размера, хотя для фотографии я задаю размеры такие-же как и сам canvas.
Проблема, как мне кажется, кроется в самой отрисовке ctx.drawImage(img, 0, 0, width, height);, но не знаю как это победить.

Цель данных телодвижений - облегчить работу браузеру, так как пользователи(Они же тетки) будут грузить фотки прямо с фотика, тоесть ситуация, когда отображается штук 500 фоток размером 5к пикселей - обычное дело.

//Готовим шаблон 
let template = document.getElementById('file-template'); 
let cTemplate = Handlebars.compile(template.innerHTML); 
 
let input = document.getElementById('file-input'); 
 
input.onchange = function() { 
  let container = document.getElementById('photos'); 
  let files = this.files; 
   
  //Перебираем файлы в мультиинпуте 
  for(let i in files) { 
    if(!files.hasOwnProperty(i)) 
      continue; 
   
    let file = files[i];  
 
    if (!file.type.match(/image.*/)) 
      continue; 
 
    let reader = new FileReader(); 
 
    //Когда картинка прочиталась 
    reader.onload = function(e) { 
      let img = new Image(); 
      img.src = e.target.result; 
 
      //Вставляем из шаблона 
      container.insertAdjacentHTML( 'beforeend', cTemplate() );   
       
      let canvas = container.querySelector('.file:last-of-type .canvas'); 
      let ctx = canvas.getContext('2d'); 
 
      let height = 100;   //Высота превьюх 100 
      let width = img.width * height / img.height; //Посчитаем их длину 
 
      canvas.style['width'] = width + 'px';   //Канвас хотим длиной с картинку 
      ctx.drawImage(img, 0, 0, width, height);  //Тут почему-то неправильно отрабатывает 
    }; 
 
    reader.readAsDataURL(file); 
  } 
};
#photos { 
  display: flex; 
  margin-top: 20px; 
} 
.file { 
  position: relative; 
  margin: 0 5px 5px 0; 
} 
.file-delete { 
  position: absolute; 
  top: 0; 
  right: 0; 
  background: #fff; 
  width: 18px; 
  color: #f00; 
  text-align: center; 
  text-decoration: none; 
} 
canvas { 
  background: #ccc; 
  width: 0px; 
  height: 100px; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js"></script> 
 
<input id="file-input" type="file" multiple="multiple"> 
<div id="photos"></div> 
 
<script id="file-template" type="text/x-handlebars-template"> 
<div class="file"> 
  <a href='#' class="file-delete">&times;</a> 
  <canvas class="canvas"></canvas> 
</div> 
</script>

Answer 1

//Готовим шаблон 
let template = document.getElementById('file-template'); 
let cTemplate = Handlebars.compile(template.innerHTML); 
 
let input = document.getElementById('file-input'); 
 
input.onchange = function() { 
  let container = document.getElementById('photos'); 
  let files = this.files; 
 
  //Перебираем файлы в мультиинпуте 
  for (let i in files) { 
    if (!files.hasOwnProperty(i)) 
      continue; 
 
    let file = files[i]; 
 
    if (!file.type.match(/image.*/)) 
      continue; 
 
    let reader = new FileReader(); 
 
    //Когда картинка прочиталась 
    reader.onload = function(e) { 
      let img = new Image(); 
      img.src = e.target.result; 
 
      //Вставляем из шаблона 
      container.insertAdjacentHTML('beforeend', cTemplate()); 
 
      let canvas = container.querySelector('.file:last-of-type').querySelector('.canvas'); 
      canvas.width = img.naturalWidth; 
      canvas.height = img.naturalHeight; 
      var ctx = canvas.getContext("2d").drawImage(img, 0, 0); 
      canvas.style['width'] = img.naturalWidth / 4 + 'px'; 
      canvas.style['height'] = img.naturalHeight / 4 + 'px'; 
    }; 
 
    reader.readAsDataURL(file); 
  } 
};
#photos { 
  display: flex; 
  margin-top: 20px; 
} 
.file { 
  position: relative; 
  margin: 0 5px 5px 0; 
} 
.file-delete { 
  position: absolute; 
  top: 0; 
  right: 0; 
  background: #fff; 
  width: 18px; 
  color: #f00; 
  text-align: center; 
  text-decoration: none; 
} 
canvas { 
  background: #ccc; 
  width: 0px; 
  height: 100px; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js"></script> 
 
<input id="file-input" type="file" multiple="multiple"> 
<div id="photos"></div> 
 
<script id="file-template" type="text/x-handlebars-template"> 
  <div class="file"> 
    <a href='#' class="file-delete">&times;</a> 
    <canvas class="canvas"></canvas> 
  </div> 
</script>

READ ALSO
Отключение очистки Canvas в WebGL

Отключение очистки Canvas в WebGL

Что сделать, чтобы элемент Canvas не очищался при каждом новом шаге?

396
Как получить состояние кнопки мышки в mouseover?

Как получить состояние кнопки мышки в mouseover?

Все предлагают запоминать состояние в событиях mousedown, mouseup

285
Не работает блок &ldquo;Поделиться&rdquo; корректно

Не работает блок “Поделиться” корректно

Вставила блок на странице сайта http://wwwsuperkot

256
Возьмут ли на работу на front-end, если я изучаю dart, а не JavaScript? [требует правки]

Возьмут ли на работу на front-end, если я изучаю dart, а не JavaScript? [требует правки]

Сейчас большинство использует js, но что если я пишу на dart? Я имею ввиду, dart ведь легко конвертируется в js (dart2js)Просто на js очень мало писал и не знаю,...

333