Введение
Эта статья о том, как набросать простенькую схемку из десятка элементов, когда под рукой нет ни Altium'а, ни Orcad'a, ни даже Visio, а Draw.io внезапно сломался.
Это совсем не сложно: современные браузеры поддерживают язык разметки SVG, с помощью которого в обычном текстовом редакторе можно легко и быстро нарисовать небольшую схему типа:
Далее я опишу процесс рисования и несколько тонкостей, полезных при этом. Ещё раз подчеркну, что большую схему намного проще нарисовать в специализированных приложениях.
Создание наброска
Набросок обычно содержит элементы/блоки и связи между ними, и может быть создан в виде отдельного текстового файла с расширением .svg или напрямую встроен в код веб-страницы.
При рисовании схем удобно использовать определенный порядок действий:
- Создать (или скопировать) используемые элементы, например
горизонтальный диод Шоттки
<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
, который потребуется на следующем шаге. - Расставить элементы на схеме и подписать их. Для этого используется группа из тэга
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> ...
При использовании одной строки на элемент получается достаточно наглядная таблица. Координаты подписей в группе — относительные, поэтому для перемещения подписанного элемента достаточно изменить координаты группы.
- Нарисовать соединения. Для этого удобно использовать тэг
path
, который позволяет легко чертить горизонтальные и вертикальные линии.Используются в основном следующие команды:
M10,5
— начать чертить с точки 10,5h10
— горизонтальная линия, 10 пикселей вправоm30,0
— перепрыгнуть на 30 пикселей вправоv15
— вертикальная линия, 15 пикселей внизm0,30
— перепрыгнуть на 30 пикселей внизl-5,-10
— косая линия, 5 пикселей влево и 10 пикселей наверх
- Расставить точки
над iсоединения линий. Ничем не отличается от расстановки элементов, но лучше делать это после того, как все соединения уже нарисованы. - Добавить красивостей по вкусу.
<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="none"/>
<path d="M40.5,15.5 h25 v60 h-25" stroke="red" fill="none"/>
<!-- Соединения -->
<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="none"/>
<path d="M35.5,20.5 v45 m0,30 v45" stroke="red" fill="none"/>
<path d="M130.5,20.5 v15 m0,30 v35 m0,30 v10" stroke="red" fill="none"/>
<path d="M155.5,20.5 v45 m0,30 v45" stroke="red" fill="none"/>
<path d="M45.5,20.5 v35 h20" stroke="red" fill="none"/>
<path d="M50.5,140.5 v-55 h15" stroke="red" fill="none"/>
<path d="M90.5,20.5 v20 h25 v15 h-10" stroke="red" fill="none"/>
<path d="M105.5,85.5 h25" stroke="red" fill="none"/>
<path d="M30.5,140.5 h130" stroke="red" fill="none"/>
<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
Где брать изображения элементов
Нарисовать самостоятельно или поискать
При этом иногда получается быстрее нарисовать самостоятельно, чем выбрать подходящий из библиотеки.
Как из .svg получить .pdf, .png, .jpg, и т.д.
Самое простое — открыть .svg в Edge и сохранить изображение как .png. Если браузер не позволяет такого, то можно распечатать .svg на PDF принтер или использовать PrintScreen.
Также есть куча онлайн сервисов, например CloudConvert. К сожалению, не все сервисы правильно обрабатывают прозрачность и/или нестандартные шрифты.
Автор: mickey99