Merge pull request #26 from PyroNicampt/touch-input
Touch Input and Mobile Optimization
This commit is contained in:
4 files changed
+171
-99
No files matched your search
+13
-12
@@ -10,6 +10,7 @@
|
|||||||
<meta property="og:url" content="https://pyronicampt.github.io/DV-Community-Map/">
|
<meta property="og:url" content="https://pyronicampt.github.io/DV-Community-Map/">
|
||||||
<meta property="og:image" content="https://pyronicampt.github.io/DV-Community-Map/opengraph.png">
|
<meta property="og:image" content="https://pyronicampt.github.io/DV-Community-Map/opengraph.png">
|
||||||
<meta property="og:description" content="Web-based map of Derail Valley">
|
<meta property="og:description" content="Web-based map of Derail Valley">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
|
||||||
<script type="module" src="index.js"></script>
|
<script type="module" src="index.js"></script>
|
||||||
<script type="module" src="legend.js"></script>
|
<script type="module" src="legend.js"></script>
|
||||||
</head>
|
</head>
|
||||||
@@ -208,20 +209,28 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="stats" class="orange">
|
||||||
|
<div id="zoomLevelDisplay"></div>
|
||||||
|
Map v0.5 alpha
|
||||||
|
<br>
|
||||||
|
Updated for Game Build 99.3
|
||||||
|
<br>
|
||||||
|
This tool is a fan work, Derail Valley owned by Altfuture
|
||||||
|
</div>
|
||||||
<div id="topleft">
|
<div id="topleft">
|
||||||
<div id="headerbar" class="panel orange">
|
<div id="headerbar" class="panel orange">
|
||||||
<div>
|
<div>
|
||||||
DV Community Map
|
DV Community Map
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="legend" style="display: flex;">
|
<div id="legend">
|
||||||
<div id="legendContents" style="display:flex; flex-direction:column; width: 400px;">
|
<div id="legendContents">
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
Welcome to the WIP community map of <a href="https://www.derailvalley.com/" style="white-space:nowrap;">Derail Valley</a>, a resource for documenting and displaying all tracks and points of interest.
|
Welcome to the WIP community map of <a href="https://www.derailvalley.com/" style="white-space:nowrap;">Derail Valley</a>, a resource for documenting and displaying all tracks and points of interest.
|
||||||
<hr>
|
<hr>
|
||||||
Hover over tracks and objects for detailed information.
|
Hover over tracks and objects for detailed information.
|
||||||
</div>
|
</div>
|
||||||
<div class="panel" style="width:330px">
|
<div class="panel">
|
||||||
<h3>Key</h3>
|
<h3>Key</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<div id="legendKey"></div>
|
<div id="legendKey"></div>
|
||||||
@@ -236,16 +245,8 @@
|
|||||||
<a href="https://derailvalley.wiki.gg/wiki/Derail_Valley_Wiki">DV Wiki</a>
|
<a href="https://derailvalley.wiki.gg/wiki/Derail_Valley_Wiki">DV Wiki</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="legendButton" class="panel orange" style="height: fit-content;"><svg style="transform:rotate(180deg) translateY(-3px)" height="25" viewBox="0 0 32 32"><path fill="currentColor" d="M31 16 20 31l-16 0L15 16 4 1l16 0Z"/></svg></div>
|
<div id="legendButton" class="panel orange"><svg style="transform:rotate(180deg) translateY(0px)" viewBox="0 0 32 32"><path fill="currentColor" d="M31 16 20 31l-16 0L15 16 4 1l16 0Z"/></svg></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer" class="orange">
|
|
||||||
<div id="zoomLevelDisplay"></div>
|
|
||||||
Map v0.4 alpha
|
|
||||||
<br>
|
|
||||||
Updated for Game Build 99.3
|
|
||||||
<br>
|
|
||||||
This tool is a fan work, Derail Valley owned by Altfuture
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -44,7 +44,12 @@ const scaleCullThresholds = [
|
|||||||
|
|
||||||
// CODE
|
// CODE
|
||||||
const map = document.getElementById('map');
|
const map = document.getElementById('map');
|
||||||
|
|
||||||
const map_container = document.getElementById('mapContainer');
|
const map_container = document.getElementById('mapContainer');
|
||||||
|
let map_container_rect = map_container.getBoundingClientRect();
|
||||||
|
const resizeObserver = new ResizeObserver(() => {map_container_rect = map_container.getBoundingClientRect();});
|
||||||
|
resizeObserver.observe(map_container);
|
||||||
|
|
||||||
const map_navigator = document.getElementById('mapNavigator');
|
const map_navigator = document.getElementById('mapNavigator');
|
||||||
const zoomLevelDisplay = document.getElementById('zoomLevelDisplay');
|
const zoomLevelDisplay = document.getElementById('zoomLevelDisplay');
|
||||||
const styleRoot = document.querySelector(':root');
|
const styleRoot = document.querySelector(':root');
|
||||||
@@ -73,7 +78,8 @@ let poiData = [];
|
|||||||
let tracks = [];
|
let tracks = [];
|
||||||
let markers = [];
|
let markers = [];
|
||||||
|
|
||||||
let currentMapNav = {};
|
//let currentMapNav = {};
|
||||||
|
let mapNav = {};
|
||||||
let previousMapScale = -1;
|
let previousMapScale = -1;
|
||||||
|
|
||||||
let MapMatrix = {};
|
let MapMatrix = {};
|
||||||
@@ -113,83 +119,127 @@ async function loadPoiData(file){
|
|||||||
|
|
||||||
/** Handling for the map scrolling and zooming */
|
/** Handling for the map scrolling and zooming */
|
||||||
function mapScrollSetup(){
|
function mapScrollSetup(){
|
||||||
let mapNav = {x:currentMapNav.x, y:currentMapNav.y, scale:currentMapNav.scale};
|
const touchCache = [];
|
||||||
let prevMouse = {x:mapNav.x, y:mapNav.y, scale:mapNav.scale};
|
let touchCount = 0;
|
||||||
const mouseDownHandler = e => {
|
let pinchDistance = null;
|
||||||
|
let previousScale = null;
|
||||||
|
const touchDownHandler = e => {
|
||||||
|
if(touchCache.length == 0){
|
||||||
map_container.style.cursor = 'grabbing';
|
map_container.style.cursor = 'grabbing';
|
||||||
prevMouse.x = e.clientX;
|
document.addEventListener('pointermove', touchMoveHandler);
|
||||||
prevMouse.y = e.clientY;
|
|
||||||
|
|
||||||
document.addEventListener('mousemove', mouseMoveHandler);
|
document.addEventListener('pointerup', touchUpHandler);
|
||||||
document.addEventListener('mouseup', mouseUpHandler);
|
document.addEventListener('pointercancel', touchUpHandler);
|
||||||
};
|
//document.addEventListener('pointerout', touchUpHandler);
|
||||||
const mouseMoveHandler = e => {
|
document.addEventListener('pointerleave', touchUpHandler);
|
||||||
mapNav.x += prevMouse.x-e.clientX;
|
|
||||||
mapNav.y += prevMouse.y-e.clientY;
|
|
||||||
|
|
||||||
prevMouse.x = e.clientX;
|
|
||||||
prevMouse.y = e.clientY;
|
|
||||||
};
|
|
||||||
const mouseUpHandler = () => {
|
|
||||||
map_container.style.removeProperty('cursor');
|
|
||||||
document.removeEventListener('mousemove', mouseMoveHandler);
|
|
||||||
document.removeEventListener('mouseup', mouseUpHandler);
|
|
||||||
};
|
|
||||||
const zoomHandler = e => {
|
|
||||||
let rect = map_container.getBoundingClientRect();
|
|
||||||
let cursorLocal = {
|
|
||||||
x: -e.clientX - rect.left,
|
|
||||||
y: -e.clientY - rect.top
|
|
||||||
};
|
|
||||||
let scaleMult = 1;
|
|
||||||
if(e.deltaY < 0){
|
|
||||||
scaleMult = zoomFactor;
|
|
||||||
}else if(e.deltaY > 0){
|
|
||||||
scaleMult = 1/zoomFactor;
|
|
||||||
}
|
}
|
||||||
mapNav.x = cursorLocal.x - scaleMult * (cursorLocal.x-mapNav.x);
|
touchCache[e.pointerId] = {x:e.clientX, y:e.clientY};
|
||||||
mapNav.y = cursorLocal.y - scaleMult * (cursorLocal.y-mapNav.y);
|
touchCount++;
|
||||||
mapNav.scale *= scaleMult;
|
if(touchCount == 2){
|
||||||
};
|
pinchDistance = getTouchDistance();
|
||||||
|
previousScale = mapNav.scale;
|
||||||
let prevMapNav = {};
|
}
|
||||||
const navUpdate = () => {
|
}
|
||||||
if(prevMapNav.x != currentMapNav.x || prevMapNav.y != currentMapNav.y || prevMapNav.scale != currentMapNav.scale){
|
const touchMoveHandler = e => {
|
||||||
updateMapview(mapNav);
|
if(!touchCache[e.pointerId]) return;
|
||||||
prevMapNav.x = currentMapNav.x;
|
if(touchCount == 1){
|
||||||
prevMapNav.y = currentMapNav.y;
|
mapNav.x += e.clientX - touchCache[e.pointerId].x;
|
||||||
prevMapNav.scale = currentMapNav.scale;
|
mapNav.y += e.clientY - touchCache[e.pointerId].y;
|
||||||
|
}else if(touchCount == 2){
|
||||||
|
getTouchAverage();
|
||||||
|
zoomAtPosition(touchCenter_x, touchCenter_y, (previousScale * getTouchDistance()/pinchDistance)/mapNav.scale);
|
||||||
|
}
|
||||||
|
touchCache[e.pointerId].x = e.clientX;
|
||||||
|
touchCache[e.pointerId].y = e.clientY;
|
||||||
|
}
|
||||||
|
const touchUpHandler = e => {
|
||||||
|
if(!touchCache[e.pointerId]) return;
|
||||||
|
touchCache[e.pointerId] = null;
|
||||||
|
touchCount--;
|
||||||
|
}
|
||||||
|
const scrollHandler = e => {
|
||||||
|
if(e.deltaY != 0) zoomAtPosition(e.clientX, e.clientY, e.deltaY > 0 ? 1/zoomFactor : zoomFactor);
|
||||||
|
}
|
||||||
|
const navUpdate = ts => {
|
||||||
|
if(ts){
|
||||||
|
updateMapview();
|
||||||
}
|
}
|
||||||
requestAnimationFrame(navUpdate);
|
requestAnimationFrame(navUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
map_container.addEventListener('mousedown', mouseDownHandler);
|
let touchDist_aX = 0;
|
||||||
map_container.addEventListener('wheel', zoomHandler);
|
let touchDist_aY = 0;
|
||||||
|
let touchDist_counter = 0;
|
||||||
|
const getTouchDistance = () => {
|
||||||
|
touchDist_counter = 0;
|
||||||
|
touchDist_aX = 0;
|
||||||
|
touchDist_aY = 0;
|
||||||
|
for(let touch of touchCache){
|
||||||
|
if(touchDist_counter == 0){
|
||||||
|
touchDist_aX += touch.x;
|
||||||
|
touchDist_aY += touch.y;
|
||||||
|
}else{
|
||||||
|
touchDist_aX -= touch.x;
|
||||||
|
touchDist_aY -= touch.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
touchDist_counter++;
|
||||||
|
}
|
||||||
|
return Math.sqrt(touchDist_aX*touchDist_aX + touchDist_aY*touchDist_aY);
|
||||||
|
};
|
||||||
|
|
||||||
|
let touchCenter_x = 0;
|
||||||
|
let touchCenter_y = 0;
|
||||||
|
let touchCenter_count = 0;
|
||||||
|
const getTouchAverage = () => {
|
||||||
|
touchCenter_x = 0;
|
||||||
|
touchCenter_y = 0;
|
||||||
|
touchCenter_count = 0;
|
||||||
|
for(let touch of touchCache){
|
||||||
|
touchCenter_x += touch.x;
|
||||||
|
touchCenter_y += touch.y;
|
||||||
|
touchCenter_count++;
|
||||||
|
}
|
||||||
|
touchCenter_x /= touchCenter_count;
|
||||||
|
touchCenter_y /= touchCenter_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
let zoomCursorLocal_x = 0;
|
||||||
|
let zoomCursorLocal_y = 0;
|
||||||
|
const zoomAtPosition = (x, y, scaleFactor) => {
|
||||||
|
zoomCursorLocal_x = x - map_container_rect.left;
|
||||||
|
zoomCursorLocal_y = y - map_container_rect.top;
|
||||||
|
mapNav.x = zoomCursorLocal_x - scaleFactor * (zoomCursorLocal_x-mapNav.x);
|
||||||
|
mapNav.y = zoomCursorLocal_y - scaleFactor * (zoomCursorLocal_y-mapNav.y);
|
||||||
|
mapNav.scale *= scaleFactor;
|
||||||
|
}
|
||||||
|
map_container.addEventListener('pointerdown', touchDownHandler);
|
||||||
|
map_container.addEventListener('wheel', scrollHandler);
|
||||||
navUpdate();
|
navUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Readjust map view to focus on position */
|
/** Readjust map view to focus on position */
|
||||||
function updateMapview(navData = {x:0, y:0, scale:1}){
|
function updateMapview(){
|
||||||
currentMapNav = navData;
|
if(mapNav == null) return;
|
||||||
map_navigator.style.transform = `translate(${-navData.x}px, ${-navData.y}px) scale(${navData.scale})`;
|
map_navigator.style.transform = `translate(${mapNav.x}px, ${mapNav.y}px) scale(${mapNav.scale})`;
|
||||||
if(navData.scale !== previousMapScale){
|
if(mapNav.scale !== previousMapScale){
|
||||||
zoomLevelDisplay.innerHTML = `Zoom: ${Math.round(navData.scale*100)/100}x`;
|
zoomLevelDisplay.innerHTML = `Zoom: ${Math.round(mapNav.scale*100)/100}x`;
|
||||||
let dirtyScale = previousMapScale < 0;
|
let dirtyScale = previousMapScale < 0;
|
||||||
for(const cullThreshold of scaleCullThresholds){
|
for(const cullThreshold of scaleCullThresholds){
|
||||||
if(dirtyScale || (previousMapScale < cullThreshold.scale && navData.scale > cullThreshold.scale) || (previousMapScale > cullThreshold.scale && navData.scale < cullThreshold.scale)){
|
if(dirtyScale || (previousMapScale < cullThreshold.scale && mapNav.scale > cullThreshold.scale) || (previousMapScale > cullThreshold.scale && mapNav.scale < cullThreshold.scale)){
|
||||||
dirtyScale = true;
|
dirtyScale = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
map_rails.setAttribute('stroke-width', Utils.clamp(trackWidth.base/navData.scale, trackWidth.min, trackWidth.max));
|
map_rails.setAttribute('stroke-width', Utils.clamp(trackWidth.base/mapNav.scale, trackWidth.min, trackWidth.max));
|
||||||
styleRoot.style.setProperty('--markerScale', 1/navData.scale);
|
styleRoot.style.setProperty('--markerScale', 1/mapNav.scale);
|
||||||
if(dirtyScale){
|
if(dirtyScale){
|
||||||
for(let i=0; i<scaleCullThresholds.length; i++){
|
for(let i=0; i<scaleCullThresholds.length; i++){
|
||||||
styleRoot.style.setProperty(`--minZoomCull_state_${i}`, navData.scale >= scaleCullThresholds[i].scale ? 'initial' : 'none');
|
styleRoot.style.setProperty(`--minZoomCull_state_${i}`, mapNav.scale >= scaleCullThresholds[i].scale ? 'initial' : 'none');
|
||||||
styleRoot.style.setProperty(`--maxZoomCull_state_${i}`, navData.scale <= scaleCullThresholds[i].scale ? 'initial' : 'none');
|
styleRoot.style.setProperty(`--maxZoomCull_state_${i}`, mapNav.scale <= scaleCullThresholds[i].scale ? 'initial' : 'none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previousMapScale = navData.scale;
|
previousMapScale = mapNav.scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,11 +278,14 @@ function establishDimensions(){
|
|||||||
}
|
}
|
||||||
map.setAttribute('viewBox', `${minX-padding} ${minY-padding} ${width+2*padding} ${height+2*padding}`);
|
map.setAttribute('viewBox', `${minX-padding} ${minY-padding} ${width+2*padding} ${height+2*padding}`);
|
||||||
map_markers.setAttribute('viewBox', map.getAttribute('viewBox'));
|
map_markers.setAttribute('viewBox', map.getAttribute('viewBox'));
|
||||||
updateMapview({
|
let baseScale = Math.min(map_container.clientWidth/map.clientWidth, map_container.clientHeight/map.clientHeight);
|
||||||
x: map.clientWidth/2-map_container.clientWidth/2,
|
let isLandscape = map_container.clientWidth > map_container.clientHeight;
|
||||||
y: map.clientHeight/2-map_container.clientHeight/2,
|
mapNav = {
|
||||||
scale: 1
|
x: isLandscape ? -map.clientWidth/2*baseScale + map_container.clientWidth/2 : 0,
|
||||||
});
|
y: isLandscape ? 0 : -map.clientHeight/2*baseScale + map_container.clientHeight/2,
|
||||||
|
scale: baseScale
|
||||||
|
};
|
||||||
|
updateMapview();
|
||||||
console.log(`(${minX}, ${minY}) to (${maxX}, ${maxY}). Altitude from ${minAlt} to ${maxAlt}`);
|
console.log(`(${minX}, ${minY}) to (${maxX}, ${maxY}). Altitude from ${minAlt} to ${maxAlt}`);
|
||||||
|
|
||||||
// Flip the z coordinate so the map doesn't display upside-down
|
// Flip the z coordinate so the map doesn't display upside-down
|
||||||
|
|||||||
@@ -75,23 +75,25 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
addSettingEntry(thisSetting, settingsPanel);
|
addSettingEntry(thisSetting, settingsPanel);
|
||||||
}
|
}
|
||||||
const legend = document.getElementById('legend');
|
const legend = document.getElementById('legend');
|
||||||
|
const legendContents = document.getElementById('legendContents');
|
||||||
const legendButton = document.getElementById('legendButton');
|
const legendButton = document.getElementById('legendButton');
|
||||||
const legendArrow = legendButton.children[0];
|
const legendArrow = legendButton.children[0];
|
||||||
let legendState = true;
|
let legendState = true;
|
||||||
let legendButtonEvent = e => {
|
let legendButtonEvent = e => {
|
||||||
legendArrow.style.transform = `rotate(${legendState ? 180 : 0}deg) translateY(${legendState ? -3 : 3}px)`;
|
legendArrow.style.transform = `rotate(${legendState ? 180 : 0}deg) translateY(${legendState ? -0 : 0}px)`;
|
||||||
legend.style.transform = `translateX(${legendState ? 0 : legendButton.clientWidth-legend.clientWidth}px)`;
|
legend.style.transform = `translateX(${legendState ? 0 : -legendContents.clientWidth}px)`;
|
||||||
legendState = !legendState;
|
legendState = !legendState;
|
||||||
};
|
};
|
||||||
legendButton.addEventListener('click', legendButtonEvent);
|
legendButton.addEventListener('click', legendButtonEvent);
|
||||||
legendButtonEvent();
|
legendButtonEvent();
|
||||||
|
if(document.body.clientWidth <= 700) legendButtonEvent();
|
||||||
populateKey();
|
populateKey();
|
||||||
});
|
});
|
||||||
|
|
||||||
function addSettingEntry(thisSetting, parent, indent=0){
|
function addSettingEntry(thisSetting, parent, indent=0){
|
||||||
thisSetting.divContainer = document.createElement('div');
|
thisSetting.divContainer = document.createElement('div');
|
||||||
thisSetting.divContainer.innerHTML = ' '.repeat(indent);
|
|
||||||
thisSetting.inputElement = document.createElement('input');
|
thisSetting.inputElement = document.createElement('input');
|
||||||
|
thisSetting.inputElement.style.margin = `0 0.5em 0 ${indent}em`;
|
||||||
thisSetting.labelElement = document.createElement('label');
|
thisSetting.labelElement = document.createElement('label');
|
||||||
parent.appendChild(thisSetting.divContainer);
|
parent.appendChild(thisSetting.divContainer);
|
||||||
thisSetting.divContainer.appendChild(thisSetting.inputElement);
|
thisSetting.divContainer.appendChild(thisSetting.inputElement);
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
--cullThreshold_state_6: none;
|
--cullThreshold_state_6: none;
|
||||||
|
|
||||||
--absScale: 1;
|
--absScale: 1;
|
||||||
|
--legendButtonSize: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body, #map, #mapContainer, h1, h2, h3, h4, h5{
|
html *{
|
||||||
|
box-sizing: border-box;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
@@ -24,6 +26,8 @@ html, body{
|
|||||||
font-family: "Noto Sans";
|
font-family: "Noto Sans";
|
||||||
font-variation-settings: "wght" 400;
|
font-variation-settings: "wght" 400;
|
||||||
color: #e9e9e9;
|
color: #e9e9e9;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
a{
|
a{
|
||||||
@@ -37,51 +41,63 @@ a:visited{
|
|||||||
color: #e79830;
|
color: #e79830;
|
||||||
}
|
}
|
||||||
|
|
||||||
#topleft{
|
|
||||||
position:fixed;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel{
|
.panel{
|
||||||
width: fit-content;
|
|
||||||
border: 2px solid #b3b3b396;
|
border: 2px solid #b3b3b396;
|
||||||
background: linear-gradient(120deg, #2c3f58, #191e2e);
|
background: linear-gradient(120deg, #2c3f58, #191e2e);
|
||||||
text-shadow: 2px 2px 5px #0003;
|
text-shadow: 2px 2px 5px #0003;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 8px 13px;
|
padding: 8px 13px;
|
||||||
border-radius: 10px;
|
border-radius: 5px;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#topleft{
|
||||||
|
position:fixed;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
pointer-events: none;
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: min(500px,100vw);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
#headerbar{
|
#headerbar{
|
||||||
background: linear-gradient(120deg, #3d5779, #121522);
|
background: linear-gradient(120deg, #3d5779, #121522);
|
||||||
font-size: 30px;
|
font-size: 2em;
|
||||||
border-left: 0px;
|
border-left: 0px;
|
||||||
font-variation-settings: "wght" 500;
|
font-variation-settings: "wght" 500;
|
||||||
padding: 10px 30px 10px 30px;
|
padding: 10px 30px 10px 30px;
|
||||||
margin: 10px 0px;
|
margin: 10px 0px;
|
||||||
border-radius: 0px 10px 10px 0px;
|
border-radius: 0px 10px 10px 0px;
|
||||||
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
#legendButton{
|
#legendButton{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
padding: 8px;
|
||||||
|
height: var(--legendButtonSize);
|
||||||
|
width: var(--legendButtonSize);
|
||||||
|
>*{
|
||||||
|
transition: transform 200ms ease;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#legend{
|
#legend{
|
||||||
transition: transform 400ms cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
transition: transform 400ms cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
||||||
}
|
|
||||||
#legendButton>*{
|
|
||||||
transition: transform 200ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
#legendKey{
|
|
||||||
font-size: 15px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column wrap;
|
flex-direction: row;
|
||||||
max-height: 310px;
|
flex-shrink: 1;
|
||||||
|
min-height: 0px;
|
||||||
|
}
|
||||||
|
#legendContents{
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #62778a #1c1e2d;
|
||||||
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#settingsPanel{
|
#settingsPanel{
|
||||||
@@ -91,12 +107,12 @@ a:visited{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer{
|
#stats{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
bottom: 5px;
|
bottom: 5px;
|
||||||
font-size: 12px;
|
font-size: 0.8em;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user