Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds
Powrót do kolekcji
Przewodnik11 min czytania

Excalidraw, szkice odręczne i biblioteka MIT

Excalidraw to tablica z odręcznym stylem i biblioteka React na licencji MIT. Osadzanie, samodzielny hosting, wersja płatna i porównanie z tldraw.

Excalidraw, szkice odręczne i biblioteka MIT

Excalidraw to tablica do rysowania diagramów, której charakterystyczną cechą jest odręczny styl kresek, oraz biblioteka Reacta pozwalająca osadzić ten sam edytor we własnej aplikacji. Bieżąca wersja pakietu nosi numer 0.18, licencja to MIT.

Warto rozdzielić dwie rzeczy noszące tę samą nazwę, bo mylenie ich prowadzi do złych wniosków. Otwarta biblioteka i darmowa tablica dostępna pod adresem publicznym to jedno. Płatna usługa z zapleczem, kontami i zarządzaniem zespołem to drugie.

Odręczny styl to nie jest ozdobnik

Wygląd kresek wygląda na decyzję estetyczną i jest decyzją funkcjonalną, wartą zrozumienia przed wyborem narzędzia.

Diagram narysowany precyzyjnymi liniami wygląda na skończony. Ten sam diagram w stylu odręcznym wygląda na szkic. Różnica dotyczy tego, jak ludzie na niego reagują: przy szkicu łatwiej powiedzieć „a może inaczej", przy dopracowanym rysunku pojawia się opór przed podważaniem czegoś, co ktoś najwyraźniej dopracował.

Przy projektowaniu architektury, omawianiu przepływu i wspólnym myśleniu ta cecha pracuje na Twoją korzyść. Przy prezentacji dla zarządu albo dokumentacji, która ma wyglądać poważnie, pracuje przeciwko i wtedy właściwym wyborem jest narzędzie o innym charakterze.

To jest zresztą główne kryterium przy wyborze między tym narzędziem a alternatywami: nie liczba funkcji, tylko to, na jakim etapie rozmowy diagram powstaje.

Osadzanie we własnej aplikacji

Biblioteka jest komponentem Reacta i osadza się w kilku linijkach.

Code
TypeScript
import { Excalidraw } from '@excalidraw/excalidraw'
import '@excalidraw/excalidraw/index.css'

export function Tablica() {
  return (
    <div style={{ height: '100vh' }}>
      <Excalidraw
        initialData={{ elements: zapisaneElementy }}
        onChange={(elementy) => zapisz(elementy)}
      />
    </div>
  )
}

Trzy rzeczy sprawiają najwięcej kłopotu przy pierwszym podejściu.

Arkusz stylów trzeba zaimportować osobno. Bez niego komponent renderuje się i wygląda na rozsypany, co łatwo pomylić z błędem konfiguracji budowania.

Kontener musi mieć określoną wysokość. Płótno rozciąga się do rodzica, więc w elemencie o wysokości automatycznej dostaje zero pikseli i znika.

W Next.js dochodzi trzecia rzecz: komponent odwołuje się do obiektów przeglądarki przy montowaniu, więc renderowanie po stronie serwera trzeba wyłączyć, ładując go dynamicznie.

Code
TypeScript
import dynamic from 'next/dynamic'

const Excalidraw = dynamic(
  () => import('@excalidraw/excalidraw').then((m) => m.Excalidraw),
  { ssr: false, loading: () => <Szkielet /> }
)

Bez tego pojawia się błąd o niezdefiniowanym obiekcie okna, wyrzucany podczas budowania, a nie w przeglądarce, przez co łatwo szukać przyczyny w niewłaściwym miejscu.

Stan rysunku to zwykła tablica obiektów, którą zapisujesz gdzie chcesz. Nie ma tu zaplecza narzucanego przez bibliotekę, więc trwałość, wersjonowanie i uprawnienia projektujesz sam, tak jak przy każdych innych danych w aplikacji.

Współpraca i samodzielny hosting

To jest miejsce, w którym warto uważać, bo materiały bywają mylące.

Uruchomienie samego edytora jako kontenera daje działającą tablicę bez współpracy. Rysujesz, zapisujesz lokalnie, koniec.

Współpraca wielu osób wymaga osobnego składnika, czyli serwera pokojów przekazującego zmiany między klientami. To jest drugi kontener i druga rzecz do utrzymania, o czym poradniki opisujące jednopolecenowe uruchomienie zwykle nie wspominają.

Praktyczna konsekwencja: jeśli chodzi Ci wyłącznie o narzędzie do rysowania, samodzielne uruchomienie jest proste. Jeśli chodzi o wspólną pracę w firmie, licz się z dwoma usługami plus konfiguracją nazw domenowych i certyfikatów.

Warto też wiedzieć, że dane rysunku przy publicznej wersji są szyfrowane po stronie przeglądarki, więc serwer pośredniczący nie widzi treści. To jest sensowna właściwość, natomiast nie zastępuje kontroli dostępu: kto ma odnośnik, ten ma dostęp, a odnośnik zawiera klucz.

Wersja płatna i co ona daje

Płatna usługa kosztuje 7 dolarów miesięcznie za osobę przy rozliczeniu miesięcznym i 6 dolarów przy rocznym, po dwutygodniowym okresie próbnym. To jedyna pozycja z jawną ceną: oferta dla dużych firm istnieje, ale kwot dostawca nie publikuje i kieruje do rozmowy handlowej.

Dostajesz w niej rzeczy, których biblioteka nie ma z natury: konta, przechowywanie rysunków w chmurze, foldery, rozmowy głosowe, udostępnianie ekranu i funkcje wspomagane modelem.

Warto rozstrzygnąć, czy tego potrzebujesz, bo odpowiedź bywa negatywna częściej, niż sugeruje strona z cennikiem. Zespół, który rysuje diagramy podczas rozmowy i wkleja wyniki do dokumentacji, obejdzie się darmową wersją. Zespół, który traktuje tablice jako trwałe artefakty z historią i uprawnieniami, potrzebuje zaplecza, więc wybór jest między tą usługą a zbudowaniem tego samemu na bibliotece.

Ta druga droga bywa sensowna właśnie dlatego, że licencja jest w pełni otwarta. Zbudowanie zaplecza z listą rysunków, uprawnieniami i wyszukiwaniem to praca na kilka dni, a przy wymogu trzymania danych we własnej infrastrukturze bywa jedyną opcją.

Do czego to się naprawdę nadaje

Warto wymienić konkretne zastosowania, bo „tablica do rysowania" nie mówi nic o tym, kiedy sięgnąć.

Diagram architektury podczas rozmowy. Trzy prostokąty, dwie strzałki i podpisy powstają szybciej niż otwarcie narzędzia z paletą gotowych kształtów, a rozmowa toczy się dalej zamiast czekać.

Szkic interfejsu przed jego zbudowaniem. Odręczny styl działa tu podwójnie: rysuje się szybko i nikomu nie przychodzi do głowy, że to już projekt do zaakceptowania.

Wyjaśnienie w zgłoszeniu błędu. Zrzut ekranu z dorysowanymi strzałkami i podpisami mówi więcej niż akapit opisu, a wklejenie obrazka do zgłoszenia zajmuje sekundy.

Materiały dydaktyczne. Diagram wyjaśniający przepływ danych albo strukturę katalogów wygląda przystępnie właśnie dlatego, że nie wygląda na oficjalny dokument.

Do czego się nie nadaje: schematy wymagające precyzji, rysunki techniczne ze skalą, diagramy generowane z kodu oraz wszystko, co ma powstawać automatycznie. Przy diagramach opisywanych tekstem i renderowanych przy budowaniu dokumentacji właściwym narzędziem jest generator, a nie edytor graficzny, bo tamten wersjonuje się jak kod.

Biblioteki kształtów i rozszerzanie

Poza podstawowymi kształtami dostępne są zestawy gotowych elementów, które warto znać, zanim zaczniesz rysować ikony ręcznie.

Biblioteki to zbiory elementów do wielokrotnego użytku: ikony chmur, symbole sieciowe, elementy interfejsu. Dodaje się je do edytora i przeciąga na płótno, a własną bibliotekę da się zbudować z narysowanych elementów i udostępnić zespołowi jako plik.

Ten ostatni scenariusz bywa niedoceniany. Zespół, który rysuje diagramy architektury tych samych systemów co tydzień, po zbudowaniu własnego zestawu kształtów przestaje rysować od zera i zaczyna składać, a diagramy stają się przy okazji spójne między osobami.

Rozszerzanie samego edytora jest tu skromniejsze niż w narzędziach, których osią jest rozbudowywalność. Można podmienić elementy interfejsu, dołożyć własne przyciski i sterować edytorem programistycznie, natomiast dodanie zupełnie nowego typu kształtu z własną logiką nie jest tym, do czego ta biblioteka została zaprojektowana.

To jest kolejny element odróżniający ją od bogatszych rozwiązań i zarazem powód, dla którego wpina się szybciej. Mniej możliwości oznacza mniej decyzji do podjęcia przy osadzaniu.

Excalidraw kontra alternatywy

NarzędzieLicencjaStylKiedy wybrać
ExcalidrawMIT, bez kluczaOdręcznySzkice, osadzanie w produkcie, budżet zerowy
tldrawWłasna, klucz wymaganyCzystyPłótno jest sercem produktu i masz budżet
Narzędzia do diagramówZamknięta, płatnaPrecyzyjnyDokumentacja, która ma wyglądać oficjalnie
Tablice w chmurzeZamknięta, za osobęDopracowanyKupujesz produkt, a nie budujesz

Pierwsze dwa wiersze to dziś najważniejsze porównanie i różnica przesunęła się wyraźnie. tldraw wprowadził wymóg klucza licencyjnego w wersjach produkcyjnych, więc osadzenie go w produkcie komercyjnym wiąże się z opłatą. Ta biblioteka pozostała na licencji MIT, bez klucza i bez znaku wodnego.

To nie znaczy, że jest lepsza. tldraw daje bogatszy system własnych kształtów i narzędzi, więc przy produkcie, w którym płótno jest głównym interfejsem, ta różnica bywa warta swojej ceny. Przy tablicy dołożonej obok głównej funkcji aplikacji trudno uzasadnić rachunek, skoro darmowa alternatywa robi to samo.

Trzeci wiersz warto rozważyć uczciwie. Diagram, który trafi do oferty dla klienta albo do dokumentacji zgodności, wygląda lepiej narysowany precyzyjnie, i to jest właśnie ten przypadek, w którym odręczny styl przeszkadza.

Sterowanie edytorem z kodu

Osadzenie komponentu to początek, a większość realnych zastosowań wymaga rozmawiania z nim programistycznie.

Komponent udostępnia obiekt sterujący, przez który odczytujesz bieżące elementy, podmieniasz zawartość płótna, przewijasz do wybranego miejsca i zmieniasz tryb pracy. To wystarcza do zbudowania rzeczy, które użytkownik odbiera jako funkcje aplikacji, a nie jako możliwości tablicy.

Typowe przykłady: przycisk wstawiający na płótno diagram wygenerowany z danych, przełącznik między trybem edycji a podglądem, zapis rysunku do własnego zaplecza przy każdej zmianie z opóźnieniem, wczytanie szablonu przy tworzeniu nowego dokumentu.

Przy zapisie obowiązuje ta sama zasada co przy każdym edytorze reagującym na zmiany: nasłuch odpala się bardzo często, w tym przy każdej klatce przeciągania elementu, więc zapis bez opóźnienia oznacza kilkadziesiąt zapisów na sekundę.

Code
TypeScript
const [api, ustawApi] = useState<ExcalidrawImperativeAPI | null>(null)

const zapiszZOpoznieniem = useMemo(
  () => debounce((elementy: readonly ExcalidrawElement[]) => {
    fetch('/api/tablica', {
      method: 'PUT',
      body: JSON.stringify({ elementy })
    })
  }, 1000),
  []
)

<Excalidraw
  excalidrawAPI={ustawApi}
  onChange={(elementy) => zapiszZOpoznieniem(elementy)}
/>

Opóźnienie rzędu sekundy od ostatniej zmiany rozwiązuje to raz. Obiekt sterujący odbierasz przez właściwość podającą go w wywołaniu zwrotnym, a nie przez referencję, i to jest rzecz, na której potyka się większość osób przy pierwszym podejściu.

Warto też wiedzieć, że stan rysunku to zwykła struktura danych, więc da się go tworzyć i modyfikować bez udziału edytora.

Code
TypeScript
import { convertToExcalidrawElements } from '@excalidraw/excalidraw'

const elementy = convertToExcalidrawElements([
  { type: 'rectangle', x: 0, y: 0, width: 180, height: 80, id: 'api' },
  { type: 'rectangle', x: 300, y: 0, width: 180, height: 80, id: 'baza' },
  {
    type: 'arrow',
    x: 190, y: 40,
    width: 100, height: 0,
    start: { id: 'api' },
    end: { id: 'baza' }
  }
])

api?.updateScene({ elements: elementy })

Funkcja pomocnicza uzupełnia pola, których nie podałeś, wartościami domyślnymi, więc nie musisz znać pełnego kształtu elementu. Generowanie diagramu z opisu w kodzie i podanie go jako zawartość początkowa to droga, która przy dokumentacji automatycznej bywa lepsza niż rysowanie ręczne.

Eksport i wpięcie w dokumentację

Rysunek da się wyeksportować do obrazu rastrowego, do formatu wektorowego oraz do własnego formatu zachowującego możliwość dalszej edycji.

Wybór między nimi ma znaczenie praktyczne większe, niż wygląda. Obraz rastrowy jest wygodny i nieedytowalny, więc poprawka po miesiącu oznacza rysowanie od nowa. Format wektorowy skaluje się bez utraty ostrości i nadaje do dokumentacji, natomiast też nie wraca do edytora.

Właściwa praktyka to trzymanie obu: pliku źródłowego w repozytorium obok dokumentacji i wyeksportowanego obrazu wstawionego do tekstu. Wtedy poprawka po pół roku jest otwarciem pliku, a nie rekonstrukcją rysunku z obrazka.

Warto też wiedzieć, że format wektorowy da się osadzić z zachowaniem danych źródłowych, więc jeden plik pełni obie role. To jest droga wygodna przy dokumentacji trzymanej w repozytorium.

Przy osadzaniu podglądu w aplikacji przydaje się tryb bez interfejsu, w którym komponent renderuje rysunek bez paska narzędzi. Diagram w dokumentacji technicznej wygląda wtedy jak obrazek, a mimo to zachowuje ostrość przy powiększeniu.

Typowe błędy

Pierwszy to pominięcie importu arkusza stylów. Komponent renderuje się rozsypany, a przyczyna wygląda na problem z narzędziem budującym.

Drugi to kontener bez określonej wysokości. Płótno dostaje zero pikseli i wygląda, jakby komponent się nie zamontował.

Trzeci to renderowanie po stronie serwera bez wyłączenia. Komponent wywala się przy montowaniu na odwołaniu do obiektu przeglądarki.

Czwarty to oczekiwanie współpracy po uruchomieniu samego edytora. Wymiana zmian między osobami wymaga osobnego serwera pokojów, który jest drugim składnikiem.

Piąty to traktowanie szyfrowania odnośnika jako kontroli dostępu. Kto ma odnośnik, ten ma dostęp, bo klucz jest jego częścią.

Szósty to zapisywanie wyłącznie eksportu do obrazu. Poprawka po miesiącu oznacza wtedy rysowanie diagramu od nowa, zamiast otwarcia pliku źródłowego.

Siódmy to zapis przy każdej zmianie bez opóźnienia. Nasłuch odpala się przy każdej klatce przeciągania elementu, więc przy większym rysunku daje to kilkadziesiąt zapisów na sekundę i zauważalne zacinanie.

FAQ

Czy Excalidraw jest darmowy?

Biblioteka i tablica dostępna pod publicznym adresem tak, na licencji MIT, bez klucza i bez znaku wodnego. Płatna jest osobna usługa z kontami, przechowywaniem w chmurze i funkcjami zespołowymi, kosztująca 7 dolarów miesięcznie za osobę albo 6 dolarów przy rozliczeniu rocznym.

Czy mogę osadzić to w produkcie komercyjnym?

Tak, licencja MIT nie stawia tu warunków ani nie wymaga klucza w wersji produkcyjnej. To jest obecnie główna różnica wobec tldraw, który od czwartej wersji wymaga licencji do użycia produkcyjnego.

Jak uruchomić to u siebie?

Sam edytor jest jednym kontenerem i daje działającą tablicę bez współpracy. Wymiana zmian między osobami wymaga dodatkowo serwera pokojów, czyli drugiego składnika, o czym poradniki opisujące jednopolecenowe uruchomienie zwykle nie wspominają.

Czy dane są bezpieczne w wersji publicznej?

Treść rysunku jest szyfrowana po stronie przeglądarki, więc serwer pośredniczący jej nie widzi. Nie zastępuje to kontroli dostępu, bo klucz jest częścią odnośnika, więc każdy, kto go otrzyma, otworzy rysunek.

Kiedy lepiej wybrać coś innego?

Gdy diagram ma wyglądać oficjalnie, bo odręczny styl przeszkadza w dokumentacji dla klienta. Oraz gdy płótno jest głównym interfejsem Twojego produktu i potrzebujesz rozbudowanego systemu własnych kształtów, bo tam tldraw daje więcej.

Dokumentacja biblioteki stoi na stronie dla programistów, a kod w repozytorium na GitHubie.