Создание интерактивных цифровых логических схем в React

Добро пожаловать в мир проектирования цифровых логических схем, где сложность сочетается с творчеством. Создание цифровой логической схемы — немалый подвиг.
Это требует точности, ясности и эффективной визуальной коммуникации. Однако правильные инструменты могут сделать этот процесс значительно более управляемым. Одним из таких инструментов является универсальный элемент управления Syncfusion React Diagram, который позволяет разработчикам быстро и без усилий создавать высококачественные логические схемы.
В этом блоге мы рассмотрим функциональные возможности элемента управления React Diagram. Мы продемонстрируем, как его интерактивный пользовательский интерфейс, оснащенный такими функциями, как перетаскивание, копирование, вставка, импорт и экспорт, а также панорамирование и масштабирование, упрощает процесс создания схемы.
Кроме того, мы рассмотрим его богатый набор функций. К концу этой статьи вы поймете, почему элемент управления React Diagram является незаменимым инструментом для любого проекта проектирования цифровой логики.

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

Flip-Flop
Flip-Flop — это схема, которая имеет два стабильных состояния и может использоваться для хранения информации о состоянии. Состояние можно изменить, применив один или несколько управляющих входов, и оно будет иметь один или два выхода. Разработчик логических схем должен иметь для проектирования флип-флопы SR, D, JK и T.

Элементы управления вводом
Элементы управления вводом могут передавать высокий (true) или низкий (false) сигнал на логические элементы или флип-флопы. Разработчик логических схем должен предоставить следующие входные элементы управления: тумблер, кнопку, часы, высокую константу и низкую константу для проектирования схем.

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

Предварительные условия
- Установите Node.js версии 14.15.1.
- Настройте элемент управления React Diagram, следуя документации по началу работы.
Создание поверхности диаграммы
Давайте создадим поверхность диаграммы, выполнив следующие шаги:
1. Создайте папку и дайте ей имя, например Logic Circuit Designer.
2. Откройте терминал или командную строку и выполните следующую команду, чтобы установить глобальный пакет Create React App NPM:
npm install -g create-react-app
3. Создайте новое приложение React. Дайте ему предпочитаемое имя приложения и выполните следующую команду:
npx create-react-app logic-circuit
4. Измените свой рабочий каталог на недавно созданное приложение, используя следующую команду:
cd logic-circuit
5. Чтобы увидеть свое приложение в действии, запустите сервер разработки с помощью следующей команды:
npm start
Ваше приложение откроется в веб-браузере по умолчанию по адресу http://localhost:3000/.
6. Откройте файл json и добавьте следующие зависимости:
"dependencies": {
"@syncfusion/ej2-react-base": "*",
"@syncfusion/ej2-react-buttons": "*",
"@syncfusion/ej2-react-diagrams": "*",
"@syncfusion/ej2-react-dropdowns": "*",
"@syncfusion/ej2-react-inputs": "*",
"@syncfusion/ej2-react-lists": "*",
"@syncfusion/ej2-react-navigations": "*",
"@syncfusion/ej2-react-popups": "*",
"@syncfusion/ej2-react-splitbuttons": "*",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
7. Используйте следующую команду для установки всех вышеперечисленных зависимых пакетов:
npm install
8. Добавьте зависимые скрипты и стилизуйте справочные ссылки CDN в файл index.html
.
<head>
<link href="https://cdn.syncfusion.com/ej2/20.4.38/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/ej2-react-buttons/styles/fluent.css" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-base/styles/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-react-popups/styles/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-react-splitbuttons/styles/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-react-navigations/styles/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-react-inputs/styles/fluent.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/20.4.38/ej2-react-dropdowns/styles/fluent.css" rel="stylesheet">
<link href="index.css" rel="stylesheet">
<link href="./assets/Diagram_Builder_Icon/style.css" rel="stylesheet">
<link href="./assets/index.css" rel="stylesheet">
<link href="./assets/dbstyle/diagrambuilder.css" rel="stylesheet" />
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/20.4.38/dist/ej2.min.js" type="text/javascript"></script>
</head>
9. Чтобы включить компонент Diagram в свое приложение, импортируйте DiagramComponent из ej2-react-diagrams
. Затем настройте необходимые аргументы, такие как ширина, высота и набор узлов и соединителей, которые будут включены в схему в файле App.js
.
Обратитесь к следующему примеру кода:
<div id="diagramContainerDiv" className='db-current-diagram-container'>
<DiagramComponent ref={diagram=>
(this.diagram = diagram)} id="diagram" width={"100%"} height={"100%"}
scrollSettings={this.scrollSettings} rulerSettings={this.rulerSettings}
pageSettings={this.pageSettings} nodes={this.nodes} connectors={this.connectors}
backgroundColor="transparent" getConnectorDefaults={this.getConnectorDefaults.bind(this)}
getNodeDefaults={this.getNodeDefaults.bind(this)}/>
</div>
На следующем изображении показан первоначальный вид диаграммы.

Создание повторно используемых символов логических схем
Элемент управления React Diagram предоставляет галерею повторно используемых узлов и соединителей под названием SymbolPalette. Он отображает коллекцию палитр, каждая из которых отображает набор узлов и соединителей. Мы можем перетаскивать их на холст диаграммы любое количество раз.
Выполните следующие шаги, чтобы создать палитру символов диаграммы с формами логических схем:
1. Создайте HTML-элемент div
, который будет выступать в качестве контейнера для палитры символов диаграммы.
Обратитесь к следующему примеру кода:
<div className='sidebar show-overview'>
<div className="db-palette-parent">
<SymbolPaletteComponent ref={symbolpalette => (this.symbolpalette) = symbolpalette} id="symbolpalette />
</div>
</div>
2. Инициализируйте палитру символов диаграммы синхронизации, передав необходимые аргументы, такие как ширина, высота и набор символов, которые будут включены в палитру.
<div className='sidebar show-overview'>
<div className="db-palette-parent">
<SymbolPaletteComponent ref={symbolpalette => (this.symbolpalette) = symbolpalette} id="symbolpalette" width="100%" height="100%"
expandMode={this.palettes.expandMode}
palettes={this.palettes.palettes}
symbolPreview={this.palettes.symbolPreview} symbolMargin={this.palettes.symbolMargin}
getSymbolInfo={this.palettes.getSymbolInfo} />
</div>
</div>
3. Определите и настройте символы палитры по мере необходимости. Обратитесь к следующему коду:
export class Palettes {
constructor() {
this.expandMode = 'Multiple';
this.symbolPreview = {height : 50, width : 50};
this.symbolMargin = {left : 5, right : 5, top : 10, bottom : 10};
this.palettes = [
{
id : 'input',
expanded : true,
symbols : this.input(),
title : 'Input Controls'
},
{
id : 'output',
expanded : true,
symbols : this.output(),
title : 'Output Controls'
},
{
id : 'flow',
expanded : true,
symbols : this.gates(),
title : 'Logic Gates'
},
{
id : 'flipflop',
expanded : true,
symbols : this.flipflops(),
title : 'Flip flops'
},
{id : 'other', expanded : true, symbols : this.other(), title : 'Other'},
];
}
getSymbolInfo(symbol) {
return {
description : {
text : symbol.shape['shape'],
overflow : 'Wrap',
fontSize : 12,
margin : {top : 10, left : 0, right : 0, bottom : 0}
}
};
}
setPaletteNodeDefaults(node) {
if (!(node.addInfo&& node.addInfo.type == = 'CustomShapes') &&
(!node.children)) {
if (node.id == = 'Terminator' || node.id == = 'Process') {
node.width = 130;
node.height = 65;
} else {
node.width = 50;
node.height = 50;
}
node.ports = [
{
offset : {x : 0, y : 0.5},
style : {fill : 'white'},
visibility : PortVisibility.Connect | PortVisibility.Hover,
constraints : PortConstraints.Draw
},
{
offset : {x : 0.5, y : 0},
style : {fill : 'white'},
visibility : PortVisibility.Connect | PortVisibility.Hover,
constraints : PortConstraints.Draw
},
{
offset : {x : 1, y : 0.5},
style : {fill : 'white'},
visibility : PortVisibility.Connect | PortVisibility.Hover,
constraints : PortConstraints.Draw
},
{
offset : {x : 0.5, y : 1},
style : {fill : 'white'},
visibility : PortVisibility.Connect | PortVisibility.Hover,
constraints : PortConstraints.Draw
}
];
node.style.strokeColor = '#3A3A3A';
}
}
getPalettes(text) {
let palettes = [];
if (text.indexOf('Flow') != = -1) {
palettes.push({
id : 'flow',
expanded : true,
symbols : this.getFlowShapes(),
title : 'Flow Shapes'
});
}
if (text.indexOf('Basic') != = -1) {
palettes.push({
id : 'basic',
expanded : false,
symbols : this.getBasicShapes(),
title : 'Basic Shapes'
});
}
if (text.indexOf('BPMN') != = -1) {
palettes.push({
id : 'bpmn',
expanded : false,
symbols : this.getBPMNShapes(),
title : 'BPMN Shapes'
});
}
if (text.indexOf('Connectors') != = -1) {
palettes.push({
id : 'connectors',
expanded : false,
symbols : this.getConnectors(),
title : 'Connectors'
});
}
if (text.indexOf('Electrical') != = -1) {
palettes = palettes.concat(this.electricalShapes.getElectricalShapes());
}
if (text.indexOf('Network') != = -1) {
palettes.push({
id : 'network',
expanded : false,
symbols : this.networkShapes.getNetworkShapes(),
title : 'Network Shapes'
});
}
if (text.indexOf('Floorplan') != = -1) {
palettes.push({
id : 'floorplan',
expanded : false,
symbols : this.floorplans.getFloorPlans(),
title : 'Floorplan Shapes'
});
}
return palettes;
}
output() {
const output = [
{
id : 'FullPath',
height : 40,
width : 30,
offsetX : 140,
offsetY : 100,
shape : {type : 'Path', data : BulbCompletePath},
style : {strokeColor : 'black', fill : 'black'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'BlackPart',
height : 8,
width : 14,
offsetX : 140,
offsetY : 108,
shape : {type : 'Path', data : BulbBlackPart},
style : {strokeColor : 'black', fill : 'black'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'InnerBluePart',
height : 10,
width : 14,
offsetX : 140,
offsetY : 97,
shape : {type : 'Path', data : BulbInnerBluePart},
style : {strokeColor : 'black', fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
visible : false,
},
{
id : 'OuterBluePart',
height : 28,
width : 32,
offsetX : 140,
offsetY : 90,
shape : {type : 'Path', data : BulbOuterBluePart},
style : {strokeColor : 'black', fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
visible : false,
},
{
id : 'Bulb',
children :
[ 'FullPath', 'BlackPart', 'InnerBluePart', 'OuterBluePart' ],
shape : {shape : 'Light Bulb'},
style : {fill : 'none', padding : '2'},
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : '4-Bit Digit',
shape : {type : 'Path', data : digitdata, shape : '4-Bit Digit'},
style : {fill : '#000000', strokeWidth : 0},
height : 55,
width : 70,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
];
return output;
}
input() {
const input = [
{
id : 'SwOffOuter',
height : 50,
width : 65,
offsetX : 140,
offsetY : 100,
shape : {type : 'Path', data : SwitchOffOuterRect},
style : {strokeColor : 'black', strokeWidth : 2},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'SwOffInner',
height : 40,
width : 30,
offsetX : 127.5,
offsetY : 100,
shape : {type : 'Path', data : SwitchOffInnerRect},
style : {strokeColor : 'black', strokeWidth : 2},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'SwOff',
height : 25,
width : 20,
offsetX : 127.5,
offsetY : 100,
shape : {type : 'Path', data : SwitchoffButton},
style : {strokeColor : 'black', strokeWidth : 2},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'SwOn',
height : 25,
width : 20,
offsetX : 127.5,
offsetY : 100,
shape : {type : 'Path', data : SWitchOnButton},
style : {
strokeColor : 'transparent',
strokeWidth : 2,
fill : 'transparent'
},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
visible : false,
},
{
id : 'Toggle Switch',
children : [ 'SwOffOuter', 'SwOffInner', 'SwOff', 'SwOn' ],
shape : {shape : 'Toggle Switch'},
style : {fill : 'none'},
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'PBOuterRect',
height : 50,
width : 65,
offsetX : 140,
offsetY : 100,
shape : {type : 'Path', data : PushButtonOuterRect},
style : {strokeColor : 'black', strokeWidth : 0, fill : 'black'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'PBOuterCircle',
height : 27,
width : 27,
offsetX : 128,
offsetY : 100,
shape : {type : 'Path', data : PushButtonOuterCircle},
style : {strokeColor : 'black', strokeWidth : 2, fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'PBInnerCircle',
height : 20,
width : 20,
offsetX : 128,
offsetY : 100,
shape : {type : 'Path', data : PushButtonInnerCircle},
style : {strokeColor : 'black', strokeWidth : 2, fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'PushButton',
children : [ 'PBOuterRect', 'PBOuterCircle', 'PBInnerCircle' ],
shape : {shape : 'Push Button'},
style : {fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'CLKOuterRect',
height : 35,
width : 65,
offsetX : 140,
offsetY : 100,
shape : {type : 'Path', data : ClockOuterRectangle},
style : {strokeColor : 'black', strokeWidth : 2},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'CLKInnerPart',
height : 20,
width : 30,
offsetX : 130,
offsetY : 100,
shape : {type : 'Path', data : ClockInnerPart},
style : {strokeColor : 'black', strokeWidth : 2, fill : 'white'},
constraints : NodeConstraints.Default & ~NodeConstraints.Select &
~NodeConstraints.InConnect,
},
{
id : 'Clock',
children : [ 'CLKOuterRect', 'CLKInnerPart' ],
shape : {shape : 'Clock'},
style : {fill : 'none'},
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'High Constant',
shape :
{shape : 'High Constant', type : 'Path', data : highconstantdata},
style : {fill : '#000000', strokeWidth : 0},
height : 55,
width : 70,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'Low Constant',
shape : {shape : 'Low Constant', type : 'Path', data : lowconstantdata},
style : {fill : '#000000', strokeWidth : 0},
height : 55,
width : 70,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
];
return input;
}
gates() {
const gates = [
{
id : 'OR Gate',
shape : {type : 'Path', data : orData, shape : 'OR Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'NOR Gate',
shape : {type : 'Path', data : nordata, shape : 'NOR Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'AND Gate',
shape : {type : 'Path', data : andData, shape : 'AND Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'NAND Gate',
shape : {type : 'Path', data : nanddata, shape : 'NAND Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'Buffer Gate',
shape : {type : 'Path', data : buffer, shape : 'Buffer'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'Not Gate',
shape : {type : 'Path', data : notData, shape : 'NOT Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'XOR Gate',
shape : {type : 'Path', data : xorData, shape : 'XOR Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'XNOR Gate',
shape : {type : 'Path', data : xnorData, shape : 'XNOR Gate'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 79,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
];
return gates;
}
flipflops() {
const flipflops = [
{
id : 'JK Flip-Flop',
shape : {shape : 'JK Flip-Flop', type : 'Path', data : jkflipflopdata},
style : {fill : '#000000', strokeWidth : 0},
height : 90,
width : 70,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'D Flip-Flop',
shape : {shape : 'D Flip-Flop', type : 'Path', data : dflipflop},
style : {fill : '#000000', strokeWidth : 0},
height : 90,
width : 65,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'T Flip-Flop',
shape : {shape : 'T Flip-Flop', type : 'Path', data : tflipflopdata},
style : {fill : '#000000', strokeWidth : 0},
height : 90,
width : 65,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'SR Flip-Flop',
shape : {shape : 'SR Flip-Flop', type : 'Path', data : srflipflopdata},
style : {fill : '#000000', strokeWidth : 0},
height : 78,
width : 73,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
];
return flipflops;
}
other() {
const other = [
{
id : 'Label',
shape : {type : 'Text', content : 'Text'},
style : {
strokeColor : 'black',
strokeWidth : 2,
fill : 'black',
color : 'white'
},
height : 50,
width : 60,
constraints : NodeConstraints.Default &
~(NodeConstraints.InConnect | NodeConstraints.OutConnect),
},
{
id : 'Bus',
shape : {type : 'Path', data : busdata, shape : 'Bus'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 80,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'Pull Up',
shape : {type : 'Path', data : pullupdata, shape : 'Pull Up'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 73,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
{
id : 'Pull Down',
shape : {type : 'Path', data : pulldowndata, shape : 'Pull Down'},
style : {fill : '#000000', strokeWidth : 0},
height : 45,
width : 73,
constraints : NodeConstraints.Default & ~NodeConstraints.InConnect,
},
];
return other;
}
}
На следующем изображении показана палитра символов, заполненная формами логических схем.

Создание цифровой логической схемы
Теперь мы можем спроектировать цифровую логическую схему, добавляя фигуры из палитры символов на поверхность схемы и соединяя их с помощью соединителей.
Шаг 1. Добавьте символы логических схем в редактор.
Чтобы добавить символы логических схем в редакторе, перетащите нужные символы из палитры символов на холст схемы.
Обратитесь к следующему изображению GIF:

Шаг 2. Перемещение символов
Вы можете изменить положение символа на поверхности диаграммы, щелкнув символ и перетащив его в любое место.

Шаг 3. Соедините символы
Вы заметите, что каждый символ схемы имеет входные и выходные точки подключения, обозначенные на символе маленькими кружками. Эти точки позволяют легко и последовательно рисовать соединители между компонентами схемы.
Создать соединение несложно. Наведите указатель мыши на точку подключения, и появится цветная точка, обозначающая начало подключения. Щелкните, перетащите соединитель и поместите его на точку входного соединения другого символа.

Шаг 4. Загрузка и сохранение диаграммы
Элемент управления «Диаграмма» также поддерживает сохранение текущей работы и ее возобновление позже путем загрузки сохраненной диаграммы обратно на холст диаграммы. Этого можно добиться, используя функцию загрузки и сохранения, показанную на следующем изображении.

Шаг 5. Распечатайте и экспортируйте диаграмму
Вы можете экспортировать созданную логическую схему в виде изображения или распечатать ее прямо с принтера. Этого можно добиться, используя функции экспорта и печати элемента управления Diagram.
Шаг 6. Панорамирование и масштабирование
Вы можете увеличивать или уменьшать масштаб диаграммы, удерживая клавишу Ctrl и прокручивая колесо мыши или нажав кнопку раскрывающегося списка в правом верхнем углу дизайнера.
Смотрите следующее изображение:

Когда загружается большая диаграмма, видна только определенная часть диаграммы. Остальные части обрезаются. Вырезанные части можно просматривать с помощью полос прокрутки по краям поверхности диаграммы или путем панорамирования диаграммы. Вы можете панорамировать диаграмму, выбрав инструмент панорамирования на панели инструментов, представленный символом руки, или выбрав Tools > Pan tool, а затем щелкнув и удерживая указатель в области диаграммы.

Вы можете скачать исходный проект этого конструктора цифровых логических схем из этого места на GitHub.
Заключение
Спасибо за прочтение! В этом блоге мы увидели, как легко создать конструктор цифровых логических схем с помощью библиотеки Syncfusion React Diagram. Точно так же вы можете использовать его для создания других диаграмм, таких как организационные диаграммы, блок-схемы и сетевые диаграммы.