Generowanie obrazu przy użyciu html2canvas

Generowanie obrazu przy użyciu html2canvas
G8
  • Rejestracja:ponad 7 lat
  • Ostatnio:około rok
  • Postów:85
0

Mam w react-leaflet mapkę z markerami. Dodałem funcję, która robi raport PDF do każdego markera i chciałem na koniec raportu dodać obraz przedstawiający kawałek mapki z tym jednym markerem, którego dotyczy raport. Problem mam z wygenerowaniem tego obrazu. Próbuję to zrobić przy pomocy html2canvas. Nie chcę w żaden sposób wyświetlać tego kawałka mapy na ekranie bo za jednym kliknięciem może generować się nawet kilkaset raportów. W const map mam ten kawałek mapy ale dostaję 

Kopiuj
index.ts:36 Uncaught (in promise) Error: Element is not attached to a Document
    at index.ts:36:1
    at step (tslib.es6.js:102:1)
    at Object.next (tslib.es6.js:83:1)
    at tslib.es6.js:76:1
    at new Promise (<anonymous>)
    at __awaiter (tslib.es6.js:72:1)
    at renderElement (index.ts:29:1)
    at html2canvas (index.ts:20:1)
    at savePDF (App.js:160:1)
    at App.js:127:1
(anonymous) @ index.ts:36
step @ tslib.es6.js:102
(anonymous) @ tslib.es6.js:83
(anonymous) @ tslib.es6.js:76
__awaiter @ tslib.es6.js:72
renderElement @ index.ts:29
html2canvas @ index.ts:20
savePDF @ App.js:160
(anonymous) @ App.js:127
await in (anonymous) (async)
(anonymous) @ App.js:127
Promise.then (async)
downloadPDFs @ App.js:124
onClick @ App.js:241
handleClick @ index.es.js:5283
callCallback @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4291
executeDispatch @ react-dom.development.js:9041
processDispatchQueueItemsInOrder @ react-dom.development.js:9073
processDispatchQueue @ react-dom.development.js:9086
dispatchEventsForPlugins @ react-dom.development.js:9097
(anonymous) @ react-dom.development.js:9288
batchedUpdates$1 @ react-dom.development.js:26140
batchedUpdates @ react-dom.development.js:3991
dispatchEventForPluginEventSystem @ react-dom.development.js:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:6465
dispatchEvent @ react-dom.development.js:6457
dispatchDiscreteEvent @ react-dom.development.js:6430
api.js:46 
Kopiuj
const savePDF = async (pdfName, images, details) => {
    const bounds = [
      [-3000, -3000],
      [3000, 3000],
    ];
  
    const map = (
      <div id="map-container" style={{display: 'none'}}>
        <MapContainer
          crs={L.CRS.Simple}
          bounds={bounds}
          center={details.locationOnDrawing} 
          zoom={13} 
          scrollWheelZoom={false}
        >
          <ImageOverlay
            url={currDrawing}
            bounds={bounds}
          >
            <Marker position={details.locationOnDrawing} />
          </ImageOverlay>
        </MapContainer>
      </div>
    );

    const input = document.getElementById("map-container");
    const canvas = await html2canvas(input);
    const imgData = canvas.toDataURL("image/jpg")
    console.log(imgData)
   

    const doc = (
      <PDF photos={images} map={imgData} details={details}/>
    );

    const pdfBlob =  await pdf(doc).toBlob();

    // Save the PDF blob as file
    saveAs(pdfBlob, pdfName);
  }

Widziałem podobne przykłady wykorzystania html2canvas ale różnica była taka, że elementy, z których były generowane obrazy były renderowane a ja mam tutaj JSX, z którym się nic nie dzieje. Nie wiem czy w tym problem...

edytowany 3x, ostatnio: Glt87
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:13 minut
  • Postów:8406
1

index.ts:36 Uncaught (in promise) Error: Element is not attached to a Document

No tutaj ci pisze błąd. Pytanie, co z tym zrobisz.

a ja mam tutaj JSX

Ale do czego jest to JSX transpilowane? Bo jak rozumiem, to nie jest React?

Chociaż w sumie w stosie wywołań masz funkcje reactowe, to już nie rozumiem.


edytowany 1x, ostatnio: LukeJL
Zobacz pozostały 1 komentarz
LukeJL
a co przyjmuje funkcja pdf? Bo w takim razie podajesz tam element Reacta (czyli w sumie czyste dane, na podstawie których React dopiero jest w stanie utworzyć obiekt DOM). To może mieć sens, ale nie musi (zależy czy funkcja pdf oczekuje właśnie elementu Reacta czy nie. Bo jeśli oczekuje elementu DOM, to nie zadziała w ten sposób)
G8
Z generowaniem pdf wszystko działa. Component PDF jest zaimportowany ale nie skopiowałem importów. Problem jest tylko z wygenerowaniem obrazu z const map.
LukeJL
ale gdzie używasz tego map? We wklejonym kodzie tylko przypisujesz JSX do tego map, ale dalej nic z tym nie robisz. może nie wkleiłeś całości?
G8
Nie używam go nigdzie. Chciałbym żeby z tego wygenerować ten obraz ale niestety tak to z tego co widzę nie działa. Wszystkie przykłady użycia html2canvas jakie znalazłem dotyczyły tworzenia obrazu z elementów widocznych na ekranie. Nie wiem jak to zrobić, jeśli nie chce tej mapki wyświetlać na ekranie
LukeJL
Zwróć uwagę, że jak masz JSX, to są tylko elementy Reacta, czyli reprezentacja obiektów na potrzeby Reacta. Żeby zrobić z tego element DOM, musiałbyś to najpierw wyrenderowac za pomocą pakietu react-dom. Tak jak już to (zapewne) robisz ze swoim głównym komponentem w aplikacji.
G1
  • Rejestracja:około 4 lata
  • Ostatnio:4 dni
  • Postów:506
1

html musi zostać wygenerowany. Stwórz sobie diva, wyślij go poza obszar ekranu, wygeneruj pdf i usuń diva.

G8
  • Rejestracja:ponad 7 lat
  • Ostatnio:około rok
  • Postów:85
0

Tak jak mówiliście, html musiał zostać wygenerowany. Wykorzysałem mapkę która już była wygenerowana z tym, że po kliknięciu 'wygeneruj pdf' renderuje się tylko jeden marker, dla danego pdf, po skończeniu przekazuje do renderowania kolejny marker i w momencie gdy wszystkie pdfy mam gotowe, wyświetlają się ponownie wszystkie naraz.

Daje też to fajny efekt wizualny, jak jest informacja Exporting to pdf... i pojawiają się i znikają kolejne markery.

Dzięki.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)