Recrearea butonului Arduino folosind SVG și <element-lit>
Publicat: 2022-03-10În acest articol, veți învăța cum să construiți componente HTML personalizate care imită obiecte fizice, cum ar fi butonul Arduino. Vom desena componenta în Inkscape de la zero, vom optimiza codul SVG generat pentru web și o vom împacheta ca componentă web de sine stătătoare folosind biblioteca
lit-element
ușoare, acordând o atenție sporită aspectelor privind accesibilitatea și utilizarea mobilă. Astăzi, vă voi ghida prin călătoria creării unei componente HTML care imită o componentă de buton de moment, care este folosită în mod obișnuit cu Arduino și în proiectele electronice. Vom folosi tehnologii precum SVG, Web Components și lit-element
și vom învăța cum să facem butonul accesibil prin intermediul unor trucuri JavaScript-CSS.
Să începem!
De la Arduino la HTML: Necesitatea unei componente de buton
Înainte de a începe călătoria, haideți să explorăm ce vom crea și, mai important, de ce. Creez un simulator Arduino open-source în JavaScript numit avr8js. Acest simulator este capabil să execute cod Arduino și îl voi folosi într-o serie de tutoriale și cursuri care îi învață pe creatori cum să programeze pentru Arduino.
Simulatorul în sine are grijă doar de execuția programului - rulează instrucțiunea de cod cu instrucțiune și își actualizează starea internă și un buffer de memorie conform logicii programului. Pentru a interacționa cu programul Arduino, trebuie să creați niște componente electronice virtuale care să trimită intrare la simulator sau să reacționeze la ieșirile acestuia.
Rularea singur a simulatorului este foarte asemănătoare cu rularea JavaScript izolat. Nu puteți interacționa cu adevărat cu utilizatorul decât dacă creați și unele elemente HTML și le conectați la codul JavaScript prin DOM.
Astfel, pe lângă simulatorul procesorului, mai lucrez la o bibliotecă de componente HTML care imită hardware-ul fizic, începând cu primele două componente pe care le vei găsi în aproape orice proiect de electronică: un LED și un buton.

LED-ul este relativ simplu, deoarece are doar două stări de ieșire: pornit și oprit. În culise, folosește un filtru SVG pentru a crea efectul de iluminare.
Butonul este mai interesant. Are și două stări, dar trebuie să reacționeze la intrarea utilizatorului și să își actualizeze starea în consecință și de aici vine provocarea, așa cum vom vedea în curând. Dar, mai întâi, să definim cerințele din componenta noastră pe care urmează să o creăm.
Definirea cerințelor pentru butonul de apăsare
Componenta noastră va semăna cu un buton de 12 mm. Aceste butoane sunt foarte comune în kiturile de pornire electronice și vin cu capace în mai multe culori, așa cum puteți vedea în fotografia de mai jos:

În ceea ce privește comportamentul, butonul ar trebui să aibă două stări: apăsat și eliberat. Acestea sunt similare cu evenimentele mousedown/mouseup HTML, dar trebuie să ne asigurăm că butoanele pot fi folosite și de pe dispozitive mobile și sunt accesibile utilizatorilor fără mouse.
Deoarece vom folosi starea butonului ca intrare pentru Arduino, nu este nevoie să acceptăm evenimentele „clic” sau „dublu clic”. Este la latitudinea programului Arduino care rulează în simulare să decidă cum să acționeze asupra stării butonului, iar butoanele fizice nu generează evenimente de clic.
Dacă doriți să aflați mai multe, consultați o discuție pe care am ținut-o cu Benjamin Gruenbaum la SmashingConf Freiburg în 2019: „Anatomy of a Click”.
Pentru a rezuma cerințele noastre, butonul nostru trebuie să:
- arata similar cu butonul fizic de 12 mm;
- au două stări distincte: apăsat și eliberat și ar trebui să fie vizibile;
- să susțină interacțiunea cu mouse-ul, dispozitivele mobile și să fie accesibilă utilizatorilor de tastatură;
- acceptă diferite culori pentru capac (cel puțin roșu, verde, albastru, galben, alb și negru).
Acum că am definit cerințele, putem începe să lucrăm la implementare.
SVG pentru victorie
Majoritatea componentelor web sunt implementate folosind o combinație de CSS și HTML. Când avem nevoie de grafice mai complexe, de obicei folosim imagini raster, fie în format JPG, fie PNG (sau GIF dacă simțiți nostalgic).
În cazul nostru, însă, vom folosi o altă abordare: grafica SVG. SVG se pretează la grafice complexe mult mai ușor decât CSS (da, știu, poți crea lucruri fascinante cu CSS, dar asta nu înseamnă că ar trebui). Dar nu vă faceți griji, nu renunțăm complet la CSS. Ne va ajuta să stilăm butoanele și, în cele din urmă, chiar să le facem accesibile.
SVG are un alt mare avantaj, în comparație cu imaginile grafice raster: este foarte ușor de manipulat din JavaScript și poate fi stilat prin CSS. Aceasta înseamnă că putem oferi o singură imagine pentru buton și putem folosi JavaScript pentru a personaliza limita de culoare, iar stilurile CSS pentru a indica starea butonului. Frumos, nu-i așa?
În cele din urmă, SVG este doar un document XML, care poate fi editat cu editori de text și încorporat direct în HTML, făcându-l o soluție perfectă pentru crearea de componente HTML reutilizabile. Ești gata să ne desenezi butonul?
Desenarea butonului cu Inkscape
Inkscape este instrumentul meu preferat pentru crearea de grafică vectorială SVG. Este gratuit și plin de funcții puternice, cum ar fi o colecție mare de presetări de filtru încorporate, urmărire bitmap și operații binare de cale. Am început să folosesc Inkscape pentru a crea artă PCB, dar în ultimii doi ani, am început să îl folosesc pentru majoritatea sarcinilor mele de editare grafică.
Desenarea butonului în Inkscape este destul de simplă. Vom desena o ilustrare de sus a butonului și a celor patru cabluri metalice ale acestuia care îl conectează la alte părți, după cum urmează:
- Dreptunghi gri închis de 12×12 mm pentru carcasa din plastic, cu colțuri ușor rotunjite pentru a o face mai moale.
- Mai mic, dreptunghi gri deschis 10,5×10,5 pentru capacul metalic.
- Patru cercuri mai întunecate, câte unul în fiecare colț pentru ace care țin butonul împreună.
- Un cerc mare în mijloc, adică conturul șapei nasturii.
- Un cerc mai mic în mijloc pentru partea de sus a capacului cu nasturi.
- Patru dreptunghiuri gri deschis în formă de „T” pentru firele metalice ale butonului.
Și rezultatul, ușor mărit:
Ca o atingere finală, vom adăuga niște magie gradient SVG la conturul butonului, pentru a-i oferi o senzație 3D:
Iată-ne! Avem imaginile, acum trebuie să le aducem pe web.
De la Inkscape la Web SVG
După cum am menționat mai sus, SVG-urile sunt destul de simplu de încorporat în HTML - puteți doar să lipiți conținutul fișierului SVG în documentul dvs. HTML, să îl deschideți într-un browser și va fi redat pe ecran. Îl puteți vedea în acțiune în următorul exemplu CodePen:
Vedeți butonul Pen SVG în HTML de @Uri Shaked
Cu toate acestea, fișierele SVG salvate din Inkscape conțin o mulțime de bagaje inutile, cum ar fi versiunea Inkscape și poziția ferestrei când ați salvat ultima dată fișierul. În multe cazuri, există, de asemenea, elemente goale, gradienți și filtre neutilizate și toate măresc dimensiunea fișierului și îngreunează lucrul cu acesta în HTML.
Din fericire, Inkscape poate curăța cea mai mare parte a mizeriei pentru noi. Iată cum o faci:
- Accesați meniul Fișier și faceți clic pe Curățare document . (Acest lucru va elimina definițiile neutilizate din documentul dvs.)
- Mergeți din nou la Fișier și faceți clic pe Salvare ca... . Când salvați, selectați SVG optimizat ( *.svg ) în meniul derulant Salvare ca tip .
- Veți vedea un dialog „Ieșire SVG optimizată” cu trei file. Verificați toate opțiunile, cu excepția „Păstrează datele editorului”, „Păstrează definițiile fără referință” și „Păstrează ID-urile create manual…”.

Eliminarea tuturor acestor lucruri va crea un fișier SVG mai mic, cu care este mai ușor de lucrat. În cazul meu, fișierul a trecut de la 4593 de octeți la doar 2080 de octeți, mai puțin de jumătate din dimensiune. Pentru fișierele SVG mai complexe, aceasta poate reprezenta o economie uriașă de lățime de bandă și poate face o diferență notabilă în timpul de încărcare a paginii dvs. web.
SVG-ul optimizat este, de asemenea, mult mai ușor de citit și de înțeles. În următorul fragment, ar trebui să puteți identifica cu ușurință cele două dreptunghiuri care formează corpul butonului:
<rect width="12" height="12" rx=".44" ry=".44" fill="#464646" stroke-width="1.0003"/> <rect x=".75" y=".75" width="10.5" height="10.5" rx=".211" ry=".211" fill="#eaeaea"/> <g fill="#1b1b1b"> <circle cx="1.767" cy="1.7916" r=".37"/> <circle cx="10.161" cy="1.7916" r=".37"/> <circle cx="10.161" cy="10.197" r=".37"/> <circle cx="1.767" cy="10.197" r=".37"/> </g> <circle cx="6" cy="6" r="3.822" fill="url(#a)"/> <circle cx="6" cy="6" r="2.9" fill="#ff2a2a" stroke="#2f2f2f" stroke-opacity=".47" stroke-width=".08"/>
Puteți scurta și mai mult codul, de exemplu, schimbând lățimea cursei primului dreptunghi de la 1.0003
la doar 1
. Nu face o diferență semnificativă în dimensiunea fișierului, dar face codul mai ușor de citit.
În general, o trecere manuală peste fișierul SVG generat este întotdeauna utilă. În multe cazuri, puteți elimina grupurile goale sau puteți aplica transformări matrice, precum și simplifica coordonatele gradientului prin maparea lor de la „spațiu utilizator în utilizare” (coordonate globale) la „caseta de delimitare a obiectului” (relativ la obiect). Aceste optimizări sunt opționale, dar obțineți cod care este mai ușor de înțeles și de întreținut.
Din acest moment, vom lăsa Inkscape deoparte și vom lucra cu reprezentarea text a imaginii SVG.
Crearea unei componente web reutilizabile
Până acum, am primit grafica pentru butonul nostru, gata să fie inserată în simulatorul nostru. Putem personaliza cu ușurință culoarea butonului schimbând atributul de fill
al cercului mai mic și culoarea de început a gradientului cercului mai mare.
Următorul nostru obiectiv este să transformăm butonul nostru într-o componentă web reutilizabilă, care poate fi personalizată prin transmiterea unui atribut de color
și reacționează la interacțiunea utilizatorului (evenimente de presă/lansare). Vom folosi lit-element
, o bibliotecă mică care simplifică crearea de componente web.
lit-element
excelează în crearea de biblioteci de componente mici, de sine stătătoare. Este construit pe baza standardului Web Components, care permite ca aceste componente să fie consumate de orice aplicație web, indiferent de cadrul utilizat: Angular, React, Vue sau Vanilla JS ar putea folosi componenta noastră.
Crearea componentelor în lit-element
se face folosind o sintaxă bazată pe clasă, cu o metodă render()
care returnează codul HTML pentru element. Un pic asemănător cu React, dacă ești familiarizat cu el. Cu toate acestea, spre deosebire de react, lit-element
folosește literale de șablon etichetate Javascript standard pentru a defini conținutul componentei.
Iată cum ați crea o componentă simplă hello-world
:
import { customElement, html, LitElement } from 'lit-element'; @customElement('hello-world') export class HelloWorldElement extends LitElement { render() { return html` <h1> Hello, World! </h1> `; } }
Această componentă poate fi apoi utilizată oriunde în codul HTML, pur și simplu scriind <hello-world></hello-world>
.
Notă : De fapt, butonul nostru necesită doar puțin mai mult cod: trebuie să declarăm o proprietate de intrare pentru culoare, folosind @property()
(și cu o valoare implicită de roșu) și să lipim codul SVG în render()
, înlocuind culoarea capacului butonului cu valoarea proprietății culoare (vezi exemplu). Biții importanți sunt în linia 5, unde definim proprietatea culorii: @property() color = 'red';
De asemenea, în linia 35 (unde folosim această proprietate pentru a defini culoarea de umplere pentru cercul care face capacul butonului), folosind sintaxa literală a șablonului JavaScript, scrisă ca ${color}
:

<circle cx="6" cy="6" r="2.9" fill="${color}" stroke="#2f2f2f" stroke-opacity=".47" stroke-width=".08" />
Fă-l interactiv
Ultima piesă a puzzle-ului ar fi să faci butonul interactiv. Există două aspecte pe care trebuie să le luăm în considerare: răspunsul vizual la interacțiune, precum și răspunsul programatic la interacțiune.
Pentru partea vizuală, putem inversa pur și simplu umplerea în gradient a conturului butonului, ceea ce va crea iluzia că butonul a fost apăsat:
Gradientul pentru conturul butonului este definit de următorul cod SVG, unde ${color}
este înlocuit cu culoarea butonului prin lit-element
, așa cum s-a explicat mai sus:
<linearGradient x1="0" x2="1" y1="0" y2="1"> <stop stop-color="#ffffff" offset="0" /> <stop stop-color="${color}" offset="0.3" /> <stop stop-color="${color}" offset="0.5" /> <stop offset="1" /> </linearGradient>
O abordare pentru aspectul butonului apăsat ar fi să definiți un al doilea gradient, să inversați ordinea culorilor și să îl folosiți ca umplere a cercului ori de câte ori butonul este apăsat. Cu toate acestea, există un truc frumos care ne permite să reutilizam același gradient: putem roti elementul svg cu 180 de grade folosind o transformare SVG:
<circle cx="6" cy="6" r="3.822" fill="url(#a)" transform="rotate(180 6 6)" />
Atributul de transform
îi spune SVG că vrem să rotim cercul cu 180 de grade și că rotația ar trebui să aibă loc în jurul punctului (6, 6) care este centrul cercului (definit de cx
și cy
). Transformările SVG afectează, de asemenea, umplerea formei și astfel și gradientul nostru va fi rotit.
Vrem să inversăm gradientul doar atunci când butonul este apăsat, așa că în loc să adăugăm atributul de transform
direct pe elementul <circle>
, așa cum am făcut mai sus, de fapt vom seta o clasă CSS pentru acest element și apoi vom profita de faptul că atributele SVG pot fi setate prin CSS, deși folosind o sintaxă ușor diferită:
transform: rotate(180deg); transform-origin: 6px 6px;
Aceste două reguli CSS fac exact la fel ca transform
pe care am avut-o mai sus - rotiți cercul cu 180 de grade în jurul centrului său la (6, 6). Dorim ca aceste reguli să fie aplicate numai atunci când butonul este apăsat, așa că vom adăuga un nume de clasă CSS la cercul nostru:
<circle class="button-contour" cx="6" cy="6" r="3.822" fill="url(#a)" />
Și acum putem folosi pseudoclasa :active CSS pentru a aplica o transformare button-contour
ori de câte ori se face clic pe elementul SVG:
svg:active .button-contour { transform: rotate(180deg); transform-origin: 6px 6px; }
lit-element
ne permite să atașăm o foaie de stil la componenta noastră declarând-o într-un getter static în interiorul clasei noastre de componente, folosind un literal șablon etichetat:
static get styles() { return css` svg:active .button-contour { transform: rotate(180deg); transform-origin: 6px 6px; } `; }
La fel ca șablonul HTML, această sintaxă ne permite să injectăm valori personalizate în codul nostru CSS, chiar dacă nu avem nevoie de el aici. lit-element
are grijă, de asemenea, de a crea Shadow DOM pentru componenta noastră, astfel încât CSS-ul să afecteze doar elementele din componenta noastră și să nu afecteze alte părți ale aplicației.
Acum, cum rămâne cu comportamentul programatic al butonului atunci când este apăsat? Dorim să declanșăm un eveniment, astfel încât utilizatorii componentei noastre să poată înțelege ori de câte ori starea butonului se schimbă. O modalitate de a face acest lucru este să ascultați evenimentele mouse-down și mouse-up pe elementul SVG și să declanșați evenimentele „apăsare buton”/„eliberare buton” în mod corespunzător. Iată cum arată cu sintaxa lit-element
:
render() { const { color } = this; return html` <svg @mousedown=${() => this.dispatchEvent(new Event('button-press'))} @mouseup=${() => this.dispatchEvent(new Event('button-release'))} ... </svg> `; }
Cu toate acestea, aceasta nu este cea mai bună soluție, așa cum vom vedea în curând. Dar mai întâi, aruncați o privire rapidă la codul pe care l-am primit până acum:
import { customElement, css, html, LitElement, property } from 'lit-element'; @customElement('wokwi-pushbutton') export class PushbuttonElement extends LitElement { @property() color = 'red'; static get styles() { return css` svg:active .button-contour { transform: rotate(180deg); transform-origin: 6px 6px; } `; } render() { const { color } = this; return html` <svg @mousedown=${() => this.dispatchEvent(new Event('button-press'))} @mouseup=${() => this.dispatchEvent(new Event('button-release'))} width="18mm" height="12mm" version="1.1" viewBox="-3 0 18 12" xmlns="https://www.w3.org/2000/svg" > <defs> <linearGradient x1="0" x2="1" y1="0" y2="1"> <stop stop-color="#ffffff" offset="0" /> <stop stop-color="${color}" offset="0.3" /> <stop stop-color="${color}" offset="0.5" /> <stop offset="1" /> </linearGradient> </defs> <rect x="0" y="0" width="12" height="12" rx=".44" ry=".44" fill="#464646" /> <rect x=".75" y=".75" width="10.5" height="10.5" rx=".211" ry=".211" fill="#eaeaea" /> <g fill="#1b1b1"> <circle cx="1.767" cy="1.7916" r=".37" /> <circle cx="10.161" cy="1.7916" r=".37" /> <circle cx="10.161" cy="10.197" r=".37" /> <circle cx="1.767" cy="10.197" r=".37" /> </g> <g fill="#eaeaea"> <path d="m-0.3538 1.4672c-0.058299 0-0.10523 0.0469-0.10523 0.10522v0.38698h-2.1504c-0.1166 0-0.21045 0.0938-0.21045 0.21045v0.50721c0 0.1166 0.093855 0.21045 0.21045 0.21045h2.1504v0.40101c0 0.0583 0.046928 0.10528 0.10523 0.10528h0.35723v-1.9266z" /> <path d="m-0.35376 8.6067c-0.058299 0-0.10523 0.0469-0.10523 0.10523v0.38697h-2.1504c-0.1166 0-0.21045 0.0939-0.21045 0.21045v0.50721c0 0.1166 0.093855 0.21046 0.21045 0.21046h2.1504v0.401c0 0.0583 0.046928 0.10528 0.10523 0.10528h0.35723v-1.9266z" /> <path d="m12.354 1.4672c0.0583 0 0.10522 0.0469 0.10523 0.10522v0.38698h2.1504c0.1166 0 0.21045 0.0938 0.21045 0.21045v0.50721c0 0.1166-0.09385 0.21045-0.21045 0.21045h-2.1504v0.40101c0 0.0583-0.04693 0.10528-0.10523 0.10528h-0.35723v-1.9266z" /> <path d="m12.354 8.6067c0.0583 0 0.10523 0.0469 0.10523 0.10522v0.38698h2.1504c0.1166 0 0.21045 0.0938 0.21045 0.21045v0.50721c0 0.1166-0.09386 0.21045-0.21045 0.21045h-2.1504v0.40101c0 0.0583-0.04693 0.10528-0.10523 0.10528h-0.35723v-1.9266z" /> </g> <g> <circle class="button-contour" cx="6" cy="6" r="3.822" fill="url(#a)" /> <circle cx="6" cy="6" r="2.9" fill="${color}" stroke="#2f2f2f" stroke-opacity=".47" stroke-width=".08" /> </g> </svg> `; } }
- Vezi demonstrația →
Puteți face clic pe fiecare dintre butoane și puteți vedea cum reacționează. Cel roșu are chiar și niște ascultători de evenimente (definiți în index.html ), așa că atunci când dați clic pe el ar trebui să vedeți câteva mesaje scrise pe consolă. Dar stai, ce se întâmplă dacă vrei să folosești tastatura?
Faceți componenta accesibilă și prietenoasă cu dispozitivele mobile
Ura! Am creat o componentă de buton reutilizabilă cu SVG și lit-element
!
Înainte de a ne semna activitatea, există câteva probleme pe care ar trebui să le analizăm. În primul rând, butonul nu este accesibil persoanelor care folosesc tastatura. În plus, comportamentul pe mobil este inconsecvent - butoanele apar apăsate atunci când țineți degetul pe ele, dar evenimentele JavaScript nu sunt declanșate dacă țineți degetul mai mult de o secundă.
Să începem prin a aborda problema tastaturii. Am putea face butonul accesibil de la tastatură adăugând un atribut tabindex la elementul svg, făcându-l focalizat. O alternativă mai bună, în opinia mea, este doar să înfășurați butonul cu un element standard <button>
. Folosind elementul standard, îl facem să se joace frumos cu cititoare de ecran și alte tehnologii de asistență.
Această abordare are un dezavantaj, după cum puteți vedea mai jos:

<button>
. (Previzualizare mare) Elementul <button>
vine cu un stil încorporat. Acest lucru ar putea fi rezolvat cu ușurință prin aplicarea unor CSS pentru a elimina aceste stiluri:
button { border: none; background: none; padding: 0; margin: 0; text-decoration: none; -webkit-appearance: none; -moz-appearance: none; } button:active .button-contour { transform: rotate(180deg); transform-origin: 6px 6px; }
Rețineți că am înlocuit și selectorul care inversează grila conturului butoanelor, folosind button:active
în locul svg:active
. Acest lucru asigură că stilul apăsat de buton se aplică ori de câte ori este apăsat elementul <button>
real, indiferent de dispozitivul de intrare utilizat.
Putem chiar face componenta noastră mai prietenoasă cu cititorul de ecran, adăugând un atribut aria-label
care include culoarea butonului:
<button aria-label="${color} pushbutton">
Mai este încă un lucru de abordat: evenimentele „apăsare buton” și „eliberare buton”. În mod ideal, vrem să le declanșăm pe baza pseudoclasei CSS :active a butonului, la fel cum am făcut în CSS-ul de mai sus. Cu alte cuvinte, am dori să declanșăm evenimentul „apăsare buton” ori de câte ori butonul devine :active
, iar evenimentul „eliberare buton” să se declanșeze ori de câte ori este :not(:active)
.
Dar cum asculți o pseudo-clasă CSS din Javascript?
Se pare că nu este atât de simplu. Am pus această întrebare comunității JavaScript Israel și, în cele din urmă, am dezgropat o idee care a funcționat din firul nesfârșit: utilizați selectorul :active
pentru a declanșa o animație CSS foarte scurtă și apoi o pot asculta din JavaScript folosind animationstart
eveniment.
Un experiment rapid CodePen a dovedit că acesta funcționează de fapt în mod fiabil. Oricât de mult mi-a plăcut rafinamentul acestei idei, am decis să merg cu o soluție diferită, mai simplă. Evenimentul animationstart
nu este disponibil pe Edge și iOS Safari, iar declanșarea unei animații CSS doar pentru detectarea schimbării stării butonului nu pare a fi modul corect de a face lucrurile.
În schimb, vom adăuga trei perechi de ascultători de evenimente la elementul <button>
: mousedown/mouseup pentru mouse, touchstart/touchend pentru dispozitive mobile și keyup/keydown pentru tastatură. Nu este cea mai elegantă soluție, după părerea mea, dar face șmecheria și funcționează pe toate browserele.
<button aria-label="${color} pushbutton" @mousedown=${this.down} @mouseup=${this.up} @touchstart=${this.down} @touchend=${this.up} @keydown=${(e: KeyboardEvent) => e.keyCode === SPACE_KEY && this.down()} @keyup=${(e: KeyboardEvent) => e.keyCode === SPACE_KEY && this.up()} >
Unde SPACE_KEY
este o constantă care este egală cu 32, iar up
/ down
sunt două metode de clasă care trimit evenimentele button-press
a button-release
:
@property() pressed = false; private down() { if (!this.pressed) { this.pressed = true; this.dispatchEvent(new Event('button-press')); } } private up() { if (this.pressed) { this.pressed = false; this.dispatchEvent(new Event('button-release')); } }
- Puteți găsi codul sursă complet aici.
Am reusit!
A fost o călătorie destul de lungă care a început cu conturarea cerințelor și desenarea ilustrației pentru butonul în Inkscape, a trecut prin conversia fișierului nostru SVG într-o componentă web reutilizabilă folosind lit-element
și, după ce ne-am asigurat că este accesibil și prietenos cu dispozitivele mobile, ne-am a ajuns cu aproape 100 de linii de cod ale unei componente încântătoare de buton virtual.
Acest buton este doar o singură componentă dintr-o bibliotecă open-source de componente electronice virtuale pe care o construiesc. Sunteți invitat să aruncați o privire la codul sursă sau să consultați Cartea de povești online, unde puteți vedea și interacționa cu toate componentele disponibile.
Și, în sfârșit, dacă sunteți interesat de Arduino, aruncați o privire la cursul de programare Simon pentru Arduino pe care îl construiesc în prezent, unde puteți vedea și butonul în acțiune.
Până data viitoare, atunci!