Идеально! Как создать и переделать свой сайт. Правильный подход и передовые техники разработки - Элиот Стокс
Шрифт:
Интервал:
Закладка:
Рисунок 5.9. Созданные миниатюры
У большинства систем управления контентом и блогов есть загрузчики файлов для создания миниатюр из изображений. Поэтому давайте использовать их в качестве нашего резерва (к тому же мы здесь не будем погружаться в серверный код):
<section>
<form>
<label for="upload">Pick image</label>
<input type="file" id=”upload" name="upload">
<input type="submit" value="Make it so!">
</form>
</section>
<output><p>Thumbnails</p></output>
Давайте добавим разные стили. И, если браузер поддерживает их, мы заменим форму на сообщение, где попросим пользователя перетащить изображения в раздел:
if (window.FileReader && (('draggable' in document.body) ||
('ondragstart' in document.body && 'ondrop' in document.body))) {
var s = document.querySelector('section'),
o = document.querySelector('output'),
c = document.createElement('canvas'),
cx = c.getContext('2d'),
thumbsize = 100;
c. width = c.height = thumbsize;
document.body.classList.add('dragdrop');
s. innerHTML = 'Drop images here';
Здесь мы проверили, как браузер поддерживает функции FileReader и DragandDrop (досадно то, что Safari не поддерживает первое, а Opera – последнее). Если браузер их не поддерживает, то мы берем те элементы, которые нам нужны. Мы создаем элемент canvas и сохраняем его 2-Dcontext. Потом мы определяем размеры миниатюр и, соответственно, меняем размеры canvas. И, наконец, мы добавляем класс dragdrop для задания стиля, и заменяем форму на сообщение, приглашающее пользователей перетаскивать изображения.
Как правило, если вы перетаскиваете изображение в браузер, он просто заменяет им текущий документ. Мы хотим избежать этого. Вот почему мы меняем поведение браузера при перетягивании. Мы также добавили класс, чтобы показать пользователю, что что-то происходит:
s. addEventListener('dragover', function (evt) {
s. classList.add('active');
evt.preventDefault();
}, false);
Мы удаляем класс, если перетаскивание отменяется:
s. addEventListener('dragleave', function (evt) {
s. classList.remove('active');
evt.preventDefault();
}, false);
Все остальные функции действуют в drop-обработчике:
s. addEventListener('drop', function (ev) {
s. classList.remove('active');
var files = ev.dataTransfer.files;
if (files.length > 0) {
var i = files.length;
while (i-) {
var file = files[i];
if (file.type.indexOf('image')!== -1) {
createthumb(file);
}
}
}
ev.preventDefault();
}, false);
Первое, что мы сделали здесь, это убрали класс active, потому что делали его с перетаскиванием. Событие перетаскивания дало нам объект dataTransfer, в котором содержатся «перетащенные» файлы. Далее мы проверяем, был ли хоть один из файлов перемещен и затем начинаем повторять это действие для каждого из них (Цикл while{} – причудливый способ сделать цикл for{}, но не помещая длину в кэш-память или не используя вторую переменную итератора). Еще проверяем, является ли текущий файл изображением, а потом отсылаем его к функции createthumb() (создания миниатюры). В конце мы предотвращаем поведение браузера по умолчанию при перетягивании изображения. И все, с этим мы разделались.
function createthumb(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (ev) {
var img = new Image();
img.src = ev.target.result;
img.onload = function() {
cx.clearRect(0, 0, thumbsize, thumbsize);
var thumbgeometry = resize(this.width, this.height,
thumbsize, thumbsize);
cx.drawImage(img, thumbgeometry.x, thumbgeometry.y,
thumbgeometry.w, thumbgeometry.h);
var thumb = new Image();
thumb.src = c.toDataURL();
o. appendChild(thumb);
};
};
}
Функция createthumb() инициирует новый FileReader и читает изображение как цепочку данных. Если считыватель загружен удачно, то мы создаем новое изображение в браузере и устанавливаем его атрибут src для результата транзакции FileReader.
Когда изображение успешно загружено, мы очищаем элемент canvas методом clearRect(). Это обязательно. Иначе нам придется создавать миниатюры, которые добавляются друг к другу каждый раз, когда вызывается функция.
Потом мы задаем размер миниатюры, который хотим получить от функции resize() и вызываем метод drawImage для элемента canvas. Этот метод использует пять параметров: изображение для получения информации о пикселях, координаты левого верхнего угла, откуда рисуется изображение, ширину и высоту. Потом мы создаем новое изображение, сохраняем пиксельный контент холста методом toDataURL() и добавляем новое изображение к выведенному элементу.
function resize(imagewidth, imageheight, thumbwidth, thumbheight) {
var w = 0, h = 0, x = 0, y = 0,
widthratio = imagewidth / thumbwidth,
heightratio = imageheight / thumbheight,
maxratio = Math.max(widthratio, heightratio);
if (maxratio > 1) {
w = imagewidth / maxratio;
h = imageheight / maxratio;
} else {
w = imagewidth;
h = imageheight;
}
x = (thumbwidth – w) / 2;
y = (thumbheight – h) / 2;
return { w: w, h: h, x: x, y: y };
};
Функция resize – математический помощник в изменении размера изображения определенной ширины и высоты на меньшее, но с теми же пропорциями. Ничего сверхъестественного, простая практика. И вот так мы получаем миниатюры в нашем браузере.
Заключение
Надеюсь, мне удалось убедить вас в том, что сегодня много отличных фишек стали «родными» для браузеров. Конечно, пока не все из них поддерживают эти функции, но по крайней мере все производители браузеров вместе работают над стандартами, и сейчас не то время, когда между первыми браузерами шла война, а инновации творились наощупь. При смешении и подгонке различных веб-технологий (HTML, CSS, JavaScript) мы можем создавать совершенно потрясающие вещи всего в нескольких строках кода. Все, что нам нужно – это пользоваться теми возможностями, которую дают нам браузеры.
Правильная технология работы
Взаимодействие CSS перемещений, трансформаций и анимаций с JavaScript – мощный инструмент, и нам следует использовать его гораздо больше. Сейчас, похоже, идет битва между теми, кто везде применяет jQuery или JavaScript, и теми, кто работает исключительно с CSS. Это не помогает нашим пользователям, а нас тормозит с написанием лаконичных, эффективных решений. Хороший веб-разработчик почерпнет достоинства из всех технологий, а не будет приверженцем какой-то определенной. Много ума не надо, чтобы использовать одну технологию на все случаи жизни. А потом оставить продукт работать только в одном браузере или на одном устройстве.
Если вам нужно, чтобы все необходимые свойства поддерживались в старых браузерах, используйте библиотеку, такую как jQuery. Вы также можете найти «заплаты» для старых браузеров в форме полифилов. А вообще, давайте уже прекратим пытаться заставить устаревшие технологии поддерживать то, чтомы создаем для новых. Никто не перестанет использовать продукт только из-за того, что браузер IE 6 не делает плавных перемещений из одного состояния в другое. А это и есть самое важное свойство хорошего веб-продукта.
Большая игра
Как веб-разработчики мы всегда сетуем на то, что технология не отвечает нашим потребностям: люди пользуются давно устаревшими браузерами, а браузеры не дают того, что нам нужно. Основная причина использования старых браузеров кроется в прошлом. Тогда разработчики типа нас с вами создавали сайты только для этих браузеров, потому что они были современными. Считалось, что лучше ничего и быть не может.
Производители браузеров не добавляют каждое свойство, которое хотят видеть разработчики из-за того, что новая технология внедряется недостаточно широко. Мало пожаловаться на то, что что-то не работает.
Производители браузеров хотят, чтобы эта технология использовалась по полной программе. И еще им нужно получать информацию от потребителей о ее действии. Если обратная связь заключается только в вопросе: «Почему вы не поддерживаете функцию X?» – вам всегда ответят: «Потому что ею никто не пользуется».
Самый яркий пример тому – новые семантические элементы HTML5. Нам грех жаловаться на недостаточную поддержку алгоритма outline в браузерах, еслимы сами не используем правильные элементы, а потом сообщаем производителю, что работает, а что – нет. У каждого производителя есть механизм обратной связи. От нас как от разработчиков зависит, давать ли быстрее реальные ситуации для решения или ждать безупречного внедрения.
Принимаем и применяем технологии будущего
Нам нужно ухватить новую технологию и использовать ее, где только возможно. Отбросим мысли о том, что надо ждать, пока все браузеры станут поддерживать определенную технологию и из-за этого не применять ее. Если мы не опробуем новые технологии, внедренные рабочими группами WHATWG и W3C, мы ни к чему не придем.