reiji-h 2 лет назад
Родитель
Сommit
464943077f
1 измененных файлов с 54 добавлено и 31 удалено
  1. 54 31
      apps/app/src/components/PageEditor/ScrollSyncHelperTest.ts

+ 54 - 31
apps/app/src/components/PageEditor/ScrollSyncHelperTest.ts

@@ -20,8 +20,12 @@
 // fn: (args) => {return list[args] < 5}
 // output: 4
 
-let topY = 0;
-const padding = 0;
+let defaultTop = 0;
+const padding = 5;
+
+const getDataLineIndex = (previewElement: Element): number => {
+  return +(previewElement.getAttribute('data-line') ?? '0') - 1;
+};
 
 const getEditorElements = (editorRootElement: HTMLElement): Array<Element> => {
   return Array.from(editorRootElement.getElementsByClassName('cm-line'));
@@ -50,68 +54,87 @@ const elementBinarySearch = (list: Array<Element>, fn: (index: number) => boolea
 const findTopElementIndex = (elements: Array<Element>): number => {
 
   const find = (index: number): boolean => {
-    return elements[index].getBoundingClientRect().y < topY + padding;
+    return elements[index].getBoundingClientRect().top < defaultTop + padding;
   };
 
   return elementBinarySearch(elements, find);
 };
 
-const findTopElement = (elements: Array<Element>): Element => {
-  return elements[findTopElementIndex(elements)];
-};
-
-const findPreviewElement = (previewElements: Array<Element>, editorElementLine: number): Element => {
+const findPreviewElementIndex = (previewElements: Array<Element>, editorElementLineIndex: number): number => {
 
   const find = (index: number): boolean => {
-    const data = +(previewElements[index].getAttribute('data-line') ?? '0');
-    return data <= editorElementLine;
+    const data = getDataLineIndex(previewElements[index]);
+    return data <= editorElementLineIndex;
   };
 
-  return previewElements[elementBinarySearch(previewElements, find)];
+  return elementBinarySearch(previewElements, find);
 };
 
-
 const calcScrollElementToTop = (element: Element): number => {
-  return element.getBoundingClientRect().y - (topY + padding);
+  return element.getBoundingClientRect().top - (defaultTop + padding);
 };
 
-const calcScorllElementByRatio = (sourceElement: Element, targetElement: Element): number => {
-  // console.log('calc raito');
-  // console.log(sourceElement.getBoundingClientRect());
-  // console.log(targetElement.getBoundingClientRect());
-  return 0;
+type SourceElement = {
+  start: Element,
+  top: Element,
+  next: Element | undefined,
+}
+
+type TargetElement = {
+  start: Element,
+  next: Element | undefined,
+}
+
+const calcScorllElementByRatio = (sourceElement: SourceElement, targetElement: TargetElement): number => {
+  if (sourceElement.start === sourceElement.next || sourceElement.next == null || targetElement.next == null) {
+    return 0;
+  }
+  const sourceAllHeight = sourceElement.next.getBoundingClientRect().top - sourceElement.start.getBoundingClientRect().top;
+  const sourceUseHeight = sourceElement.top.getBoundingClientRect().top - sourceElement.start.getBoundingClientRect().top;
+  const sourceTopHeight = defaultTop + padding - sourceElement.top.getBoundingClientRect().top;
+  const sourceRaito = (sourceUseHeight + sourceTopHeight) / sourceAllHeight;
+
+  const targetAllHeight = targetElement.next.getBoundingClientRect().top - targetElement.start.getBoundingClientRect().top;
+
+  return targetAllHeight * sourceRaito;
 };
 
 export const scrollEditor = (editorRootElement: HTMLElement, previewRootElement: HTMLElement): void => {
 
-  topY = editorRootElement.getBoundingClientRect().y;
+  defaultTop = editorRootElement.getBoundingClientRect().top;
 
   const editorElements = getEditorElements(editorRootElement);
   const previewElements = getPreviewElements(previewRootElement);
 
   const topEditorElementIndex = findTopElementIndex(editorElements);
+  const targetPreviewElementIndex = findPreviewElementIndex(previewElements, topEditorElementIndex);
 
-  const sourceEditorElement = editorElements[topEditorElementIndex];
-  const targetPreviewElement = findPreviewElement(previewElements, topEditorElementIndex + 1);
+  const startEditorElementIndex = getDataLineIndex(previewElements[targetPreviewElementIndex]);
+  const nextEditorElementIndex = getDataLineIndex(previewElements[targetPreviewElementIndex + 1]);
 
   let newScrollTop = previewRootElement.scrollTop;
-  newScrollTop += calcScrollElementToTop(targetPreviewElement);
-  newScrollTop += calcScorllElementByRatio(sourceEditorElement, targetPreviewElement);
-
-
-  console.log(previewRootElement.scrollTop, newScrollTop);
-  previewRootElement.scrollTo({ top: newScrollTop, behavior: 'smooth' });
 
-  // console.log(topEditorElement);
-  // console.log(topEditorElement.getBoundingClientRect());
-  // console.log(editorRootElement.scrollTop);
+  newScrollTop += calcScrollElementToTop(previewElements[targetPreviewElementIndex]);
+  newScrollTop += calcScorllElementByRatio(
+    {
+      start: editorElements[startEditorElementIndex],
+      top: editorElements[topEditorElementIndex],
+      next: editorElements[nextEditorElementIndex],
+    },
+    {
+      start: previewElements[targetPreviewElementIndex],
+      next: previewElements[targetPreviewElementIndex + 1],
+    },
+  );
+
+  previewRootElement.scrollTop = newScrollTop;
 
 };
 
 
 export const scrollPreview = (editorRootElement: HTMLElement, previewRootElement: HTMLElement): void => {
 
-  // topY = previewRootElement.getBoundingClientRect().y;
+  // defaultTop = previewRootElement.getBoundingClientRect().y;
 
   // const previewElements = getPreviewElements(previewRootElement);