Скриншоты без десктопа на HTML5

    Практически каждый день я пользуюсь почтой Gmail, но вот недавно заметил, что если сделать скриншот экрана (www.take-a-screenshot.org), то простым нажатием Ctrl + V этот скриншот можно скопировать прямо в текст письма Gmail. Это работает везде, но естественно кроме IE. Заинтересовавшись вопросом как это происходит нагуглил следующий пост на Stackoverflow. Под сильным впечатлением от возможностей HTML5 clipboardData решил сделать простенький портал, где без всяких Desktop приложений любой юзер может загрузить скриншот просто скопировав его.


    Поддержка браузерами


    Во первых надо отметить, что для того, чтобы что-то скопировать из буфера (например скриншот) в браузере должна быть поддержка Clipboard API. Как можно видеть на caniuse только самые последние браузеры работают с этим API. IE, к сожалению, курит в сторонке не смотря на partial support.

    Загрузка скриншотов на javascript


    Для загрузки изображения из буфера (скриншота) сначала нужно определить обработчик paste события:
    document.body.addEventListener("paste", function(e) {
       ...
    });
    


    Обработчик будет вызываться всегда, когда в рабочей области окна браузера происходит событие «Вставить», например по нажатию Ctrl + V. Далее нужно определить код, который собственно и примет файл изображения из буфера. Этот код идентичен для браузеров Chrome и Opera, но разный для FireFox, так как у последнего по каким-то соображениям безопасности закрыты методы объекта clipboardData.

    Chrome, Opera

    // e.clipboardData.items - это и есть файлы находящиеся в буфер обмене
    for (var i = 0; i < e.clipboardData.items.length; i++) {
        
        // выбираем только картинки
        if (e.clipboardData.items[i].kind == "file" && e.clipboardData.items[i].type == "image/png") {
    
            // Получаем файл как Blob (бинарные данные)
            var imageFile = e.clipboardData.items[i].getAsFile();
            var fileReader = new FileReader();
            fileReader.onloadend = function(e) {
                // Файл прочитан в this.result его Base64 представление
                loadImg(this.result);
            };
    
            // Читаем Blob как DataURL (Base64 представление бинарных данных)
            fileReader.readAsDataURL(imageFile);
            e.preventDefault();
            break;
        }
    }
    


    FireFox

    В FireFox у нас нет возможности прочитать файл через clipboardData. При вставке, браузер самостоятельно создает <img> тег с src в виде DataURL. Поэтому придется сделать «костыль»:
    // При инициализации js, если браузера Mozilla, то добавляем скрытый, редактируемый (contenteditable) div и
    // ставим на него фокус.
    if ($.browser.mozilla) {
        $(document.body).prepend('<div id="temp" contenteditable="true" style="height:1px;width:1px;color:#FFFFFF;"></div>');
        $('#temp').focus();
    }
    
    // Определяем событие "Вставить"
    document.body.addEventListener("paste", function(e) {
    
        if ($.browser.mozilla) {
    
            // Если Mozilla, то фокусируем на созданный ранее div
            // (это нужно для того, чтобы FireFox вставил img в нужном месте)
        	$('#temp').focus();
    
            // Удаляем предыдущий img (вдруг мы копируем 2, 3, ..., N раз)
        	$('#temp img').remove();
    
            // У FireFox при создании img нет callback-а и единственный способ получить img - использовать небольшую паузу
            setTimeout(function() {
                // Вот тут FireFox точно вставил img в temp div, мы можем взять его DataURL и загрузить картинку
                loadImg($('#temp img').attr('src'));
            }, 1);
            return true;
        }
    });
    


    Куда загрузить картинку?


    Загрузить картинку можно сразу на сервер, передавая через POST DataURL или например в canvas как сделано на Your screen:
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    ...
    function loadImg(dataURL) {
        var imageObj = new Image();
        imageObj.onload = function() {
            var width = this.width, height = this.height;
            canvas.width  = width;
            canvas.height = height;
            ctx.drawImage(this, 0, 0, width, height);
        };
        imageObj.src = dataURL;
    }
    


    Canvas удобен тем, что перед загрузкой скриншота на сервер можно его отредактировать: подчеркнуть, нарисовать, обвести, вырезать и т.д.

    Что происходит на сервере?


    На сервере должен быть POST контроллер, который бы принимал body в формате Base64 (DataURL) и декодировал его в бинарный файл изображения, например png. Контроллер может быть написан на любом языке, например Java с использованием SpringMVC:
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public @ResponseBody String save(@RequestBody String b64) {
        File file = null;
        FileOutputStream out = null;
        try {
            // Создаем Output поток
            out = new FileOutputStream("/opt/files/somename.png");
    
            // Декодируем Base64 в байты и сохраняем в поток
            out.write(Base64.decodeBase64(StringUtils.replace(b64, "data:image/png;base64,", "")));
    
            // Закрываем поток
            IOUtils.closeQuietly(out);
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file.getName();
    }
    


    Для внимательных отмечу, что вот эта конструкция StringUtils.replace(b64, «data:image/png;base64,», "") нужна для нормализации передаваемого из Javascript DataURL. Дело в том, что при создании DataURL вначале ставится его тип и формат и после идет Base64 представление, например data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVYAAAMAC…

    Дополнительно можно ещё проверить размер файла, и если он превышает определенный максимум сжать в jpg.

    Варианты использования


    Сервис Your screen мы в компании Cackle используем каждый день в качестве быстрого и простого средства для снимка экранов наших клиентов. К сожалению, подобных решений в сети очень мало и те, что есть неудобны или работают только через Desktop:
    • prntscr.com — копировать скриншот можно только в Chrome и без редактирования
    • snag.gy — уже лучше, но скрншоты загружаются очень медленно и только один раз (первый)
    • Больше не нашел...


    В скором времени мы планируем перенести весь этот функционал в наш Онлайн консультант Cackle. Таким образом у клиентов будет возможность сделать скриншот и передать изображение прямо через консультанта оператору. Это в некотором смысле лучшая замена Co-Browser, так как позволяет показывать весь экран (а не только браузер), снизить издержки на разработку и минимизировать ошибки.

    В заключении скажу, что проект Your screen совсем новый и будет развиваться дальше, поэтому жду вашей критики и пожеланий по функционалу.
    Cackle 35,63
    Компания
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 38
    • +1
      Скриншоты действительно загружаются быстрее чем на snag.gy. И полупрозрачность корректнее сохраняется. Попользуемся, спасибо!

      Необходим только короткий адрес и короткие ссылки на загруженные изображения.
      • +2
        +1
        Сейчас это через bit.ly сделано, но редирект идет все равно на длинный URL (у нас имя файла как md5 хеш).
        Так же очень нужна поддержка crop-а, то есть сохранения только выделенной области изображения, если кто знает библиотеку для canvas буду рад ссылке.
      • +1
        Думаю, что буду не единственным, кому не понравилась главная страница Вашего сервиса. Конкретно, не понравилась инструкция — нажать PrtScr и Ctrl+V. Для мака это неверно, т.к. клавиши PrtScr нет, а хоткей для вставки — Cmd + V. Предлагаю либо определять ОС пользователя и подстраиваться под нее, либо сделать надпись нейтральной, без четких указаний клавишь. Подробнее о скриншотах на маке.
        • 0
          Определить ОС — отличный вариант. Сделаем!
          • +1
            Не знаю, особенный ли я, но на моем ноуте скриншот делается сочетанием Fn+PrtScr
            • –2
              Наверняка на вашем ноуте есть кнопочка FnLock, нажав которую можно делать скрины только одной клавишей PrtScr, как у меня :)
              • +2
                Но в некоторых ноутбуках (моём например) — в этом режиме все F1-F12 клавиши будут отвечать за спец.функции (изменить громкость-яркость и т.п.).
                • 0
                  У себя (HP compaq presario cq61) я кнопки FnLock не нашел :)
              • +1
                Кроме того, можно делать скрин не всего рабочего стола, а только текущего окна с помощью комбинации Alt + PrtScr, что часто бывает полезно.
                • 0
                  А в gnome через Ctrl + PrtScn (либо Ctrl + Shift + PrtScn, чтобы либо в буфер скопировать изображение, либо сразу сохранить в файлик в дефолтной ~/pictures/). Полный скриншот с двух мониторов редко бывает нужен, всегда пользуюсь такой комбинацией, чтобы запринтскринить только нужное. :)
              • +1
                Shift Insert — проверено, вставляет :) (Windows)
              • +4
                Ребята, всё супер! Добавьте теперь crop, панель с инструментами для рисования всего чего захочется и будет вообще шик! =)
                • –1
                  Я пользуюсь snag.gy. Там можно откропать скриншот, обвести что-нибудь квадратиком, и написать «WTF?»

                  Вообще была бы в тему такая штука, но с каким-то контролем доступа. Либо просто опенсорсная, чтобы можно было в интранет ставить. А то так можно наскриншотить что-нибудь NDA-шного случайно.
                  • +2
                  • 0
                    Довольно старый пост, не удивительно, что вы уже забыли о нём: Три способа поддержать вставку картинок в поле ввода от разработчиков Яндекс.Почты там и ссылка на замечательный плагин для TinyMCE имеется.
                    • +1
                      В это посте, к сожалению, нет ни одного упоминания про то, что вот это clipboard.items[0] не будет работать в FireFox.
                    • +4
                      Crop — обязательная штука, как же можно полностью экран (или даже окно) кому-то показывать.
                      • 0
                        У этого пути есть один веселый недостаток. Ну либо я не поборол когда пол года назад делал аналогичную вещь после описания этого процесса от Яндекса. OneNote всегда отдает в буфер обмена и картинку и текст. Так система теперь всегда принимает картинку игнорирую текст
                        • +1
                          Пользуюсь snaggy, действительно файл вставляется как-то медленно 8(

                          А теперь пожелания которые уже реализованы на snaggy.

                          — личный кабинет с возможность удаления файлов (да я хочу иметь контроль над тем что загружаю)
                          — инструменты для работы с изображениям (crop и тд)

                          PS
                          Недавно был пост про сервис добавления аннотаций к изображениям (http://habrahabr.ru/post/198918/), очень не хватает таких штук. Так вот — если вы запилите аннотации (наряду с crop функцией и тд) то был бы вообще респект, это еще может увеличить вашу аудиторию. Буквально в пару кликов можно было бы расшарить скриншот и добавить пояснения, довольно часто это приходится делать при работе например с дизайнером или банально отправить другу какую-то пояснялку как и куда нажать, оставить на форуме скриншот с пояснением об ошибке и тд.

                          Спасибо
                          • 0
                            Собственно сам работаю по следующей схеме и, причем, не только в браузере. Добавил папку со скриншотами в Ubuntu One и теперь если нужно отправить скриншот с примечаниями, то делаю так:
                            1) Жму обычный PrtSrc или Alt + PrtSrc
                            2) Правой кнопкой по файлу — и копирую адрес расшаренной ссылки.
                            3) Вставляю на http://linch.me/ и добавляю аннотации.
                          • 0
                            Видимо я что-то не так делаю, но сделал скриншот, нажал Ctrl+V на сайте, и вот уже 15 минут бегает ползунок загрузки и ничего не происходит.
                            Инет нормальный.
                            p.s. Chrome
                            • 0
                              А версия Chrome какая? Поддержки clipboradData в ранних версиях не было.
                            • 0
                              На imgur.com данная технология используется достаточно давно.
                              • +1
                                В таких сайтах плохо то, что слишком много функционала.
                                Например я даже не понял как отредактировать изображение после загрузки. Ну а обычный юзер, возможно даже не пойме как его загрузить.
                                ИМХО
                                • 0
                                  Пользуюсь imgur уже год или два. Нужно понять принцип работы, и все будет отлично :)
                                  Загрузить, просто перетащив файл в окно браузера, или по старинке через форму, или по внешней ссылке. Удобно и понятно.
                                  • 0
                                    Еще можно воспользоваться удобной утилитой ClipUpload, в результате загрузка на imgur происходит нажатием сочетания клавиш.
                                    • 0
                                      Программка под винду мне как-то не вариант.
                                      А так я пользуюсь расширением-скриншотилкой для Chrome, которое умеет заливать в мой аккаунт на imgur.
                                • +1
                                  Отлично, только вот редактирования не хватает (например что-то подчеркнуть или обвести).
                                  • +1
                                    Зато там намного более полезная вещь, как кадрирование есть. В вашем сервисе за 5 секунд — не нашел.
                                • 0
                                  Лайфхак. Как данным сервисом быстро получить data URI для верстки писем.
                                  Если открыть сервис в ff можно загрузить картинку с компа, затем ЛКМ -> Открыть изображение.
                                  В адресной строке получаем картинку в формате data URI, используем для верстки писем.
                                  • +1
                                    Вот еще неплохой пример.
                                    • +1
                                      Работает неплохо, но есть пара замечаний:

                                      1. У меня после нажатия Ctrl + V две секунды ничего не происходило, потом скриншот появился. Согласен, два монитора 1920 x 1200 — это много, но прелоадер бы не помешал
                                      2. После вставки скриншота по нему, оказывается, можно рисовать — но форма курсора не соответствует действию. Я думал, что можно будет перетаскивать или выделять область.
                                      3. Очень хочется Ctrl + Z для отмены нарисованного поверх скриншота, если сделал это случайно.

                                      • 0
                                        Лоадер должен появляться при вставке изображения сверху от ссылки save. По всем остальным пунктам +1!
                                        • +1
                                          Если вы разработчик этого сервиса, то у меня для вас плохие новости. Отличное размытие, просто класс! Но в ваших статьях убого красной кистью данные сокрыты…
                                          • 0
                                            У вас баг =)
                                            Попробовал зарегистрироваться через СВОЙ twitter, и попал на чужой аккаунт, с чужими загруженными скриншотами, чужим e-mail.
                                            Как так произошло-то?
                                            Через Facebook, VK все нормально.
                                          • 0
                                            Ещё один сервис (выглядит не очень, но всё есть)
                                            www.onlineprintscreen.com

                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                            Самое читаемое