lionleaf / dwitter

Social network for short js demos
https://www.dwitter.net
Apache License 2.0
771 stars 67 forks source link

Helper addition: M (mouse coordinate translation) #141

Open FireyFly opened 7 years ago

FireyFly commented 7 years ago

I wanted to see if I could add an interactive element to a dweet, so I decided to attach a mousemove listener to take the mouse coordinate into account. Now, paying for the cost of adding an event listener and whatnot is fair game, but I didn't anticipate how expensive it'd be just to get something canvas-usable out of the mouse event. In the end I dweeted this little paint demo.

The annoying boilerplate-y part is the computation of the mouse (x,y) coordinate in relation to canvas coordinates, especially when taking different resolutions (non-fullscreen, fullscreen at different resolutions) into account. It seems reasonable to suggest a helper function to help deal with different resolutions, since that part seems to be meant to be transparent to the dweet (i.e., the canvas is always 1920×1080).

So, I suggest a helper function M:

M = (e) => [ e.offsetX/c.offsetWidth *1920,
             e.offsetY/c.offsetHeight*1080 ]

The dweeter could then get the mouse coordinates in canvas coordinates via a simple [X,Y]=M(e).

Thoughts? I do realise new helpers should have quite a lot of friction to being added, or we'll just end up abbreviating everything…

sigvef commented 7 years ago

Can we make it totally transparent for the dweet code? So we get the correct coordinates without having to add new helpers?

sigvef commented 7 years ago

Fwiw the first iteration was always in fullscreen, so if we have old demos relying on the coordinates being correct, transparently patching the coordinates would restore them!

FireyFly commented 7 years ago

Oh hm… that would probably be better, yes. I'm not sure if there is a nice way to patch offsetX/offsetY up, I guess one could write a setter for c.onmousemove (and -up, -down, -click) and then call the real event hander with an object that inherits from the real MouseEvent object, but overrides those properties.

Something like this maybe? It's a bit icky though.

void function () {
  var handler
  Object.defineProperty(c, 'onmousemove', {
    get: function () {
      return handler
    },
    set: function (f) {
      if (handler != null) c.removeEventListener('mousemove', handler)
      handler = function (ev) {
        var ev_ = Object.create(ev)
        Object.defineProperty(ev_, 'offsetX', { get: () => ev.offsetX / c.offsetWidth  * c.width  })
        Object.defineProperty(ev_, 'offsetY', { get: () => ev.offsetY / c.offsetHeight * c.height })
        return f(ev_)
      }
      c.addEventListener('mousemove', handler, false)
    }
  })
}()

Edit: although this would mess up https://www.dwitter.net/d/809 (which only works in not-fullscreen currently)… not sure if messing with offsetX/offsetY would do more good or harm.