An imageview is used to host a rather large image which then could be zoomed, centering the image during the zoom, and panned.
It can be converted to a custom view. Zooming center loses its meaning when the image is fully displayed and pan is not possible, another center
for zoom could now be selected. The zoom is done by two buttons (+/-). Panning is done by two-finger touch (pinch in and out).
Watch the b4a demo on my Youtube channel
picture from: https://unsplash.com/photos/green-s...ntains-during-daytime-photography-lWAOc0UuJ-A
It can be converted to a custom view. Zooming center loses its meaning when the image is fully displayed and pan is not possible, another center
for zoom could now be selected. The zoom is done by two buttons (+/-). Panning is done by two-finger touch (pinch in and out).
Watch the b4a demo on my Youtube channel
picture from: https://unsplash.com/photos/green-s...ntains-during-daytime-photography-lWAOc0UuJ-A
B4X:
#Region Project Attributes
#MainFormWidth: 900
#MainFormHeight: 680
#End Region
Sub Process_Globals
Private fx As JFX
Private MainForm As Form
Private ZoomPane As Pane
Private ZoomImageView As ImageView
Private ScrollContainer As ScrollPane
Private btnZoomIn As Button
Private btnZoomOut As Button
Private bmp As Image
Private ScaleFactor As Float = 1.0
Private TargetScaleFactor As Float
Private AnimationSteps As Int = 10
Private AnimationStepCounter As Int
Private AnimationTimer As Timer
Private CurrentXOffset As Float = 0
Private CurrentYOffset As Float = 0
Private LastX As Float
Private LastY As Float
Private StartX As Double
Private StartY As Double
End Sub
Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.RootPane.LoadLayout("Layout1") ' Load layout if you have one
MainForm.SetFormStyle("UNIFIED")
MainForm.Show
btnZoomIn.Initialize("btnZoomIn")
btnZoomOut.Initialize("btnZoomOut")
MainForm.RootPane.AddNode(btnZoomIn,0,20,50,20)
MainForm.RootPane.AddNode(btnZoomOut,70,20,50,20)
btnZoomIn.TextSize=24
btnZoomIn.Text="+"
btnZoomOut.TextSize=24
btnZoomOut.Text="-"
' Initialize UI components
ScrollContainer.Initialize("sc")
MainForm.RootPane.AddNode(ScrollContainer, 0, 75, 900, 600)
ZoomPane.Initialize("zp")
ScrollContainer.InnerNode = ZoomPane
ZoomImageView.Initialize("zimg")
ZoomPane.AddNode(ZoomImageView, 0, 0, 600, 400)
' Load Image
bmp = fx.LoadImage(File.DirAssets, "nature.jpg")
ZoomImageView.SetImage(bmp)
' Initialize Timer
AnimationTimer.Initialize("AnimationTimer", 20)
' Use jReflection to handle mouse events
'/AddMouseEvents(ZoomPane)
' Center the image
CenterImage
' Enable mouse events for pan
'' ZoomImageView.SetMousePressed(True)
'' ZoomPane.AddEventHandler("OnMousePressed", "Pane_MousePressed")
'' ZoomPane.AddEventHandler("OnMouseDragged", "Pane_MouseDragged")
End Sub
Sub AddMouseEvents(Pane As Pane)
Dim r As Reflector
r.Target = Pane
r.AddEventHandler("MousePressed","javafx.scene.input.MouseEvent.MOUSE_PRESSED" )
r.AddEventHandler("MouseDragged","javafx.scene.input.MouseEvent.MOUSE_DRAGGED")
End Sub
Sub MousePressed_Event (EventData As Object)
Dim r As Reflector
r.Target = EventData
StartX = r.GetField("sceneX") ' Get the X position of the mouse press
StartY = r.GetField("sceneY") ' Get the Y position of the mouse press
End Sub
Sub MouseDragged_Event (EventData As Object)
Dim r As Reflector
r.Target = EventData
Dim CurrentX As Double = r.GetField("sceneX")
Dim CurrentY As Double = r.GetField("sceneY")
' Pan logic
Dim dx As Double = CurrentX - StartX
Dim dy As Double = CurrentY - StartY
StartX = CurrentX
StartY = CurrentY
ZoomPane.Left = ZoomPane.Left + dx
ZoomPane.Top = ZoomPane.Top + dy
End Sub
Sub zp_MousePressed (Event As MouseEvent)
LastX = Event.X
LastY = Event.Y
End Sub
Sub zp_MouseDragged (Event As MouseEvent)
Dim dx As Float = Event.X - LastX
Dim dy As Float = Event.Y - LastY
CurrentXOffset = CurrentXOffset + dx
CurrentYOffset = CurrentYOffset + dy
DrawImage
LastX = Event.X
LastY = Event.Y
End Sub
Sub CenterImage()
CurrentXOffset = (ScrollContainer.Width - bmp.Width * ScaleFactor) / 2
CurrentYOffset = (ScrollContainer.Height - bmp.Height * ScaleFactor) / 2
DrawImage
End Sub
Sub btnZoomIn_Click
StartSmoothZoom(ScaleFactor * 1.2)
End Sub
Sub btnZoomOut_Click
StartSmoothZoom(ScaleFactor / 1.2)
End Sub
Sub StartSmoothZoom(NewScaleFactor As Float)
If NewScaleFactor < 0.5 Or NewScaleFactor > 5 Then Return
TargetScaleFactor = NewScaleFactor
AnimationStepCounter = 0
AnimationTimer.Enabled = True
End Sub
Sub AnimationTimer_Tick
Dim factor As Float = AnimationStepCounter / AnimationSteps
Dim interpolatedScale As Float = ScaleFactor + (TargetScaleFactor - ScaleFactor) * factor
ZoomImage(interpolatedScale)
AnimationStepCounter = AnimationStepCounter + 1
If AnimationStepCounter > AnimationSteps Then
ScaleFactor = TargetScaleFactor
AnimationTimer.Enabled = False
End If
End Sub
Sub ZoomImage(NewScaleFactor As Float)
Dim visibleCenterX As Float = (ScrollContainer.Width / 2 - CurrentXOffset) / ScaleFactor
Dim visibleCenterY As Float = (ScrollContainer.Height / 2 - CurrentYOffset) / ScaleFactor
ScaleFactor = NewScaleFactor
CurrentXOffset = ScrollContainer.Width / 2 - visibleCenterX * ScaleFactor
CurrentYOffset = ScrollContainer.Height / 2 - visibleCenterY * ScaleFactor
Dim newWidth As Float = bmp.Width * ScaleFactor
Dim newHeight As Float = bmp.Height * ScaleFactor
Dim minXOffset As Float = Min(0, ScrollContainer.Width - newWidth)
Dim minYOffset As Float = Min(0, ScrollContainer.Height - newHeight)
CurrentXOffset = Max(minXOffset, Min(CurrentXOffset, 0))
CurrentYOffset = Max(minYOffset, Min(CurrentYOffset, 0))
DrawImage
End Sub
Sub DrawImage()
ZoomPane.SetSize(bmp.Width * ScaleFactor, bmp.Height * ScaleFactor)
ZoomImageView.SetLayoutAnimated(0, CurrentXOffset, CurrentYOffset, bmp.Width * ScaleFactor, bmp.Height * ScaleFactor)
End Sub
Last edited: