mirror of
https://github.com/FlamedDogo99/EaglerMobile.git
synced 2024-11-21 11:36:05 -08:00
Reworked touch & drag controls
This commit is contained in:
parent
4fea1b9d7e
commit
03ad0553b4
|
@ -18,13 +18,14 @@ try {
|
||||||
unsafeWindow.console.warn("DANGER: This userscript is using unsafeWindow. Unsafe websites could potentially use this to gain access to data and other content that the browser normally wouldn't allow!")
|
unsafeWindow.console.warn("DANGER: This userscript is using unsafeWindow. Unsafe websites could potentially use this to gain access to data and other content that the browser normally wouldn't allow!")
|
||||||
Object.defineProperty(window, "clientWindow", {
|
Object.defineProperty(window, "clientWindow", {
|
||||||
value: unsafeWindow
|
value: unsafeWindow
|
||||||
});
|
}); // If this is a userscript, use unsafeWindow
|
||||||
} catch {
|
} catch {
|
||||||
Object.defineProperty(window, "clientWindow", {
|
Object.defineProperty(window, "clientWindow", {
|
||||||
value: window
|
value: window
|
||||||
});
|
}); // If this is plain javascript, use window
|
||||||
}
|
}
|
||||||
// To-do: remove the mobile check is implement the dynamic enabling and disabling of individual features
|
clientWindow.console.log("Eagler Mobile v3.0.4")
|
||||||
|
// TODO: remove the mobile check is implement the dynamic enabling and disabling of individual features
|
||||||
function isMobile() {
|
function isMobile() {
|
||||||
try {
|
try {
|
||||||
document.createEvent("TouchEvent");
|
document.createEvent("TouchEvent");
|
||||||
|
@ -42,12 +43,22 @@ clientWindow.sprintLock = false; // Used for sprint mobile control
|
||||||
clientWindow.keyboardFix = false; // keyboardFix ? "Standard Keyboard" : "Compatibility Mode"
|
clientWindow.keyboardFix = false; // keyboardFix ? "Standard Keyboard" : "Compatibility Mode"
|
||||||
clientWindow.inputFix = false; // If true, Duplicate Mode
|
clientWindow.inputFix = false; // If true, Duplicate Mode
|
||||||
clientWindow.blockNextInput = false; // Used for Duplicate Mode
|
clientWindow.blockNextInput = false; // Used for Duplicate Mode
|
||||||
clientWindow.hiddenInputFocused = false;
|
clientWindow.hiddenInputFocused = false; // Used for keyboard display on mobile
|
||||||
|
clientWindow.canvasTouchMode = 0; // Used for canvas touch handling
|
||||||
// Used for changing touchmove events to mousemove events
|
/*
|
||||||
var previousTouchX = null;
|
0 Idle
|
||||||
var previousTouchY = null;
|
1 Touch initiated
|
||||||
var startTouchX = null;
|
2 Primary touch
|
||||||
|
3 Secondary touch
|
||||||
|
4 Scroll
|
||||||
|
5 Finished
|
||||||
|
*/
|
||||||
|
clientWindow.canvasTouchStartX = null;
|
||||||
|
clientWindow.canvasTouchStartY = null;
|
||||||
|
clientWindow.canvasTouchPreviousX = null;
|
||||||
|
clientWindow.canvasTouchPreviousY = null;
|
||||||
|
clientWindow.canvasPrimaryID = null;
|
||||||
|
clientWindow.buttonTouchStartX = null;
|
||||||
|
|
||||||
// charCodeAt is designed for unicode characters, and doesn't match the behavior of the keyCodes used by KeyboardEvents, thus necessitating this function
|
// charCodeAt is designed for unicode characters, and doesn't match the behavior of the keyCodes used by KeyboardEvents, thus necessitating this function
|
||||||
String.prototype.toKeyCode = function() {
|
String.prototype.toKeyCode = function() {
|
||||||
|
@ -61,12 +72,12 @@ Object.defineProperty(EventTarget.prototype, "addEventListener", {
|
||||||
value: function (type, fn, ...rest) {
|
value: function (type, fn, ...rest) {
|
||||||
if(type == 'keydown') { // Check if a keydown event is being added
|
if(type == 'keydown') { // Check if a keydown event is being added
|
||||||
_addEventListener.call(this, type, function(...args) {
|
_addEventListener.call(this, type, function(...args) {
|
||||||
if(!args[0].isValid && clientWindow.keyboardFix) { // Inject check for isValid flag and Compatibility Mode
|
if(args[0].isTrusted && clientWindow.keyboardFix) { // When we are in compatibility mode, we ignore all trusted keyboard events
|
||||||
return; // When we are in Compatibility Mode, standard key presses will be ignored
|
return;
|
||||||
}
|
}
|
||||||
return fn.apply(this, args); // Appends the rest of the function specified by addEventListener
|
return fn.apply(this, args); // Appends the rest of the function specified by addEventListener
|
||||||
}, ...rest);
|
}, ...rest);
|
||||||
} else { // If it's not a keydown event, behave like normal
|
} else { // If it's not a keydown event, behave like normal (hopefully)
|
||||||
_addEventListener.call(this, type, fn, ...rest);
|
_addEventListener.call(this, type, fn, ...rest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,11 +102,10 @@ function keyEvent(name, state) {
|
||||||
keyCode: charCode,
|
keyCode: charCode,
|
||||||
which: charCode
|
which: charCode
|
||||||
});
|
});
|
||||||
evt.isValid = true; // Disables fix for bad keyboard input
|
|
||||||
clientWindow.dispatchEvent(evt);
|
clientWindow.dispatchEvent(evt);
|
||||||
}
|
}
|
||||||
function mouseEvent(number, state, canvas) {
|
function mouseEvent(number, state, canvas, clientX, clientY) {
|
||||||
canvas.dispatchEvent(new PointerEvent(state, {"button": number}))
|
canvas.dispatchEvent(new PointerEvent(state, {"button": number, "buttons": number, "clientX": clientX ?? 0, "clientY" : clientY ?? 0, "screenX": clientX ?? 0, "screenY": clientY ?? 0}))
|
||||||
}
|
}
|
||||||
function wheelEvent(canvas, delta) {
|
function wheelEvent(canvas, delta) {
|
||||||
canvas.dispatchEvent(new WheelEvent("wheel", {
|
canvas.dispatchEvent(new WheelEvent("wheel", {
|
||||||
|
@ -168,8 +178,8 @@ const _createElement = document.createElement;
|
||||||
document.createElement = function(type, ignore) {
|
document.createElement = function(type, ignore) {
|
||||||
this._createElement = _createElement;
|
this._createElement = _createElement;
|
||||||
var element = this._createElement(type);
|
var element = this._createElement(type);
|
||||||
if(type == "input" && !ignore) {
|
if(type == "input" && !ignore) { // We set the ingore flag to true when we create the hiddenInput
|
||||||
document.querySelectorAll('#fileUpload').forEach(e => e.parentNode.removeChild(e));
|
document.querySelectorAll('#fileUpload').forEach(e => e.parentNode.removeChild(e)); // Get rid of any left over fileUpload inputs
|
||||||
element.id = "fileUpload";
|
element.id = "fileUpload";
|
||||||
element.addEventListener('change', function(e) {
|
element.addEventListener('change', function(e) {
|
||||||
element.hidden = true;
|
element.hidden = true;
|
||||||
|
@ -237,30 +247,100 @@ waitForElm('canvas').then(() => {insertCanvasElements()});
|
||||||
function insertCanvasElements() {
|
function insertCanvasElements() {
|
||||||
// Translates touchmove events to mousemove events when inGame, and touchmove events to wheele events when inMenu
|
// Translates touchmove events to mousemove events when inGame, and touchmove events to wheele events when inMenu
|
||||||
var canvas = document.querySelector('canvas');
|
var canvas = document.querySelector('canvas');
|
||||||
canvas.addEventListener("touchmove", function(e) {
|
canvas.addEventListener("touchstart", function(e) {
|
||||||
e.preventDefault();
|
if(clientWindow.canvasTouchMode < 2) { // If a touch is initiated but not assigned
|
||||||
const touch = e.targetTouches[0]; // We can get away with this because every other touch event will be on different elements
|
if(clientWindow.canvasPrimaryID == null) {
|
||||||
|
clientWindow.canvasTouchMode = 1;
|
||||||
|
const primaryTouch = e.changedTouches[0];
|
||||||
|
clientWindow.canvasPrimaryID = primaryTouch.identifier
|
||||||
|
canvasTouchStartX = primaryTouch.clientX;
|
||||||
|
canvasTouchStartY = primaryTouch.clientY;
|
||||||
|
canvasTouchPreviousX = canvasTouchStartX
|
||||||
|
canvasTouchPreviousY = canvasTouchStartY
|
||||||
|
|
||||||
if (!previousTouchX) {
|
clientWindow.touchTimer = setTimeout(function(e) {
|
||||||
previousTouchX = touch.pageX;
|
// If our touch is still set to initiaited, set it to secondary touch
|
||||||
previousTouchY = touch.pageY;
|
if(clientWindow.canvasTouchMode == 1) {
|
||||||
|
clientWindow.canvasTouchMode = 3;
|
||||||
|
mouseEvent(2, "mousedown", canvas, primaryTouch.clientX, primaryTouch.clientY)
|
||||||
|
if(clientWindow.fakelock) { // We only dispatch mouseup inGame because we want to be able to click + drag items in GUI's
|
||||||
|
mouseEvent(2, "mouseup", canvas, primaryTouch.clientX, primaryTouch.clientY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
} else if(clientWindow.canvasTouchMode == 1 && !clientWindow.fakelock) { // If we already have a primary touch, it means we're using two fingers
|
||||||
|
clientWindow.canvasTouchMode = 4;
|
||||||
|
clearTimeout(clientWindow.crouchTimer); // TODO: Find out why this isn't redudnant
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e.movementX = touch.pageX - previousTouchX;
|
|
||||||
e.movementY = touch.pageY - previousTouchY;
|
|
||||||
var evt = clientWindow.fakelock ? new MouseEvent("mousemove", {movementX: e.movementX, movementY: e.movementY}) : new WheelEvent("wheel", {"wheelDeltaY": e.movementY});
|
|
||||||
canvas.dispatchEvent(evt);
|
|
||||||
previousTouchX = touch.pageX;
|
|
||||||
previousTouchY = touch.pageY;
|
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
canvas.addEventListener("touchend", function(e) {
|
canvas.addEventListener("touchmove", function(e) {
|
||||||
previousTouchX = null;
|
e.preventDefault() // Prevents window zoom when using two fingers
|
||||||
previousTouchY = null;
|
var primaryTouch;
|
||||||
}, false)
|
for (let touchIndex = 0; touchIndex < e.targetTouches.length; touchIndex++) { // Iterate through our touches to find a touch event matching the primary touch ID
|
||||||
//Updates button visibility on load
|
if(e.targetTouches[touchIndex].identifier == clientWindow.canvasPrimaryID) {
|
||||||
setButtonVisibility(clientWindow.fakelock != null);
|
primaryTouch = e.targetTouches[touchIndex];
|
||||||
// Adds all of the touch screen controls
|
break;
|
||||||
// Theres probably a better way to do this but this works for now
|
}
|
||||||
|
}
|
||||||
|
if(primaryTouch) {
|
||||||
|
primaryTouch.distanceX = primaryTouch.clientX - canvasTouchStartX;
|
||||||
|
primaryTouch.distanceY = primaryTouch.clientY - canvasTouchStartY;
|
||||||
|
primaryTouch.squaredNorm = (primaryTouch.distanceX * primaryTouch.distanceX) + (primaryTouch.distanceY * primaryTouch.distanceY);
|
||||||
|
primaryTouch.movementX = primaryTouch.clientX - canvasTouchPreviousX;
|
||||||
|
primaryTouch.movementY = primaryTouch.clientY - canvasTouchPreviousY;
|
||||||
|
if(clientWindow.canvasTouchMode == 1) { // If the primary touch is still only initiated
|
||||||
|
if (primaryTouch.squaredNorm > 25) { // If our touch becomes a touch + drag
|
||||||
|
clearTimeout(clientWindow.crouchTimer);
|
||||||
|
clientWindow.canvasTouchMode = 2;
|
||||||
|
if(!clientWindow.fakelock) { // When we're inGame, we don't want to be placing blocks when we are moving the camera around
|
||||||
|
mouseEvent(1, "mousedown", canvas, primaryTouch.clientX, primaryTouch.clientY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // If our touch is primary, secondary, scroll or finished
|
||||||
|
if(clientWindow.canvasTouchMode == 4) { // If our touch is scrolling
|
||||||
|
wheelEvent(canvas, primaryTouch.movementY)
|
||||||
|
} else {
|
||||||
|
canvas.dispatchEvent(new MouseEvent("mousemove", {
|
||||||
|
"clientX": primaryTouch.clientX,
|
||||||
|
"clientY": primaryTouch.clientY,
|
||||||
|
"screenX": primaryTouch.screenX,
|
||||||
|
"screenY": primaryTouch.screenY, // The top four are used for item position when in GUI's, the bottom two are for moving the camera inGame
|
||||||
|
"movementX": primaryTouch.movementX,
|
||||||
|
"movementY": primaryTouch.movementY
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
canvasTouchPreviousX = primaryTouch.clientX
|
||||||
|
canvasTouchPreviousY = primaryTouch.clientY
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
function canvasTouchEnd(e) {
|
||||||
|
for(let touchIndex = 0; touchIndex < e.changedTouches.length; touchIndex++) { // Iterate through changed touches to find primary touch
|
||||||
|
if(e.changedTouches[touchIndex].identifier == clientWindow.canvasPrimaryID) {
|
||||||
|
let primaryTouch = e.changedTouches[touchIndex]
|
||||||
|
// When any of the controlling fingers go away, we want to wait until we aren't receiving any other touch events
|
||||||
|
if(clientWindow.canvasTouchMode == 2) {
|
||||||
|
mouseEvent(1, "mouseup", canvas, primaryTouch.clientX, primaryTouch.clientY)
|
||||||
|
} else if (clientWindow.canvasTouchMode == 3) {
|
||||||
|
e.preventDefault(); // This prevents some mobile devices from dispatching a mousedown + mouseup event after a touch is ended
|
||||||
|
mouseEvent(2, "mouseup", canvas, primaryTouch.clientX, primaryTouch.clientY)
|
||||||
|
}
|
||||||
|
clientWindow.canvasTouchMode = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(e.targetTouches.length == 0) { // We want to wait until all fingers are off the canvas before we reset for the next cycle
|
||||||
|
clientWindow.canvasTouchMode = 0;
|
||||||
|
clientWindow.canvasPrimaryID = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.addEventListener("touchend", canvasTouchEnd, false);
|
||||||
|
canvas.addEventListener("touchcancel", canvasTouchEnd, false); // TODO: Find out why this is different than touchend
|
||||||
|
setButtonVisibility(clientWindow.fakelock != null); //Updates our mobile controls when the canvas finally loads
|
||||||
|
// All of the touch buttons
|
||||||
let strafeRightButton = createTouchButton("strafeRightButton", "inGame", "div");
|
let strafeRightButton = createTouchButton("strafeRightButton", "inGame", "div");
|
||||||
strafeRightButton.style.cssText = "left:20vh;bottom:20vh;"
|
strafeRightButton.style.cssText = "left:20vh;bottom:20vh;"
|
||||||
document.body.appendChild(strafeRightButton);
|
document.body.appendChild(strafeRightButton);
|
||||||
|
@ -268,7 +348,7 @@ function insertCanvasElements() {
|
||||||
strafeLeftButton.style.cssText = "left:0vh;bottom:20vh;"
|
strafeLeftButton.style.cssText = "left:0vh;bottom:20vh;"
|
||||||
document.body.appendChild(strafeLeftButton);
|
document.body.appendChild(strafeLeftButton);
|
||||||
|
|
||||||
let forwardButton = createTouchButton("forwardButton", "inGame", "div");
|
let forwardButton = createTouchButton("forwardButton", "inGame", "div"); // We use a div here so can use the targetTouches property of touchmove events. If we didn't it would require me to make an actual touch handler and I don't want to
|
||||||
forwardButton.style.cssText = "left:10vh;bottom:20vh;"
|
forwardButton.style.cssText = "left:10vh;bottom:20vh;"
|
||||||
forwardButton.addEventListener("touchstart", function(e){
|
forwardButton.addEventListener("touchstart", function(e){
|
||||||
keyEvent("w", "keydown");
|
keyEvent("w", "keydown");
|
||||||
|
@ -278,12 +358,12 @@ function insertCanvasElements() {
|
||||||
}, false);
|
}, false);
|
||||||
forwardButton.addEventListener("touchmove", function(e) {
|
forwardButton.addEventListener("touchmove", function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const touch = e.targetTouches[0]; // We can get away with this because every other touch event will be on different elements
|
const touch = e.targetTouches[0]; // We are just hoping that the user will only ever use one finger on the forward button
|
||||||
|
|
||||||
if (!startTouchX) {
|
if (!buttonTouchStartX) { // TODO: move this to a touchstart event handler
|
||||||
startTouchX = touch.pageX;
|
buttonTouchStartX = touch.pageX;
|
||||||
}
|
}
|
||||||
let movementX = touch.pageX - startTouchX;
|
let movementX = touch.pageX - buttonTouchStartX;
|
||||||
if((movementX * 10) > clientWindow.innerHeight) {
|
if((movementX * 10) > clientWindow.innerHeight) {
|
||||||
strafeRightButton.classList.add("active");
|
strafeRightButton.classList.add("active");
|
||||||
strafeLeftButton.classList.remove("active");
|
strafeLeftButton.classList.remove("active");
|
||||||
|
@ -302,7 +382,7 @@ function insertCanvasElements() {
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
forwardButton.addEventListener("touchend", function(e) {
|
forwardButton.addEventListener("touchend", function(e) {
|
||||||
keyEvent("w", "keyup");
|
keyEvent("w", "keyup"); // Luckily, it doesn't seem like eagler cares if we dispatch extra keyup events, so we can get away with just dispatching all of them here
|
||||||
keyEvent("d", "keyup");
|
keyEvent("d", "keyup");
|
||||||
keyEvent("a", "keyup");
|
keyEvent("a", "keyup");
|
||||||
strafeRightButton.classList.remove("active");
|
strafeRightButton.classList.remove("active");
|
||||||
|
@ -311,7 +391,7 @@ function insertCanvasElements() {
|
||||||
strafeLeftButton.classList.add("hide");
|
strafeLeftButton.classList.add("hide");
|
||||||
forwardButton.classList.remove("active");
|
forwardButton.classList.remove("active");
|
||||||
|
|
||||||
startTouchX = null;
|
buttonTouchStartX = null;
|
||||||
}, false);
|
}, false);
|
||||||
strafeRightButton.classList.add("hide");
|
strafeRightButton.classList.add("hide");
|
||||||
strafeLeftButton.classList.add("hide");
|
strafeLeftButton.classList.add("hide");
|
||||||
|
@ -344,7 +424,7 @@ function insertCanvasElements() {
|
||||||
crouchButton.addEventListener("touchstart", function(e){
|
crouchButton.addEventListener("touchstart", function(e){
|
||||||
keyEvent("shift", "keydown")
|
keyEvent("shift", "keydown")
|
||||||
clientWindow.crouchLock = clientWindow.crouchLock ? null : false
|
clientWindow.crouchLock = clientWindow.crouchLock ? null : false
|
||||||
clientWindow.crouchTimer = setTimeout(function(e) {
|
clientWindow.crouchTimer = setTimeout(function(e) { // Allows us to lock the button after a long press
|
||||||
clientWindow.crouchLock = (clientWindow.crouchLock != null);
|
clientWindow.crouchLock = (clientWindow.crouchLock != null);
|
||||||
crouchButton.classList.toggle('active');
|
crouchButton.classList.toggle('active');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -361,7 +441,10 @@ function insertCanvasElements() {
|
||||||
document.body.appendChild(crouchButton);
|
document.body.appendChild(crouchButton);
|
||||||
let inventoryButton = createTouchButton("inventoryButton", "inGame");
|
let inventoryButton = createTouchButton("inventoryButton", "inGame");
|
||||||
inventoryButton.style.cssText = "right:0vh;bottom:30vh;"
|
inventoryButton.style.cssText = "right:0vh;bottom:30vh;"
|
||||||
inventoryButton.addEventListener("touchstart", function(e){keyEvent("e", "keydown")}, false);
|
inventoryButton.addEventListener("touchstart", function(e) {
|
||||||
|
keyEvent("shift", "keyup"); // Sometimes shift gets stuck on, which interferes with item manipulation in GUI's
|
||||||
|
keyEvent("e", "keydown");
|
||||||
|
}, false);
|
||||||
inventoryButton.addEventListener("touchend", function(e){keyEvent("e", "keyup")}, false);
|
inventoryButton.addEventListener("touchend", function(e){keyEvent("e", "keyup")}, false);
|
||||||
document.body.appendChild(inventoryButton);
|
document.body.appendChild(inventoryButton);
|
||||||
let exitButton = createTouchButton("exitButton", "inMenu");
|
let exitButton = createTouchButton("exitButton", "inMenu");
|
||||||
|
@ -450,7 +533,7 @@ function insertCanvasElements() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
hiddenInput.addEventListener("blur", function(e) {
|
hiddenInput.addEventListener("blur", function(e) { // Updates clientWindow.hiddenInputFocused to reflect the actual state of the focus
|
||||||
clientWindow.hiddenInputFocused = false;
|
clientWindow.hiddenInputFocused = false;
|
||||||
});
|
});
|
||||||
document.body.appendChild(hiddenInput);
|
document.body.appendChild(hiddenInput);
|
||||||
|
@ -567,39 +650,47 @@ customStyle.textContent = `
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 10vh;
|
width: 10vh;
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
font-size:4vh;
|
font-size: 4vh;
|
||||||
-webkit-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
line-height: 0px;
|
line-height: 0px;
|
||||||
padding:0px;
|
padding: 0px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
outline:none;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
outline: none;
|
||||||
|
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||||
}
|
}
|
||||||
.mobileControl:active, .mobileControl.active {
|
.mobileControl:active, .mobileControl.active {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 10vh;
|
width: 10vh;
|
||||||
height: 10vh;
|
height: 10vh;
|
||||||
font-size:4vh;
|
font-size: 4vh;
|
||||||
-webkit-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
line-height: 0px;
|
line-height: 0px;
|
||||||
padding:0px;
|
padding: 0px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: #ffffff;
|
|
||||||
text-shadow: 0.35vh 0.35vh #000000;
|
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
background-size: contain, cover;
|
background-size: cover;
|
||||||
outline:none;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
touch-action: pan-x pan-y;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
outline: none;
|
||||||
|
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||||
}
|
}
|
||||||
html, body, canvas {
|
html, body, canvas {
|
||||||
height: 100svh !important;
|
height: 100svh !important;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user