How do I add markers to a moving, zoomable UI map

Hi there,

I have a UI map which has a zoom feature, as well as a panning feature. I also want to add markers on the map using buttons, so they can have clickable features. When I add these icons to the map, they stay in position when panning but when zooming, they move away from the original location.

Code
local UIS = game:GetService("UserInputService")
local frame = script.Parent
local detectFrame = script.Parent.Parent

local dragToggle = nil
local dragSpeed = 0.01
local dragStart = nil
local startPos = nil

local scrollIncrement = 0.25
local scrollSpeed = 0.01
local startSize = nil
local scrollIncrease = nil
local currentScale = 0.5
local maxZoomScale = 5

local mouseInWindow = false



local function updateInput(input)
	local delta = input.Position - dragStart
	local xScale = startPos.X.Scale + delta.X/750
	local yScale = startPos.Y.Scale + delta.Y/750

	local xScalePositive
	local xScaleNegative

	local yScalePositive
	local yScaleNegative

	if currentScale >= 0 then
		xScalePositive = 0.75 + currentScale/5
		yScalePositive = 1 + currentScale/2.5

		xScaleNegative = 0.25 - currentScale/5
		yScaleNegative = -0.5  - currentScale/2.5
	else
		xScalePositive = 0.75 - currentScale/5
		yScalePositive = 1 - currentScale/2.5

		xScaleNegative = 0.25 + currentScale/5
		yScaleNegative = -0.5  + currentScale/2.5
	end

	if yScale < yScaleNegative then
		yScale = yScaleNegative
	end

	if yScale > yScalePositive then
		yScale = yScalePositive
	end

	if xScale < xScaleNegative then
		xScale = xScaleNegative
	end

	if xScale > xScalePositive then
		xScale = xScalePositive
	end

	local position = UDim2.new(xScale, startPos.X.Offset,
		yScale, startPos.Y.Offset)

	game:GetService("TweenService"):Create(frame, TweenInfo.new(dragSpeed), {Position = position}):Play()
end




local function scrollSize()
	local size = UDim2.new(startSize.X.Scale + scrollIncrease, startSize.X.Offset,
		startSize.Y.Scale  + scrollIncrease, startSize.Y.Offset)

	game:GetService("TweenService"):Create(frame, TweenInfo.new(scrollSpeed), {Size = size}):Play()
end






detectFrame.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		dragToggle = true
		dragStart = input.Position
		startPos = frame.Position

		input.Changed:Connect(function()
			if input.UserInputState == Enum.UserInputState.End then
				dragToggle = false
			end
		end)
	end
end)

UIS.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then
		if dragToggle then
			updateInput(input)
		end
	end
end)




UIS.InputChanged:Connect(function(input)
	if mouseInWindow == true then
		if input.UserInputType == Enum.UserInputType.MouseWheel then
			startSize = frame.Size
			if input.Position.Z > 0 then


				if currentScale < maxZoomScale then
					print("Up")
					scrollIncrease = scrollIncrement

					currentScale += scrollIncrement
					scrollSize()
				end
			else

				if currentScale > 0 then
					print("Down")
					scrollIncrease = -scrollIncrement

					currentScale -= scrollIncrement
					scrollSize()
				end
			end


		end
	end
end)

detectFrame.MouseEnter:Connect(function()
	mouseInWindow = true
end)

detectFrame.MouseLeave:Connect(function()
	mouseInWindow = false
end)

This text will be hidden

This is what happens when I zoom in currently. As you can see, the white box is moving position relative to the map when zoomed in.

Any help would be greatly appreciated to make these icons stay in the same relative position on the map when zooming in/out. Thank you :).

1 Like

This calculation likely doesn’t preserve the aspect ratio of your frame (also indicated by the marker becoming wider/thinner depending on your zoom level). I’m not sure it’s the only issue, but it probably contributes to it. Consider reworking your math to be something like:

local size = UDim2.new(startSize.X.Scale * scrollIncrease, startSize.X.Offset * scrollIncrease,
		startSize.Y.Scale  * scrollIncrease, startSize.Y.Offset * scrollIncrease)

Does the imageLabel in your frame have size (1,0,1,0)?

1 Like

Yeah that’s correct, Image Label is (1,0,1,0). With your code above, when scrolling in the map zooms out to a point where it’s invisibly small and doesn’t seem to come back? The size of the white box representing a marker seems to stay correct, but it seems like the position relative to the rest of the map is affected when zooming in or out, to be clear. Your help is greatly appreciated, thanks again.

I’ve tried using UI Constraints inside the marker, but had no luck with those - unless I am doing something wrong with them. I presume the solution would be to make some kind of calculation to reposition the markers accordingly, but not entirely sure. Thanks again for your help.