简体   繁体   中英

How do you add an annotation to a website without altering the layout?

I'm working on a hobby project similar to markup.io where you can load in any website and annotate it. I can't figure out how to add an annotation that behaves like it does in markup.io:

  • Doesn't interrupt the styling or layout of the website you are annotating
  • The annotation keeps the correct position when scrolling and resizing the window

From what I can see they place an absolute positioned div inside the element that you clicked on. From my understanding by reading the docs that div would position itself based on the closest positioned ancestor. How would you calculate the correct top and left values to position the annotation to where the user clicked? Is there a better way to do this?

I'm using React if that matters.

Things that I have tried:

  1. Append the following bit of html to the element that was clicked:
<div style="width:0px; height:0px; position:relative;">
<div style="width:50px;height:50px;position:absolute; ">this is the annotation </div> 
</div>

Problem: This would mess with the page layout because of the relative positioned div that is not ignored by the document flow.

  1. Create fixed overlay over the entire page. Get the css selector of the clicked element. Draw annotation on the fixed overlay at the x,y position of the element.

Problem: Whenever the user would scroll or resize the window the annotation would need to be redrawn at the new position of the element. I used getBoundintClientRect to get the new position and this would cause a reflow and caused the whole website to have severe perfomance issues when dealing with 100+ annotations.

Hopefully someone can point me in the right direction!

The general idea is as follows:

  1. Find the parent of the element that you clicked on
  2. Check if they are positioned (anything other than static)
  3. If it is static search for the closest element that is positioned.
  4. Set the new badge/annotation top and left position to that of the mouse minus the top and left of the element that you're going to append it to (in this case called parent).
  5. Also account for the width and height by subtracting half of each to perfectly center your annotation.
 // In my case I put the webpage in an Iframe. If this is your own page 
 // you can just use document.   
 iframe.contentWindow.document.addEventListener(
                'click',
                (e: MouseEvent) => {
// step 1: find the parent.
                  let parent = e.target.parentElement;
                  let computedStyle = window.getComputedStyle(parent);

// step 2 & 3: Look up the first positioned element and make this the
// the element that you're going to append your badge/annotation to.
                  while (
                    computedStyle.position === 'static' &&
                    parent.parentElement !== null
                  ) {
                    parent = parent.parentElement;
                    computedStyle = window.getComputedStyle(parent);
                  }

// style the annotation the way you want to
                  const badge = document.createElement('div');               

                  const { top, left } = parent.getBoundingClientRect();
                 
                  badge.style.position = 'absolute';

// step 4 and 5 get the mouse position through e.clientX and Y and 
// subtract the appropriate value like below to place it exactly at the mouse position
                  badge.style.top = `${e.clientY - top - 5}px`;
                  badge.style.left = `${e.clientX - left - 5}px`;

                  badge.style.backgroundColor = 'red';
                  badge.style.width = '10px';
                  badge.style.height = '10px';
                  badge.style.borderRadius = '50%';
                  badge.style.zIndex = '9999';
                  parent.appendChild(badge);
                }
              );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM