Використання SVG для малювання ескізів схем

Введення
Ця стаття про те, як накидати простеньку схему з десятка елементів, коли під рукою немає ні Altium'а, ні Orcad'a, ні навіть Visio Draw.io раптово зламався.

Це зовсім не складно: сучасні браузери підтримують мову розмітки SVG, за допомогою якого в звичайному текстовому редакторі можна легко і швидко намалювати невелику схему типу:

Sketch of a low-power step-up converter

Далі я опишу процес малювання і кілька тонкощів, корисних при цьому. Ще раз підкреслю, що велику схему набагато простіше намалювати в спеціалізованих програмах.

Створення начерку
Начерк зазвичай містить елементи/блоки і зв'язки між ними, і може бути створений у вигляді окремого текстового файлу з розширенням .svg або безпосередньо вбудований код веб-сторінки.

При малюванні схем зручно використовувати певний порядок дій:

  1. Створити (або копіювати) використовувані елементи, наприклад

    горизонтальний діод Шотткі
    <defs>
    ...
    <g width="30" height="10" id="schottky">
    <path
    style="fill:none;stroke:black;stroke-width:1"
    d="M0.5,5.5 h10 v-5 l10,5 l-10,5 v-5 m7,-4 v-2 h3 v12 h3 v-2 m-3,-4 h10"
    />
    </g>
    ...
    </defs>
    


    або

    вертикальний резистор
    <defs>
    ...
    <g width="30" height="10" id="resistor">
    <path
    transform="translate(1,0) rotate(90,15,5)"
    style="fill:none;stroke:black;stroke-width:1"
    d="M0.5,5.5 h3 l2,-3 l4,6 l4,-6 l4,6 l4,-6 l4,6 l2,-3 h3"
    />
    </g>
    ...
    </defs>
    


    Якщо елементи копіюються з різних місць, вже на цьому етапі варто уніфікувати їх розміри. Замість безпосередньої правки координат для цього простіше використовувати перетворення (
    translate
    ,
    rotate
    ,
    scale
    і т. д.).

    Зверніть увагу, що визначення елементів знаходяться всередині тега
    defs
    , і тому поки що не відображаються. Кожне визначення елемента повинна мати унікальний
    id
    , який буде потрібно на наступному кроці.

  2. Розставити елементи на схемі і підписати їх. Для цього використовується група з тега
    use
    для малювання елементу і одного або декількох тегів
    text
    для підписів.

    Приклад
    ...
    <g transform="translate(115,45)"><use xlink:href="#resistor"/><text x="20" font-size="10">R1</text><text x="20" y="10" font-size="8">470k</text></g>
    ...
    


    При використанні одного рядка на елемент виходить досить наочна таблиця. Координати підписів у групі — відносні, тому для переміщення підписаного елемента досить змінити координати групи.

  3. Намалювати з'єднання. Для цього зручно використовувати тег
    path
    , який дозволяє легко креслити горизонтальні і вертикальні лінії.

    В основному використовуються наступні команди:

    • M10,5
      — почати креслити з точки 10,5
    • h10
      — горизонтальна лінія, 10 пікселів вправо
    • m30,0
      — перестрибнути на 30 пікселів вправо
    • v15
      — вертикальна лінія, 15 пікселів вниз
    • m0,30
      — перестрибнути на 30 пікселів вниз
    • l-5,-10
      — коса лінія, 5 пікселів вліво і 10 пікселів наверх
  4. Розставити крапки над i з'єднання ліній. Нічим не відрізняється від розстановки елементів, але краще робити це після того, як всі з'єднання вже намальовані.

  5. Додати красивостей за смаком.
Код і картинка простої схеми
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Визначення елементів -->
<defs>
<circle x="0.5" y="0.5" r="1.5" style="fill:blue;stroke:blue;" id="junction"/>
<g width="30" height="10" id="connector">
<path
style="fill:none;stroke:black;stroke-width:1"
d="M10.5,5.5 a3,3,0,0,1,-6,0 a3,3,0,0,1,6,0 h20"
/>
</g>
<g width="30" height="10" id="resistor">
<path
transform="translate(1,0) rotate(90,15,5)"
style="fill:none;stroke:black;stroke-width:1"
d="M0.5,5.5 h3 l2,-3 l4,6 l4,-6 l4,6 l4,-6 l4,6 l2,-3 h3"
/>
</g>
</defs>
<!-- Розстановка елементів -->
<g transform="translate(5, 10)"><use xlink:href="#connector"/><text x="20" font-size="10">+</text> </g>
<g transform="translate(25,40)"><use xlink:href="#resistor"/> <text x="-5" y="10" font-size="10">R1</text></g>
<g transform="translate(5, 70)"><use xlink:href="#connector"/><text x="20" font-size="10"></text> </g>
<!-- Зв'язку -->
<path d="M35.5,15.5 h5 v15 m0,30 v15 h-5" stroke="red" fill="ні"/>
<path d="M40.5,15.5 h25 v60 h-25" stroke="red" fill="ні"/>
<!-- З'єднання -->
<use xlink:href="#junction" transform="translate(40,15)"/>
<use xlink:href="#junction" transform="translate(40,75)"/>
<!-- Інше -->
<text x="50" y="88" width="100" text-anchor="middle" font-family="cursive" font-size="10">Опір</text>
<text x="50" y="98" width="100" text-anchor="middle" font-family="monospace" font-size="10">нешкідливо</text>
</svg>

Код схеми з початку статті
<svg width="200" height="150" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>Step-up DC-DC converter</desc>
<defs>
<circle x="0.5" y="0.5" r="1.5" style="fill:blue;stroke:blue;" id="junction"/>
<g width="30" height="10" id="connector">
<path
style="fill:none;stroke:black;stroke-width:1"
d="M10.5,5.5 a3,3,0,0,1,-6,0 a3,3,0,0,1,6,0 h20"
/>
</g>
<g width="30" height="10" id="connector180">
<path
transform="translate(1,1) rotate(180,15,5)"
style="fill:none;stroke:black;stroke-width:1"
d="M10.5,5.5 a3,3,0,0,1,-6,0 a3,3,0,0,1,6,0 h20"
/>
</g>
<g width="30" height="10" id="resistor">
<path
transform="translate(1,0) rotate(90,15,5)"
style="fill:none;stroke:black;stroke-width:1"
d="M0.5,5.5 h3 l2,-3 l4,6 l4,-6 l4,6 l4,-6 l4,6 l2,-3 h3"
/>
</g>
<g width="30" height="10" id="capacitor">
<path
transform="translate(1,0) rotate(90,15,5)"
style="fill:none;stroke:black;stroke-width:1"
d="M0.5,5.5 h13 m0,-7 v14 m4,0 v-14 m0,7 h13"
/>
</g>
<g width="30" height="10" id="inductance">
<path
style="fill:none;stroke:black;stroke-width:1"
d="M0.5,5.5 h0.7 a5,10,0,0,1,9.3,5 a5,10,0,0,1,10,0 a5,10,0,0,1,9.3,-5 h0.7"
/>
</g>
<g width="30" height="10" id="schottky">
<path
style="fill:none;stroke:black;stroke-width:1"
d="M0.5,5.5 h10 v-5 l10,5 l-10,5 v-5 m7,-4 v-2 h3 v12 h3 v-2 m-3,-4 h10"
/>
</g>
<g width="40" height="40" id="stepup">
<rect x="0.5" y="0.5" width="40" height="40" style="fill:none;stroke:black;stroke-width:1px;"/>
<text x="2" y="10" font-size="8">VIN</text>
<text x="2" y="37" font-size="8">GND</text>
<text x="25" y="10" font-size="8">SW</text>
<text x="27" y="37" font-size="8">FB</text>
</g>
</defs>
<g transform="translate(0,15)"><use xlink:href="#connector"/><text x="5" y="-5" font-size="10">+Vin</text></g>
<g transform="translate(0,135)"><use xlink:href="#connector"/><text x="5" y="-5" font-size="10">Gnd</text></g>
<g transform="translate(160,15)"><use xlink:href="#connector180"/><text y="-5" font-size="10">+Vout</text></g>
<g transform="translate(160,135)"><use xlink:href="#connector180"/><text y="-5" font-size="10">Gnd</text></g>

<g transform="translate(65,50)"><use xlink:href="#stepup"/><text y="55" font-size="10">SX1308</text></g>

<g transform="translate(115,45)"><use xlink:href="#resistor"/><text x="20" font-size="10">R1</text></g>
<g transform="translate(115,110)"><use xlink:href="#resistor"/><text x="20" font-size="10">R2</text></g>
<g transform="translate(20,75)"><use xlink:href="#capacitor"/><text x="20" font-size="10">C1</text></g>
<g transform="translate(140,75)"><use xlink:href="#capacitor"/><text x="20" font-size="10">C2</text></g>
<g transform="translate(50,15)"><use xlink:href="#inductance"/><text x="10" y="-5" font-size="10">L1</text></g>
<g transform="translate(95,15)"><use xlink:href="#schottky"/><text x="10" y="-5" font-size="10">D1</text></g>

<path d="M30.5,20.5 h20 m30,0 h15 m30,0 h35" stroke="red" fill="ні"/>
<path d="M35.5,20.5 v45 m0,30 v45" stroke="red" fill="ні"/>
<path d="M130.5,20.5 v15 m0,30 v35 m0,30 v10" stroke="red" fill="ні"/>
<path d="M155.5,20.5 v45 m0,30 v45" stroke="red" fill="ні"/>
<path d="M45.5,20.5 v35 h20" stroke="red" fill="ні"/>
<path d="M50.5,140.5 v-55 h15" stroke="red" fill="ні"/>
<path d="M90.5,20.5 v20 h25 v15 h-10" stroke="red" fill="ні"/>
<path d="M105.5,85.5 h25" stroke="red" fill="ні"/>
<path d="M30.5,140.5 h130" stroke="red" fill="ні"/>

<use xlink:href="#junction" transform="translate(35,20)"/>
<use xlink:href="#junction" transform="translate(45,20)"/>
<use xlink:href="#junction" transform="translate(90,20)"/>
<use xlink:href="#junction" transform="translate(130,20)"/>
<use xlink:href="#junction" transform="translate(155,20)"/>
<use xlink:href="#junction" transform="translate(130,85)"/>
<use xlink:href="#junction" transform="translate(35,140)"/>
<use xlink:href="#junction" transform="translate(50,140)"/>
<use xlink:href="#junction" transform="translate(130,140)"/>
<use xlink:href="#junction" transform="translate(155,140)"/>
</svg>


Тонкощі малювання
Загалом, малювати за допомогою SVG досить просто. Нижче кілька не дуже очевидних, але здатних заощадити трохи часу деталей.

Чому розмиваються лінії

SVG використовує суб-піксельну точність при малюванні ліній. Тому для ліній товщиною в непарне число пікселів координати початку і кінця повинні розташовуватися в середині пікселя. Якщо для малювання використовувалися тільки відносні координати, то можна просто зрушити координати початкової точки на 0.5,0.5. Універсальне рішення —
translate(0.5,0.5)
.

Кола або дуги
Коло можна намалювати тегом
circle
або командою
a
(від Arc (дуга) тега
path
. Якщо є вибір, використовуйте
circle
.

Єдине виправдання малювання кола за допомогою дуг — якщо хочеться намалювати елемент, що містить кола, одним єдиним тегом
path
. Для цього потрібно дві послідовні дуги:
... a3,3,0,0,1,-6,0 a3,3,0,0,1,6,0 ...
,
3
— радіус кола, а
6
— його діаметр.

Використання елементів з інших файлів
Дуже просто — замість
<use xlink:href="#connector"/>
використовується
<use xlink:href="library.svg#connector"/>
.

Окремий файл або вбудований в HTML код
Окремий файл набагато зручніше, але

  • якщо .svg містить посилання на інші .svg, то його потрібно включати в HTML тег
    object


    <object data="image.svg" type="image/svg+xml"></object>

  • якщо .svg не містить посилань на інші .svg, то тег
    image
    працює не гірше тега
    object


    <image src="image.svg"/>
    <object data="image.svg" type="image/svg+xml"></object>
    

  • Елементи вбудованого зображення простіше і швидше настроюються через CSS
Де брати зображення елементів
Намалювати самостійно або пошукати

в Гугліwww.google.nl/search?q=svg+library+of+electronic+components
www.google.nl/search?q=svg+clipart+library

При цьому іноді виходить швидше намалювати самостійно, ніж вибрати підходящий з бібліотеки.

Як .svg отримати .pdf .png .jpg, і т. д.
Найпростіше відкрити .svg Edge і зберегти зображення як .png. Якщо браузер не дозволяє такого, то можна роздрукувати .svg, PDF принтер або використовувати PrintScreen.

Також є купа онлайн сервісів, наприклад CloudConvert. На жаль, не всі сервіси правильно обробляють прозорість та/або нестандартні шрифти.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.