Ui Examples Continued
ΠΡΠΎ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ ΡΠ°Π·Π΄Π΅Π»Π° Ρ ΠΏΡΠΈΠΌΠ΅ΡΠ°ΠΌΠΈ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ². ΠΠ΅ΡΠ²ΡΡ ΡΠ°ΡΡΡ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π½Π°ΠΉΡΠΈ Π² 4.ui-examples.md.
ΠΠ΅ΡΠΎΠ΄Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΠ΅ΠΌ (ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅)
ΠΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠ»Π°ΡΡΠ° Inventory
Ρ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΠ΅ΠΌ:
class Inventory {
// ... (Π½Π°ΡΠ°Π»ΠΎ ΠΊΠ»Π°ΡΡΠ° Π² ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌ ΡΠ°ΠΉΠ»Π΅)
renderInventory() {
const grid = document.getElementById('inventoryGrid');
grid.innerHTML = '';
// Π€ΠΈΠ»ΡΡΡΠ°ΡΠΈΡ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠΎΠ² ΠΏΠΎ ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π²ΠΊΠ»Π°Π΄ΠΊΠ΅
const filteredItems = this.currentFilter === 'all'
? this.items
: this.items.filter(item => item.type === this.currentFilter);
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ»ΠΎΡΠΎΠ² Π΄Π»Ρ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠΎΠ²
for (let i = 0; i < 24; i++) {
const slot = document.createElement('div');
slot.className = 'wg-inventory-slot';
slot.dataset.index = i;
// ΠΡΠ»ΠΈ Π² ΡΡΠΎΠΌ ΡΠ»ΠΎΡΠ΅ Π΅ΡΡΡ ΠΏΡΠ΅Π΄ΠΌΠ΅Ρ
const item = filteredItems.find(item => item.slotIndex === i);
if (item) {
slot.innerHTML = `
<div class="wg-item" data-id="${item.id}" draggable="true">
<img src="${item.icon}" alt="${item.name}">
${item.quantity > 1 ? `<span class="wg-item-quantity">${item.quantity}</span>` : ''}
${item.equipped ? '<span class="wg-item-equipped">E</span>' : ''}
</div>
`;
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΏΠ΅ΡΠ΅ΡΠ°ΡΠΊΠΈΠ²Π°Π½ΠΈΡ
this.setupDragAndDrop(slot.querySelector('.wg-item'));
}
grid.appendChild(slot);
}
}
setupDragAndDrop(itemElement) {
itemElement.addEventListener('dragstart', (e) => {
this.draggedItem = this.items.find(item => item.id === itemElement.dataset.id);
e.dataTransfer.setData('text/plain', itemElement.dataset.id);
setTimeout(() => {
itemElement.classList.add('dragging');
}, 0);
});
itemElement.addEventListener('dragend', () => {
itemElement.classList.remove('dragging');
this.draggedItem = null;
});
}
setupEventListeners() {
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π²ΠΊΠ»Π°Π΄ΠΎΠΊ
document.querySelectorAll('.wg-tab-button').forEach(button => {
button.addEventListener('click', () => {
document.querySelector('.wg-tab-button.active').classList.remove('active');
button.classList.add('active');
this.currentFilter = button.dataset.tab;
this.renderInventory();
});
});
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠ»ΠΎΡΠΎΠ² Π΄Π»Ρ ΠΏΡΠΈΠ΅ΠΌΠ° ΠΏΠ΅ΡΠ΅ΡΠ°ΡΠΊΠΈΠ²Π°Π΅ΠΌΡΡ
ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠΎΠ²
document.querySelectorAll('.wg-inventory-slot').forEach(slot => {
slot.addEventListener('dragover', (e) => {
e.preventDefault();
slot.classList.add('drag-over');
});
slot.addEventListener('dragleave', () => {
slot.classList.remove('drag-over');
});
slot.addEventListener('drop', async (e) => {
e.preventDefault();
slot.classList.remove('drag-over');
if (this.draggedItem) {
const targetIndex = parseInt(slot.dataset.index);
// ΠΡΠ·ΠΎΠ² ΠΌΠ΅ΡΠΎΠ΄Π° Π΄Π²ΠΈΠΆΠΊΠ° Π΄Π»Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΠ΅Π½ΠΈΡ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ°
await engine.call('moveInventoryItem', {
itemId: this.draggedItem.id,
targetSlot: targetIndex
});
}
});
// ΠΡΠ±ΠΎΡ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ° ΠΏΡΠΈ ΠΊΠ»ΠΈΠΊΠ΅
slot.addEventListener('click', () => {
const itemElement = slot.querySelector('.wg-item');
if (itemElement) {
const itemId = itemElement.dataset.id;
this.selectItem(itemId);
}
});
});
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΊΠ½ΠΎΠΏΠΎΠΊ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ
document.getElementById('btnSort').addEventListener('click', () => this.sortItems());
document.getElementById('btnStack').addEventListener('click', () => this.stackItems());
document.getElementById('btnDrop').addEventListener('click', () => this.dropSelectedItem());
document.getElementById('btnUse').addEventListener('click', () => this.useSelectedItem());
document.getElementById('btnEquip').addEventListener('click', () => this.equipSelectedItem());
}
selectItem(itemId) {
this.selectedItem = this.items.find(item => item.id === itemId);
this.showItemDetails();
}
showItemDetails() {
if (!this.selectedItem) return;
document.getElementById('itemName').textContent = this.selectedItem.name;
document.getElementById('itemType').textContent = this.selectedItem.type;
document.getElementById('itemImage').src = this.selectedItem.icon;
document.getElementById('itemDescription').textContent = this.selectedItem.description;
// ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Ρ
Π°ΡΠ°ΠΊΡΠ΅ΡΠΈΡΡΠΈΠΊ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ°
const statsContainer = document.getElementById('itemStats');
statsContainer.innerHTML = '';
if (this.selectedItem.stats) {
Object.entries(this.selectedItem.stats).forEach(([key, value]) => {
const statElement = document.createElement('div');
statElement.className = 'wg-item-stat';
statElement.innerHTML = `<span class="wg-stat-name">${key}:</span> <span class="wg-stat-value">${value}</span>`;
statsContainer.appendChild(statElement);
});
}
// ΠΠΎΠΊΠ°Π·Π°ΡΡ/ΡΠΊΡΡΡΡ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ°
document.getElementById('btnUse').style.display =
['consumable', 'potion', 'scroll'].includes(this.selectedItem.type) ? 'block' : 'none';
document.getElementById('btnEquip').style.display =
['weapon', 'armor', 'accessory'].includes(this.selectedItem.type) ? 'block' : 'none';
document.getElementById('btnEquip').textContent =
this.selectedItem.equipped ? 'Π‘Π½ΡΡΡ' : 'ΠΠΊΠΈΠΏΠΈΡΠΎΠ²Π°ΡΡ';
// ΠΠΎΠΊΠ°Π·Π°ΡΡ ΠΏΠ°Π½Π΅Π»Ρ Π΄Π΅ΡΠ°Π»Π΅ΠΉ
document.getElementById('itemDetails').classList.add('visible');
}
updateInventoryStats() {
const totalWeight = this.items.reduce((sum, item) => sum + (item.weight || 0) * (item.quantity || 1), 0);
const usedSlots = this.items.length;
document.getElementById('currentWeight').textContent = totalWeight.toFixed(1);
document.getElementById('usedSlots').textContent = usedSlots;
}
async sortItems() {
await engine.call('sortInventory', { criteria: 'type' });
}
async stackItems() {
await engine.call('stackInventoryItems');
}
async dropSelectedItem() {
if (!this.selectedItem) return;
if (confirm(`ΠΡ ΡΠ²Π΅ΡΠ΅Π½Ρ, ΡΡΠΎ Ρ
ΠΎΡΠΈΡΠ΅ Π²ΡΠ±ΡΠΎΡΠΈΡΡ ${this.selectedItem.name}?`)) {
await engine.call('dropInventoryItem', { itemId: this.selectedItem.id });
this.selectedItem = null;
document.getElementById('itemDetails').classList.remove('visible');
}
}
async useSelectedItem() {
if (!this.selectedItem) return;
await engine.call('useInventoryItem', { itemId: this.selectedItem.id });
}
async equipSelectedItem() {
if (!this.selectedItem) return;
await engine.call('toggleEquipItem', { itemId: this.selectedItem.id });
}
}
Π‘ΠΈΡΡΠ΅ΠΌΠ° Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²
ΠΡΠΈΠΌΠ΅Ρ HTML-ΡΡΡΡΠΊΡΡΡΡ Π΄Π»Ρ ΡΠΈΡΡΠ΅ΠΌΡ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ² Ρ NPC:
<div class="wg-dialog-system">
<div class="wg-dialog-portrait">
<img id="npcPortrait" src="npc/merchant.png" alt="NPC">
<div class="wg-dialog-name" id="npcName">Π’ΠΎΡΠ³ΠΎΠ²Π΅Ρ</div>
</div>
<div class="wg-dialog-content">
<div class="wg-dialog-text" id="dialogText">
ΠΡΠΈΠ²Π΅ΡΡΡΠ²ΡΡ ΡΠ΅Π±Ρ, ΠΏΡΡΠ½ΠΈΠΊ! Π§ΡΠΎ ΠΏΡΠΈΠ²Π΅Π»ΠΎ ΡΠ΅Π±Ρ Π² Π½Π°Ρ Π³ΠΎΡΠΎΠ΄?
</div>
<div class="wg-dialog-options" id="dialogOptions">
<!-- ΠΠ°ΡΠΈΠ°Π½ΡΡ ΠΎΡΠ²Π΅ΡΠΎΠ² Π±ΡΠ΄ΡΡ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈ -->
</div>
</div>
</div>
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π΄ΠΈΠ°Π»ΠΎΠ³Π°ΠΌΠΈ:
class DialogSystem {
constructor() {
this.currentDialog = null;
this.dialogHistory = [];
this.npcData = null;
this.initialize();
}
async initialize() {
// ΠΠΎΠ΄ΠΏΠΈΡΠΊΠ° Π½Π° ΡΠΎΠ±ΡΡΠΈΡ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
engine.subscribe('dialogStarted', (data) => {
this.startDialog(data.npcId, data.dialogId);
});
engine.subscribe('dialogEnded', () => {
this.endDialog();
});
}
async startDialog(npcId, dialogId) {
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ
NPC ΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
this.npcData = await engine.call('getNpcData', { npcId });
this.currentDialog = await engine.call('getDialogData', { dialogId });
// ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΎ NPC
document.getElementById('npcPortrait').src = this.npcData.portrait;
document.getElementById('npcName').textContent = this.npcData.name;
// ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
this.displayDialogNode(this.currentDialog.startNode);
// ΠΠΎΠΊΠ°Π·Π°ΡΡ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ
document.querySelector('.wg-dialog-system').classList.add('visible');
}
displayDialogNode(nodeId) {
const node = this.currentDialog.nodes.find(n => n.id === nodeId);
if (!node) return;
// ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΠ° Π΄ΠΈΠ°Π»ΠΎΠ³Π°
document.getElementById('dialogText').textContent = node.text;
// ΠΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΠΎΡΠ²Π΅ΡΠΎΠ²
const optionsContainer = document.getElementById('dialogOptions');
optionsContainer.innerHTML = '';
node.options.forEach(option => {
// ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠ»ΠΎΠ²ΠΈΠΉ Π΄Π»Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π²Π°ΡΠΈΠ°Π½ΡΠ° ΠΎΡΠ²Π΅ΡΠ°
if (option.condition && !this.checkCondition(option.condition)) {
return;
}
const optionElement = document.createElement('div');
optionElement.className = 'wg-dialog-option';
optionElement.textContent = option.text;
optionElement.addEventListener('click', () => {
this.selectOption(option);
});
optionsContainer.appendChild(optionElement);
});
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΠ° "ΠΡΡ
ΠΎΠ΄" Π΅ΡΠ»ΠΈ ΡΡΠΎ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ ΡΠ·Π΅Π»
if (node.isEnd || node.options.length === 0) {
const exitOption = document.createElement('div');
exitOption.className = 'wg-dialog-option wg-dialog-exit';
exitOption.textContent = 'ΠΠ°Π²Π΅ΡΡΠΈΡΡ ΡΠ°Π·Π³ΠΎΠ²ΠΎΡ';
exitOption.addEventListener('click', () => {
this.endDialog();
});
optionsContainer.appendChild(exitOption);
}
// ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΡ ΡΠ΅ΠΊΡΡΠ°
wgAnimate.animate(document.getElementById('dialogText'), {
opacity: [0, 1]
}, {
duration: 300,
easing: 'ease-out'
});
// ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΡ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΠΎΡΠ²Π΅ΡΠΎΠ²
wgAnimate.animate(optionsContainer.children, {
opacity: [0, 1],
transform: ['translateY(10px)', 'translateY(0)']
}, {
duration: 300,
delay: (el, i) => 100 + i * 50,
easing: 'ease-out'
});
}
checkCondition(condition) {
// ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠ»ΠΎΠ²ΠΈΡ ΡΠ΅ΡΠ΅Π· Π΄Π²ΠΈΠΆΠΎΠΊ
return engine.call('checkDialogCondition', { condition });
}
async selectOption(option) {
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΡΠ±ΠΎΡΠ° Π² ΠΈΡΡΠΎΡΠΈΡ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
this.dialogHistory.push({
text: option.text,
timestamp: Date.now()
});
// ΠΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ, ΡΠ²ΡΠ·Π°Π½Π½ΡΡ
Ρ Π²ΡΠ±ΠΎΡΠΎΠΌ
if (option.actions) {
for (const action of option.actions) {
await engine.call('executeDialogAction', { action });
}
}
// ΠΠ΅ΡΠ΅Ρ
ΠΎΠ΄ ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ ΡΠ·Π»Ρ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
if (option.nextNode) {
this.displayDialogNode(option.nextNode);
} else {
this.endDialog();
}
}
endDialog() {
// Π‘ΠΊΡΡΡΠΈΠ΅ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π°
document.querySelector('.wg-dialog-system').classList.remove('visible');
// Π‘Π±ΡΠΎΡ Π΄Π°Π½Π½ΡΡ
Π΄ΠΈΠ°Π»ΠΎΠ³Π°
this.currentDialog = null;
// Π£Π²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅ Π΄Π²ΠΈΠΆΠΊΠ° ΠΎ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
engine.call('dialogCompleted', {
npcId: this.npcData.id,
history: this.dialogHistory
});
// Π‘Π±ΡΠΎΡ ΠΈΡΡΠΎΡΠΈΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³Π°
this.dialogHistory = [];
this.npcData = null;
}
}
// ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠΈΡΡΠ΅ΠΌΡ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²
const dialogSystem = new DialogSystem();
Π‘ΡΠΈΠ»ΠΈΠ·Π°ΡΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
Wudgine ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ CSS ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Π΄Π»Ρ Π»Π΅Π³ΠΊΠΎΠΉ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ Π²ΠΈΠ΄Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²:
:root {
/* ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΡΠ²Π΅ΡΠ° */
--wg-primary-color: #4a90e2;
--wg-secondary-color: #5a6268;
--wg-danger-color: #e25c5c;
--wg-success-color: #5ce25c;
--wg-warning-color: #e2c25c;
--wg-info-color: #5ccde2;
/* Π¦Π²Π΅ΡΠ° ΡΠ΅ΠΊΡΡΠ° */
--wg-text-color: #ffffff;
--wg-text-color-secondary: #b8b8b8;
--wg-text-color-disabled: #6c757d;
/* Π€ΠΎΠ½ΠΎΠ²ΡΠ΅ ΡΠ²Π΅ΡΠ° */
--wg-bg-color: #1e2124;
--wg-bg-color-light: #2c3035;
--wg-bg-color-lighter: #3a3f44;
/* ΠΡΠ°Π½ΠΈΡΡ */
--wg-border-color: #3a3f44;
--wg-border-radius: 4px;
/* Π’Π΅Π½ΠΈ */
--wg-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
/* Π Π°Π·ΠΌΠ΅ΡΡ ΡΡΠΈΡΡΠΎΠ² */
--wg-font-size-small: 12px;
--wg-font-size-normal: 14px;
--wg-font-size-large: 16px;
--wg-font-size-xlarge: 20px;
}
Π‘Π»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ
ΠΠΎΡΠ»Π΅ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ² ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅:
- ΠΠ΄Π°ΠΏΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½Π½ΡΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ ΠΏΠΎΠ΄ ΡΠ²ΠΎΠΈ Π½ΡΠΆΠ΄Ρ
- ΠΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠΎΠ²Π°ΡΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ»ΠΎΠΆΠ½ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²
- Π‘ΠΎΠ·Π΄Π°ΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΡΡΠΈΠ»ΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ CSS ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
- ΠΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Ρ ΠΈΠ³ΡΠΎΠ²ΠΎΠΉ Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ ΡΠ΅ΡΠ΅Π· JavaScript API
ΠΠ»Ρ Π±ΠΎΠ»Π΅Π΅ ΡΠ»ΠΎΠΆΠ½ΡΡ
ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ React ΠΈΠ»ΠΈ Vue.js, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°ΡΡ Ρ Wudgine.