Swing Apache Batik - Zoom an einer bestimmten Stelle

FrittenFritze

Mitglied
Moin zusammen,

ich sitze gerade an einem Problem und zwar, ich verwende in meinem Projekt Apache Batik. s gibt dort die Möglichkeit die geladene SVG Grafik zu zoomen, das funktioniert auch soweit sehr gut.

Code:
import java.awt.Point;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;

import org.apache.batik.swing.JSVGCanvas;

public class WDSMouseWheelListener implements MouseWheelListener {
  
   protected JSVGCanvas _svgCanvas;
   protected double _factor = 0.1;
  
   public WDSMouseWheelListener (JSVGCanvas svgCanvas) {
     this._svgCanvas = svgCanvas;
   }

   @Override
   public void mouseWheelMoved(MouseWheelEvent e) {
     AffineTransform at = _svgCanvas.getRenderingTransform();
    
     double scaleX = at.getScaleX();
     double  scaleY = at.getScaleY();
  
  if (e.getWheelRotation() > 0) {
  scaleX = scaleX - _factor;
  scaleY = scaleY - _factor;
  } else {
  scaleX = scaleX + _factor;
  scaleY = scaleY + _factor;
  }
  
  if (scaleX < 0.1) {
  return;
  }
  
  at.setToScale(scaleX, scaleY);
  _svgCanvas.setRenderingTransform(at, true);
   }

}

Nur ist es aber so, dass die Grafik an der oberen linken Ecke aufgehängt ist und es von da aus gezoomt wird, was sehr komisch aussieht. Sprich es ist nicht so, dass die Grafik am Mauscursor gezoomt wird, was an der Stelle natürlicher wäre.

Über den JSVGCanvas kriege ich zwar die Cursorposition raus, mehr aber auch nicht...

Hat jemand eine Idee, wie es doch gehen könnte? Ich habe leider nichts diesbezüglich in der Doku gefunden 🙁
 
Zuletzt bearbeitet:
Du könntest das hier versuchen:
Java:
at.translate(mousePosX, mousePosY).scale(1.1, 1.1).translate(-mousePosX, -mousePosY)
 
Guten Morgen erstmal und sorry für die späte Rückmeldung.

Ich habe es ausprobiert:

Code:
public class TestMouseWheelListener implements java.awt.event.MouseWheelListener {

   @Override
   public void mouseWheelMoved(MouseWheelEvent e) {
     JSVGCanvas canvas = null;
     int wheelRotation = e.getWheelRotation();
     double scaleX = 0;
     double scaleY = 0;
     double stepSize = 0.1;
     
     if (e.getSource() instanceof JSVGCanvas) {
       canvas = (JSVGCanvas) e.getSource();
       scaleX = canvas.getRenderingTransform().getScaleX();
       scaleY = canvas.getRenderingTransform().getScaleY();
       
       System.out.println ("OLD: " + scaleX + ":" + scaleY);
     }
     
     switch (wheelRotation) {
     case -1:
       scaleX = scaleX - stepSize;
       scaleY = scaleY - stepSize;
       break;
     case 1:
       scaleX = scaleX + stepSize;
       scaleY = scaleY + stepSize;
       break;
     }
     
     System.out.println (wheelRotation);
     System.out.println ("New: " + scaleX + ":" + scaleY);
     
     AffineTransform at = canvas.getRenderingTransform();
     at.translate(e.getX(), e.getY());
     at.scale(scaleX, scaleY);
     at.translate(-e.getX(), -e.getY());
     canvas.setRenderingTransform(at, true);
   }
}

Das Ergebnis sieht so aus (System.out):

OLD: 1.0:1.0
1
New: 1.1:1.1
OLD: 1.1:1.1
1
New: 1.2000000000000002:1.2000000000000002
OLD: 1.3200000000000003:1.3200000000000003
1
New: 1.4200000000000004:1.4200000000000004
OLD: 1.874400000000001:1.874400000000001
-1
New: 1.7744000000000009:1.7744000000000009
OLD: 3.3259353600000034:3.3259353600000034
-1
New: 3.2259353600000034:3.2259353600000034

Das heißt, dass Bild wird nur noch größer... und dann auch in riesigen Schritten. Beim ersten und dem zweiten Inkrementieren aber scheint es sauber zu funktionieren...

Ideen?
 
In deinem Code sind scaleX und Y immer positiv auch nachdem du das Mausrad ein paar mal rückwärts bewegt hast.
Setze scaleX und scaleY auf 1.1 bzw -1.1 je nachdem in welche Richtung gescrollt wurde. getScaleX und getScaleY brauchst du nicht und du musst auch nichts addieren.
 
Hab es gestern doch noch hinbekommen:

Code:
public class TestMouseWheelListener implements java.awt.event.MouseWheelListener {

   private double _scaleX = 1;
  private double _scaleY = 1;
  private double _stepSize = 0.1;

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
    JSVGCanvas canvas = null;
    int wheelRotation = e.getWheelRotation();
  
    Point2D p1 = e.getPoint();
    Point2D p2 = null;
  
    if (e.getSource() instanceof JSVGCanvas) {
    canvas = (JSVGCanvas) e.getSource();
    }
  
    AffineTransform at = canvas.getRenderingTransform();
  
    try {
       p2 = at.inverseTransform(p1, null);
     } catch (NoninvertibleTransformException e1) {
       e1.printStackTrace();
     }
  
    System.out.println ("OLD: " + _scaleX + ":" + _scaleY);
  
    _scaleX -= (_stepSize * e.getWheelRotation());
    _scaleY -= (_stepSize * e.getWheelRotation());
    _scaleX = Math.max(_scaleX, _stepSize);
    _scaleY = Math.max(_scaleY, _stepSize);
  
    System.out.println (wheelRotation);
  
    System.out.println ("New: " + _scaleX + ":" + _scaleY);
  
    at.setToIdentity();
    at.translate(p1.getX(), p1.getY());
    at.scale(_scaleX, _scaleY);
    at.translate(-p2.getX(), -p2.getY());
    canvas.setRenderingTransform(at, true);
    }
   }

Macht genau das, was es soll 🙂

Was ist aber nicht verstehe, was machen diese beiden Zeilen denn genau?

Code:
    at.translate(p1.getX(), p1.getY());
    at.scale(_scaleX, _scaleY);
    at.translate(-p2.getX(), -p2.getY());
 

Neue Themen


Zurück
Oben