two.js icon indicating copy to clipboard operation
two.js copied to clipboard

ZUI Rotation

Open rttll opened this issue 6 months ago • 2 comments

I'm trying to add a rotation method to the ZUI. The two things I'm stuck on are: 1. getting an accurate rotation point/origin. 2. maintaining zoom Not sure why it's zooming, and I think the pivot point is off because it's not account for the zui's object orientation? I'm a little lost, thanks for any help!

// zui.js
rotateBy(amount, surfaceX, surfaceY) {
    this.surfaceMatrix.translate(-surfaceX, -surfaceY);
    this.surfaceMatrix.rotate(amount);

    this.rotation += amount;
    this.updateSurface();
    return this;
  }

updateSurface() {
    const e = this.surfaceMatrix.elements;
    for (let i = 0; i < this.surfaces.length; i++) {
      this.surfaces[i].apply(e[2], e[5], e[0], this.rotation);
    }

    return this;
  }

// Surface#apply
apply(px, py, s, rotation) {
    this.object.translation.set(px, py);
    this.object.scale = s;
    this.object.rotation = rotation;
    return this;
  }

Here's the scene setup (minimal setup based on my actual code). ZuiManager is an event handler/wrapper for the zui. ZuiManager.instance is the two.js ZUI

   // .... more class def / code here.

    this.$el = document.getElementById('map');
    this.two = new Two({ fullscreen: true, autostart: true });
    this.two.add(this.layer);
    this.two.appendTo(this.$el);

    this.layer = new Two.Group();
    this.layer.position.set(this.two.width / 2, this.two.height / 2);
    this.two.add(this.layer);

    this.zuiManager = new ZuiManager(this.layer, this.two);
    this.zui = this.zuiManager.instance;
    
    // where the action happens for the demo
    this.zuiManager.on('dblclick', ({ surface }) => {
      this.zuiManager.instance.rotateBy(5, surface.x, surface.y);
    });

    // Add some shapes for visual reference.
    this.container = new Two.Group();
    this.layer.add(this.container);
    const r1 = new Two.Rectangle(0, 0, 200, 100);
    const r2 = new Two.Rectangle(200, -100, 100, 200);
    const r3 = new Two.Rectangle(400, 0, 200, 100);
    this.container.add(r1);
    this.container.add(r2);
    this.container.add(r3);

    // The red rectangle. just a visual guide to see original state
    setTimeout(() => {
      const elem = this.two.scene._renderer.elem;
      const rect = elem.getBoundingClientRect();
      const div = document.createElement('div');
      div.style.position = 'fixed';
      div.style.top = `${rect.top}px`;
      div.style.left = `${rect.left}px`;
      div.style.width = `${rect.width}px`;
      div.style.height = `${rect.height}px`;
      div.style.border = '1px solid red';
      div.style.zIndex = 1000;
      this.$el.appendChild(div);
    }, 100);

   // ... rest of the real code here...

Screenshots

Initial state Screen Shot 2024-08-14 at 2 59 24 PM

after one dbl click. The click was just left/down of the red square. But it's not zoomed around that point, and it's also zoomed way out now. it is rotated though.

Screen Shot 2024-08-14 at 2 59 34 PM

Environment (please select one):

  • [x] Packaged software (e.g: ES6 imports, react, angular, vue.js)

rttll avatar Aug 14 '24 22:08 rttll