diff --git a/modules/save.js b/modules/save.js
index 138928e1..84d0aaaa 100644
--- a/modules/save.js
+++ b/modules/save.js
@@ -71,7 +71,7 @@ async function saveJPEG() {
}
// parse map svg to object url
-async function getMapURL(type, options=[]) {
+async function getMapURL(type, {globe=false, noLabels=false, noWater=false}) {
const cloneEl = document.getElementById("map").cloneNode(true); // clone svg
cloneEl.id = "fantasyMap";
document.body.appendChild(cloneEl);
@@ -83,13 +83,13 @@ async function getMapURL(type, options=[]) {
const isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
if (isFirefox && type === "mesh") clone.select("#oceanPattern").remove();
- if (options.includes("globe")) clone.select("#scaleBar").remove();
- if (options.includes("noLabels")) {
+ if (globe) clone.select("#scaleBar").remove();
+ if (noLabels) {
clone.select("#labels #states").remove();
clone.select("#labels #burgLabels").remove();
clone.select("#icons #burgIcons").remove();
}
- if (options.includes("noWater")) {
+ if (noWater) {
clone.select("#oceanBase").attr("opacity", 0);
clone.select("#oceanPattern").attr("opacity", 0);
}
diff --git a/modules/ui/3d.js b/modules/ui/3d.js
index 474c50c1..42552f2d 100644
--- a/modules/ui/3d.js
+++ b/modules/ui/3d.js
@@ -15,6 +15,7 @@ let Renderer, scene, camera, controls, animationFrame, material, texture,
const drawSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg");
document.body.appendChild(drawSVG);
let textMeshs = [], iconMeshs = [];
+const fontCache = {"Georgia": "", "Times New Roman": "", "Comic Sans MS": "", "Lucida Sans Unicode": "", "Courier New": "", "Verdana": "", "Arial": "", "Impact": ""} // default are web-safe fonts
// initiate 3d scene
const create = async function(canvas, type = "viewMesh") {
@@ -115,10 +116,14 @@ const toggleSky = function() {
}
const toggleLabels = function() {
- if (options.labels3d) deleteLabels(); else createLabels();
+ if (options.labels3d) {
+ deleteLabels();
+ update();
+ } else {
+ createLabels().then(() => update());
+ }
options.labels3d = !options.labels3d;
- update();
}
const setColors = function(sky, water) {
@@ -219,10 +224,11 @@ function svg2mesh(svg, sx=1, sy=1) {
return mesh;
}
-function createStateText(font, size, color, label) {
+async function createStateText(font, size, color, label) {
drawSVG.innerHTML = "";
drawSVG.appendChild(label.cloneNode(true));
- drawSVG.children[0].innerHTML = ``;
+ if (fontCache[font] == undefined) {fontCache[font] = await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)}
+ drawSVG.children[0].innerHTML = ``;
drawSVG.children[0].appendChild(svg.select(label.childNodes[0].href.baseVal).node().cloneNode(true)); // href of path in defs
drawSVG.children[1].setAttribute("transform", `scale(${5} ${5})`)
drawSVG.children[1].setAttribute('font-family', font);
@@ -235,20 +241,21 @@ function createStateText(font, size, color, label) {
return mesh;
}
-function createBurgText(text, font, size, color) {
+async function createBurgText(text, font, size, color) {
+ if (fontCache[font] == undefined) {fontCache[font] = await GFontToDataURI(`https://fonts.googleapis.com/css?family=${font}`)}
drawSVG.innerHTML = `${text}
-`;
+`;
return svg2mesh(drawSVG, 7*2, 7*2);
}
function get3dCoords(base_x, base_y) {
- const x = base_x - svg.attr("width")/2;
+ const x = base_x - graphWidth/2;
const y = getMeshHeight(findGridCell(base_x, base_y)); // work better than getMeshHeight(burg.cell) but I don't know why
- const z = base_y - svg.attr("height")/2;
+ const z = base_y - graphHeight/2;
return [x, y, z];
}
-function createLabels() {
+async function createLabels() {
// Burg labels
const cities = svg.select("#viewbox #labels #burgLabels #cities");
const towns = svg.select('#viewbox #labels #burgLabels #towns');
@@ -260,9 +267,9 @@ function createLabels() {
if(layerIsOn("toggleLabels")) {
if (burg.capital) {
- var text_mesh = createBurgText(burg.name, cities.attr('font-family'), cities.attr('font-size'), cities.attr('fill')); // cities.attr('font-size')
+ var text_mesh = await createBurgText(burg.name, cities.attr('font-family'), cities.attr('font-size'), cities.attr('fill')); // cities.attr('font-size')
} else {
- var text_mesh = createBurgText(burg.name, towns.attr('font-family'), towns.attr('font-size'), towns.attr('fill')); // towns.attr('font-size')
+ var text_mesh = await createBurgText(burg.name, towns.attr('font-family'), towns.attr('font-size'), towns.attr('fill')); // towns.attr('font-size')
}
if (burg.capital) {
@@ -310,7 +317,7 @@ function createLabels() {
// State labels
const state_labels = svg.select("#viewbox #labels #states")
for (const label of state_labels.node().children) {
- const text_mesh = createStateText(state_labels.attr("font-family"), state_labels.attr("font-size"), state_labels.attr("fill"), label);
+ const text_mesh = await createStateText(state_labels.attr("font-family"), state_labels.attr("font-size"), state_labels.attr("fill"), label);
const id = label.id.match(/\d+$/);
const pos = pack.states[id].pole
const [x, y, z] = get3dCoords(pos[0], pos[1])
@@ -341,9 +348,9 @@ function deleteLabels() {
// create a mesh from pixel data
async function createMesh(width, height, segmentsX, segmentsY) {
- const mapOptions = []
- if (options.labels3d) mapOptions.push("noLabels");
- if (options.extendedWater) mapOptions.push("noWater");
+ const mapOptions = {}
+ if (options.labels3d) mapOptions.noLabels = true;
+ if (options.extendedWater) mapOptions.noWater = true;
const url = await getMapURL("mesh", mapOptions);
window.setTimeout(() => window.URL.revokeObjectURL(url), 3000);
@@ -373,7 +380,7 @@ async function createMesh(width, height, segmentsX, segmentsY) {
iconMeshs = [];
if (options.labels3d) {
- createLabels();
+ await createLabels();
}
}
@@ -397,9 +404,9 @@ function extendWater(width, height) {
async function update3dTexture() {
if (texture) texture.dispose();
- const mapOptions = []
- if (options.labels3d) mapOptions.push("noLabels");
- if (options.extendedWater) mapOptions.push("noWater");
+ const mapOptions = {}
+ if (options.labels3d) mapOptions.noLabels = true;
+ if (options.extendedWater) mapOptions.noWater = true;
const url = await getMapURL("mesh", mapOptions);
window.setTimeout(() => window.URL.revokeObjectURL(url), 3000);
texture = new THREE.TextureLoader().load(url, render);
@@ -473,7 +480,7 @@ async function updateGlobeTexure(addMesh) {
material.map = texture;
if (addMesh) addGlobe3dMesh();
};
- img2.src = await getMapURL("mesh", ["globe"]);
+ img2.src = await getMapURL("mesh", {globe: true});
}
async function getOBJ() {