javascript – React Native View Peak and Peak of a div inside an internet view

0
1
javascript – React Native View Peak and Peak of a div inside an internet view


I do know the title isnt clear however what im basically attempting to do is do my very own rendering for an EPUB and im presently taking a naive strategy in the direction of paginating the chapter content material and attempting to render it in a WebView after splitting the content material primarily based on the tags.

My problem begins from the purpose the place i can’t appear to precisely cut up the content material to suit into the web page, and it overflows within the rendered internet view.

I’ve a separate internet view which renders off display screen and calculates the scrollHeight of the div the place the content material is being injected in.

The web page is principally constructed block by block (tag by tag) till the div begins to overflow and the peak of the div is bigger than the View that its rendered to.

The pagination perform yields the content material gathered simply earlier than the peak is exceeded.

The issue is that it by no means suits to display screen and there’s all the time a little bit of vertical overflow left.

My goal is to in the end generate an inventory of animated WebViews the consumer can scroll via horizontally like an precise web page flip of a e book.

I might actually admire some assist in figuring out the logic or calculation flaw right here within the format top comparisons. Let me know if ive missed one thing.

Under is the react native part which does the pagination and rendering

import { EPUBChapter, epubHtmlTemplate, ParsedEPUB } from "@/lib/EpubParser";
import { useEffect, useRef, useState } from "react";
import { parseDocument, DomUtils } from "htmlparser2";
import render from "dom-serializer";
import { WebView } from "react-native-webview";
import { Textual content } from "./ui/textual content";
import { useHtmlHeightMeasurer } from "@/hooks/useHtmlHeightMeasurer";
import { View, PixelRatio, FlatList } from "react-native";

export perform WebViewCarousel({
  parsedEpub,
  currentChapterIndex = 0,
}: {
  parsedEpub: ParsedEPUB;
  currentChapterIndex: quantity;
}) {
  const chapters = parsedEpub.chapters;
  const [currentChapter, setCurrentChapter] = useState(
    undefined
  );
  const view = useRef(null);
  // const { html } = useHtmlHeightMeasurer(viewDimensions.width, viewDimensions.top);
  const { measureHtmlHeight, MeasuringWebView, resizeWebView } =
    useHtmlHeightMeasurer(355, 355);
  const [pages, setPages] = useState([]);

  async perform* pageGenerator(
    chapterHtml: string,
    dimensions: { width: quantity; top: quantity }
  ) {
    resizeWebView({ top: dimensions.width, width: dimensions.top });
    const parsedChapterHtml = parseDocument(chapterHtml);
    const htmlNodes = parsedChapterHtml.kids;
    let pageNodes: typeof parsedChapterHtml.kids = [];
    const chapterContent = DomUtils.findOne(
      (elem) => elem.title === "part",
      htmlNodes
    );
    // const pixelHeight = PixelRatio.getPixelSizeForLayoutSize(dimensions.top);
    const pixelHeight = dimensions.top;


    if (chapterContent) {
      for (const [index, node] of chapterContent.kids.entries()) {
        const testPage = render([...pageNodes, node]);
        // console.log('Node: ' + render(node));
        if (testPage.trim()) {
          const webViewHeight = await measureHtmlHeight(
            epubHtmlTemplate(testPage)
          );
          console.log("View top: " + pixelHeight);
          console.log("Measured Peak: " + webViewHeight);
          if (webViewHeight >= pixelHeight) {
            console.log("Yielding Web page");
            
            yield pageNodes;
            pageNodes = [];
          }

          pageNodes.push(node);
        }
      }
    }

    console.log("Last web page");
    return pageNodes;
  }

  // const generatePage = pageGenerator(chapters[currentChapterIndex].content material);

  async perform generatePages({
    width,
    top,
  }: {
    width: quantity;
    top: quantity;
  }) {
    const pagesToAdd = [];

    for await (const web page of pageGenerator(
      chapters[currentChapterIndex].content material,
      { width, top }
    )) {
      console.log(render(web page));
      pagesToAdd.push(render(web page));
    }

    setPages([...pages, ...pagesToAdd]);
  }

  return (
     {
        generatePages({
          top: e.nativeEvent.format.top,
          width: e.nativeEvent.format.width,
        });
      }}
    >
      
      {pages.size > 0 && (
        
      )}
    
  );
}

The offscreen part used to measure the content material till it overflows

import { epubHtmlTemplate } from "@/lib/EpubParser";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { WebView } from "react-native-webview";

const measureJs = `
  (() => {
    const observer = new MutationObserver(measure)
    let debounce;
    
    perform measure() {
      clearTimeout(debounce);
      debounce = setTimeout(() => {
        strive {
          const container = doc.getElementById('epub-content');
          if(container) {
            const top = container.scrollHeight;
            window.ReactNativeWebView.postMessage(JSON.stringify({
              kind: 'measurement',
              worth: top
            }));
          } else {
            window.ReactNativeWebView.postMessage(JSON.stringify({
              kind: 'error',
              worth: 'Lacking container with id epub-content'
            }));
          }
        } catch (error) {
          window.ReactNativeWebView.postMessage(JSON.stringify({
            kind: 'error',
            worth: error.message
          }));
        }
      }, 150);
    }

    observer.observe(doc.physique, { 
      childList: true, 
      subtree: true,
      attributes: true
    });

    measure();
  })()
`;

export perform useHtmlHeightMeasurer(width: quantity, top: quantity) {
  const [html, setHtml] = useState("");
  const resolver = useRef<(h: quantity) => void>();
  const webViewRef = useRef(null);
  const [webViewDimensions, setWebViewDimensions] = useState({
    top: 0,
    width: 0
  });

  const measureHtmlHeight = (htmlString: string) =>
    new Promise((resolve) => {
      resolver.present = resolve;
      setHtml(htmlString);
    });
  
  const resizeWebView = ({ width, top }: { width: quantity, top: quantity }) => {
    setWebViewDimensions({ width, top })
  }

  const MeasuringWebView = () => (
    
       {
          const knowledge = JSON.parse(occasion.nativeEvent.knowledge);
          if(knowledge.kind === 'error') {
            console.error(knowledge.worth)
          }
          if (knowledge.kind === "measurement") {
            const h = Quantity(knowledge.worth);
            if (resolver.present) {
              resolver.present(h);
              resolver.present = undefined;
            }
          }
        }}
        fashion={{ width: webViewDimensions.width, top: webViewDimensions.top, backgroundColor: "clear" }}
      />
    
  );

  return { measureHtmlHeight, MeasuringWebView, resizeWebView };
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here