How do I make image label stay inside the frame, while position is being changed

recently, I have been trying to figure out on to make a marker system, but I can’t figure out on how to make a marker stay inside the frame

local script

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer or Players.PlayerAdded:Wait()
local PlayerGui = LocalPlayer:FindFirstChildWhichIsA("PlayerGui")

local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "MarkerSystem"
ScreenGui.Parent = PlayerGui

local Frame = Instance.new("Frame")
Frame.Size = UDim2.new(1, 0, 1, 0)
Frame.BackgroundTransparency = 1
Frame.Parent = ScreenGui

local MarkerIcon = Instance.new("ImageLabel")
MarkerIcon.Size = UDim2.new(0, 100, 0, 100)
MarkerIcon.Parent = ScreenGui

RunService.RenderStepped:Connect(function(DeltaTime)

   local WorldToScreenPoint: Vector3 = workspace.CurrentCamera:WorldToScreenPoint(workspace.Part.Position)
   MarkerIcon.Position = UDim2.new(0, WorldToScreenPoint.X, 0, WorldToScreenPoint.Y)

   if MarkerIcon.AbsolutePosition.X > Frame.AbsoluteSize.X then
      print("Test")
      MarkerIcon.Position = UDim2.new(0, Frame.X - MarkerIcon.AbsolutePosition.X, 0, 0)
   end

end)

Please note I’m only making it stay in one direction for now.

This code will constrain the marker to within the horizontal expanse of the frame:

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer or Players.PlayerAdded:Wait()
local PlayerGui = LocalPlayer:FindFirstChildWhichIsA("PlayerGui")

local ScreenGui = Instance.new("ScreenGui")
ScreenGui.Name = "MarkerSystem"
ScreenGui.Parent = PlayerGui

local Frame = Instance.new("Frame")
Frame.Size = UDim2.new(1, 0, 1, 0)
Frame.BackgroundTransparency = 1
Frame.Parent = ScreenGui

local MarkerIcon = Instance.new("ImageLabel")
MarkerIcon.Size = UDim2.new(0, 100, 0, 100)
MarkerIcon.Parent = ScreenGui

RunService.RenderStepped:Connect(function(DeltaTime)

	local WorldToScreenPoint: Vector3 = workspace.CurrentCamera:WorldToScreenPoint(workspace.Part.Position)
	MarkerIcon.Position = UDim2.new(0,
		math.clamp(WorldToScreenPoint.X,
			Frame.AbsolutePosition.X,
			Frame.AbsolutePosition.X + Frame.AbsoluteSize.X - MarkerIcon.AbsoluteSize.X),
		0, WorldToScreenPoint.Y)

end)

You could apply similar constraints to the Y dimension to force the marker within frame at all times.

Bear in mind, however, that this code currently assumes that MarkerIcon.AnchorPoint is (0,0) and does not handle the case where the object is directly behind the camera (as this does bring the marker back onto screen even though the ray is projecting “through” the screen rather than into the world).

2 Likes

local Markers = {}
local Screen = script.Parent.Holder.AbsoluteSize
local T = game:GetService(“TweenService”)

for i,v in pairs(game.ReplicatedStorage.Markers:GetChildren()) do
local Marker = script.Sample:Clone()
Marker.Parent = script.Parent.Holder
Marker.ImageColor3 = v.Config.MarkerColor.Value
Marker.RotateLabel.Arrow.ImageColor3 = v.Config.MarkerColor.Value
Marker.Icon.Image = v.Config.Icon.Value
table.insert(Markers,{Marker,v})
end

function ClampMarkerToBorder(X,Y,Absolute)
X = Screen.X - X
Y = Screen.Y - Y

local DistanceToXBorder = math.min(X,Screen.X-X)
local DistanceToYBorder = math.min(Y,Screen.Y-Y)

if DistanceToYBorder < DistanceToXBorder then 
	if Y < (Screen.Y-Y) then
		return math.clamp(X,0,Screen.X-Absolute.X),0
	else
		return math.clamp(X,0,Screen.X-Absolute.X),Screen.Y - Absolute.Y
	end
else
	if X < (Screen.X-X) then
		return 0,math.clamp(Y,0,Screen.Y-Absolute.Y)
	else
		return Screen.X - Absolute.X,math.clamp(Y,0,Screen.Y-Absolute.Y)
	end
end

end

game:GetService(“RunService”).Heartbeat:Connect(function()
for i,Stat in pairs(Markers) do
local Marker = Stat[1]
local Location = Stat[2]
Marker.Visible = Location.Config.Enabled.Value

	if Location.Config.Enabled.Value then
		local MarkerPosition , MarkerVisible = game.Workspace.CurrentCamera:WorldToScreenPoint(Location.Position)
		local MarkerRotation = game.Workspace.CurrentCamera.CFrame:Inverse()*Location.CFrame
		local MarkerAbsolute = Marker.AbsoluteSize
		
		local MarkerPositionX = MarkerPosition.X - MarkerAbsolute.X/2
		local MarkerPositionY = MarkerPosition.Y - MarkerAbsolute.Y/2
		
		if MarkerPosition.Z < 0  then
			MarkerPositionX,MarkerPositionY = ClampMarkerToBorder(MarkerPositionX,MarkerPositionY,MarkerAbsolute)
		else
			if MarkerPositionX < 0 then
				MarkerPositionX = 0
			elseif MarkerPositionX > (Screen.X - MarkerAbsolute.X) then
				MarkerPositionX = Screen.X - MarkerAbsolute.X
			end
			if MarkerPositionY < 0 then
				MarkerPositionY = 0
			elseif MarkerPositionY > (Screen.Y - MarkerAbsolute.Y) then
				MarkerPositionY = Screen.Y - MarkerAbsolute.Y
			end
		end
			
		Marker.RotateLabel.Visible = not MarkerVisible
		Marker.RotateLabel.Rotation = 90 + math.deg(math.atan2(MarkerRotation.Z,MarkerRotation.X))
		Marker.Position = UDim2.new(0,MarkerPositionX,0,MarkerPositionY)
		
		T:Create(Marker,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
		T:Create(Marker.RotateLabel.Arrow,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
		local CurrentTime = tick()
		if Location.Config.BurstType.Value == "Normal" then
			if math.floor((CurrentTime%1.5)*100)/100 <= .01 then
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Location.Config.MarkerColor.Value
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			end
		elseif Location.Config.BurstType.Value == "Police" then
			if math.floor((CurrentTime%1.5)*100)/100 <= .01 then
				warn("Blue")
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Color3.fromRGB(82,124,174)
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			elseif math.floor((CurrentTime%.75)*100)/100 <= .01 then
				warn("Red")
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Color3.fromRGB(255,89,89)
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			end
		end
	end
end

end)

for i,v in pairs(game.ReplicatedStorage.Markers:GetChildren()) do
local Marker = script.Sample:Clone()
Marker.Parent = script.Parent.Holder
Marker.ImageColor3 = v.Config.MarkerColor.Value
Marker.RotateLabel.Arrow.ImageColor3 = v.Config.MarkerColor.Value
Marker.Icon.Image = v.Config.Icon.Value
table.insert(Markers,{Marker,v})
end

function ClampMarkerToBorder(X,Y,Absolute)
X = Screen.X - X
Y = Screen.Y - Y

local DistanceToXBorder = math.min(X,Screen.X-X)
local DistanceToYBorder = math.min(Y,Screen.Y-Y)

if DistanceToYBorder < DistanceToXBorder then 
	if Y < (Screen.Y-Y) then
		return math.clamp(X,0,Screen.X-Absolute.X),0
	else
		return math.clamp(X,0,Screen.X-Absolute.X),Screen.Y - Absolute.Y
	end
else
	if X < (Screen.X-X) then
		return 0,math.clamp(Y,0,Screen.Y-Absolute.Y)
	else
		return Screen.X - Absolute.X,math.clamp(Y,0,Screen.Y-Absolute.Y)
	end
end

end

game:GetService(“RunService”).Heartbeat:Connect(function()
for i,Stat in pairs(Markers) do
local Marker = Stat[1]
local Location = Stat[2]
Marker.Visible = Location.Config.Enabled.Value

	if Location.Config.Enabled.Value then
		local MarkerPosition , MarkerVisible = game.Workspace.CurrentCamera:WorldToScreenPoint(Location.Position)
		local MarkerRotation = game.Workspace.CurrentCamera.CFrame:Inverse()*Location.CFrame
		local MarkerAbsolute = Marker.AbsoluteSize
		
		local MarkerPositionX = MarkerPosition.X - MarkerAbsolute.X/2
		local MarkerPositionY = MarkerPosition.Y - MarkerAbsolute.Y/2
		
		if MarkerPosition.Z < 0  then
			MarkerPositionX,MarkerPositionY = ClampMarkerToBorder(MarkerPositionX,MarkerPositionY,MarkerAbsolute)
		else
			if MarkerPositionX < 0 then
				MarkerPositionX = 0
			elseif MarkerPositionX > (Screen.X - MarkerAbsolute.X) then
				MarkerPositionX = Screen.X - MarkerAbsolute.X
			end
			if MarkerPositionY < 0 then
				MarkerPositionY = 0
			elseif MarkerPositionY > (Screen.Y - MarkerAbsolute.Y) then
				MarkerPositionY = Screen.Y - MarkerAbsolute.Y
			end
		end
			
		Marker.RotateLabel.Visible = not MarkerVisible
		Marker.RotateLabel.Rotation = 90 + math.deg(math.atan2(MarkerRotation.Z,MarkerRotation.X))
		Marker.Position = UDim2.new(0,MarkerPositionX,0,MarkerPositionY)
		
		T:Create(Marker,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
		T:Create(Marker.RotateLabel.Arrow,TweenInfo.new(.5),{ImageColor3 = Location.Config.MarkerColor.Value}):Play()
		local CurrentTime = tick()
		if Location.Config.BurstType.Value == "Normal" then
			if math.floor((CurrentTime%1.5)*100)/100 <= .01 then
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Location.Config.MarkerColor.Value
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			end
		elseif Location.Config.BurstType.Value == "Police" then
			if math.floor((CurrentTime%1.5)*100)/100 <= .01 then
				warn("Blue")
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Color3.fromRGB(82,124,174)
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			elseif math.floor((CurrentTime%.75)*100)/100 <= .01 then
				warn("Red")
				local Burst = script.BurstRings:Clone()
				Burst.ImageColor3 = Color3.fromRGB(255,89,89)
				Burst.Parent = Marker
				T:Create(Burst,TweenInfo.new(1),{Size = UDim2.new(2,0,2,0),ImageTransparency = 1}):Play()
				game.Debris:AddItem(Burst,1)
			end
		end
	end
end

end)
this should workimage

image
I also added bank and home as examples you can change them if you want

starter GUI should have this image
and for ReplicatedStorageimage

1 Like