mirror of
https://github.com/NohamR/Pocket-Bird.git
synced 2026-05-24 19:59:36 +00:00
Switch to absolute positioning when on element
This commit is contained in:
60
birb.js
60
birb.js
@@ -32,7 +32,7 @@ const HOP_SPEED = CONFIG.hopSpeed;
|
|||||||
const FLY_SPEED = CONFIG.flySpeed;
|
const FLY_SPEED = CONFIG.flySpeed;
|
||||||
const HOP_DISTANCE = CONFIG.hopDistance;
|
const HOP_DISTANCE = CONFIG.hopDistance;
|
||||||
// Time in milliseconds until the user is considered AFK
|
// Time in milliseconds until the user is considered AFK
|
||||||
const AFK_TIME = (debugMode || isMobile()) ? 0 : 1000 * 30;
|
const AFK_TIME = debugMode ? 0 : 1000 * 30;
|
||||||
const SPRITE_HEIGHT = 32;
|
const SPRITE_HEIGHT = 32;
|
||||||
const MENU_ID = "birb-menu";
|
const MENU_ID = "birb-menu";
|
||||||
const MENU_EXIT_ID = "birb-menu-exit";
|
const MENU_EXIT_ID = "birb-menu-exit";
|
||||||
@@ -957,11 +957,6 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
|
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
lastActionTimestamp = Date.now();
|
lastActionTimestamp = Date.now();
|
||||||
// Can't keep up with scrolling on mobile devices so fly down instead
|
|
||||||
if (isMobile()) {
|
|
||||||
// focusOnGround();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onClick(document, (e) => {
|
onClick(document, (e) => {
|
||||||
@@ -1668,22 +1663,30 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getFocusedElementY() {
|
|
||||||
// if (focusedElement === null) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// const rect = focusedElement.getBoundingClientRect();
|
|
||||||
// return window.innerHeight - rect.top;
|
|
||||||
// }
|
|
||||||
|
|
||||||
function getFocusedY() {
|
function getFocusedY() {
|
||||||
return window.innerHeight - focusedBounds.top;
|
return getFullWindowHeight() - focusedBounds.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The render-safe height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getSafeWindowHeight() {
|
||||||
|
// Necessary because iOS 26 Safari is terrible and won't render
|
||||||
|
// fixed elements behind the address bar
|
||||||
|
return window.innerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The true height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getFullWindowHeight() {
|
||||||
|
return document.documentElement.clientHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusOnGround() {
|
function focusOnGround() {
|
||||||
console.log("Focusing on ground");
|
console.log("Focusing on ground");
|
||||||
focusedElement = null;
|
focusedElement = null;
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getSafeWindowHeight() };
|
||||||
flyTo(Math.random() * window.innerWidth, 0);
|
flyTo(Math.random() * window.innerWidth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1713,7 +1716,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
function updateFocusedElementBounds() {
|
function updateFocusedElementBounds() {
|
||||||
if (focusedElement === null) {
|
if (focusedElement === null) {
|
||||||
// Update ground location to bottom of window
|
// Update ground location to bottom of window
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getFullWindowHeight() };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rect = focusedElement.getBoundingClientRect();
|
const rect = focusedElement.getBoundingClientRect();
|
||||||
@@ -1771,6 +1774,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
setAnimation(Animations.FLYING);
|
setAnimation(Animations.FLYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} Whether the bird should be absolutely positioned
|
||||||
|
*/
|
||||||
|
function isAbsolute() {
|
||||||
|
return focusedElement !== null && (currentState === States.IDLE || currentState === States.HOP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current animation and reset the animation timer
|
* Set the current animation and reset the animation timer
|
||||||
* @param {Anim} animation
|
* @param {Anim} animation
|
||||||
@@ -1792,6 +1802,12 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
if (state === States.IDLE) {
|
if (state === States.IDLE) {
|
||||||
setAnimation(Animations.BOB);
|
setAnimation(Animations.BOB);
|
||||||
}
|
}
|
||||||
|
if (isAbsolute()) {
|
||||||
|
canvas.classList.add("birb-absolute");
|
||||||
|
} else {
|
||||||
|
canvas.classList.remove("birb-absolute");
|
||||||
|
}
|
||||||
|
setY(birdY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1806,7 +1822,15 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
* @param {number} y
|
* @param {number} y
|
||||||
*/
|
*/
|
||||||
function setY(y) {
|
function setY(y) {
|
||||||
canvas.style.bottom = `${y}px`;
|
let bottom;
|
||||||
|
if (isAbsolute()) {
|
||||||
|
// Position is absolute, convert from fixed
|
||||||
|
bottom = y - window.scrollY;
|
||||||
|
} else {
|
||||||
|
// Position is fixed
|
||||||
|
bottom = y;
|
||||||
|
}
|
||||||
|
canvas.style.bottom = `${bottom}px`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
2
build.js
2
build.js
@@ -24,7 +24,7 @@ const userScriptHeader =
|
|||||||
`// ==UserScript==
|
`// ==UserScript==
|
||||||
// @name Pocket Bird
|
// @name Pocket Bird
|
||||||
// @namespace https://idreesinc.com
|
// @namespace https://idreesinc.com
|
||||||
// @version 2025-10-22-04
|
// @version 2025-10-23-01
|
||||||
// @description birb
|
// @description birb
|
||||||
// @author Idrees
|
// @author Idrees
|
||||||
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/birb.user.js
|
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/birb.user.js
|
||||||
|
|||||||
64
dist/birb.js
vendored
64
dist/birb.js
vendored
@@ -32,7 +32,7 @@ const HOP_SPEED = CONFIG.hopSpeed;
|
|||||||
const FLY_SPEED = CONFIG.flySpeed;
|
const FLY_SPEED = CONFIG.flySpeed;
|
||||||
const HOP_DISTANCE = CONFIG.hopDistance;
|
const HOP_DISTANCE = CONFIG.hopDistance;
|
||||||
// Time in milliseconds until the user is considered AFK
|
// Time in milliseconds until the user is considered AFK
|
||||||
const AFK_TIME = (debugMode || isMobile()) ? 0 : 1000 * 30;
|
const AFK_TIME = debugMode ? 0 : 1000 * 30;
|
||||||
const SPRITE_HEIGHT = 32;
|
const SPRITE_HEIGHT = 32;
|
||||||
const MENU_ID = "birb-menu";
|
const MENU_ID = "birb-menu";
|
||||||
const MENU_EXIT_ID = "birb-menu-exit";
|
const MENU_EXIT_ID = "birb-menu-exit";
|
||||||
@@ -74,6 +74,10 @@ const STYLESHEET = `:root {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.birb-absolute {
|
||||||
|
position: absolute !important;
|
||||||
|
}
|
||||||
|
|
||||||
.birb-decoration {
|
.birb-decoration {
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -1296,11 +1300,6 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
|
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
lastActionTimestamp = Date.now();
|
lastActionTimestamp = Date.now();
|
||||||
// Can't keep up with scrolling on mobile devices so fly down instead
|
|
||||||
if (isMobile()) {
|
|
||||||
// focusOnGround();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onClick(document, (e) => {
|
onClick(document, (e) => {
|
||||||
@@ -2007,22 +2006,30 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getFocusedElementY() {
|
|
||||||
// if (focusedElement === null) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// const rect = focusedElement.getBoundingClientRect();
|
|
||||||
// return window.innerHeight - rect.top;
|
|
||||||
// }
|
|
||||||
|
|
||||||
function getFocusedY() {
|
function getFocusedY() {
|
||||||
return window.innerHeight - focusedBounds.top;
|
return getFullWindowHeight() - focusedBounds.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The render-safe height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getSafeWindowHeight() {
|
||||||
|
// Necessary because iOS 26 Safari is terrible and won't render
|
||||||
|
// fixed elements behind the address bar
|
||||||
|
return window.innerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The true height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getFullWindowHeight() {
|
||||||
|
return document.documentElement.clientHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusOnGround() {
|
function focusOnGround() {
|
||||||
console.log("Focusing on ground");
|
console.log("Focusing on ground");
|
||||||
focusedElement = null;
|
focusedElement = null;
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getSafeWindowHeight() };
|
||||||
flyTo(Math.random() * window.innerWidth, 0);
|
flyTo(Math.random() * window.innerWidth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2052,7 +2059,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
function updateFocusedElementBounds() {
|
function updateFocusedElementBounds() {
|
||||||
if (focusedElement === null) {
|
if (focusedElement === null) {
|
||||||
// Update ground location to bottom of window
|
// Update ground location to bottom of window
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getFullWindowHeight() };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rect = focusedElement.getBoundingClientRect();
|
const rect = focusedElement.getBoundingClientRect();
|
||||||
@@ -2110,6 +2117,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
setAnimation(Animations.FLYING);
|
setAnimation(Animations.FLYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} Whether the bird should be absolutely positioned
|
||||||
|
*/
|
||||||
|
function isAbsolute() {
|
||||||
|
return focusedElement !== null && (currentState === States.IDLE || currentState === States.HOP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current animation and reset the animation timer
|
* Set the current animation and reset the animation timer
|
||||||
* @param {Anim} animation
|
* @param {Anim} animation
|
||||||
@@ -2131,6 +2145,12 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
if (state === States.IDLE) {
|
if (state === States.IDLE) {
|
||||||
setAnimation(Animations.BOB);
|
setAnimation(Animations.BOB);
|
||||||
}
|
}
|
||||||
|
if (isAbsolute()) {
|
||||||
|
canvas.classList.add("birb-absolute");
|
||||||
|
} else {
|
||||||
|
canvas.classList.remove("birb-absolute");
|
||||||
|
}
|
||||||
|
setY(birdY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2145,7 +2165,15 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
* @param {number} y
|
* @param {number} y
|
||||||
*/
|
*/
|
||||||
function setY(y) {
|
function setY(y) {
|
||||||
canvas.style.bottom = `${y}px`;
|
let bottom;
|
||||||
|
if (isAbsolute()) {
|
||||||
|
// Position is absolute, convert from fixed
|
||||||
|
bottom = y - window.scrollY;
|
||||||
|
} else {
|
||||||
|
// Position is fixed
|
||||||
|
bottom = y;
|
||||||
|
}
|
||||||
|
canvas.style.bottom = `${bottom}px`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
66
dist/birb.user.js
vendored
66
dist/birb.user.js
vendored
@@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Pocket Bird
|
// @name Pocket Bird
|
||||||
// @namespace https://idreesinc.com
|
// @namespace https://idreesinc.com
|
||||||
// @version 2025-10-22-04
|
// @version 2025-10-23-01
|
||||||
// @description birb
|
// @description birb
|
||||||
// @author Idrees
|
// @author Idrees
|
||||||
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/birb.user.js
|
// @downloadURL https://github.com/IdreesInc/Pocket-Bird/raw/refs/heads/main/dist/birb.user.js
|
||||||
@@ -46,7 +46,7 @@ const HOP_SPEED = CONFIG.hopSpeed;
|
|||||||
const FLY_SPEED = CONFIG.flySpeed;
|
const FLY_SPEED = CONFIG.flySpeed;
|
||||||
const HOP_DISTANCE = CONFIG.hopDistance;
|
const HOP_DISTANCE = CONFIG.hopDistance;
|
||||||
// Time in milliseconds until the user is considered AFK
|
// Time in milliseconds until the user is considered AFK
|
||||||
const AFK_TIME = (debugMode || isMobile()) ? 0 : 1000 * 30;
|
const AFK_TIME = debugMode ? 0 : 1000 * 30;
|
||||||
const SPRITE_HEIGHT = 32;
|
const SPRITE_HEIGHT = 32;
|
||||||
const MENU_ID = "birb-menu";
|
const MENU_ID = "birb-menu";
|
||||||
const MENU_EXIT_ID = "birb-menu-exit";
|
const MENU_EXIT_ID = "birb-menu-exit";
|
||||||
@@ -88,6 +88,10 @@ const STYLESHEET = `:root {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.birb-absolute {
|
||||||
|
position: absolute !important;
|
||||||
|
}
|
||||||
|
|
||||||
.birb-decoration {
|
.birb-decoration {
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -1310,11 +1314,6 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
|
|
||||||
window.addEventListener("scroll", () => {
|
window.addEventListener("scroll", () => {
|
||||||
lastActionTimestamp = Date.now();
|
lastActionTimestamp = Date.now();
|
||||||
// Can't keep up with scrolling on mobile devices so fly down instead
|
|
||||||
if (isMobile()) {
|
|
||||||
// focusOnGround();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onClick(document, (e) => {
|
onClick(document, (e) => {
|
||||||
@@ -2021,22 +2020,30 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
return birdX >= focusedBounds.left && birdX <= focusedBounds.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getFocusedElementY() {
|
|
||||||
// if (focusedElement === null) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// const rect = focusedElement.getBoundingClientRect();
|
|
||||||
// return window.innerHeight - rect.top;
|
|
||||||
// }
|
|
||||||
|
|
||||||
function getFocusedY() {
|
function getFocusedY() {
|
||||||
return window.innerHeight - focusedBounds.top;
|
return getFullWindowHeight() - focusedBounds.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The render-safe height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getSafeWindowHeight() {
|
||||||
|
// Necessary because iOS 26 Safari is terrible and won't render
|
||||||
|
// fixed elements behind the address bar
|
||||||
|
return window.innerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The true height of the inner browser window
|
||||||
|
*/
|
||||||
|
function getFullWindowHeight() {
|
||||||
|
return document.documentElement.clientHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusOnGround() {
|
function focusOnGround() {
|
||||||
console.log("Focusing on ground");
|
console.log("Focusing on ground");
|
||||||
focusedElement = null;
|
focusedElement = null;
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getSafeWindowHeight() };
|
||||||
flyTo(Math.random() * window.innerWidth, 0);
|
flyTo(Math.random() * window.innerWidth, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2066,7 +2073,7 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
function updateFocusedElementBounds() {
|
function updateFocusedElementBounds() {
|
||||||
if (focusedElement === null) {
|
if (focusedElement === null) {
|
||||||
// Update ground location to bottom of window
|
// Update ground location to bottom of window
|
||||||
focusedBounds = { left: 0, right: window.innerWidth, top: window.innerHeight };
|
focusedBounds = { left: 0, right: window.innerWidth, top: getFullWindowHeight() };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rect = focusedElement.getBoundingClientRect();
|
const rect = focusedElement.getBoundingClientRect();
|
||||||
@@ -2124,6 +2131,13 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
setAnimation(Animations.FLYING);
|
setAnimation(Animations.FLYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} Whether the bird should be absolutely positioned
|
||||||
|
*/
|
||||||
|
function isAbsolute() {
|
||||||
|
return focusedElement !== null && (currentState === States.IDLE || currentState === States.HOP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current animation and reset the animation timer
|
* Set the current animation and reset the animation timer
|
||||||
* @param {Anim} animation
|
* @param {Anim} animation
|
||||||
@@ -2145,6 +2159,12 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
if (state === States.IDLE) {
|
if (state === States.IDLE) {
|
||||||
setAnimation(Animations.BOB);
|
setAnimation(Animations.BOB);
|
||||||
}
|
}
|
||||||
|
if (isAbsolute()) {
|
||||||
|
canvas.classList.add("birb-absolute");
|
||||||
|
} else {
|
||||||
|
canvas.classList.remove("birb-absolute");
|
||||||
|
}
|
||||||
|
setY(birdY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2159,7 +2179,15 @@ Promise.all([loadSpriteSheetPixels(SPRITE_SHEET), loadSpriteSheetPixels(DECORATI
|
|||||||
* @param {number} y
|
* @param {number} y
|
||||||
*/
|
*/
|
||||||
function setY(y) {
|
function setY(y) {
|
||||||
canvas.style.bottom = `${y}px`;
|
let bottom;
|
||||||
|
if (isAbsolute()) {
|
||||||
|
// Position is absolute, convert from fixed
|
||||||
|
bottom = y - window.scrollY;
|
||||||
|
} else {
|
||||||
|
// Position is fixed
|
||||||
|
bottom = y;
|
||||||
|
}
|
||||||
|
canvas.style.bottom = `${bottom}px`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,10 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.birb-absolute {
|
||||||
|
position: absolute !important;
|
||||||
|
}
|
||||||
|
|
||||||
.birb-decoration {
|
.birb-decoration {
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
Reference in New Issue
Block a user