mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-02-04 17:41:23 +01:00
v1.0.32
This commit is contained in:
parent
1ad74e6e3d
commit
0bafcc33ca
4 changed files with 152 additions and 10 deletions
20
index.css
20
index.css
|
|
@ -191,7 +191,7 @@ i.icon-lock {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#religionInfo {
|
.chartInfo {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|
@ -204,13 +204,24 @@ i.icon-lock {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
||||||
#religionHierarchy text {
|
#religionHierarchy text,
|
||||||
|
#provincesTree text {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
stroke: none;
|
stroke: none;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#provincesTree .selected {
|
||||||
|
stroke: #c13119;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#provincesTree .selected {
|
||||||
|
stroke: #c13119;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.dragLine {
|
.dragLine {
|
||||||
marker-end: url(#end-arrow);
|
marker-end: url(#end-arrow);
|
||||||
stroke: #333333;
|
stroke: #333333;
|
||||||
|
|
@ -1293,6 +1304,11 @@ div.states.selected {
|
||||||
background-image: linear-gradient(to right, #f2f2f2 0%, #ebe7e7 50%, #E5DADB 100%);
|
background-image: linear-gradient(to right, #f2f2f2 0%, #ebe7e7 50%, #E5DADB 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.states.active {
|
||||||
|
border: 1px solid #c4c4c4;
|
||||||
|
background-image: linear-gradient(to right, #dedede 100%, #f2f2f2 50%, #fcfcfc 0%);
|
||||||
|
}
|
||||||
|
|
||||||
div.states.Self {
|
div.states.Self {
|
||||||
border-color: #858b8e;
|
border-color: #858b8e;
|
||||||
background-image: linear-gradient(to right, #f2f2f2 0%, #b0c6d9 100%);
|
background-image: linear-gradient(to right, #f2f2f2 0%, #b0c6d9 100%);
|
||||||
|
|
|
||||||
|
|
@ -2557,6 +2557,7 @@
|
||||||
<div id="provincesBottom">
|
<div id="provincesBottom">
|
||||||
<button id="provincesEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
<button id="provincesEditorRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
||||||
<button id="provincesPercentage" data-tip="Toggle percentage / absolute values views" class="icon-percent"></button>
|
<button id="provincesPercentage" data-tip="Toggle percentage / absolute values views" class="icon-percent"></button>
|
||||||
|
<button id="provincesChart" data-tip="Show provinces chart" class="icon-chart-area"></button>
|
||||||
<button id="provincesToggleLabels" data-tip="Toggle province labels" class="icon-font"></button>
|
<button id="provincesToggleLabels" data-tip="Toggle province labels" class="icon-font"></button>
|
||||||
<button id="provincesExport" data-tip="Save provinces-related data as a text file (.csv)" class="icon-download"></button>
|
<button id="provincesExport" data-tip="Save provinces-related data as a text file (.csv)" class="icon-download"></button>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ function editProvinces() {
|
||||||
document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor);
|
document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor);
|
||||||
document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines);
|
document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines);
|
||||||
document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode);
|
document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode);
|
||||||
|
document.getElementById("provincesChart").addEventListener("click", showChart);
|
||||||
document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels);
|
document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels);
|
||||||
document.getElementById("provincesExport").addEventListener("click", downloadProvincesData);
|
document.getElementById("provincesExport").addEventListener("click", downloadProvincesData);
|
||||||
document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces);
|
document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces);
|
||||||
|
|
@ -151,17 +152,25 @@ function editProvinces() {
|
||||||
|
|
||||||
function provinceHighlightOn(event) {
|
function provinceHighlightOn(event) {
|
||||||
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.remove("placeholder"));
|
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.remove("placeholder"));
|
||||||
|
|
||||||
|
const province = +event.target.dataset.id;
|
||||||
|
const el = body.querySelector(`div[data-id='${province}']`);
|
||||||
|
if (el) el.classList.add("active");
|
||||||
|
|
||||||
if (!layerIsOn("toggleProvinces")) return;
|
if (!layerIsOn("toggleProvinces")) return;
|
||||||
if (customization) return;
|
if (customization) return;
|
||||||
const province = +event.target.dataset.id;
|
|
||||||
const animate = d3.transition().duration(2000).ease(d3.easeSinIn);
|
const animate = d3.transition().duration(2000).ease(d3.easeSinIn);
|
||||||
provs.select("#province"+province).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#d0240f");
|
provs.select("#province"+province).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#d0240f");
|
||||||
}
|
}
|
||||||
|
|
||||||
function provinceHighlightOff(event) {
|
function provinceHighlightOff(event) {
|
||||||
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.add("placeholder"));
|
if (!customization) event.target.querySelectorAll(".hoverButton").forEach(el => el.classList.add("placeholder"));
|
||||||
if (!layerIsOn("toggleProvinces")) return;
|
|
||||||
const province = +event.target.dataset.id;
|
const province = +event.target.dataset.id;
|
||||||
|
const el = body.querySelector(`div[data-id='${province}']`);
|
||||||
|
if (el) el.classList.remove("active");
|
||||||
|
|
||||||
|
if (!layerIsOn("toggleProvinces")) return;
|
||||||
provs.select("#province"+province).transition().attr("stroke-width", null).attr("stroke", null);
|
provs.select("#province"+province).transition().attr("stroke-width", null).attr("stroke", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -272,6 +281,119 @@ function editProvinces() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showChart() {
|
||||||
|
// build hierarchy tree
|
||||||
|
const states = pack.states.map(s => {
|
||||||
|
return {id:s.i, state: s.i?0:null, color: s.i && s.color[0] === "#" ? d3.color(s.color).darker() : "#666"}
|
||||||
|
});
|
||||||
|
const provinces = pack.provinces.filter(p => p.i && !p.removed);
|
||||||
|
provinces.forEach(p => p.id = p.i + states.length - 1);
|
||||||
|
const data = states.concat(provinces);
|
||||||
|
const root = d3.stratify().parentId(d => d.state)(data).sum(d => d.area);
|
||||||
|
|
||||||
|
const width = 800, height = 300;
|
||||||
|
const margin = {top: 10, right: 10, bottom: 0, left: 10};
|
||||||
|
const w = width - margin.left - margin.right;
|
||||||
|
const h = height - margin.top - margin.bottom;
|
||||||
|
const treeLayout = d3.treemap().size([w, h]).padding(2);
|
||||||
|
|
||||||
|
// prepare svg
|
||||||
|
alertMessage.innerHTML = `<select id="provincesTreeType" style="display:block; margin-left:13px; font-size:11px">
|
||||||
|
<option value="area" selected>Area</option>
|
||||||
|
<option value="population">Total population</option>
|
||||||
|
<option value="rural">Rural population</option>
|
||||||
|
<option value="urban">Urban population</option>
|
||||||
|
</select>`;
|
||||||
|
alertMessage.innerHTML += `<div id='provinceInfo' class='chartInfo'>‍</div>`;
|
||||||
|
const svg = d3.select("#alertMessage").insert("svg", "#provinceInfo").attr("id", "provincesTree")
|
||||||
|
.attr("width", width).attr("height", height).attr("font-size", "10px");
|
||||||
|
const graph = svg.append("g").attr("transform", `translate(10, 0)`);
|
||||||
|
document.getElementById("provincesTreeType").addEventListener("change", updateChart);
|
||||||
|
|
||||||
|
treeLayout(root);
|
||||||
|
|
||||||
|
const node = graph.selectAll("g").data(root.leaves()).enter()
|
||||||
|
.append("g").attr("data-id", d => d.data.i)
|
||||||
|
.on("mouseenter", d => showInfo(event, d))
|
||||||
|
.on("mouseleave", d => hideInfo(event, d));
|
||||||
|
|
||||||
|
function showInfo(ev, d) {
|
||||||
|
d3.select(ev.target).select("rect").classed("selected", 1);
|
||||||
|
const name = d.data.fullName;
|
||||||
|
const state = pack.states[d.data.state].fullName;
|
||||||
|
|
||||||
|
const unit = areaUnit.value === "square" ? " " + distanceUnitInput.value + "²" : " " + areaUnit.value;
|
||||||
|
const area = d.data.area * (distanceScaleInput.value ** 2) + unit;
|
||||||
|
const rural = rn(d.data.rural * populationRate.value);
|
||||||
|
const urban = rn(d.data.urban * populationRate.value * urbanization.value);
|
||||||
|
|
||||||
|
const value = provincesTreeType.value === "area" ? "Area: " + area
|
||||||
|
: provincesTreeType.value === "rural" ? "Rural population: " + si(rural)
|
||||||
|
: provincesTreeType.value === "urban" ? "Urban population: " + si(urban)
|
||||||
|
: "Population: " + si(rural + urban);
|
||||||
|
|
||||||
|
provinceInfo.innerHTML = `${name}. ${state}. ${value}`;
|
||||||
|
provinceHighlightOn(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideInfo(ev) {
|
||||||
|
provinceHighlightOff(ev);
|
||||||
|
if (!document.getElementById("provinceInfo")) return;
|
||||||
|
provinceInfo.innerHTML = "‍";
|
||||||
|
d3.select(ev.target).select("rect").classed("selected", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.append("rect").attr("stroke", d => d.parent.data.color)
|
||||||
|
.attr("stroke-width", 1).attr("fill", d => d.data.color)
|
||||||
|
.attr("x", d => d.x0).attr("y", d => d.y0)
|
||||||
|
.attr("width", d => d.x1 - d.x0).attr("height", d => d.y1 - d.y0);
|
||||||
|
|
||||||
|
node.append("text").attr("dx", ".2em").attr("dy", "1em")
|
||||||
|
.attr("x", d => d.x0).attr("y", d => d.y0);
|
||||||
|
|
||||||
|
function hideNonfittingLabels() {
|
||||||
|
node.select("text").each(function(d) {
|
||||||
|
this.innerHTML = d.data.name;
|
||||||
|
let b = this.getBBox();
|
||||||
|
if (b.y + b.height > d.y1 + 1) this.innerHTML = "";
|
||||||
|
|
||||||
|
while(b.width > 0 && b.x + b.width > d.x1) {
|
||||||
|
if (this.innerHTML.length < 3) {this.innerHTML = ""; break;}
|
||||||
|
this.innerHTML = this.innerHTML.slice(0, -2) + "…";
|
||||||
|
b = this.getBBox();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateChart() {
|
||||||
|
const value = this.value === "area" ? d => d.area
|
||||||
|
: this.value === "rural" ? d => d.rural
|
||||||
|
: this.value === "urban" ? d => d.urban
|
||||||
|
: d => d.rural + d.urban;
|
||||||
|
|
||||||
|
const newRoot = d3.stratify().parentId(d => d.state)(data).sum(value);
|
||||||
|
node.data(treeLayout(newRoot).leaves())
|
||||||
|
|
||||||
|
node.select("rect").transition().duration(1500)
|
||||||
|
.attr("x", d => d.x0).attr("y", d => d.y0)
|
||||||
|
.attr("width", d => d.x1 - d.x0).attr("height", d => d.y1 - d.y0);
|
||||||
|
|
||||||
|
node.select("text").attr("opacity", 1).transition().duration(1500)
|
||||||
|
.attr("x", d => d.x0).attr("y", d => d.y0);
|
||||||
|
|
||||||
|
setTimeout(hideNonfittingLabels, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#alert").dialog({
|
||||||
|
title: "Provinces chart", width: fitContent(), resizable: false,
|
||||||
|
position: {my: "left center", at: "left+10 center", of: "svg"}, buttons: {},
|
||||||
|
close: () => {alertMessage.innerHTML = "";}
|
||||||
|
});
|
||||||
|
|
||||||
|
hideNonfittingLabels();
|
||||||
|
}
|
||||||
|
|
||||||
function toggleLabels() {
|
function toggleLabels() {
|
||||||
const hidden = provs.select("#provinceLabels").style("display") === "none";
|
const hidden = provs.select("#provinceLabels").style("display") === "none";
|
||||||
provs.select("#provinceLabels").style("display", `${hidden ? "block" : "none"}`);
|
provs.select("#provinceLabels").style("display", `${hidden ? "block" : "none"}`);
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,9 @@ function editReligions() {
|
||||||
info.innerHTML = `${r.name}${type}${form}${population}${hint}`;
|
info.innerHTML = `${r.name}${type}${form}${population}${hint}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const el = body.querySelector(`div[data-id='${religion}']`);
|
||||||
|
if (el) el.classList.add("active");
|
||||||
|
|
||||||
if (!layerIsOn("toggleReligions")) return;
|
if (!layerIsOn("toggleReligions")) return;
|
||||||
if (customization) return;
|
if (customization) return;
|
||||||
relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119");
|
relig.select("#religion"+religion).raise().transition(animate).attr("stroke-width", 2.5).attr("stroke", "#c13119");
|
||||||
|
|
@ -167,6 +170,10 @@ function editReligions() {
|
||||||
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path").classed("selected", 0);
|
d3.select("#religionHierarchy").select("g[data-id='"+religion+"'] > path").classed("selected", 0);
|
||||||
info.innerHTML = "‍";
|
info.innerHTML = "‍";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const el = body.querySelector(`div[data-id='${religion}']`)
|
||||||
|
if (el) el.classList.remove("active");
|
||||||
|
|
||||||
relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null);
|
relig.select("#religion"+religion).transition().attr("stroke-width", null).attr("stroke", null);
|
||||||
debug.select("#religionsCenter"+religion).transition().attr("r", 4).attr("stroke-width", 1.2).attr("stroke", null);
|
debug.select("#religionsCenter"+religion).transition().attr("r", 4).attr("stroke-width", 1.2).attr("stroke", null);
|
||||||
}
|
}
|
||||||
|
|
@ -245,13 +252,9 @@ function editReligions() {
|
||||||
.attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1])
|
.attr("cx", d => pack.cells.p[d.center][0]).attr("cy", d => pack.cells.p[d.center][1])
|
||||||
.on("mouseenter", d => {
|
.on("mouseenter", d => {
|
||||||
tip(d.name+ ". Drag to move the religion center", true);
|
tip(d.name+ ". Drag to move the religion center", true);
|
||||||
const el = body.querySelector(`div[data-id='${d.i}']`);
|
|
||||||
if (el) el.classList.add("selected");
|
|
||||||
religionHighlightOn(event);
|
religionHighlightOn(event);
|
||||||
}).on("mouseleave", d => {
|
}).on("mouseleave", d => {
|
||||||
tip('', true);
|
tip('', true);
|
||||||
const el = body.querySelector(`div[data-id='${d.i}']`)
|
|
||||||
if (el) el.classList.remove("selected");
|
|
||||||
religionHighlightOff(event);
|
religionHighlightOff(event);
|
||||||
}).call(d3.drag().on("start", religionCenterDrag));
|
}).call(d3.drag().on("start", religionCenterDrag));
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +296,7 @@ function editReligions() {
|
||||||
// build hierarchy tree
|
// build hierarchy tree
|
||||||
pack.religions[0].origin = null;
|
pack.religions[0].origin = null;
|
||||||
const religions = pack.religions.filter(r => !r.removed);
|
const religions = pack.religions.filter(r => !r.removed);
|
||||||
let root = d3.stratify().id(d => d.i).parentId(d => d.origin)(religions);
|
const root = d3.stratify().id(d => d.i).parentId(d => d.origin)(religions);
|
||||||
const treeWidth = root.leaves().length;
|
const treeWidth = root.leaves().length;
|
||||||
const treeHeight = root.height;
|
const treeHeight = root.height;
|
||||||
const width = treeWidth * 40, height = treeHeight * 60;
|
const width = treeWidth * 40, height = treeHeight * 60;
|
||||||
|
|
@ -304,7 +307,7 @@ function editReligions() {
|
||||||
const treeLayout = d3.tree().size([w, h]);
|
const treeLayout = d3.tree().size([w, h]);
|
||||||
|
|
||||||
// prepare svg
|
// prepare svg
|
||||||
alertMessage.innerHTML = "<div id='religionInfo'>‍</div>";
|
alertMessage.innerHTML = "<div id='religionInfo' class='chartInfo'>‍</div>";
|
||||||
const svg = d3.select("#alertMessage").insert("svg", "#religionInfo").attr("id", "religionHierarchy")
|
const svg = d3.select("#alertMessage").insert("svg", "#religionInfo").attr("id", "religionHierarchy")
|
||||||
.attr("width", width).attr("height", height).style("text-anchor", "middle");
|
.attr("width", width).attr("height", height).style("text-anchor", "middle");
|
||||||
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
|
const graph = svg.append("g").attr("transform", `translate(10, -45)`);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue