Ju99ernaut / grapesjs-rulers

Rulers and guides for grapesjs designer mode
MIT License
37 stars 14 forks source link

Cursor Tracking in Editor #7

Closed leo-paz closed 3 years ago

leo-paz commented 3 years ago

Hi @Ju99ernaut,

Please forgive my laziness but I wrote up an issue on the GrapesJS repo describing a weird offset when I try to modify the plugin to also have rulers along the cursor. Would be greatful if you can point me in the right direction.

Thank you in advance!

Ju99ernaut commented 3 years ago

Seems like the canvas' mouse events are interfering with the mouse events for tracking the cursor, so I'm not sure what kind of solution would work best.

Ju99ernaut commented 3 years ago

This is the code responsible for tracking the cursor, if there's a solution to improve the tracking I'll be happy to merge it.

https://github.com/Ju99ernaut/grapesjs-rulers/blob/9aa43f8d6f28084d33ed360fbb174b83c9769595/src/ruler.js#L416-L446

azatkama commented 3 years ago

Hello @Ju99ernaut , I think need to use screenX/screenY instead of clientX/clientY here const posX = e.clientX; const posY = e.clientY;

Ju99ernaut commented 3 years ago

According to this explanation, I don't think screenX/screenY would be the best solution.

img

azatkama commented 3 years ago

ok, thanks, but with zoom when cursor moves from .gjs-cv-canvas to inner iframe clientX would be 0 again maybe need to find .gjs-cv-canvas__frames parent of iframe and use left of this block too if cursor on iframe

azatkama commented 3 years ago

works fine with next changes


        run(editor) {
            !rulers && (rulers = new Ruler({
                container: editor.Canvas.getElement(),
                containerFrame: editor.Canvas.getFramesEl(),
                rulerHeight: rulH,
                strokeStyle: 'white',
                fillStyle: 'white',
                zoom,
                ...options.rulerOpts

const mousemove = (e) => {
      let posX = e.clientX;
      let posY = e.clientY;

      if (e.target.tagName === 'IFRAME') {
          posX = (posX * options.zoom / 100) + options.containerFrame.getBoundingClientRect().left;
          posY = (posY * options.zoom / 100) + options.containerFrame.getBoundingClientRect().top;
      }

      if (dimension === 2) {
          tracker.style.left = this.utils.pixelize(posX - options.container.getBoundingClientRect().left);
      } else {
          tracker.style.top = this.utils.pixelize(posY - options.container.getBoundingClientRect().top);
      }
  };```
Ju99ernaut commented 3 years ago

The tracker is still offset on my end. This seems to slightly improve the offset but from my understanding the main issue is with the iframe element having different clientX/Y values.

Ju99ernaut commented 3 years ago

Your solution is correct but I had missed the options.containerFrame part, so sorry about that. Here's the current solution, I'll probably move some stuff around but this is more or less the final solution:

        const mousemove = (e) => {
            let x = e.clientX, y = e.clientY,
                left = parseInt(options.container.getBoundingClientRect().left),
                top = parseInt(options.container.getBoundingClientRect().top),
                zoom = getScale() ** -1;

            if (e.target.tagName === 'IFRAME') {
                x = x * zoom + e.target.getBoundingClientRect().left;
                y = y * zoom + e.target.getBoundingClientRect().top;
            }

            if (dimension === 2) {
                tracker.style.left = this.utils.pixelize(x - left);
            } else {
                tracker.style.top = this.utils.pixelize(y - top);
            }
        };