Рубрики
Без рубрики

Сервировка кликабельная масштабируемая векторная графика (SVG) Часть 2

Продолжение того, как сделать веб-страницу, отображающую чистый штат Петри.

Автор оригинала: Richard Leddy.

Служить SVG с Express на Node.js

P1.PNG.PNG

В этом руководстве предполагает некоторые знания JavaScript, HTML и Node.js

SVG Масштабируемая векторная графика – это часть HTML5. Это также язык разметки.

SVG Допускает рендеринг графики в виде линейных рисунков. Вы делаете чертежи, которые выглядят как HTML-страница. Или вы можете создавать художественные мастер-кусочки.

Продолжая от предыдущего поста, SVG Часть 1, мы готовы служить некоторое СВГ, которое мы уже подготовили.

Мы уже прошли несколько шагов, чтобы получить файл готов:

  • Создайте графику SVG для обслуживания на странице.
  • Сделайте небольшую утилиту JavaScript для создания некоторых кода для инструментов анимации.

Следует пройти несколько шагов, прежде чем мы сможем получить живую страницу. Вот что осталось сделать:

  • Настройте простой сервер Node.js с использованием Express для обслуживания страницы
  • Создать JavaScript, который будет анимировать SVG
  • Запустите страницу в браузере.

Оставаться с более легкой стороной вещей, будет что-то показывать, когда мы закончим.

Для моего сервера я выбрал Node.js и экспресс. Этот выбор популярен в данный момент. И, на самом деле, это может быть излишек для нашего маленького проекта. Но Node.js – хорошая платформа для работы с сетью. Экспресс позволяет нам просто писать пути с обработчиками. Это ведь, роутер. И это победитель, потому что это позволяет четко объяснить шаблон ответа.

Программа, которую я собираюсь производить, очень коротко. На самом деле, я собираюсь отбросить все это в следующий код код. В этот момент вы можете подумать, что учебник сделан. Но я немного украсим сервер, чтобы сделать его особенным для нашего текущего заявления. И, есть немного чего-то, что я хочу сделать с HTML, чтобы заработать его хорошо работать.

Вот сервер:

const express = require('express');
const app = express();
const fs = require('fs');

const appPort = 3000;

// Use on generic function to load file stuff and send it to the client
function loadPage(filename, res) {
    fs.readFile(filename,'utf8', (err,data) => {
                    if ( err ) {
                    	res.send(JSON.stringify(err));
                    } else {
                        var page = data.toString();
                        res.send(page);
                    }
                })
}

// The paths (routes) to the files we want to send.
app.get('/', (req, res) => {
            loadPage('example.html',res);
        });

app.get('/:file', (req, res) => {
            loadPage(req.params.file,res);
        });

app.get('/svg/:svFile',(req,res) => {  // look in a particular directory
            loadPage('./svg/' + req.params.svFile,res);
    });

// Run it.  Really, you have to or else this app will terminate and the bowser 
// will put up error messages.
app.listen(appPort, () => console.log(`Example app listening on port ${appPor}!`))

И так, что здесь происходит? Ну, это очень простое приложение Express, сервер, слушающий порт, 3000 в этом случае. Этот сервер отвечает на три разных узора URL.

Первые шаблоны URL является корнем, ‘/’, который отвечает только на одной странице, в этом случае страница является примером.html, которая читается из файла. (Нет причудливых трюков здесь.)

Вторые узоры URL для любого файла. Какой файл файла веб-страницы говорит мне отправить. Это позволяет для изображений, CSS и JavaScript отправляться в браузер.

Третий, и последний шаблон для любого файла, который находится в SVG каталог.

Настройте HTML-страницу и какой-то JavaScript, чтобы потянуть в SVG

Итак, это выглядит довольно просто. И это не обещает много активности. Просто сервер работает. Это помещает файлы, если у вас их. И он имеет нулевую безопасность. Итак, вы не захотите это быть вашим производственным сервером. Но, приятно работать на вашем собственном компьютере, настольном компьютере или ноутбуке, и он может Resonse до localhost Запросы.

Эти запросы будут иметь в этой форме: http://localhost: 3000/svg/pic.svg http://localhost: 3000/ , так далее.

Итак, не было бы неплохо, если бы все, что нам нужно было сделать, это введите localhost: 3000 в браузер и вставьте рабочую страницу HTML с SVG в нем? Конечно!

Итак, мы должны исправить страницу HTML, чтобы сделать что-то полезное. Итак, теперь пришло время перестать выполнять JavaScript Server Side JavaScript и провести немного времени, выполнив несколько клиентских боковых JavaScript.

Фактически, у нас может быть страница HTML будет довольно скелетной страницей, и она принесла его SVG после того, как она загружена. Или мы можем иметь кнопку на странице, которая захватывает файл SVG, когда мы нажимаем на него. На самом деле, мы можем сделать обоими. Итак, вот как:

Держите HTML короткий и минимальный

Для нашей веб-страницы нам все равно понадобится HTML, в частности HTML 5 Отказ HTLM 5 обнажает элементы SVG на одном уровне, что и элементы HTML. Но на странице должно быть только рамки.

Если мы создали страницу без SVG, мы могли бы создать много нашего дисплея с HTML и с библиотекой изображений, .png и .jpg файлами и другими. HTML будет долго и сложен. Там было бы много ручного крута и особенного JS код, чтобы сделать все это отображаться.

Но для наших целей все, что нам действительно нужно сделать, это иметь место, поставьте SVG. Это должно быть правильная коробка размера. И тогда нам нужно получить файл в эту позицию. Мы могли бы написать HTML-страницу с SVG, вставленной. Но нам не нужно. SVG может быть немного загружен после HTML Framework. (Я в основном забыл одну Санфу, где поздняя загрузка SVG решила ошибку в одном браузере.) Мы можем позже эксплуатировать на нашу ленивую загрузку SVG и загрузить более одного образа на странице, когда мы так желаем.

Итак, давайте начнем с простого HTML, который можно использовать много раз, чтобы загрузить любое количество страниц SVG.


    
        
        svg demo
    
    
    

Simple example that loads an SVG application

Итак, это файл HTML5. Использует jquery , что довольно популярно. И, для небольшой помощи с SVG, он использует svg.js Отказ Вы можете узнать больше об этой библиотеке SVG At (svgjs.com) [http://svgjs.com/]. Этот пример будет использовать только svg.js загрузить в SVG. Тем не менее, вы можете сделать гораздо больше с этим.

Внизу HTML-страницы, а только от ссылок JavaScript – это небольшое количество JavaScript, которое устанавливает несколько широких переменных. Эти переменные определяют код в файле petriclientapp.js Что загрузить и куда это поставить.

Последний эталон JavaScript загружает файл, petriclientapp.js Отказ Файл, petriclientapp.js , предоставляет код для загрузки SVG после завершения страницы.

Поддерживающая сторона клиента JavaScript

Есть два вида клиентской стороне JavaScript CSJS Что нам нужно сделать для нашего приложения веб-страницы для работы. Один вид CSJS Обращается к загрузке новых ресурсов и отвечает на изменения, отправленные сервером. Другой вид CSJS Вносит изменения в графические интерфейсы.

В этой части учебника Часть 2 Мы ориентированы на первый вид. Этот вид имеет больше системных программирования вкуса и сделки с сетью, известными на HTML-странице. Мы хотим убедиться, что данные идет вперед и назад между страницей и сервером, как запланировано.

Первые данные, которые мы хотим получить, это сама страница SVG. Мы можем загрузить его, как только документ готов. Когда документ готов, будет существовать элемент

, предназначенный для содержения SVG. И весь файл SVG будет прикреплен как ребенок для этого
.

$(document).ready(function() {
  // Loading this part of the page on demand. 
    // Imagine a case where many versions of the SVG might be loaded 
    // into our same HTML context. Or, imagine parts of an SVG image
    // being loaded on demand.
    secondFetch();

    // do other things here.
});

function secondFetch() {

    var section = window.fetchSections;

    // fetch the svg section from the server...
    // Do that if that is what is require by the HTML context.
    if ( window.useFetchSVG ) {
    	// 
        var page = window.fetchPage;
        // it's in the svg directory on the server
        var dataFetchPage = `/svg/${page}`;  
        // then put it here
        var parentEl =  "#" + window.targetDiv;

    // let jquery do the work of getting ht page.
        $.get( dataFetchPage, function( data ) {
            $( parentEl ).html( data );  // put it where it belongs
        });
    }
}

Так что это все, что нужно для загрузки SVG лениво, по требованию и т. Д.

Запустите сервер

Итак, теперь у нас есть код клиента и код сервера. В моем каталоге у меня есть example.html Как брат к Petriexpress.js Отказ И у меня есть SVG каталог, содержащий Петри.свг Отказ

Я управляю сервером таким образом:

node petriexpress.js 

И ожидаемый выходной выход: Пример приложения, слушающего порта 3000!

Итак, оттуда я хожу в браузер и введите localhost: 3000 в Наварбур. И тогда я вижу картину.

Держите состояние машины на сервере

Итак, мы можем получить SVG с сервера. Мы можем загрузить это. Мы можем получить больше файлов, если мы знаем их имена. Это все хорошо. Но, так что же!

Вот две вещи, оставленные для достижения.

  • Анимировать страницу
  • Сделать это значимым

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

Мы можем использовать сетки Петри для реальных вещей. И нам не нужно делать тонны работы, чтобы сделать их полезными. Это большая победа.

Но как насчет просто показывая всех, как сделать некоторую анимацию? Хорошая точка зрения! Но, сетки Petri могут быть использованы для демонстрации базовой анимации, не попадая в огромные проекты или даже слегка утомительные проекты. Тем не менее, Petri Nets заставляют нас задать один довольно важный вопрос.

Где мы должны хранить состояние, что наш интерфейс отображается, в клиенте или на сервере?

Это важный вопрос. Почему?

Ну, если вы посмотрите на множество CMS доступен для использования сегодня, вы увидите, что либо клиент очень занят, более необходимым, или что один сервер несет вес всего мира на его крошечном процессоре (или Маленькие ноги или булавки или что-то еще …).

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

В нашем случае вся чистая обработка Петри может быть на клиенте. На клиенте может быть одна сеть для каждой проверки процесса. И государственные переходы могут быть отправлены от клиента на сервер для запуска процесса.

Это кажется в порядке. Но предположим, что ваш процесс перемещает такие вещи, как кислота из контейнера до контейнера и вашего мобильного телефона, проведение всей вещи, умирает моменты смерти батареи, прежде чем предохранительный клапан должен быть отключен? Оооп! Не помещайте управление процессом на клиенту!

Ну тогда, зачем беспокоиться с рисунком сетки и анимации на клиенте? Почему бы не просто понравиться определенные популярные CMS, написанные в PHP? Визуализируйте все на сервере и сделайте это один раз для каждого клиента и отправьте полные обновления изображения (SVG или иным образом) на каждую открытую страницу каждый раз, когда что-то происходит на сервере? На самом деле, если вы делаете это, как и определенные CMS, вы можете смешивать рендеринг и управление процессом, чтобы одновременно работать примерно в 256 мб. Ну, эта ситуация может оказаться таким же плохим, как сотовый телефон умирает смерть батареи.

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

Таким образом, сервер становится клиентом сети сети. И клиенты браузера ждут событий, чтобы прийти с веб-сервера, прежде чем сообщить нам, что произошло.

Итак, что мы можем сделать, это у вас сервер (отправная точка для нашей настройки администратора) порождают менеджер процесса (одинаковую или другую машину). Детский процесс может отправлять события на веб-сервер (наше приложение Simple Express), которое, в свою очередь, может отправлять события Socket.io на веб-страницу.

Итак, наша HTML-страница, так и экспресс-сервера должны расти немного. Мы можем внести эти изменения, чтобы получить информацию о рассмотрении информации. И, после этого мы будем готовы закончить нашу анимацию, показывающую изменения государства.

Давайте начнем на изменениях.

Менеджер государства процесса, который запускает нашу чистую Петри

Первое, что я хочу сделать, это сделать веб-сервер, способный говорить с менеджером чистых процессов Петри. Говорящая часть – это все, что я действительно беспокоюсь на данный момент. И я мог бы выбрать ряд способов установить связь.

Вот несколько вариантов, которые я могу сделать для общения:

  • Читайте и запишите на общий файл (очень неуклюжем)
  • Установите IPC и управляйте этим своим собственным кодом.
  • Настройте соединение TCP и пакеты обмена
  • Прочитайте и напишите UART между машинами с моим собственным протоколом ASCII.
  • Сократите процесс в Node.js с включенным IPC и используйте соответствующие обработчики отправки и событий.

Почему последний звучит так хорошо?

Итак, я собираюсь изменить приложение Express. Это первое изменение этого:

const express = require('express');
const fs = require('fs');
// Here is where the node.js child process mechanics is introduced
const { spawn } = require('child_process');

// ---------
const appPort = 3000;
// ---------
const app = express();
const server = require('http').createServer(app);

// ---------
// Spawn a child process. Let node.js hadle the communication.

const HWProc = spawn('node', ['./petriState.js'], // a new file in our directory
                     {   // Tell nodeljs how to talk to the child process
                         stdio: [process.stdin, process.stdout, process.stderr, 'ipc']
                     });

// When the child process finishes or crashes
HWProc.on('close', (code) => {
              console.log(`child process exited with code ${code}`);
});

// Receive message to be forwarded to socket.io clients.
HWProc.on('message', (message) => {
              console.log(message);
          });

// ---------

// Use on generic function to load file stuff and send it to the client
function loadPage(filename, res) {
    fs.readFile(filename,'utf8', (err,data) => {
                    if ( err ) {
                        res.send(JSON.stringify(err));
                    } else {
                        var page = data.toString();
                        res.send(page);
                    }
                })
}

// The paths (routes) to the files we want to send.
app.get('/', (req, res) => {
            loadPage('example.html',res);
        });

app.get('/:file', (req, res) => {
            loadPage(req.params.file,res);
        });

app.get('/svg/:svFile',(req,res) => {  // look in a particular directory
            loadPage('./svg/' + req.params.svFile,res);
        });

// add a way to relay data from the browser client
app.get('/changes/:type/:parameter',(req, res) => {
             // put stuff into the Petri Net application
             // This might not have to change - ever.
             HWProc.send({ "type" : req.params.type, "message" : req.params.parameter })
         });

app.listen(appPort, () => console.log(`Example app listening on port ${appPort}!`))

Итак, мы добавили около десяти строк, некоторые из которых были выбором стиля кода. И теперь мы можем реле с машины в браузер. Мы можем сделать это, конечно, только если наша дочерняя программа разговаривает с машиной. Это не нужно. Но, главное, веб-сервер не должен знать, что происходит. Это просто реле информации.

Чтобы проверить наш код, мы можем написать очень простую дочернюю программу, Petrustate.js Отказ Все, что нужно сделать, это получить сообщение и отправить сообщение веб-серверу каждый сейчас и затем. Вот эти несколько строк, которые могут сделать работу:

process.on('message', (m) => {
  console.log('CHILD got message:', m);
});

setInterval(() => {
                process.send({ state: 'OK', data: "ready" });
            },1000);

Веб-страница, в которой полей изменения состояния

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

Давайте использовать Socket.io сделать реле происходить. На данный момент мы можем просто убедиться, что данные идут там, где мы хотим. Во-первых, мы хотим, чтобы данные в конечном итоге в контексте нашей HTML-страницы. Итак, мы настроили некоторые клиентский код, позволяя одной странице присоединиться к получению событий, указывающих чистое состояние Петри.

Для работы следующего кода необходимо загрузить этот Socket.io Библиотека в HTML-контекст. Итак, следующая строка должна быть добавлена к HTML-странице, example.html Отказ


Затем мы добавляем несколько строк к CSJS Файл, petriclientapp.js Отказ

// Here we are connecting to our known host. 
// And, further, we are picking a particular name space that socket.io knows
// how to handle.
var petriIo = io.connect('http://localhost:3000/petri');

petriIo.on('connect', function (message) {
     // tell the interface...
    console.log(message);
 });

// here comes the data
petriIo.on('datum', function (message) {
     // put data in the right recepticle
    console.log(message);
 });

Теперь, когда сервер готов к обслуживанию подключения, веб-страницы example.html начнет получать события.

Веб-сервер, который реле государства

Это простой шаг для настройки соединения Socket.IO. Но мы также можем захотеть отправлять данные всем слушателям. Для этого хорошо, мы должны быть только осторожны в одном.

Мы должны добавить еще несколько строк кода на нашем сервере, чтобы получить Socket.io Работа на стороне сервера.

В верхней части файла мы должны добавить требуется заявление, которое приносит Socket.io Отказ

const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);   // io socket.io

Здесь третья строка – это новая линия, которая приносит Socket.io и связывает это к нашему http сервер.

Теперь мы можем сделать реле из дочернего процесса клиенту.

// This is a line you can find for reference
HWProc.on('close', (code) => {
              console.log(`child process exited with code ${code}`);
});

// New lines here...

HWProc.io = io;  // saving this here.

// make a petri namespace for the socket event lister, the web browser client
HWProc.petriEvents = io.of('/petri').on('connection', function (socket) {
    socket.on('message', function (data) {  // this is from the client
        console.log(data);
    });
});

// Here is the actual message relay.
// Receive message to be forwarded to socket.io clients.
HWProc.on('message', (message) => {
            HWProc.petriEvents.emit('datum', message);
          });

Итак, теперь, что мы должны быть осторожны, чтобы убедиться, что все клиенты получают информацию о состоянии? Мы должны быть осторожны, чтобы ничего не делать. Dafault Socket.io Beatabvior – отправить неквалифицированный Эмит всем клиентам, связанным с Петри пространство имен. На самом деле, мы могли бы получить много Fancier с «номерами» и конкретные ответы на идентификатор клиента. Но нет необходимости. У нас достаточно, чтобы реле информации.

Готов к следующему шагу

Теперь у нас есть система, чем реле и отвечать на данные. Но мы все еще пытаемся достичь нашей цели значимого применения. Итак, может быть следующее сделать, будет делать файл Petrustate.js сделать что-то полезное. Фактически, мы можем запрограммировать чистую чистую Петри, которая определяется данными, которые мы определили в части одной из этого приема Tartorial.

В следующей части Часть 3 Мы расширимся на использование чистую Петри для управления физическими процессами. В частности, мы возьмем результаты предварительной обработки и используем тех, кто определяет процесс, который мы хотим управлять.

Казалось, хорошая вещь, чтобы дать чистую обработку Петри своей собственной части. Сетки просты. Объяснение их немного сложнее. Как только мы сможем запустить сеть, которая принимает данные от датчиков, реальных или виртуальных, и может изменить состояния машин, нам будет что-то отображать на нашей странице.

Для последней части, Часть 4 Мы создадим некоторую книгу клиента JavaScript, и система будет оживлена. В этой части мы сделаем свои собственные анимационные трюки.