Файловая система в реальной жизни

Файловая система в реальной жизни.

Для того чтобы хорошо понять потенциал изученных концепций, всегда полезно изучить пример из реальной жизни. В завершение главы мы создадим приложение, объединяющее несколько техник файлового API с возможностями манипулирования изображениями, предоставляемыми API Canvas (Холст).

В этом примере мы считываем несколько файлов изображений и выводим эти изображения на холсте, выбирая местоположение случайным образом. Все изменения элемента canvas сохраняются в файл, для того чтобы их можно было считать и использовать позже. Таким образом, каждый раз, когда вы запускаете приложение, на экране отображается результат предыдущего выполнения.

HTML-документ для примера аналогичен первому шаблону из данной главы. Однако на этот раз он включает в себя элемент canvas внутри databox (листинг 12.21).

Листинг 12.21. Новый шаблон с элементом <canvas>

<!DOCTYPE html>

<html lang="ru">

<head>

<title>Файловый API</title>

<link rel="stylesheet" href="file. css">

<script src="file. js"></script>

</head>

<body>

<section id="formbox"> form name="form">

<p>Изображения:<br><input type="file" name="myfiles" id="myfiles" multiple></p>

</form>

</section>

<section id="databox">

<canvas id="canvas" width="500" height="350"></canvas> </section>

</body>

</html>

Код для нашего примера включает в себя уже знакомые вам методы и техники программирования, однако разобраться в сочетании спецификаций поначалу может быть довольно сложно. Давайте сначала познакомимся с кодом, а затем проанализируем его шаг за шагом.

Листинг 12.22. Приложение на основе холста, использующее возможности файлового API

Function initiate(){

Var elem=document. getElementById(‘canvas’); canvas=elem. getContext(’2d’); var myfiles=document. getElementById(‘myfiles’); myfiles. addEventListener(‘change’, process, false); window. webkitRequestFileSystem(window. PERSISTENT, 5*1024*1024,

Createhd, showerror);

}

Function createhd(fs){ hd=fs. root; loadcanvas();

}

Function showerror(e){ alert(’0i^6Ka: ‘+e. code);

}

Function process(e){

Var files=e. target. files; for(var f=0;f<files. length;f++){ var file=files[f]; if(file. type. match(/image.*/i)){ var reader=new FileReader(); reader. onload=show; reader. readAsDataURL(file);

}

}

}

Function show(e){

Var result=e. target. result; var image=new Image(); image. src=result;

Image. addEventListener("load", function(){ var x=Math. floor(Math. random()*451); var y=Math. floor(Math. random()*301); canvas. drawImage(image, x,y,100,100); savecanvas();

}, false);

}

Function loadcanvas(){

Hd. getFile(‘canvas. dat’, {create: false}, function(entry) {

Entry. file(function(file){ var reader=new FileReader(); reader. onload=function(e){ var image=new Image(); image. src=e. target. result; image. addEventListener("load", function(){ canvas. drawlmage(image,0,0);

}, false);

};

Reader. readAsBinaryString(file);

}, showerror);

}, showerror);

}

Function savecanvas(){

Var elem=document. getElementById(‘canvas’); var info=elem. toDataURL();

Hd. getFile(‘canvas. dat’, {create: true, exclusive: false}, function(entry) { entry. createWriter(function(fileWriter){ var blob=new WebKitBlobBuilder(); blob. append(info); fileWriter. write(blob. getBlob());

}, showerror);

}, showerror);

}

Window. addEventListener(‘load’, initiate, false);

В этом примере мы работаем с двумя API: API File (Файл) с расширениями и API Canvas (Холст). В функции initiate() происходит инициализация обоих API. Сначала с помощью getContext() генерируется контекст рисования для холста, а затем посредством requestFileSystem() запрашивается файловая система.

Как всегда, как только подготовка файловой системы завершается, мы вызываем функцию createhd(), инициализируя переменную hd и присваивая ей ссылку на корень файловой системы. На этот раз в конец функции createhd() мы добавили вызов новой функции, которая загружает файл с изображением, сгенерированным при прошлом запуске приложения.

Однако давайте сначала все же посмотрим, как это изображение генерируется. Когда пользователь выбирает новые файлы изображений в форме, содержащейся в HTML-документе, на элементе <input> срабатывает событие change и происходит вызов функции process(). Эта функция принимает файлы, перечисленные в поле ввода, извлекает из массива все объекты File, проверяет каждый файл на соответствие формату изображения и считывает содержимое всех записей в методе readAsDataURL(). Результирующее значение возвращается в формате data:url.

Как видите, функция process() считывает файлы индивидуально, по одному за раз. Если операция завершается успешно, то срабатывает событие load и для очередного изображения вызывается функция show(). Таким образом, эта функция последовательно обрабатывает каждое изображение, которое выбирает пользователь.

Функция show() принимает данные из объекта reader, создает с помощью конструктора Image() новый объект изображения и в строке image. src=result объявляет источником этого изображения данные, считанные из очередного файла.

Работая с изображениями, всегда необходимо принимать во внимание время, необходимое на загрузку файлов. По этой причине после объявления нового источника для объекта изображения добавляем слушатель события load. Мы хотим быть абсолютно уверены в том, что изображение полностью загрузилось, прежде чем приступать к обработке его данных. После срабатывания события load (что означает завершение загрузки изображения) выполняется анонимная функция, объявленная в методе addEventListener(). Эта функция вычисляет для изображения случайную позицию и выводит его на холст посредством метода drawImage(). Для каждого изображения определяется фиксированный размер 100 X 100 пикселов (для того чтобы понять, как проходит процесс обработки, изучите код функции show() в листинге 12.22).

После того как изображение нарисовано, происходит вызов функции savecanvas(). Эта функция сохраняет состояние холста после каждого изменения, таким образом, при каждом последующем запуске приложения на экране восстанавливается картинка, сохраненная в прошлый раз. Для возвращения содержимого холста в формате data:url используется метод из API Canvas (Холст) под названием toDataURL(). Затем в функции savecanvas() выполняется последовательность операций по обработке данных. Сначала данные в формате data:url, сгенерированные на основе содержимого холста, сохраняются в переменной info. Затем файл canvas. dat создается (если он еще не существует) и открывается с помощью метода getFile(). Если операция getFile() выполняется успешно, то эта запись файловой системы передается анонимной функции, где в методе createWriter() создается объект FileWriter. Если объект успешно создается, то этот метод также вызывает анонимную функцию, которая присоединяет значение переменной info к объекту BlobBuilder, а затем обновленный бинарный блок в методе write() записывается в файл.

В этот раз мы не прослушиваем никакие события объекта FileWriter, так как в случае успеха или ошибки не собираемся предпринимать никаких специальных действий.

Однако вы всегда можете воспользоваться функциональностью событий для вывода на экран статуса операции или для обеспечения абсолютного контроля над каждым шагом процесса.

Итак, возвращаемся к функции loadcanvas(). Как говорилось ранее, эта функция вызывается внутри функции createhd() в момент запуска приложения. Ее назначение — загрузить файл с ранее сохраненными данными изображения и вывести эту картинку на холст. Вы уже знаете, о каком файле идет речь и как он создается, поэтому давайте рассмотрим последовательность действий, выполняемую данной функцией.

Функция createhd() вызывает функцию loadcanvas(), как только становится понятно, что файловая система готова к использованию. Задача функции loadcanvas() (как понятно из ее названия) заключается в том, чтобы загрузить файл canvas. dat, получить данные в формате data:url, сгенерированные после предыдущей модификации элемента холста, и вывести их на холст. Если такого файла не существует, то метод getFile() возвращает ошибку, если же файл найден, то метод вызывает анонимную функцию, которая принимает запись файловой системы и с помощью метода file() генерирует на ее основе объект File. Этот метод в случае успешного выполнения также вызывает анонимную функцию, которая считывает содержимое файла как двоичную строку (посредством метода readAsBinaryString()). Данные, которые мы получаем из файла, представляют собой строку в формате data:url, которую необходимо объявить источником изображения, чтобы его можно было вывести на холст. Таким образом, внутри анонимной функции, которую вызывает событие load, мы создаем объект изображения, объявляем data:url из файла источником этого изображения и, когда изображение полностью загружено, выводим его на холст в методе drawImage().

На экране все это выглядит очень просто: изображения, выбранные с помощью элемента <input>, выводятся на холсте в случайных точках,

И результирующая картинка сохраняется в файле. Если закрыть и заново открыть браузер, то при запуске приложения холст восстанавливается и мы снова видим результат предыдущей работы. Возможно, это не самое полезное приложение в мире, но вы ведь поняли, насколько велик потенциал файлового API?

Применяя возможности API Drag and Drop (Перетаскивание), файлы изображений можно перетаскивать на холст, а не загружать через элемент <input>. Попробуйте объединить код из листинга 12.22 с примерами кода из главы 8, чтобы попрактиковаться во взаимном интегрировании этих API.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *