mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
v1.5.15 - svg save data cleansing
This commit is contained in:
parent
6987474c2e
commit
002160ed21
8 changed files with 164 additions and 135 deletions
13
index.css
13
index.css
|
|
@ -134,6 +134,17 @@ button, select, a {
|
||||||
#armies text {
|
#armies text {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
stroke: none;
|
||||||
|
fill: #fff;
|
||||||
|
text-shadow: 0 0 4px #000;
|
||||||
|
dominant-baseline: central;
|
||||||
|
text-anchor: middle;
|
||||||
|
font-family: Helvetica;
|
||||||
|
fill-opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#armies text.regimentIcon {
|
||||||
|
font-size: .8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#statesBody, #provincesBody {
|
#statesBody, #provincesBody {
|
||||||
|
|
@ -1405,11 +1416,11 @@ div.states>input.riverType {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.states > .coaIcon {
|
div.states > .coaIcon {
|
||||||
|
stroke-width: 3;
|
||||||
width: 1.4em;
|
width: 1.4em;
|
||||||
height: 1.4em;
|
height: 1.4em;
|
||||||
margin: -.3em 0;
|
margin: -.3em 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all .4s ease-in-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.states > .coaIcon > use {
|
div.states > .coaIcon > use {
|
||||||
|
|
|
||||||
206
index.html
206
index.html
File diff suppressed because one or more lines are too long
5
main.js
5
main.js
|
|
@ -108,7 +108,7 @@ fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("hei
|
||||||
fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("fill", "#e8f0f6").attr("filter", "url(#splotch)");
|
fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("fill", "#e8f0f6").attr("filter", "url(#splotch)");
|
||||||
|
|
||||||
// assign events separately as not a viewbox child
|
// assign events separately as not a viewbox child
|
||||||
scaleBar.on("mousemove", () => tip("Click to open Units Editor"));
|
scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", () => editUnits());
|
||||||
legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend());
|
legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend());
|
||||||
|
|
||||||
// main data variables
|
// main data variables
|
||||||
|
|
@ -1761,7 +1761,8 @@ const regenerateMap = debounce(function() {
|
||||||
// clear the map
|
// clear the map
|
||||||
function undraw() {
|
function undraw() {
|
||||||
viewbox.selectAll("path, circle, polygon, line, text, use, #zones > g, #armies > g, #ruler > g").remove();
|
viewbox.selectAll("path, circle, polygon, line, text, use, #zones > g, #armies > g, #ruler > g").remove();
|
||||||
defs.selectAll("path, clipPath").remove();
|
document.getElementById("deftemp").querySelectorAll("path, clipPath, svg").forEach(el => el.remove());
|
||||||
|
document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
|
||||||
notes = [];
|
notes = [];
|
||||||
unfog();
|
unfog();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -848,7 +848,7 @@
|
||||||
const divisionGroup = division ? templateDivision() : "";
|
const divisionGroup = division ? templateDivision() : "";
|
||||||
const overlay = `<path d="${shieldPath}" fill="url(#backlight_${id})" stroke="#333"/>`;
|
const overlay = `<path d="${shieldPath}" fill="url(#backlight_${id})" stroke="#333"/>`;
|
||||||
|
|
||||||
const svg= `<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="${viewBox}">
|
const svg= `<svg id="${id}" width="200" height="200" viewBox="${viewBox}">
|
||||||
<defs>${shieldClip}${divisionClip}${loadedCharges}${loadedPatterns}${blacklight}</defs>
|
<defs>${shieldClip}${divisionClip}${loadedCharges}${loadedPatterns}${blacklight}</defs>
|
||||||
<g clip-path="url(#${shield}_${id})">${field}${divisionGroup}${templateAboveAll()}</g>
|
<g clip-path="url(#${shield}_${id})">${field}${divisionGroup}${templateAboveAll()}</g>
|
||||||
${overlay}</svg>`;
|
${overlay}</svg>`;
|
||||||
|
|
|
||||||
|
|
@ -96,23 +96,56 @@ async function getMapURL(type, subtype) {
|
||||||
|
|
||||||
// add displayed emblems
|
// add displayed emblems
|
||||||
if (layerIsOn("toggleEmblems")) {
|
if (layerIsOn("toggleEmblems")) {
|
||||||
const defsEmblems = cloneEl.getElementById("defs-emblems");
|
const defs = cloneEl.getElementById("defs-emblems") || cloneEl.getElementById("deftemp");
|
||||||
clone.selectAll("#emblems use").each(function() {
|
clone.selectAll("#emblems use").each(function() {
|
||||||
const href = this.getAttribute("href");
|
const href = this.getAttribute("href");
|
||||||
if (!href) return;
|
if (!href) return;
|
||||||
const emblem = document.getElementById(href.slice(1)).cloneNode(true); // clone emblem
|
const emblem = document.getElementById(href.slice(1)).cloneNode(true); // clone emblem
|
||||||
defsEmblems.append(emblem);
|
defs.append(emblem);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const fontStyle = await GFontToDataURI(getFontsToLoad()); // load non-standard fonts
|
// remove unused filters
|
||||||
if (fontStyle) clone.select("defs").append("style").text(fontStyle.join('\n')); // add font to style
|
const filters = cloneEl.querySelectorAll("filter");
|
||||||
|
for (let i=0; i < filters.length; i++) {
|
||||||
|
const id = filters[i].id;
|
||||||
|
if (cloneEl.querySelector("[filter='url(#"+id+")']")) continue;
|
||||||
|
if (cloneEl.getAttribute("filter") === "url(#"+id+")") continue;
|
||||||
|
filters[i].remove();
|
||||||
|
}
|
||||||
|
|
||||||
clone.append("metadata").text("<dc:format>image/svg+xml</dc:format>");
|
// remove unused patterns
|
||||||
const serialized = (new XMLSerializer()).serializeToString(clone.node());
|
const patterns = cloneEl.querySelectorAll("pattern");
|
||||||
const svg_xml = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + serialized;
|
for (let i=0; i < patterns.length; i++) {
|
||||||
|
const id = patterns[i].id;
|
||||||
|
if (cloneEl.querySelector("[fill='url(#"+id+")']")) continue;
|
||||||
|
patterns[i].remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove unused symbols
|
||||||
|
const symbols = cloneEl.querySelectorAll("symbol");
|
||||||
|
for (let i=0; i < symbols.length; i++) {
|
||||||
|
const id = symbols[i].id;
|
||||||
|
if (cloneEl.querySelector("[use='#"+id+"']")) continue;
|
||||||
|
symbols[i].remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cloneEl.getElementById("hatching").children.length) cloneEl.getElementById("hatching").remove(); //remove unused hatching group
|
||||||
|
if (!cloneEl.getElementById("defs-icons").children.length) cloneEl.getElementById("defs-icons").remove(); //remove unused icons group
|
||||||
|
if (!cloneEl.getElementById("compass")) cloneEl.getElementById("rose").remove(); //remove unused rose
|
||||||
|
if (!cloneEl.getElementById("fogging-cont")) cloneEl.getElementById("fog").remove(); //remove unused fog
|
||||||
|
if (!cloneEl.getElementById("regions")) cloneEl.getElementById("statePaths").remove(); // removed unused statePaths
|
||||||
|
if (!cloneEl.getElementById("labels")) cloneEl.getElementById("textPaths").remove(); // removed unused textPaths
|
||||||
|
|
||||||
|
// add armies style
|
||||||
|
if (cloneEl.getElementById("armies")) cloneEl.insertAdjacentHTML("afterbegin", "<style>#armies text {stroke: none; fill: #fff; text-shadow: 0 0 4px #000; dominant-baseline: central; text-anchor: middle; font-family: Helvetica; fill-opacity: 1;}#armies text.regimentIcon {font-size: .8em;}</style>");
|
||||||
|
|
||||||
|
const fontStyle = await GFontToDataURI(getFontsToLoad(clone)); // load non-standard fonts
|
||||||
|
if (fontStyle) clone.select("defs").append("style").text(fontStyle.join('\n')); // add font to style
|
||||||
clone.remove();
|
clone.remove();
|
||||||
const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
|
|
||||||
|
const serialized = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + (new XMLSerializer()).serializeToString(cloneEl);
|
||||||
|
const blob = new Blob([serialized], {type: 'image/svg+xml;charset=utf-8'});
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
window.setTimeout(() => window.URL.revokeObjectURL(url), 5000);
|
window.setTimeout(() => window.URL.revokeObjectURL(url), 5000);
|
||||||
return url;
|
return url;
|
||||||
|
|
@ -181,11 +214,11 @@ function inlineStyle(clone) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get non-standard fonts used for labels to fetch them from web
|
// get non-standard fonts used for labels to fetch them from web
|
||||||
function getFontsToLoad() {
|
function getFontsToLoad(clone) {
|
||||||
const webSafe = ["Georgia", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New", "Verdana", "Arial", "Impact"]; // fonts to not fetch
|
const webSafe = ["Georgia", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New", "Verdana", "Arial", "Impact"]; // fonts to not fetch
|
||||||
|
|
||||||
const fontsInUse = new Set(); // to store fonts currently in use
|
const fontsInUse = new Set(); // to store fonts currently in use
|
||||||
labels.selectAll("g").each(function() {
|
clone.selectAll("#labels > g").each(function() {
|
||||||
if (!this.hasChildNodes()) return;
|
if (!this.hasChildNodes()) return;
|
||||||
const font = this.dataset.font;
|
const font = this.dataset.font;
|
||||||
if (!font || webSafe.includes(font)) return;
|
if (!font || webSafe.includes(font)) return;
|
||||||
|
|
@ -513,6 +546,8 @@ function uploadMap(file, callback) {
|
||||||
const fileReader = new FileReader();
|
const fileReader = new FileReader();
|
||||||
fileReader.onload = function(fileLoadedEvent) {
|
fileReader.onload = function(fileLoadedEvent) {
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
|
document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
|
||||||
|
|
||||||
const dataLoaded = fileLoadedEvent.target.result;
|
const dataLoaded = fileLoadedEvent.target.result;
|
||||||
const data = dataLoaded.split("\r\n");
|
const data = dataLoaded.split("\r\n");
|
||||||
|
|
||||||
|
|
@ -753,7 +788,7 @@ function parseLoadedData(data) {
|
||||||
ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd));
|
ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd));
|
||||||
ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd));
|
ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd));
|
||||||
|
|
||||||
scaleBar.on("mousemove", () => tip("Click to open Units Editor"));
|
scaleBar.on("mousemove", () => tip("Click to open Units Editor")).on("click", () => editUnits());
|
||||||
legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend());
|
legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend());
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -953,7 +988,6 @@ function parseLoadedData(data) {
|
||||||
BurgsAndStates.generateCampaigns();
|
BurgsAndStates.generateCampaigns();
|
||||||
|
|
||||||
// v 1.3 added militry layer
|
// v 1.3 added militry layer
|
||||||
svg.select("defs").append("style").text(armiesStyle()); // add armies style
|
|
||||||
armies = viewbox.insert("g", "#icons").attr("id", "armies");
|
armies = viewbox.insert("g", "#icons").attr("id", "armies");
|
||||||
armies.attr("opacity", 1).attr("fill-opacity", 1).attr("font-size", 6).attr("box-size", 3).attr("stroke", "#000").attr("stroke-width", .3);
|
armies.attr("opacity", 1).attr("fill-opacity", 1).attr("font-size", 6).attr("box-size", 3).attr("stroke", "#000").attr("stroke-width", .3);
|
||||||
turnButtonOn("toggleMilitary");
|
turnButtonOn("toggleMilitary");
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ function editEmblem(type, id, el) {
|
||||||
reader.onload = function(readerEvent) {
|
reader.onload = function(readerEvent) {
|
||||||
const result = readerEvent.target.result;
|
const result = readerEvent.target.result;
|
||||||
const defs = document.getElementById("defs-emblems");
|
const defs = document.getElementById("defs-emblems");
|
||||||
|
const coa = document.getElementById(id); // old emblem
|
||||||
|
|
||||||
if (type === "image") {
|
if (type === "image") {
|
||||||
const svg = `<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><image x="0" y="0" width="200" height="200" href="${result}"/></svg>`;
|
const svg = `<svg id="${id}" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><image x="0" y="0" width="200" height="200" href="${result}"/></svg>`;
|
||||||
|
|
@ -217,9 +218,7 @@ function editEmblem(type, id, el) {
|
||||||
newEmblem.setAttribute("height", 200);
|
newEmblem.setAttribute("height", 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
const coa = document.getElementById(id);
|
|
||||||
if (coa) coa.remove(); // remove old emblem
|
if (coa) coa.remove(); // remove old emblem
|
||||||
|
|
||||||
el.coa = "custom";
|
el.coa = "custom";
|
||||||
emblemShapeSelector.disabled = true;
|
emblemShapeSelector.disabled = true;
|
||||||
};
|
};
|
||||||
|
|
@ -282,7 +281,6 @@ function editEmblem(type, id, el) {
|
||||||
|
|
||||||
function getSVG(svg, coa, size) {
|
function getSVG(svg, coa, size) {
|
||||||
const clone = svg.cloneNode(true); // clone svg
|
const clone = svg.cloneNode(true); // clone svg
|
||||||
const d = clone.getElementsByTagName("defs")[0];
|
|
||||||
|
|
||||||
clone.setAttribute("width", size);
|
clone.setAttribute("width", size);
|
||||||
clone.setAttribute("height", size);
|
clone.setAttribute("height", size);
|
||||||
|
|
|
||||||
|
|
@ -1304,15 +1304,15 @@ function drawEmblems() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const burgNodes = nodes.filter(node => node.type === "burg");
|
const burgNodes = nodes.filter(node => node.type === "burg");
|
||||||
const burgString = burgNodes.map(d => `<use data-i="${d.i}" x="${d.x - d.size / 2}" y="${d.y - d.size / 2}" width="1em" height="1em"/>`).join("");
|
const burgString = burgNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.size / 2)}" y="${rn(d.y - d.size / 2)}" width="1em" height="1em"/>`).join("");
|
||||||
emblems.select("#burgEmblems").attr("font-size", sizeBurgs).html(burgString);
|
emblems.select("#burgEmblems").attr("font-size", sizeBurgs).html(burgString);
|
||||||
|
|
||||||
const provinceNodes = nodes.filter(node => node.type === "province");
|
const provinceNodes = nodes.filter(node => node.type === "province");
|
||||||
const provinceString = provinceNodes.map(d => `<use data-i="${d.i}" x="${d.x - d.size / 2}" y="${d.y - d.size / 2}" width="1em" height="1em"/>`).join("");
|
const provinceString = provinceNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.size / 2)}" y="${rn(d.y - d.size / 2)}" width="1em" height="1em"/>`).join("");
|
||||||
emblems.select("#provinceEmblems").attr("font-size", sizeProvinces).html(provinceString);
|
emblems.select("#provinceEmblems").attr("font-size", sizeProvinces).html(provinceString);
|
||||||
|
|
||||||
const stateNodes = nodes.filter(node => node.type === "state");
|
const stateNodes = nodes.filter(node => node.type === "state");
|
||||||
const stateString = stateNodes.map(d => `<use data-i="${d.i}" x="${d.x - d.size / 2}" y="${d.y - d.size / 2}" width="1em" height="1em"/>`).join("");
|
const stateString = stateNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.size / 2)}" y="${rn(d.y - d.size / 2)}" width="1em" height="1em"/>`).join("");
|
||||||
emblems.select("#stateEmblems").attr("font-size", sizeStates).html(stateString);
|
emblems.select("#stateEmblems").attr("font-size", sizeStates).html(stateString);
|
||||||
|
|
||||||
invokeActiveZooming();
|
invokeActiveZooming();
|
||||||
|
|
|
||||||
|
|
@ -664,14 +664,9 @@ function fetchTextureURL(url) {
|
||||||
img.src = url;
|
img.src = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
function armiesStyle() {
|
|
||||||
return `#armies text {stroke: none; fill: #fff; text-shadow: 0 0 4px #000; dominant-baseline: central; text-anchor: middle; font-family: Helvetica; fill-opacity: 1;}#armies text.regimentIcon {font-size: .8em;}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply default or custom style settings on load
|
// apply default or custom style settings on load
|
||||||
function applyStyleOnLoad() {
|
function applyStyleOnLoad() {
|
||||||
addDefaulsStyles(); // add FMG system styles to localStorage
|
addDefaulsStyles(); // add FMG system styles to localStorage
|
||||||
svg.select("defs").append("style").text(armiesStyle()); // add armies style
|
|
||||||
|
|
||||||
const preset = localStorage.getItem("presetStyle");
|
const preset = localStorage.getItem("presetStyle");
|
||||||
const style = preset ? localStorage.getItem(preset) : null;
|
const style = preset ? localStorage.getItem(preset) : null;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue