воспроизведение gif только при помощи javascript

352
17 августа 2017, 23:39

здравствуйте, вообщем хочу сделать воспроизведение гиф, думаю всем понятно о чем идет речь, есть статическая картинка, на ней иконка Play и при нажатии src меняется на гифку. я знаю как это сделать на php+js создавая заранее статичное изображение, но хотел бы узнать можно ли сделать это на чистом js/jq имя только gif картинку? чтобы не создавать каждый раз на пыхе jpeg изображение

Answer 1

Если хотите purejs-решение, пожалуйста. Надеюсь вы не расчитывали что оно будет простым. В данном случае я использовал библиотеку gif-frames, но её работа (на клиенте?) приводит к артефактам.

Ну и на последок снова прочту вам Отче наш: Никто не занимается такими вещами на клиенте и причин тому несколько:

  1. Потребность писать кроссбраузерный скрипт т.к. браузеров множество, как и клиентских реализаций JavaScript. Добиться работоспособности такого кода на всех и вся будет проблематично.
  2. Клиент будет выполнять этот код каждый раз при загрузке страницы.
  3. Трафик: клиент будет качать тяжелый gif-файл, только для того что бы увидеть его превью. Для мобильных устройств это веский аргумент.
  4. Высока вероятность "повесить" пользовательский клиент на таких вычислениях.
  5. Сервер проделает эту операцию один раз и закеширует результат. Далее клиент будет качать это превью и, только при необходимости, весь gif.

var $file = document.querySelector('#file'), 
    $frames = document.querySelector('#frames'), 
    $type = document.querySelector('#type'), 
    $output = document.querySelector('.output'), 
    $extract = document.querySelector('#extract'); 
 
/** 
 * Конвертирует тип File в строку base64 
 * @see https://ru.wikipedia.org/wiki/Base64 
 * @param {File} file 
 * @param {Function} callback 
 */ 
function fileToBase64(file, callback) { 
  var reader = new FileReader(); 
  reader.readAsDataURL(file); 
  reader.onload = function onload() { callback(reader.result); }; 
  reader.onerror = function onerror(error) { alert('Error: ', error); }; 
} 
 
/** 
 * Извлечёт указанные кадры 
 * @param {File} file Файл gif-анимации 
 * @param {String} frames перечисление кадров 
 * @param {string} mime тип изображения (по умолчанию image/png) 
 * @param {Function} callback 
 */ 
function extractFrames(file, frames, mime, callback) { 
  // начала нужно сконвертировать файл в base64 
  fileToBase64(file, function(data){ 
 
    // опции для gif-frames 
    var options = { 
      // ссылка на файл. Т.к. файл загружается не по ссылке 
      // а выбирается пользователем, мы привели файл к ссылке 
      url: data, 
      frames: frames, // кадры для извлечения 
      outputType: 'canvas' // тип результата 
    }; 
 
    // вызов функции библиотеки gif-frames 
    gifFrames(options, function(error, data){ 
      var $canvas, 
          $image, 
          result = []; 
 
      for (var i = 0; i < data.length; i++) { 
        $canvas = data[0].getImage(); // извлекаем результат в виде html-элемента canvas 
        $image = new Image(); // создаём пустое изображение 
        $image.src = $canvas.toDataURL(mime); // извлекаем изобажение из canvas 
 
        result.push({ 
          $canvas: $canvas, 
          element: $image, 
          width: $canvas.width, 
          height: $canvas.height 
        }); 
      } 
 
      // возвращаем результат 
      callback(result); 
    }); 
  }); 
} 
 
// при клике на кнопку "Извлечь" 
$extract.addEventListener('click', function(){ 
 
  // выбираем всю неоходимую информацию введённую 
  // в поля формы 
  var file = $file.files[0], 
      frames = $frames.value, 
      type = $type.value; 
 
  // проверка введённых данных 
  if (file instanceof File === false || file.type !== 'image/gif') { 
    alert('Необходимо выбрать GIF-файл'); 
    $file.click(); 
    return; 
  } 
 
  if (!frames) { 
    alert('Укажите какие кадры нужно извлечь из анимации\nФормат: 1, 2-4, 5, 6)'); 
    $frames.focus(); 
    return; 
  } 
 
  // вызов функции извлекающей кадры 
  extractFrames(file, frames, type, function(images){ 
 
    // очистка списка изображений 
    $output.innerHTML = ''; 
 
    // перебираем извлечённые кадры 
    for (var i = 0; i < images.length; i++) { 
      var image = images[i], 
          $item = document.createElement('li'), 
          $element = image.element; 
 
      // меняем размер картинки 
      $element.width = 200; 
      $element.height = 200 / (image.width / image.height); 
 
      // выгружаем данные в DOM 
      $item.appendChild($element); 
      $output.appendChild($item); 
    } 
  }); 
});
.controls { 
  padding: 10px; 
  background: #fafafa; 
  border: 1px solid gray; 
} 
 
.control { 
  padding: 10px; 
} 
 
.control > label { 
  min-width: 80px; 
  display: block; 
  float: left; 
} 
 
.output { 
  list-style: none; 
}
<script src="https://unpkg.com/gif-frames@0.3.0?main=bundled-min&name.js"></script> 
<div class="controls"> 
  <div class="control"> 
    <label for="file">File</label> 
    <input type="file" name="file" id="file"> 
  </div> 
  <div class="control"> 
    <label for="frames">Frames</label> 
    <input type="text" name="frames" id="frames" value="1"> 
  </div> 
  <div class="control"> 
    <label for="type">Type</label> 
    <select name="type" id="type"> 
      <option value="image/png">PNG</option> 
      <option value="image/jpeg">JPEG</option> 
    </select> 
  </div> 
  <div class="control"> 
    <label for="extract"></label> 
    <input type="button" name="extract" id="extract" value="Извлечь"> 
  </div> 
</div> 
 
<ul class="output"></ul>

READ ALSO
Посимвольный вывод слов

Посимвольный вывод слов

Здравствуйте!

307
Как прочитать файл xlsx библиотекой PHPExcel

Как прочитать файл xlsx библиотекой PHPExcel

Здравствуйте, помогите пожалуйста решить вопрос

281
Как запустить Laravel из внешнего php скрипта?

Как запустить Laravel из внешнего php скрипта?

Было написано консольное приложения на Laravel 54 для определённой задачи

264
Как заменить тег h3 на span в виджете?

Как заменить тег h3 на span в виджете?

Подскажите, как в виджете заменить тег h3 на тег span?

356