mirror of
https://github.com/ND-Framework/ND_Core.git
synced 2026-08-17 05:56:01 +01:00
Add files via upload
This commit is contained in:
22
ND_ATMs/fxmanifest.lua
Normal file
22
ND_ATMs/fxmanifest.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
-- For support join my discord: https://discord.gg/Z9Mxu72zZ6
|
||||
|
||||
author "Andyyy#7666"
|
||||
description "ND Framework ATMs"
|
||||
version "1.1"
|
||||
|
||||
fx_version "cerulean"
|
||||
game "gta5"
|
||||
lua54 "yes"
|
||||
|
||||
ui_page "source/ui/index.html"
|
||||
|
||||
files {
|
||||
"source/ui/index.html",
|
||||
"source/ui/js/jquery-3.6.0.min.js",
|
||||
"source/ui/js/listener.js",
|
||||
"source/ui/img/mazebank.png",
|
||||
"source/ui/style.css",
|
||||
}
|
||||
|
||||
server_script "source/server.lua"
|
||||
client_script "source/client.lua"
|
||||
143
ND_ATMs/source/client.lua
Normal file
143
ND_ATMs/source/client.lua
Normal file
@@ -0,0 +1,143 @@
|
||||
------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------
|
||||
-- DO NOT EDIT IF YOU DON'T KNOW WHAT YOU'RE DOING --
|
||||
-- --
|
||||
-- For support join my discord: https://discord.gg/Z9Mxu72zZ6 --
|
||||
------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------
|
||||
|
||||
--PlaySoundFrontend(-1, "PIN_BUTTON", "ATM_SOUNDS", 1)
|
||||
|
||||
local display = false
|
||||
local balance = nil
|
||||
|
||||
local atmModels = {
|
||||
"-870868698", -- older atms
|
||||
"-1126237515", -- blue atm
|
||||
"-1364697528", -- red atm
|
||||
"506770882" -- green atm
|
||||
}
|
||||
|
||||
local days = {
|
||||
[0] = "Sunday",
|
||||
[1] = "Monday",
|
||||
[2] = "Tuesday",
|
||||
[3] = "Wednesday",
|
||||
[4] = "Thursday",
|
||||
[5] = "Friday",
|
||||
[6] = "Saturday"
|
||||
}
|
||||
|
||||
local months = {
|
||||
[1] = "January",
|
||||
[2] = "February",
|
||||
[3] = "March",
|
||||
[4] = "April",
|
||||
[5] = "May",
|
||||
[6] = "June",
|
||||
[7] = "July",
|
||||
[8] = "August",
|
||||
[9] = "September",
|
||||
[10] = "October",
|
||||
[11] = "November",
|
||||
[12] = "December"
|
||||
}
|
||||
|
||||
RegisterNUICallback("close", function(data)
|
||||
PlaySoundFrontend(-1, "PIN_BUTTON", "ATM_SOUNDS", 1)
|
||||
SetDisplay(false)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("sound", function(data)
|
||||
PlaySoundFrontend(-1, "PIN_BUTTON", "ATM_SOUNDS", 1)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("withdraw", function(data)
|
||||
TriggerServerEvent("ND:withdraw", data.amount)
|
||||
end)
|
||||
|
||||
RegisterNUICallback("deposit", function(data)
|
||||
TriggerServerEvent("ND:deposit", data.amount)
|
||||
end)
|
||||
|
||||
-- Alert thread
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Citizen.Wait(0)
|
||||
if not display and IsNearATM() then
|
||||
alert("Press ~INPUT_CONTEXT~ to use the ATM")
|
||||
if IsControlJustPressed(0, 51) then
|
||||
SetDisplay(true)
|
||||
end
|
||||
if display then
|
||||
TriggerScreenblurFadeIn(1000)
|
||||
else
|
||||
TriggerScreenblurFadeOut(1000)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Hide/Show ui
|
||||
function SetDisplay(bool)
|
||||
display = bool
|
||||
SetNuiFocus(bool, bool)
|
||||
SendNUIMessage({
|
||||
status = bool,
|
||||
playerName = exports["ND_Core"]:getCharacterInfo(1) .. " " .. exports["ND_Core"]:getCharacterInfo(2),
|
||||
balance = "Account Balance: $" .. exports["ND_Core"]:getCharacterInfo(8) .. ".00",
|
||||
date = getDay() .. ", " .. getMonth() .. " " .. GetClockDayOfMonth() .. ", " .. GetClockYear(),
|
||||
time = getTime()
|
||||
})
|
||||
end
|
||||
|
||||
-- Get the time
|
||||
function getTime()
|
||||
local hours = GetClockHours()
|
||||
local minutes = GetClockMinutes()
|
||||
if hours <= 9 then
|
||||
hours = "0" .. hours
|
||||
end
|
||||
if minutes <= 9 then
|
||||
minutes = "0" .. minutes
|
||||
end
|
||||
return hours .. ":" .. minutes
|
||||
end
|
||||
|
||||
-- Get the day of the week
|
||||
function getDay()
|
||||
local currentDay = GetClockDayOfWeek()
|
||||
for k, v in pairs(days) do
|
||||
if currentDay == k then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get Month of the year
|
||||
function getMonth()
|
||||
local currentMonth = GetClockMonth()
|
||||
for k, v in pairs(months) do
|
||||
if currentMonth == k then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Alert on top left of screen
|
||||
function alert(msg)
|
||||
BeginTextCommandDisplayHelp("STRING")
|
||||
AddTextComponentSubstringPlayerName(msg)
|
||||
EndTextCommandDisplayHelp(0, 0, 1, -1)
|
||||
end
|
||||
|
||||
-- Check if player is near an atm
|
||||
function IsNearATM()
|
||||
local playerCoords = GetEntityCoords(PlayerPedId(), 0)
|
||||
for k, v in pairs(atmModels) do
|
||||
ATM = GetCoordsAndRotationOfClosestObjectOfType(playerCoords.x, playerCoords.y, playerCoords.z, 0.7, tonumber(v), 0)
|
||||
if ATM == 1 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
75
ND_ATMs/source/server.lua
Normal file
75
ND_ATMs/source/server.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
-- For support join my discord: https://discord.gg/Z9Mxu72zZ6
|
||||
|
||||
expectedName = "ND_ATMs" -- This is the resource and is not suggested to be changed.
|
||||
resource = GetCurrentResourceName()
|
||||
|
||||
-- check if resource is renamed
|
||||
if resource ~= expectedName then
|
||||
print("^1[^4" .. expectedName .. "^1] WARNING^0")
|
||||
print("Change the resource name to ^4" .. expectedName .. " ^0or else it won't work!")
|
||||
end
|
||||
|
||||
-- check if resource version is up to date
|
||||
PerformHttpRequest("https://raw.githubusercontent.com/Andyyy7666/ND_Framework/main/ND_ATMs/fxmanifest.lua", function(error, res, head)
|
||||
i, j = string.find(tostring(res), "version")
|
||||
res = string.sub(tostring(res), i, j + 6)
|
||||
res = string.gsub(res, "version ", "")
|
||||
res = string.gsub(res, '"', "")
|
||||
resp = tonumber(res)
|
||||
verFile = GetResourceMetadata(expectedName, "version", 0)
|
||||
|
||||
if verFile then
|
||||
if tonumber(verFile) < resp then
|
||||
print("^1[^4" .. expectedName .. "^1] WARNING^0")
|
||||
print("^4" .. expectedName .. " ^0is outdated. Please update it from ^5https://github.com/Andyyy7666/ND_Framework ^0| Current Version: ^1" .. verFile .. " ^0| New Version: ^2" .. resp .. " ^0|")
|
||||
elseif tonumber(verFile) > tonumber(resp) then
|
||||
print("^1[^4" .. expectedName .. "^1] WARNING^0")
|
||||
print("^4" .. expectedName .. "s ^0version number is higher than we expected. | Current Version: ^3" .. verFile .. " ^0| Expected Version: ^2" .. resp .. " ^0|")
|
||||
else
|
||||
print("^4" .. expectedName .. " ^0is up to date | Current Version: ^2" .. verFile .. " ^0|")
|
||||
end
|
||||
else
|
||||
print("^1[^4" .. expectedName .. "^1] WARNING^0")
|
||||
print("You may not have the latest version of ^4" .. expectedName .. "^0. A newer, improved version may be present at ^5https://github.com/Andyyy7666/ND_Framework^0")
|
||||
end
|
||||
end)
|
||||
|
||||
function GetPlayerIdentifierFromType(type, source) -- Credits: xander1998, Post: https://forum.cfx.re/t/solved-is-there-a-better-way-to-get-lic-steam-and-ip-than-getplayeridentifiers/236243/2?u=andyyy7666
|
||||
local identifiers = {}
|
||||
local identifierCount = GetNumPlayerIdentifiers(source)
|
||||
|
||||
for a = 0, identifierCount do
|
||||
table.insert(identifiers, GetPlayerIdentifier(source, a))
|
||||
end
|
||||
|
||||
for b = 1, #identifiers do
|
||||
if string.find(identifiers[b], type, 1) then
|
||||
return identifiers[b]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
RegisterNetEvent("ND:withdraw")
|
||||
AddEventHandler("ND:withdraw", function(amount)
|
||||
local player = source
|
||||
local characterId = exports["ND_Core"]:getCharacterTable()[player].characterId
|
||||
exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), characterId}, function(result)
|
||||
if result then
|
||||
exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), characterId})
|
||||
TriggerClientEvent("updateMoney", player)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("ND:deposit")
|
||||
AddEventHandler("ND:deposit", function(amount)
|
||||
local player = source
|
||||
local characterId = exports["ND_Core"]:getCharacterTable()[player].characterId
|
||||
exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), characterId}, function(result)
|
||||
if result then
|
||||
exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), characterId})
|
||||
TriggerClientEvent("updateMoney", player)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
BIN
ND_ATMs/source/ui/img/mazebank.png
Normal file
BIN
ND_ATMs/source/ui/img/mazebank.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
40
ND_ATMs/source/ui/index.html
Normal file
40
ND_ATMs/source/ui/index.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="https://use.fontawesome.com/releases/v5.15.4/js/all.js" data-auto-a11y="true"></script>
|
||||
<script src="js/jquery-3.6.0.min.js" type="text/javascript"></script>
|
||||
<script src="js/listener.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<section id="overlay">
|
||||
<div id="info">
|
||||
<img src="img/mazebank.png" id="logo">
|
||||
<p id="date"></p>
|
||||
<p id="time"></p>
|
||||
<hr id="redline">
|
||||
<hr id="redbox">
|
||||
<p id="welcome">Welcome back</p>
|
||||
<h1 id="playername">John Doe</h1>
|
||||
</div>
|
||||
<form id="atm">
|
||||
<p id="balance"></p>
|
||||
<input id="enteredAmount" class="input" type="number" placeholder="AMOUNT" min="10" max="2500">
|
||||
<button id="withdrawButton" class="input"><i class="fas fa-coins"></i> WITHDRAW</button>
|
||||
<button id="depositButton" class="input"><i class="fas fa-credit-card"></i> DEPOSIT</button>
|
||||
</form>
|
||||
<div id="loader"></div>
|
||||
<div id="confirmationScreen">
|
||||
<p id="confirmText">Are you sure you'd like to perform this action</p>
|
||||
<button id="confirmButton" type="submit" form="atm" class="input"><i class="fas fa-check-circle"></i> CONFIRM</button>
|
||||
<button id="cancelButton" type="reset" form="atm" class="input"><i class="fas fa-times-circle"></i> CANCEL</button>
|
||||
</div>
|
||||
<div id="successScreen">
|
||||
<p id="confirmText">Success!</p>
|
||||
<button id="mainMenuButton" type="reset" form="atm" class="input"><i class="fas fa-chevron-circle-left"></i> BACK TO MAIN MENU</button>
|
||||
</div>
|
||||
<button id="closeButton" type="reset" form="atm" class="input"><i class="fas fa-sign-out-alt"></i> EXIT</button>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
2
ND_ATMs/source/ui/js/jquery-3.6.0.min.js
vendored
Normal file
2
ND_ATMs/source/ui/js/jquery-3.6.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
145
ND_ATMs/source/ui/js/listener.js
Normal file
145
ND_ATMs/source/ui/js/listener.js
Normal file
@@ -0,0 +1,145 @@
|
||||
$(function() {
|
||||
let deposit = false
|
||||
let withdraw = false
|
||||
|
||||
function display(bool) {
|
||||
if (bool) {
|
||||
$("#overlay").show();
|
||||
} else {
|
||||
$("#overlay").hide();
|
||||
}
|
||||
}
|
||||
function atmDisplay(bool) {
|
||||
if (bool) {
|
||||
$("#atm").show();
|
||||
$("#loader").hide();
|
||||
$("#confirmationScreen").hide();
|
||||
$("#successScreen").hide()
|
||||
} else {
|
||||
$("#atm").hide();
|
||||
}
|
||||
}
|
||||
function loader(bool) {
|
||||
if (bool) {
|
||||
$("#loader").show();
|
||||
$("#atm").hide();
|
||||
$("#confirmationScreen").hide();
|
||||
$("#successScreen").hide()
|
||||
} else {
|
||||
$("#loader").hide();
|
||||
}
|
||||
}
|
||||
function confirmationScreen(bool) {
|
||||
if (bool) {
|
||||
$("#confirmationScreen").show();
|
||||
$("#atm").hide();
|
||||
$("#loader").hide();
|
||||
$("#successScreen").hide()
|
||||
} else {
|
||||
$("#confirmationScreen").hide();
|
||||
}
|
||||
}
|
||||
function successScreen(bool) {
|
||||
if (bool) {
|
||||
$("#successScreen").show()
|
||||
$("#confirmationScreen").hide();
|
||||
$("#atm").hide();
|
||||
$("#loader").hide();
|
||||
} else {
|
||||
$("#successScreen").hide()
|
||||
}
|
||||
}
|
||||
display(false)
|
||||
atmDisplay(true)
|
||||
loader(false)
|
||||
confirmationScreen(false)
|
||||
successScreen(false)
|
||||
|
||||
window.addEventListener("message", function(event) {
|
||||
const item = event.data;
|
||||
if (item.status) {
|
||||
display(true)
|
||||
$("#playername").text(item.playerName)
|
||||
$("#balance").text(item.balance)
|
||||
$("#date").text(item.date)
|
||||
$("#time").text(item.time)
|
||||
} else {
|
||||
display(false)
|
||||
}
|
||||
})
|
||||
|
||||
$("#withdrawButton").click(function() {
|
||||
withdraw = true
|
||||
$.post("https://ND_ATMs/sound", JSON.stringify({}));
|
||||
atmDisplay(false)
|
||||
loader(true)
|
||||
setTimeout(() => {
|
||||
loader(false)
|
||||
confirmationScreen(true)
|
||||
}, 400);
|
||||
return false
|
||||
})
|
||||
|
||||
$("#depositButton").click(function() {
|
||||
deposit = true
|
||||
$.post("https://ND_ATMs/sound", JSON.stringify({}));
|
||||
atmDisplay(false)
|
||||
loader(true)
|
||||
setTimeout(() => {
|
||||
loader(false)
|
||||
confirmationScreen(true)
|
||||
}, 400);
|
||||
return false
|
||||
})
|
||||
|
||||
$("#cancelButton").click(function() {
|
||||
withdraw = false
|
||||
deposit = false
|
||||
$.post("https://ND_ATMs/sound", JSON.stringify({}));
|
||||
confirmationScreen(false)
|
||||
loader(true)
|
||||
setTimeout(() => {
|
||||
loader(false)
|
||||
atmDisplay(true)
|
||||
}, 300);
|
||||
return false
|
||||
})
|
||||
|
||||
$("#atm").submit(function() {
|
||||
$.post("https://ND_ATMs/sound", JSON.stringify({}));
|
||||
confirmationScreen(false)
|
||||
loader(true)
|
||||
setTimeout(() => {
|
||||
loader(false)
|
||||
if (withdraw) {
|
||||
$.post("https://ND_ATMs/withdraw", JSON.stringify({
|
||||
amount: $("#enteredAmount").val()
|
||||
}));
|
||||
} else if (deposit) {
|
||||
$.post("https://ND_ATMs/deposit", JSON.stringify({
|
||||
amount: $("#enteredAmount").val()
|
||||
}));
|
||||
}
|
||||
withdraw = false
|
||||
deposit = false
|
||||
successScreen(true)
|
||||
}, 2500);
|
||||
return false
|
||||
})
|
||||
|
||||
$("#mainMenuButton").click(function() {
|
||||
$.post("https://ND_ATMs/sound", JSON.stringify({}));
|
||||
successScreen(false)
|
||||
loader(true)
|
||||
setTimeout(() => {
|
||||
loader(false)
|
||||
atmDisplay(true)
|
||||
}, 300);
|
||||
return false
|
||||
})
|
||||
|
||||
$("#closeButton").click(function() {
|
||||
$.post("https://ND_ATMs/close", JSON.stringify({}));
|
||||
return
|
||||
})
|
||||
});
|
||||
211
ND_ATMs/source/ui/style.css
Normal file
211
ND_ATMs/source/ui/style.css
Normal file
@@ -0,0 +1,211 @@
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
#overlay {
|
||||
position: absolute;
|
||||
height: 60vh;
|
||||
width: 50vw;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border-radius: 10px;
|
||||
background-image: linear-gradient(rgb(255, 255, 255), rgb(199, 199, 199));
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#logo {
|
||||
position: absolute;
|
||||
width: 300px;
|
||||
top: 2vh;
|
||||
left: 6vw;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#date {
|
||||
position: absolute;
|
||||
top: 3.5vh;
|
||||
right: 6vw;
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
#time {
|
||||
position: absolute;
|
||||
font-weight: 500;
|
||||
top: -1.5vh;
|
||||
right: 6vw;
|
||||
color: black;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
#balance {
|
||||
position: absolute;
|
||||
top: 23vh;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;;
|
||||
font-weight: 500;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
color: black;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#confirmText {
|
||||
position: absolute;
|
||||
top: 26vh;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;;
|
||||
font-weight: 500;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
color: black;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#redline {
|
||||
position: absolute;
|
||||
height: 1vh;
|
||||
width: 80%;
|
||||
top: 9vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
background-color: red;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#redbox {
|
||||
position: absolute;
|
||||
height: 5vh;
|
||||
width: 80%;
|
||||
top: 11vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
background-color: red;
|
||||
background-image: linear-gradient(rgb(204, 2, 2), rgb(255, 0, 0));
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#playername {
|
||||
position: absolute;
|
||||
top: 13vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#welcome {
|
||||
position: absolute;
|
||||
top: 11.5vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input {
|
||||
height: 4vh;
|
||||
width: 7.3vw;
|
||||
background-color: rgb(255, 0, 0);
|
||||
font-weight: 1000;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
margin: auto;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;;
|
||||
transition: 50ms;
|
||||
}
|
||||
|
||||
.input:hover {
|
||||
transition: 50ms;
|
||||
background-color: rgb(214, 2, 2);
|
||||
}
|
||||
|
||||
#enteredAmount {
|
||||
position: absolute;
|
||||
width: 15.8vw;
|
||||
top: 28vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: black;
|
||||
background-color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#withdrawButton {
|
||||
position: absolute;
|
||||
top: 36.5vh;
|
||||
left: 17vw;
|
||||
}
|
||||
|
||||
#depositButton {
|
||||
position: absolute;
|
||||
top: 36.5vh;
|
||||
right: 17vw;
|
||||
}
|
||||
|
||||
#mainMenuButton {
|
||||
position: absolute;
|
||||
width: 10vw;
|
||||
top: 34vh;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#closeButton {
|
||||
position: absolute;
|
||||
height: 4.8vh;
|
||||
width: 80%;
|
||||
top: 50vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#confirmButton{
|
||||
position: absolute;
|
||||
top: 33vh;
|
||||
left: 17vw;
|
||||
}
|
||||
|
||||
#cancelButton {
|
||||
position: absolute;
|
||||
top: 33vh;
|
||||
right: 17vw;
|
||||
}
|
||||
|
||||
#confirmationScreen {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loader {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
border: 16px solid #d1d1d1;
|
||||
border-radius: 50%;
|
||||
border-top: 16px solid red;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
Reference in New Issue
Block a user