Clamping ImageLabel within circle?

I’m currently not at my PC to give an example.
However, I have a Minimap / Radar that I’ve been working on that pinpoints both the Players location and others, converts the Position to Udim2 and then displays on a GUI.

I’m currently using UICornerRadius to keep the UI circular however the RadarPoints go out of the circular bounds - I’m looking for a way to clamp the Points to the boundary?

1 Like

You can use ClipDescendants which will automatically clip all descendants of the UI

2 Likes

You can use some math to determine the maximum position of the UI. You can use trigonometry, distance math and or the formula for a circle, or use a Vector2 (of the distance from the center of the circle) on which you clamp the magnitude (maximum magnitude from center is equal to the radius of the circle)

I don’t know how you calculate the position of your radar, so it’s hard to really give insight into how to add clamping as ideally that logic can be added directly to the calculation for the position

Anyway, code for clamping Vector2 magnitude should be something like this

local Radius = 150 -- Pixels?

-- If magnitude is smaller than Radius, do not change Vector
-- If magnitude is above Radius, get the Unit vector (magnitude of 1), and multiply it by Radius, which will give you a point at the max allowed distance
local Vector = Vector.Magnitude <= Radius and Vector or Vector.Unit*Radius
3 Likes

Avoiding this as the Frame rotates to match camera angle and Clipping doesn’t really like rotation.

Looks promising!
I’ll attempt this tonight and upload my code to this forum.

Not had much luck with this as of yet…

Below is my code that I use:

	local Core = { ... }
	local Server, Script = game, script
	
	self = {}
	self.__index = self
	
	self.Camera = Server:GetService('Workspace'):WaitForChild('Camera')
	self.Player = Server:GetService('Players').LocalPlayer
	self.Character = self.Player.Character or self.Player.CharacterAdded:Wait(2)
	self.HumanoidRootPart = self.Character:WaitForChild('HumanoidRootPart')
	
	self.Gui  = Script.Parent
	self.Circle = self.Gui.Frame.Circle
	
	self.Icon = {}
	self.Icon[self.Player] = self.Circle.Player
	
	local RadarPoints = {}
	for __,i in (Server:GetService('CollectionService'):GetTagged('Part')) do
		local Point = Script.Icon:Clone(...)
		Point.Size = UDim2.new(0, i.Size.X * 2, 0, i.Size.Z * 2)
		Point.BackgroundColor3 = i.Color
		Point.Parent = self.Circle
		table.insert(RadarPoints, Point)
	end
	
	function getOffset(obj)
		local xOrigin,yOrigin = self.HumanoidRootPart.Position.X, self.HumanoidRootPart.Position.Z
		local xTarget,yTarget = obj.Position.X, obj.Position.Z
		local xOffset,yOffset = xTarget-xOrigin,yTarget-yOrigin
		return Vector2.new(xOffset,yOffset)
	end
	
	function updateRadar()
		local relativePosition = self.HumanoidRootPart.Position - self.Camera.CFrame.Position
		local angle = math.atan2(relativePosition.z, relativePosition.x)
		
		self.Circle.Rotation = -(math.deg(angle) + 90)
		self.Icon[self.Player].Rotation = (math.deg(angle) + 90) - 180
	end
	
	Server:GetService('RunService').PreRender:Connect(function(dt, ...)
		for __,Part in (Server:GetService('CollectionService'):GetTagged('Part')) do
			local convertedOffset = getOffset(Part) * 2
			local radarPoint = RadarPoints[__]
			if (Part.Position - self.HumanoidRootPart.Position).Magnitude < 50 then
				radarPoint.Visible = true
			else
				radarPoint.Visible = false
			end
			radarPoint.Position = UDim2.new(0.5, convertedOffset.X, 0.5, convertedOffset.Y)
		end
		updateRadar(...)
	end)
	
	return Core
	Server:GetService('RunService').PreRender:Connect(function(dt, ...)

		-- Getting the radius of the circle. The radius is the maximum magnitude convertedOffset will be allowed to have
		local Radius = self.Circle.AbsoluteSize.X/2 -- Can also use Y, as both are the same size

		for __,Part in (Server:GetService('CollectionService'):GetTagged('Part')) do
			local convertedOffset = getOffset(Part) * 2
			local radarPoint = RadarPoints[__]
			if (Part.Position - self.HumanoidRootPart.Position).Magnitude < 50 then
				radarPoint.Visible = true
			else
				radarPoint.Visible = false
			end

			-- Limit the magnitude of convertedOffset to Radius
			convertedOffset = convertedOffset.Magnitude <= Radius and convertedOffset or convertedOffset.Unit*Radius
			radarPoint.Position = UDim2.new(0.5, convertedOffset.X, 0.5, convertedOffset.Y)
		end
		updateRadar(...)
	end)

The way your code works is perfect for adding clamping, just had to add those two lines where I put the comments, inside the RunService loop

1 Like