Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
Expand Up @@ -1907,6 +1907,12 @@ div.editorLine {
stroke: #737373;
}

#rulerShowText {
display: inline-block;
vertical-align: middle;
margin-right: 5px;
}

#militaryOptionsTable select {
border: 1px solid #d4d4d4;
}
Expand Down
40 changes: 40 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,46 @@
</tr>
</tbody>

<tbody id="styleRuler">
<tr data-tip="Set ruler initial length. Percentage of screen width.">
<td><label for="rulerInitialLength">Initial Length (%):</label></td>
<td><input type="number" id="rulerInitialLength" min="1" max="100" step="1"></td>
</tr>

<tr data-tip="Show or hide text for all rulers">
<td>
<input id="rulerShowText" type="checkbox" class="checkbox" checked>
<label for="rulerShowText">Show ruler text (click to toggle)</label>
</td>
</tr>

<tr data-tip="Set ruler white line color">
<td>White line color</td>
<td>
<input id="rulerWhiteLineColor" type="color" value="#ffffff" />
<output id="rulerWhiteLineColorOutput">#ffffff</output>
</td>
</tr>

<tr data-tip="Set ruler gray line color">
<td>Gray line color</td>
<td>
<input id="rulerGrayLineColor" type="color" value="#808080" />
<output id="rulerGrayLineColorOutput">#808080</output>
</td>
</tr>

<tr data-tip="Set ruler white line width value">
<td><label for="rulerWhiteLineWidth">White line width:</label></td>
<td><input type="number" id="rulerWhiteLineWidth" min="0.1" max="5" step="0.1" value="1"></td>
</tr>

<tr data-tip="Set ruler gray line width value">
<td><label for="rulerGrayLineWidth">Gray line width:</label></td>
<td><input type="number" id="rulerGrayLineWidth" min="0.1" max="5" step="0.1" value="1.2"></td>
</tr>
</tbody>

<tbody id="styleTexture">
<tr data-tip="Select texture image. Big textures can highly affect performance">
<td>Image</td>
Expand Down
11 changes: 10 additions & 1 deletion modules/io/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,16 @@ async function parseLoadedData(data, mapVersion) {
void (function parseConfiguration() {
if (data[2]) mapCoordinates = JSON.parse(data[2]);
if (data[4]) notes = JSON.parse(data[4]);
if (data[33]) rulers.fromString(data[33]);
if (data[33]) {
rulers.fromString(data[33]);
const rulerPreferences = JSON.parse(data[33]);
localStorage.setItem("rulerInitialLength", rulerPreferences.initialLength);
localStorage.setItem("rulerWhiteLineColor", rulerPreferences.whiteColor);
localStorage.setItem("rulerGrayLineColor", rulerPreferences.grayColor);
localStorage.setItem("rulerWhiteLineWidth", rulerPreferences.whiteWidth);
localStorage.setItem("rulerGrayLineWidth", rulerPreferences.grayWidth);
localStorage.setItem("rulerShowText", rulerPreferences.showText);
}
if (data[34]) {
const usedFonts = JSON.parse(data[34]);
usedFonts.forEach(usedFont => {
Expand Down
9 changes: 9 additions & 0 deletions modules/io/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ function prepareMapData() {
const coords = JSON.stringify(mapCoordinates);
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
const notesData = JSON.stringify(notes);
const rulerPreferences = JSON.stringify({
initialLength: localStorage.getItem("rulerInitialLength") || "100",
whiteColor: localStorage.getItem("rulerWhiteLineColor") || "#ffffff",
grayColor: localStorage.getItem("rulerGrayLineColor") || "#3d3d3d",
whiteWidth: parseFloat(localStorage.getItem("rulerWhiteLineWidth")) || 1,
grayWidth: parseFloat(localStorage.getItem("rulerGrayLineWidth")) || 1.2,
showText: localStorage.getItem("rulerShowText") || true
});
const rulersString = rulers.toString();
const fonts = JSON.stringify(getUsedFonts(svg.node()));

Expand Down Expand Up @@ -148,6 +156,7 @@ function prepareMapData() {
provinces,
namesData,
rivers,
rulerPreferences,
rulersString,
fonts,
markers,
Expand Down
14 changes: 12 additions & 2 deletions modules/ui/measurers.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ class Ruler extends Measurer {
const size = this.getSize();
const dash = this.getDash();

const whiteColor = localStorage.getItem("rulerWhiteLineColor") || "#ffffff";
const grayColor = localStorage.getItem("rulerGrayLineColor") || "#808080";
const whiteWidth = parseFloat(localStorage.getItem("rulerWhiteLineWidth")) || 1;
const grayWidth = parseFloat(localStorage.getItem("rulerGrayLineWidth")) || 1.2;
const showText = localStorage.getItem("rulerShowText") !== "false"; // by default, show the text


const el = (this.el = ruler
.append("g")
.attr("class", "ruler")
Expand All @@ -149,12 +156,14 @@ class Ruler extends Measurer {
el.append("polyline")
.attr("points", points)
.attr("class", "white")
.attr("stroke-width", size)
.style("stroke", whiteColor)
.style("stroke-width", size * whiteWidth)
.call(d3.drag().on("start", () => this.addControl(this)));
el.append("polyline")
.attr("points", points)
.attr("class", "gray")
.attr("stroke-width", rn(size * 1.2, 2))
.style("stroke", grayColor)
.style("stroke-width", size * grayWidth)
.attr("stroke-dasharray", dash);
el.append("g")
.attr("class", "rulerPoints")
Expand All @@ -163,6 +172,7 @@ class Ruler extends Measurer {
el.append("text")
.attr("dx", ".35em")
.attr("dy", "-.45em")
.style("display", showText ? "inline" : "none")
.on("click", () => rulers.remove(this.id));
this.drawPoints(el);
this.updateLabel();
Expand Down
105 changes: 89 additions & 16 deletions modules/ui/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,30 @@ styleElementSelect.addEventListener("change", selectStyleElement);

function selectStyleElement() {
const styleElement = styleElementSelect.value;
console.log("Selecting style for element:", styleElement);
let el = d3.select("#" + styleElement);

// if element not found, return
if (!el.node()) {
console.warn(`Element ${styleElement} not found`);
return;
}

styleElements.querySelectorAll("tbody").forEach(e => (e.style.display = "none")); // hide all sections

// show alert line if layer is not visible
const isLayerOff = styleElement !== "ocean" && (el.style("display") === "none" || !el.selectAll("*").size());
styleIsOff.style.display = isLayerOff ? "block" : "none";

// active group element
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders", "terrs"].includes(styleElement)) {
if (["anchors", "borders", "burgIcons", "coastline", "labels", "lakes", "routes", "ruler", "terrs"].includes(styleElement)) {
const group = styleGroupSelect.value;
const defaultGroupSelector = styleElement === "terrs" ? "#landHeights" : "g";
el = group && el.select("#" + group).size() ? el.select("#" + group) : el.select(defaultGroupSelector);
}

// opacity
if (!["landmass", "ocean", "regions", "legend"].includes(styleElement)) {
if (!["landmass", "legend", "ocean", "regions"].includes(styleElement)) {
styleOpacity.style.display = "block";
styleOpacityInput.value = el.attr("opacity") || 1;
}
Expand All @@ -103,7 +110,7 @@ function selectStyleElement() {
}

// fill
if (["rivers", "lakes", "landmass", "prec", "ice", "fogging", "scaleBar", "vignette"].includes(styleElement)) {
if (["fogging", "ice", "lakes", "landmass", "prec", "rivers", "scaleBar", "vignette"].includes(styleElement)) {
styleFill.style.display = "block";
styleFillInput.value = styleFillOutput.value = el.attr("fill");
}
Expand All @@ -112,19 +119,19 @@ function selectStyleElement() {
if (
[
"armies",
"routes",
"lakes",
"borders",
"cults",
"relig",
"cells",
"coastline",
"prec",
"coordinates",
"cults",
"gridOverlay",
"ice",
"icons",
"coordinates",
"lakes",
"prec",
"relig",
"routes",
"zones",
"gridOverlay"
].includes(styleElement)
) {
styleStroke.style.display = "block";
Expand All @@ -135,7 +142,7 @@ function selectStyleElement() {

// stroke dash
if (
["routes", "borders", "temperature", "legend", "population", "coordinates", "zones", "gridOverlay"].includes(
["borders", "coordinates", "gridOverlay", "legend", "population", "ruler", "routes", "temperature", "zones"].includes(
styleElement
)
) {
Expand Down Expand Up @@ -344,9 +351,48 @@ function selectStyleElement() {
emblemsBurgSizeInput.value = emblems.select("#burgEmblems").attr("data-size") || 1;
}

if (styleElement === "ruler") {
styleRuler.style.display = "block";
styleStrokeDash.style.display = "block";

const rulerEl = el.select("polyline");
styleStrokeDasharrayInput.value = rulerEl.attr("stroke-dasharray") || "";
styleStrokeLinecapInput.value = rulerEl.attr("stroke-linecap") || "inherit";

// Ruler preferences
const rulerInitialLength = byId("rulerInitialLength");
if (rulerInitialLength) {
rulerInitialLength.value = localStorage.getItem("rulerInitialLength") || "10";
}

// Color and width controls
const whiteLineColor = localStorage.getItem("rulerWhiteLineColor") || "#ffffff";
const grayLineColor = localStorage.getItem("rulerGrayLineColor") || "#808080";
const whiteLineWidth = localStorage.getItem("rulerWhiteLineWidth") || "1";
const grayLineWidth = localStorage.getItem("rulerGrayLineWidth") || "1.2";

byId("rulerWhiteLineColor").value = whiteLineColor;
byId("rulerGrayLineColor").value = grayLineColor;
byId("rulerWhiteLineWidth").value = whiteLineWidth;
byId("rulerGrayLineWidth").value = grayLineWidth;

// Update color outputs if they exist
const whiteColorOutput = byId("rulerWhiteLineColorOutput");
const grayColorOutput = byId("rulerGrayLineColorOutput");
if (whiteColorOutput) whiteColorOutput.value = whiteLineColor;
if (grayColorOutput) grayColorOutput.value = grayLineColor;

// Text visibility control
const rulerShowText = byId("rulerShowText");
if (rulerShowText) {
rulerShowText.checked = localStorage.getItem("rulerShowText") !== "false";
rulerShowText.addEventListener("change", toggleRulerText);
}
}

// update group options
styleGroupSelect.options.length = 0; // remove all options
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders", "terrs"].includes(styleElement)) {
if (["anchors", "borders", "burgIcons", "coastline", "labels", "lakes", "routes", "ruler", "terrs"].includes(styleElement)) {
const groups = byId(styleElement).querySelectorAll("g");
groups.forEach(el => {
if (el.id === "burgLabels") return;
Expand Down Expand Up @@ -427,10 +473,15 @@ styleStrokeInput.addEventListener("input", function () {
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});

styleStrokeWidthInput.addEventListener("input", e => {
getEl().attr("stroke-width", e.target.value);
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});
const styleStrokeWidthInput = document.getElementById('styleStrokeWidthInput');
if (styleStrokeWidthInput && styleStrokeWidthInput.querySelector('input')) {
styleStrokeWidthInput.querySelector('input').addEventListener("input", e => {
getEl().attr("stroke-width", e.target.value);
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});
} else {
console.warn('styleStrokeWidthInput not found or does not contain an input element');
}

styleStrokeDasharrayInput.addEventListener("input", function () {
getEl().attr("stroke-dasharray", this.value);
Expand Down Expand Up @@ -1075,6 +1126,28 @@ styleVignetteBlur.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("filter", `blur(${e.target.value}px)`);
});

document.addEventListener('DOMContentLoaded', function() {
const rulerInitialLength = document.getElementById("rulerInitialLength");

if (rulerInitialLength) {
rulerInitialLength.addEventListener("change", e => {
localStorage.setItem("rulerInitialLength", e.target.value);
});
}
});

function toggleRulerText() {
const checkbox = byId("rulerShowText");
const showText = checkbox.checked;

// Update visibility for existing rulers
d3.selectAll("g.ruler text").style("display", showText ? "inline" : "none");
console.log(`toggleRulerText called with showText: ${showText}`);

// Save the preference for future rulers
localStorage.setItem("rulerShowText", showText);
}

styleScaleBar.addEventListener("input", function (event) {
const scaleBarBack = scaleBar.select("#scaleBarBack");
if (!scaleBarBack.size()) return;
Expand Down
Loading