Fit map to screen size (#1018)

* feat: fit map to screen size

* chore: pump version

---------

Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
Azgaar 2023-11-19 17:03:48 +04:00 committed by GitHub
parent a349d40868
commit a1f70afd57
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 80 deletions

View file

@ -1410,9 +1410,11 @@
</p>
<table>
<tr
data-tip="Canvas width and height in pixels. Defines map size on generation that cannot be changed later. Always keep canvas size equal to your screen size or less. The best option is to use the default value. For full-globe maps use aspect ratio 2:1"
data-tip="Set original map size on generation. It cannot be changed later. Always keep canvas size equal to your screen size or less. The best option is to use the default value. For full-globe maps use aspect ratio 2:1"
>
<td></td>
<td>
<i data-tip="Restore default canvas size" id="restoreDefaultCanvasSize" class="icon-ccw"></i>
</td>
<td>Canvas size</td>
<td>
<input id="mapWidthInput" class="paired" type="number" min="240" value="960" />
@ -1420,13 +1422,7 @@
<input id="mapHeightInput" class="paired" type="number" min="135" value="540" />
<span>px</span>
</td>
<td>
<i
data-tip="Toggle between the current screen size and the initial canvas size"
id="toggleFullscreen"
class="icon-resize-full-alt"
></i>
</td>
<td></td>
</tr>
<tr data-tip="Map seed number. Seed produces the same map only if canvas size and options are the same">
@ -7934,7 +7930,7 @@
<script src="modules/military-generator.js"></script>
<script src="modules/markers-generator.js?v=1.93.04"></script>
<script src="modules/coa-generator.js?v=1.91.05"></script>
<script src="modules/submap.js?v=1.91.05"></script>
<script src="modules/submap.js?v=1.94.01"></script>
<script src="libs/polylabel.min.js"></script>
<script src="libs/lineclip.min.js"></script>
<script src="libs/alea.min.js"></script>
@ -7943,9 +7939,9 @@
<script src="modules/ui/measurers.js?v=1.87.02"></script>
<script src="modules/ui/stylePresets.js?v=1.94.00"></script>
<script src="modules/ui/general.js?v=1.94.00"></script>
<script src="modules/ui/options.js?v=1.94.00"></script>
<script src="main.js?v=1.94.00"></script>
<script src="modules/ui/general.js?v=1.94.01"></script>
<script src="modules/ui/options.js?v=1.94.01"></script>
<script src="main.js?v=1.94.01"></script>
<script defer src="modules/relief-icons.js"></script>
<script defer src="modules/ui/style.js?v=1.94.00"></script>

View file

@ -308,6 +308,7 @@ async function generateMapOnLoad() {
await generate(); // generate map
focusOn(); // based on searchParams focus on point, cell or burg from MFCG
applyPreset(); // apply saved layers preset
fitMapToScreen();
}
// focus on coordinates, cell or burg provided in searchParams
@ -607,7 +608,7 @@ async function generate(options) {
setSeed(precreatedSeed);
INFO && console.group("Generated Map " + seed);
applyMapSize();
applyGraphSize();
randomizeOptions();
if (shouldRegenerateGrid(grid, precreatedSeed)) grid = precreatedGraph || generateGrid();
@ -1942,6 +1943,7 @@ const regenerateMap = debounce(async function (options) {
if (ThreeD.options.isOn) ThreeD.redraw();
if ($("#worldConfigurator").is(":visible")) editWorld();
fitMapToScreen();
shouldShowLoading && hideLoading();
clearMainTip();
}, 250);

View file

@ -618,7 +618,7 @@ async function parseLoadedData(data) {
}
})();
changeMapSize();
fitMapToScreen();
// remove href from emblems, to trigger rendering on load
emblems.selectAll("use").attr("href", null);

View file

@ -39,7 +39,7 @@ window.Submap = (function () {
DEBUG && console.log("Using Options:", options);
// create new grid
applyMapSize();
applyGraphSize();
grid = generateGrid();
drawScaleBar(scale);

View file

@ -1,12 +1,11 @@
"use strict";
// Module to store general UI functions
// Module to store generic UI functions
// fit full-screen map if window is resized
window.addEventListener("resize", function (e) {
if (stored("mapWidth") && stored("mapHeight")) return;
mapWidthInput.value = window.innerWidth;
mapHeightInput.value = window.innerHeight;
changeMapSize();
fitMapToScreen();
});
if (location.hostname !== "localhost" && location.hostname !== "127.0.0.1") {
@ -28,7 +27,7 @@ const tipBackgroundMap = {
error: "linear-gradient(0.1turn, #ffffff00, #e11d1dcc, #ffffff00)"
};
function tip(tip = "Tip is undefined", main = false, type = "info", time = 0) {
function tip(tip, main = false, type = "info", time = 0) {
tooltip.innerHTML = tip;
tooltip.style.background = tipBackgroundMap[type];

View file

@ -623,10 +623,12 @@ function drawScaleBar(scaleLevel) {
// fit ScaleBar to canvas size
function fitScaleBar() {
if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return;
const px = isNaN(+barPosX.value) ? 0.99 : barPosX.value / 100;
const py = isNaN(+barPosY.value) ? 0.99 : barPosY.value / 100;
const bbox = scaleBar.select("rect").node().getBBox();
const x = rn(svgWidth * px - bbox.width + 10),
y = rn(svgHeight * py - bbox.height + 20);
const x = rn(svgWidth * px - bbox.width + 10);
const y = rn(svgHeight * py - bbox.height + 20);
scaleBar.attr("transform", `translate(${x},${y})`);
}

View file

@ -139,7 +139,7 @@ optionsContent.addEventListener("change", function (event) {
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
else if (id === "optionsSeed") generateMapWithSeed("seed change");
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value);
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUiSize(value);
else if (id === "shapeRendering") setRendering(value);
else if (id === "yearInput") changeYear();
else if (id === "eraInput") changeEra();
@ -148,7 +148,7 @@ optionsContent.addEventListener("change", function (event) {
optionsContent.addEventListener("click", function (event) {
const id = event.target.id;
if (id === "toggleFullscreen") toggleFullscreen();
if (id === "restoreDefaultCanvasSize") restoreDefaultCanvasSize();
else if (id === "optionsMapHistory") showSeedHistoryDialog();
else if (id === "optionsCopySeed") copyMapURL();
else if (id === "optionsEraRegenerate") regenerateEra();
@ -165,7 +165,7 @@ function mapSizeInputChange() {
const $mapWidthInput = byId("mapWidthInput");
const $mapHeightInput = byId("mapHeightInput");
changeMapSize();
fitMapToScreen();
localStorage.setItem("mapWidth", $mapWidthInput.value);
localStorage.setItem("mapHeight", $mapHeightInput.value);
@ -173,79 +173,67 @@ function mapSizeInputChange() {
const tooHigh = +$mapHeightInput.value > window.innerHeight;
if (tooWide || tooHigh) {
const message = `Canvas size is larger than actual window size (${window.innerWidth} x ${window.innerHeight}). It can affect the performance if you are going to create a new map`;
const message = `Canvas size is larger than window size (${window.innerWidth} x ${window.innerHeight}). It can affect performance`;
tip(message, false, "warn", 4000);
}
}
// change svg size on manual size change or window resize (do not change graph size!)
function changeMapSize() {
// on map creation
function applyGraphSize() {
console.log("applyGraphSize");
graphWidth = +mapWidthInput.value;
graphHeight = +mapHeightInput.value;
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
oceanLayers.select("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
fogging.selectAll("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
defs.select("mask#fog > rect").attr("width", graphWidth).attr("height", graphHeight);
defs.select("mask#water > rect").attr("width", graphWidth).attr("height", graphHeight);
}
// on generate, on load, on resize, on canvas size change
function fitMapToScreen() {
console.log("fitMapToScreen");
svgWidth = Math.min(+mapWidthInput.value, window.innerWidth);
svgHeight = Math.min(+mapHeightInput.value, window.innerHeight);
svg.attr("width", svgWidth).attr("height", svgHeight);
const maxWidth = Math.max(+mapWidthInput.value, graphWidth);
const maxHeight = Math.max(+mapHeightInput.value, graphHeight);
zoom.translateExtent([
const zoomExtent = [
[0, 0],
[maxWidth, maxHeight]
]);
[graphWidth, graphHeight]
];
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
oceanLayers.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
fogging.selectAll("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
defs.select("mask#fog > rect").attr("width", maxWidth).attr("height", maxHeight);
defs.select("mask#water > rect").attr("width", maxWidth).attr("height", maxHeight);
const zoomMin = rn(Math.max(svgWidth / graphWidth, svgHeight / graphHeight), 2);
zoomExtentMin.value = zoomMin;
const zoomMax = +zoomExtentMax.value;
zoom.translateExtent(zoomExtent).scaleExtent([zoomMin, zoomMax]).scaleTo(svg, zoomMin);
fitScaleBar();
if (window.fitLegendBox) fitLegendBox();
}
// just apply canvas size that was already set
function applyMapSize() {
const zoomMin = +zoomExtentMin.value;
const zoomMax = +zoomExtentMax.value;
graphWidth = +mapWidthInput.value;
graphHeight = +mapHeightInput.value;
svgWidth = Math.min(graphWidth, window.innerWidth);
svgHeight = Math.min(graphHeight, window.innerHeight);
svg.attr("width", svgWidth).attr("height", svgHeight);
zoom
.translateExtent([
[0, 0],
[graphWidth, graphHeight]
])
.scaleExtent([zoomMin, zoomMax])
.scaleTo(svg, zoomMin);
}
function toggleFullscreen() {
if (mapWidthInput.value != window.innerWidth || mapHeightInput.value != window.innerHeight) {
mapWidthInput.value = window.innerWidth;
mapHeightInput.value = window.innerHeight;
localStorage.removeItem("mapHeight");
localStorage.removeItem("mapWidth");
} else {
mapWidthInput.value = graphWidth;
mapHeightInput.value = graphHeight;
}
changeMapSize();
function restoreDefaultCanvasSize() {
mapWidthInput.value = window.innerWidth;
mapHeightInput.value = window.innerHeight;
localStorage.removeItem("mapHeight");
localStorage.removeItem("mapWidth");
}
function toggleTranslateExtent(el) {
const on = (el.dataset.on = +!+el.dataset.on);
if (on)
if (on) {
zoom.translateExtent([
[-graphWidth / 2, -graphHeight / 2],
[graphWidth * 1.5, graphHeight * 1.5]
]);
else
} else {
zoom.translateExtent([
[0, 0],
[graphWidth, graphHeight]
]);
}
}
// add voice options
@ -309,12 +297,6 @@ function restoreSeed(id) {
regeneratePrompt({seed});
}
function restoreDefaultZoomExtent() {
zoomExtentMin.value = 1;
zoomExtentMax.value = 20;
zoom.scaleExtent([1, 20]).scaleTo(svg, 1);
}
function copyMapURL() {
const locked = document.querySelectorAll("i.icon-lock").length; // check if some options are locked
const search = `?seed=${optionsSeed.value}&width=${graphWidth}&height=${graphHeight}${
@ -414,7 +396,7 @@ function changeStatesNumber(value) {
labels.select("#countries").attr("data-size", Math.max(rn(18 - value / 6), 4));
}
function changeUIsize(value) {
function changeUiSize(value) {
if (isNaN(+value) || +value < 0.5) return;
const max = getUImaxSize();
@ -529,6 +511,12 @@ function changeZoomExtent(value) {
zoom.scaleTo(svg, scale);
}
function restoreDefaultZoomExtent() {
zoomExtentMin.value = 1;
zoomExtentMax.value = 20;
zoom.scaleExtent([1, 20]).scaleTo(svg, 1);
}
// restore options stored in localStorage
function applyStoredOptions() {
if (!stored("mapWidth") || !stored("mapHeight")) {
@ -571,8 +559,8 @@ function applyStoredOptions() {
if (stored("regions")) changeStatesNumber(stored("regions"));
uiSizeInput.max = uiSizeOutput.max = getUImaxSize();
if (stored("uiSize")) changeUIsize(stored("uiSize"));
else changeUIsize(minmax(rn(mapWidthInput.value / 1280, 1), 1, 2.5));
if (stored("uiSize")) changeUiSize(stored("uiSize"));
else changeUiSize(minmax(rn(mapWidthInput.value / 1280, 1), 1, 2.5));
// search params overwrite stored and default options
const params = new URL(window.location.href).searchParams;