Skip to content

Instantly share code, notes, and snippets.

@sirolf2009
Created May 23, 2019 14:30
Show Gist options
  • Save sirolf2009/41921d045e4d64323f925ed50792094c to your computer and use it in GitHub Desktop.
Save sirolf2009/41921d045e4d64323f925ed50792094c to your computer and use it in GitHub Desktop.
Zoom on scroll
import javafx.animation.KeyFrame
import javafx.animation.KeyValue
import javafx.animation.Timeline
import javafx.event.EventHandler
import javafx.geometry.Bounds
import javafx.scene.Node
import javafx.scene.input.ScrollEvent
import javafx.util.Duration
class AnimatedZoomOperator {
static val DEFAULT_ZOOM_FACTOR = 1.5
val Timeline timeline
new() {
this.timeline = new Timeline(60)
}
def EventHandler<ScrollEvent> zoom(Node node) {
return zoom(node, DEFAULT_ZOOM_FACTOR)
}
def EventHandler<ScrollEvent> zoom(Node node, double zoomFactor) {
new EventHandler<ScrollEvent>() {
override handle(ScrollEvent evt) {
zoom(node, evt, zoomFactor)
}
}
}
def void zoom(Node node, ScrollEvent evt) {
zoom(node, evt, DEFAULT_ZOOM_FACTOR)
}
def void zoom(Node node, ScrollEvent evt, double zoomFactor) {
if(evt.getDeltaY() <= 0) { // zoom out
zoom(node, 1 / zoomFactor, evt.getSceneX(), evt.getSceneY())
} else {
zoom(node, zoomFactor, evt.getSceneX(), evt.getSceneY())
}
}
def void zoom(Node node, double factor, double x, double y) {
// determine scale
val double oldScale = node.getScaleX()
val double scale = oldScale * factor
val double f = (scale / oldScale) - 1
// determine offset that we will have to move the node
val Bounds bounds = node.localToScene(node.getBoundsInLocal())
val double dx = (x - (bounds.getWidth() / 2 + bounds.getMinX()))
val double dy = (y - (bounds.getHeight() / 2 + bounds.getMinY()))
// timeline that scales and moves the node
timeline.getKeyFrames().clear()
timeline.getKeyFrames().addAll(new KeyFrame(Duration.millis(200), new KeyValue(node.translateXProperty(), node.getTranslateX() - f * dx)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.translateYProperty(), node.getTranslateY() - f * dy)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.scaleXProperty(), scale)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.scaleYProperty(), scale)))
timeline.play()
}
def void resetZoom(Node node) {
timeline.getKeyFrames().clear()
timeline.getKeyFrames().addAll(new KeyFrame(Duration.millis(200), new KeyValue(node.translateXProperty(), 0)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.translateYProperty(), 0)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.scaleXProperty(), 1)), //
new KeyFrame(Duration.millis(200), new KeyValue(node.scaleYProperty(), 1)))
timeline.play()
}
}
val label = new Label("Hello World!")
val zoomOperator = new AnimatedZoomOperator()
label.setOnScroll(zoomOperator.zoom(label))
new Button("Reset Zoom") => [
setOnAction [
zoomOperator.resetZoom(label)
]
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment