Научно-исследовательская лаборатория систем ЧПУ |
|||||||||||||||||
|
|||||||||||||||||
|
Использование SVG в приложениях SCADAАвтор: Антон Попов
|
Обозначение | Описание |
Двигатель в выключенном состоянии | |
Двигатель в рабочем состоянии | |
Двигатель в состоянии <неисправность> |
В данный момент, для вывода таких обозначений используются компоненты ActiveX и растровые изображения. Но известно, что растровые изображения плохо масштабируются. Если изображение увеличивать, то очень скоро оно начинает выглядеть пиксилизированным для человеческого взгляда. К тому же, для того, чтобы изменить состояние устройства, обозначаемого изображением необходимо загрузить совершенно другой файл изображения, даже если требуется всего лишь изменить цвет, чтобы отразить изменение состояния устройства. Векторная графика, в свою очередь, описывает изображение примитивами, такими как линия, окружность, прямоугольник и т. п. Изображение получается в результате обработки заданного списка примитивов, которые не зависят от используемого пользователем устройства отображения. Таким образом, при масштабировании векторная графика не теряет качество, так как изображение каждый раз высчитывается при изменении размера заново, к тому же векторная графика обычно занимает меньший размер файлов по сравнению с растровыми графическими файлами. Изменение же состояния устройства обычно проще с использованием векторной графики, нежели чем растровыми изображениями, ввиду того, что требуется только изменить свойство, такое как цвет линии или прямоугольника для того, чтобы обозначить новое состояние устройства. В некоторых случаях, однако, может оказаться быстрее сменить одно растровое изображение на другое, нежели чем изменить свойство в векторной графике и выполнить обработку, но преимущества векторной графики бесспорны с точки зрения модульности, настраиваемости и расширяемости.
Изменение в состоянии устройства относятся только к тем графическим элементам, которые должны изменить свои свойства. Эти изменения могут быть объединены для демонстрации широкого списка возможных состояний. В растровых изображениях требуется отдельное изображение для каждого состояния, а для сложных графических компонентов комбинация всех возможных графических свойств, таких как цвет, толщина линий или заливка могут привести к необходимости иметь громадное количество растровых файлов только ради того, чтобы продемонстрировать все возможные состояния компонента.
Как правило, компании используют собственные стандарты для выражения состояний графических компонентов. Кроме того, существуют общепринятые правила использования специальных графических свойств для представления определенных состояний, таких, например, как использование красного цвета для демонстрации неисправного состояния. Конкретные графические свойства принятые одной компанией в тоже время могут отличаться от используемых в другой. Свойства компонента, описанного открытым векторным форматом, могут быть легко изменены пользователем, в то время как компонент представленный растровыми изображениями должен редактироваться графическими редакторами. Поскольку в этом случае пиксели изображения изменяются напрямую, изменение многих свойств, таких, например, как толщина бордюра может оказаться весьма сложной задачей.
Как и в настраиваемости, проще увеличить количество возможных графических состояний в векторной графике, нежели чем в растровых изображениях.
Большое количество современных интерфейсов оператора создаются с помощью компонентов ActiveX. Эта технология базируется на компонентной объектной модели COM (Component Object Model) и на языках программирования позволяющих создавать COM компоненты, таких как C++ и Visual Basic.
Компоненты ActiveX могут включать в себя формы Windows, растровые изображения и векторную графику для визуального отображения компонента. Многие компании работающие в сфере автоматизации промышленного производства разработали собственные наборы библиотек образов для HMI базирующихся на компонентах ActiveX. Качество графики этих компонентов может сильно отличаться и зависит от качества используемых графических библиотек. Как правило, интерфейсы использующие векторную графику создаются процедурно на основе функций примитивов GDI (Graphics Device Interface) - графического Windows API, а не на основе декларативного SVG. Однако GDI также позволяет сохранять векторную графику в метафайлах, которые могут быть позже обработаны вызовом соответствующих функций библиотеки. Эти механизмы, позволяющие разрабатывать инструментальные средства рисования позволяют сохранять, манипулировать и сохранять метафайлы, освобождая пользователя от программирования графических библиотек. Также компоненты ActiveX, как и SVG могут быть интегрированы на web-страницы, но только на системах Microsoft Windows и только браузер Internet Explorer в состоянии отобразить их. Это одно из самых важных недостатков технологии ActiveX - она запатентованная. В дополнение к этому, компоненты ActiveX выполняют <родной> код Windows, создавая, таким образом, серьезные проблемы в безопасности пользователей. В любом случае, ActiveX является успешной технологией в построении HMI благодаря повсеместности операционной системы Windows, совершенности технологии COM и относительной простоте написания ActiveX компонентов на Visual Basic.
Одной из идей, стоящей за распространением SVG является идея создания библиотек графических образов каждым сообществом. Тег <use> позволяет повторное использование графических символов описанных в этом же или других файлах SVG. Эти SVG-фрагменты могут комбинироваться в структурные схемы управляющей логики, электронные узлы, диаграммы классов UML или в любой другой вид графики. Промышленная автоматизация является одной из отраслей, где применение SVG крайне удобно, что демонстрируется успехом компонентов ActiveX. Но насколько графика SVG соответствует потребностям промышленных интерфейсов?
В качестве образца архитектуры для промышленных SVG компонентов возьмем следующие 4 идеи:
Технология CSS была изначально разработана для модернизации страниц HTML. На обычной web-странице каждый тег служит для описания логической части документа. Например, тег <h1> означает, что текст внутри него является главным заголовком. В таком случае таблица стилей CSS может использовать селектор h1 для определения стиля текста обрамленного тегом <h1>. Теги HTML описывают логическую структуру документа, тогда как CSS определяет стиль каждой структуры документа.
В SVG обычно не имеет смысла использовать селекторы для определенного тега, как в HTML, потому что графический документ не является логически структурным документом. Это становится бесполезным, например, для определения стиля всех прямоугольников в рисунке (это применимо скорее к единообразным элементам и не применимо к определенным стандартным описаниям символов). Таким образом, самое простое и распространенное применение CSS селекторов на HTML страницах становится бесполезным в SVG.
С другой стороны, в HTML есть тег <div>, который не описывает логическую структуру содержимого и используется только для группировки других элементов. Как и в SVG документах довольно бессмысленно применять к этому тегу один стиль, так как это отразится на всех тегах <div> присутствующих на странице. В то же время, часто случается, что нам необходимо применить определенный стиль к разным элементам на HTML странице в независимости от тега. Атрибут class позволяет это сделать, связывая элемент HTML с соответствующим стилем. Добавляя в таблицу стилей CSS селектор .classname, который относится ко всем элементам класса classname. Эту же практику, в свою очередь, удобно использовать и для SVG документов. Нам может быть неудобно применять определенный стиль для всех прямоугольников, но только для некоторых, которые принадлежат определенному классу. В частности, в SVG существует тег <g>, который очень напоминает тег <div> HTML и который служит для группировки других графических элементов. Так же и как тег <div>, тег <g> особенно полезен с точки зрения возможности привязки к определенному классу, так как обычно бессмысленно привязывать один стиль ко всем группам, определенным в SVG файле.
В дополнение к этому, каждый элемент в SVG документе или на странице HTML может быть идентифицирован атрибутом id. CSS позволяет выбирать уникальный элемент используя нотацию #identifier и применять стиль только к такому элементу. Селекторы CSS могут также комбинироваться для того, чтобы достичь определенных элементов дерева SVG или HTML. Последнее особенно удобно для нашей архитектуры компонентов SVG.
Тег <use> позволяет ссылаться на компоненты SVG описанные в этом же или другом файле. Этот тег является базой для нашей компонентной архитектуры. Однако, совместное использование тега <use> и таблиц стилей CSS имеет два препятствия:
В первом случае получается, что селекторы CSS не могут обращаться к внутренней структуре компонента, что снижает удобство применения стилей для элементов <use> до самых простейших. Например, мы можем назначить стиль элемента <use> используя атрибут class. Но этот стиль будет назначен для всех подкомпонентов внутри компонента, на который ссылается тег <use>. Таким образом, получается невозможным выбрать подкомпонент и назначить ему один цвет, в тоже время как другому подкомпоненту назначить другой цвет. Во втором случае, проблемы вытекают из того факта, что внешняя таблица стилей неизвеста текущему документу - он импортирует SVG документ, а не таблицу стилей. На рис. 1 видно, как цвет обозначения двигателя может быть изменен применением определенного атрибута class для элемента <use>.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml-stylesheet href="simplestyle.css" type="text/css"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"> <defs> <symbol id="motor" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" stroke-width="2"> <circle cx="50" cy="50" r="30"/> <path d="M 40 60 L 40 40 L 50 50 L 60 40 L 60 60"/> </symbol> </defs> <g> <use xlink:href="#motor" class="on" x="10" y="10" height="80" width="80"/> <use xlink:href="#motor" class="off" x="110" y="10" height="80" width="80"/> <use xlink:href="#motor" class="alarm" x="10" y="110" height="80" width="80"/> <use xlink:href="#motor" class="repair" x="110" y="110" height="80" width="80"/> </g> </svg> |
.on { stroke: black; fill: lime; } .off { stroke: black; fill: lightgrey; } .alarm { stroke: black; fill: red; } .repair { stroke: black; fill: deepskyblue; } |
Выше, при обозначении двигателя в различных состояниях мы обозначили состояние неисправности красным кругом, однако в табл. 1 было показано, что обычная схема обозначения двигателя в состоянии неисправности - красный прямоугольник с серым кругом. Чтобы продемонстрировать это мы расширим код представляющий обозначение двигателя и разделим его на 2 подкомпонента - задний и передний фон с помощью атрибута class.
На этом примере можно показать как тег <use> скрывает дерево SVG документа предотвращая возможность использования CSS селекторов для подкомпонентов. Чтобы доказать это, сделаем копию обозначения двигателя используя тег <g> в отображаемой секции документа SVG. В противоположность изображению, полученному с использованием элемента <use>, дерево этой копии доступно для применения стилей CSS.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml-stylesheet href="motorstyle.css" type="text/css"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="240" height="120"> <defs> <symbol id="motor" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" stroke-width="2"> <g class="background"> <rect x="0" y="0" width="100" height="100"/> </g> <g class="foreground"> <circle cx="50" cy="50" r="30"/> <path d="M 40 60 L 40 40 L 50 50 L 60 40 L 60 60"/> </g> </symbol> </defs> <g> <!-- Копия обозначения двигателя --> <g id="motor1" transform="translate(10,10)" stroke-width="2" class="alarm"> <g class="background"> <rect x="0" y="0" width="100" height="100"/> </g> <g class="foreground"> <circle cx="50" cy="50" r="30"/> <path d="M 40 60 L 40 40 L 50 50 L 60 40 L 60 60"/> </g> </g> <!-- Использование тега <use> скрывает подкомпоненты --> <use xlink:href="#motor" class="alarm" x="130" y="10" height="100" width="100"/> </g> </svg> |
Ниже приведен код CSS, который применяется для отображения этого SVG документа. Эта таблица стилей заполняет красным цветом все элементы класса alarm, в тоже время, заполняя серым цветом те элементы, которые одновременно принадлежат и классу alarm и классу foreground.
.alarm { stroke: black; fill: red; } .alarm .foreground { stroke: black; fill: lightgrey; } |
Результат представлен на рис. 2. Слева представлено изображение копии обозначения двигателя. В данном случае селекторы CSS определили группу элементов класса foreground, которые также наследуют класс alarm от родительского элемента и, следуя правилам описанным в motorstyle.css, окрасили круг в серый цвет, а прямоугольник в красный цвет. С правой стороны результат отображения элемента <use>. Как видно, все окрашено в красный цвет в соответствии с классом alarm, так как подкомпонент foreground скрыт от таблицы стилей. Отсюда можно сделать вывод, что подкомпоненты SVG документов невидны для тиблиц стилей CSS.
Тот факт, что таблицы стилей применяются для всего документа, а не для отдельных компонентов и то, что полное дерево SVG компонента скрыто во время его использования внутри другого SVG файла ограничивает возможности совместного применения SVG и CSS. Однако, разрабатываемая в данный момент версия SVG 1.2 позволит избежать подобного рода проблем со стилями благодаря тому, что всю работу по внешнему виду документов SVG возьмут на себя XSLT (XSL Transformations) преобразования. Таблицы стилей XSL (Extensible Stylesheet Language) будут определять, каким образом трансформировать оригинальный SVG документ в изображение.
Лаборатория систем ЧПУ МГТУ "Станкин" © 2002-3601
Россия, Москва, Вадковский переулок, д. 3а Телефон: +7 (499) 972-9440 Факс: +7 (499) 972-1873 |