diff --git a/index.html b/index.html index 33c29a5a..2c9fce59 100644 --- a/index.html +++ b/index.html @@ -752,7 +752,7 @@ Color scheme - @@ -764,14 +764,14 @@ Terracing - + 0 Reduce layers - + 5 @@ -779,7 +779,7 @@ Simplify line - + 0 @@ -787,7 +787,7 @@ Line style - @@ -953,7 +953,7 @@ - 10K + 10K @@ -1151,7 +1151,7 @@ - + @@ -1364,14 +1364,14 @@
Depressions filling max iterations: - - + +
Depression depth threshold: - - + +
@@ -3086,8 +3086,8 @@
Bar size:
- - + +
@@ -3408,8 +3408,8 @@

Generator uses pop-up window to download files. Please ensure your browser does not block popups.

PNG / JPEG scale: - - + +
@@ -3430,18 +3430,19 @@

Map will be split into tiles and downloaded as a single zip file. Avoid saving to big images

Columns:
- - + +
Rows:
- - + +
Scale:
- - + +
Total size:
diff --git a/modules/load.js b/modules/load.js index 500c390a..60c5b3e3 100644 --- a/modules/load.js +++ b/modules/load.js @@ -125,7 +125,7 @@ function parseLoadedData(data) { if (settings[3]) applyOption(heightUnit, settings[3]); if (settings[4]) heightExponentInput.value = heightExponentOutput.value = settings[4]; if (settings[5]) temperatureScale.value = settings[5]; - if (settings[6]) barSize.value = barSizeOutput.value = settings[6]; + if (settings[6]) barSizeInput.value = barSizeOutput.value = settings[6]; if (settings[7] !== undefined) barLabel.value = settings[7]; if (settings[8] !== undefined) barBackOpacity.value = settings[8]; if (settings[9]) barBackColor.value = settings[9]; diff --git a/modules/save.js b/modules/save.js index 72e73028..d612799c 100644 --- a/modules/save.js +++ b/modules/save.js @@ -417,7 +417,7 @@ function getMapData() { const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator"; const params = [version, license, dateString, seed, graphWidth, graphHeight, mapId].join("|"); - const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSize.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate.value, urbanization.value, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked].join("|"); + const settings = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, barSizeInput.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate.value, urbanization.value, mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(options), mapName.value, +hideLabels.checked].join("|"); const coords = JSON.stringify(mapCoordinates); const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|"); const notesData = JSON.stringify(notes); diff --git a/modules/ui/measurers.js b/modules/ui/measurers.js index 6f27a53b..1d97a2d1 100644 --- a/modules/ui/measurers.js +++ b/modules/ui/measurers.js @@ -20,10 +20,7 @@ class Rulers { for (const rulerString of rulers) { const [type, pointsString] = rulerString.split(": "); const points = pointsString.split(" ").map(el => el.split(",").map(n => +n)); - const Type = type === "Ruler" ? Ruler : - type === "Opisometer" ? Opisometer : - type === "RouteOpisometer" ? RouteOpisometer : - type === "Planimeter" ? Planimeter : null; + const Type = type === "Ruler" ? Ruler : type === "Opisometer" ? Opisometer : type === "RouteOpisometer" ? RouteOpisometer : type === "Planimeter" ? Planimeter : null; this.create(Type, points); } } @@ -57,7 +54,7 @@ class Measurer { } getSize() { - return rn(1 / scale ** .3 * 2, 2); + return rn((1 / scale ** 0.3) * 2, 2); } getDash() { @@ -66,10 +63,11 @@ class Measurer { drag() { const tr = parseTransform(this.getAttribute("transform")); - const x = +tr[0] - d3.event.x, y = +tr[1] - d3.event.y; + const x = +tr[0] - d3.event.x, + y = +tr[1] - d3.event.y; - d3.event.on("drag", function() { - const transform = `translate(${(x + d3.event.x)},${(y + d3.event.y)})`; + d3.event.on("drag", function () { + const transform = `translate(${x + d3.event.x},${y + d3.event.y})`; this.setAttribute("transform", transform); }); } @@ -89,9 +87,9 @@ class Measurer { const MIN_DIST2 = 900; const optimized = []; - for (let i=0, p1 = this.points[0]; i < this.points.length; i++) { + for (let i = 0, p1 = this.points[0]; i < this.points.length; i++) { const p2 = this.points[i]; - const dist2 = !i || i === this.points.length-1 ? Infinity : (p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2; + const dist2 = !i || i === this.points.length - 1 ? Infinity : (p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2; if (dist2 < MIN_DIST2) continue; optimized.push(p2); p1 = p2; @@ -105,7 +103,6 @@ class Measurer { undraw() { this.el?.remove(); } - } class Ruler extends Measurer { @@ -136,12 +133,29 @@ class Ruler extends Measurer { const size = this.getSize(); const dash = this.getDash(); - const el = this.el = ruler.append("g").attr("class", "ruler").call(d3.drag().on("start", this.drag)).attr("font-size", 10 * size); - el.append("polyline").attr("points", points).attr("class", "white").attr("stroke-width", size) + const el = (this.el = ruler + .append("g") + .attr("class", "ruler") + .call(d3.drag().on("start", this.drag)) + .attr("font-size", 10 * size)); + el.append("polyline") + .attr("points", points) + .attr("class", "white") + .attr("stroke-width", size) .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)).attr("stroke-dasharray", dash); - el.append("g").attr("class", "rulerPoints").attr("stroke-width", .5 * size).attr("font-size", 2 * size); - el.append("text").attr("dx", ".35em").attr("dy", "-.45em").on("click", () => rulers.remove(this.id)); + el.append("polyline") + .attr("points", points) + .attr("class", "gray") + .attr("stroke-width", rn(size * 1.2, 2)) + .attr("stroke-dasharray", dash); + el.append("g") + .attr("class", "rulerPoints") + .attr("stroke-width", 0.5 * size) + .attr("font-size", 2 * size); + el.append("text") + .attr("dx", ".35em") + .attr("dy", "-.45em") + .on("click", () => rulers.remove(this.id)); this.drawPoints(el); this.updateLabel(); return this; @@ -151,7 +165,7 @@ class Ruler extends Measurer { const g = el.select(".rulerPoints"); g.selectAll("circle").remove(); - for (let i=0; i < this.points.length; i++) { + for (let i = 0; i < this.points.length; i++) { const [x, y] = this.points[i]; this.drawPoint(g, x, y, i); } @@ -160,14 +174,25 @@ class Ruler extends Measurer { drawPoint(el, x, y, i) { const context = this; el.append("circle") - .attr("r", "1em").attr("cx", x).attr("cy", y) + .attr("r", "1em") + .attr("cx", x) + .attr("cy", y) .attr("class", this.isEdge(i) ? "edge" : "control") - .on("click", function() {context.removePoint(context, i)}) - .call(d3.drag().clickDistance(3).on("start", function() {context.dragControl(context, i)})); + .on("click", function () { + context.removePoint(context, i); + }) + .call( + d3 + .drag() + .clickDistance(3) + .on("start", function () { + context.dragControl(context, i); + }) + ); } isEdge(i) { - return i === 0 || i === this.points.length-1; + return i === 0 || i === this.points.length - 1; } updateLabel() { @@ -179,9 +204,9 @@ class Ruler extends Measurer { getLength() { let length = 0; - for (let i=0; i < this.points.length - 1; i++) { + for (let i = 0; i < this.points.length - 1; i++) { const [x1, y1] = this.points[i]; - const [x2, y2] = this.points[i+1]; + const [x2, y2] = this.points[i + 1]; length += Math.hypot(x1 - x2, y1 - y2); } return length; @@ -189,20 +214,20 @@ class Ruler extends Measurer { dragControl(context, pointId) { let addPoint = context.isEdge(pointId) && d3.event.sourceEvent.ctrlKey; - let circle = context.el.select(`circle:nth-child(${pointId+1})`); + let circle = context.el.select(`circle:nth-child(${pointId + 1})`); const line = context.el.selectAll("polyline"); let x0 = rn(d3.event.x, 1); let y0 = rn(d3.event.y, 1); let axis; - d3.event.on("drag", function() { + d3.event.on("drag", function () { if (addPoint) { - if (d3.event.dx < .1 && d3.event.dy < .1) return; + if (d3.event.dx < 0.1 && d3.event.dy < 0.1) return; context.pushPoint(pointId); context.drawPoints(context.el); if (pointId) pointId++; - circle = context.el.select(`circle:nth-child(${pointId+1})`); + circle = context.el.select(`circle:nth-child(${pointId + 1})`); addPoint = false; } @@ -253,13 +278,38 @@ class Opisometer extends Measurer { const dash = this.getDash(); const context = this; - const el = this.el = ruler.append("g").attr("class", "opisometer").call(d3.drag().on("start", this.drag)).attr("font-size", 10 * size); + const el = (this.el = ruler + .append("g") + .attr("class", "opisometer") + .call(d3.drag().on("start", this.drag)) + .attr("font-size", 10 * size)); el.append("path").attr("class", "white").attr("stroke-width", size); el.append("path").attr("class", "gray").attr("stroke-width", size).attr("stroke-dasharray", dash); - const rulerPoints = el.append("g").attr("class", "rulerPoints").attr("stroke-width", .5 * size).attr("font-size", 2 * size); - rulerPoints.append("circle").attr("r", "1em").call(d3.drag().on("start", function() {context.dragControl(context, 0)})); - rulerPoints.append("circle").attr("r", "1em").call(d3.drag().on("start", function() {context.dragControl(context, 1)})); - el.append("text").attr("dx", ".35em").attr("dy", "-.45em").on("click", () => rulers.remove(this.id)); + const rulerPoints = el + .append("g") + .attr("class", "rulerPoints") + .attr("stroke-width", 0.5 * size) + .attr("font-size", 2 * size); + rulerPoints + .append("circle") + .attr("r", "1em") + .call( + d3.drag().on("start", function () { + context.dragControl(context, 0); + }) + ); + rulerPoints + .append("circle") + .attr("r", "1em") + .call( + d3.drag().on("start", function () { + context.dragControl(context, 1); + }) + ); + el.append("text") + .attr("dx", ".35em") + .attr("dy", "-.45em") + .on("click", () => rulers.remove(this.id)); this.updateCurve(); this.updateLabel(); @@ -267,7 +317,7 @@ class Opisometer extends Measurer { } updateCurve() { - lineGen.curve(d3.curveCatmullRom.alpha(.5)); + lineGen.curve(d3.curveCatmullRom.alpha(0.5)); const path = round(lineGen(this.points)); this.el.selectAll("path").attr("d", path); @@ -288,7 +338,7 @@ class Opisometer extends Measurer { const MIN_DIST = d3.event.sourceEvent.shiftKey ? 9 : 100; let prev = rigth ? last(context.points) : context.points[0]; - d3.event.on("drag", function() { + d3.event.on("drag", function () { const point = [d3.event.x | 0, d3.event.y | 0]; const dist2 = (prev[0] - point[0]) ** 2 + (prev[1] - point[1]) ** 2; @@ -301,7 +351,7 @@ class Opisometer extends Measurer { context.updateLabel(); }); - d3.event.on("end", function() { + d3.event.on("end", function () { if (!d3.event.sourceEvent.shiftKey) context.optimize(); }); } @@ -367,13 +417,37 @@ class RouteOpisometer extends Measurer { const dash = this.getDash(); const context = this; - const el = this.el = ruler.append("g").attr("class", "opisometer").attr("font-size", 10 * size); + const el = (this.el = ruler + .append("g") + .attr("class", "opisometer") + .attr("font-size", 10 * size)); el.append("path").attr("class", "white").attr("stroke-width", size); el.append("path").attr("class", "gray").attr("stroke-width", size).attr("stroke-dasharray", dash); - const rulerPoints = el.append("g").attr("class", "rulerPoints").attr("stroke-width", .5 * size).attr("font-size", 2 * size); - rulerPoints.append("circle").attr("r", "1em").call(d3.drag().on("start", function() {context.dragControl(context, 0)})); - rulerPoints.append("circle").attr("r", "1em").call(d3.drag().on("start", function() {context.dragControl(context, 1)})); - el.append("text").attr("dx", ".35em").attr("dy", "-.45em").on("click", () => rulers.remove(this.id)); + const rulerPoints = el + .append("g") + .attr("class", "rulerPoints") + .attr("stroke-width", 0.5 * size) + .attr("font-size", 2 * size); + rulerPoints + .append("circle") + .attr("r", "1em") + .call( + d3.drag().on("start", function () { + context.dragControl(context, 0); + }) + ); + rulerPoints + .append("circle") + .attr("r", "1em") + .call( + d3.drag().on("start", function () { + context.dragControl(context, 1); + }) + ); + el.append("text") + .attr("dx", ".35em") + .attr("dy", "-.45em") + .on("click", () => rulers.remove(this.id)); this.updateCurve(); this.updateLabel(); @@ -381,7 +455,7 @@ class RouteOpisometer extends Measurer { } updateCurve() { - lineGen.curve(d3.curveCatmullRom.alpha(.5)); + lineGen.curve(d3.curveCatmullRom.alpha(0.5)); const path = round(lineGen(this.points)); this.el.selectAll("path").attr("d", path); @@ -399,7 +473,7 @@ class RouteOpisometer extends Measurer { } dragControl(context, rigth) { - d3.event.on("drag", function() { + d3.event.on("drag", function () { const mousePoint = [d3.event.x | 0, d3.event.y | 0]; const cells = pack.cells; @@ -422,7 +496,11 @@ class Planimeter extends Measurer { if (this.el) this.el.selectAll("*").remove(); const size = this.getSize(); - const el = this.el = ruler.append("g").attr("class", "planimeter").call(d3.drag().on("start", this.drag)).attr("font-size", 10 * size); + const el = (this.el = ruler + .append("g") + .attr("class", "planimeter") + .call(d3.drag().on("start", this.drag)) + .attr("font-size", 10 * size)); el.append("path").attr("class", "planimeter").attr("stroke-width", size); el.append("text").on("click", () => rulers.remove(this.id)); @@ -432,7 +510,7 @@ class Planimeter extends Measurer { } updateCurve() { - lineGen.curve(d3.curveCatmullRomClosed.alpha(.5)); + lineGen.curve(d3.curveCatmullRomClosed.alpha(0.5)); const path = round(lineGen(this.points)); this.el.selectAll("path").attr("d", path); } @@ -458,36 +536,79 @@ function drawScaleBar() { // calculate size const init = 100; // actual length in pixels if scale, dScale and size = 1; - const size = +barSize.value; - let val = init * size * dScale / scale; // bar length in distance unit - if (val > 900) val = rn(val, -3); // round to 1000 - else if (val > 90) val = rn(val, -2); // round to 100 - else if (val > 9) val = rn(val, -1); // round to 10 - else val = rn(val) // round to 1 - const l = val * scale / dScale; // actual length in pixels on this scale + const size = +barSizeInput.value; + let val = (init * size * dScale) / scale; // bar length in distance unit + if (val > 900) val = rn(val, -3); + // round to 1000 + else if (val > 90) val = rn(val, -2); + // round to 100 + else if (val > 9) val = rn(val, -1); + // round to 10 + else val = rn(val); // round to 1 + const l = (val * scale) / dScale; // actual length in pixels on this scale - scaleBar.append("line").attr("x1", 0.5).attr("y1", 0).attr("x2", l+size-0.5).attr("y2", 0).attr("stroke-width", size).attr("stroke", "white"); - scaleBar.append("line").attr("x1", 0).attr("y1", size).attr("x2", l+size).attr("y2", size).attr("stroke-width", size).attr("stroke", "#3d3d3d"); + scaleBar + .append("line") + .attr("x1", 0.5) + .attr("y1", 0) + .attr("x2", l + size - 0.5) + .attr("y2", 0) + .attr("stroke-width", size) + .attr("stroke", "white"); + scaleBar + .append("line") + .attr("x1", 0) + .attr("y1", size) + .attr("x2", l + size) + .attr("y2", size) + .attr("stroke-width", size) + .attr("stroke", "#3d3d3d"); const dash = size + " " + rn(l / 5 - size, 2); - scaleBar.append("line").attr("x1", 0).attr("y1", 0).attr("x2", l+size).attr("y2", 0) - .attr("stroke-width", rn(size * 3, 2)).attr("stroke-dasharray", dash).attr("stroke", "#3d3d3d"); + scaleBar + .append("line") + .attr("x1", 0) + .attr("y1", 0) + .attr("x2", l + size) + .attr("y2", 0) + .attr("stroke-width", rn(size * 3, 2)) + .attr("stroke-dasharray", dash) + .attr("stroke", "#3d3d3d"); const fontSize = rn(5 * size, 1); - scaleBar.selectAll("text").data(d3.range(0,6)).enter().append("text") - .attr("x", d => rn(d * l/5, 2)).attr("y", 0).attr("dy", "-.5em") - .attr("font-size", fontSize).text(d => rn(d * l/5 * dScale / scale) + (d<5 ? "" : " " + unit)); + scaleBar + .selectAll("text") + .data(d3.range(0, 6)) + .enter() + .append("text") + .attr("x", d => rn((d * l) / 5, 2)) + .attr("y", 0) + .attr("dy", "-.5em") + .attr("font-size", fontSize) + .text(d => rn((((d * l) / 5) * dScale) / scale) + (d < 5 ? "" : " " + unit)); if (barLabel.value !== "") { - scaleBar.append("text").attr("x", (l+1) / 2).attr("y", 2 * size) + scaleBar + .append("text") + .attr("x", (l + 1) / 2) + .attr("y", 2 * size) .attr("dominant-baseline", "text-before-edge") - .attr("font-size", fontSize).text(barLabel.value); + .attr("font-size", fontSize) + .text(barLabel.value); } const bbox = scaleBar.node().getBBox(); // append backbround rectangle - scaleBar.insert("rect", ":first-child").attr("x", -10).attr("y", -20).attr("width", bbox.width + 10).attr("height", bbox.height + 15) - .attr("stroke-width", size).attr("stroke", "none").attr("filter", "url(#blur5)") - .attr("fill", barBackColor.value).attr("opacity", +barBackOpacity.value); + scaleBar + .insert("rect", ":first-child") + .attr("x", -10) + .attr("y", -20) + .attr("width", bbox.width + 10) + .attr("height", bbox.height + 15) + .attr("stroke-width", size) + .attr("stroke", "none") + .attr("filter", "url(#blur5)") + .attr("fill", barBackColor.value) + .attr("opacity", +barBackOpacity.value); fitScaleBar(); } @@ -495,9 +616,10 @@ function drawScaleBar() { // fit ScaleBar to canvas size function fitScaleBar() { if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return; - const px = isNaN(+barPosX.value) ? .99 : barPosX.value / 100; - const py = isNaN(+barPosY.value) ? .99 : barPosY.value / 100; + 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), + y = rn(svgHeight * py - bbox.height + 20); scaleBar.attr("transform", `translate(${x},${y})`); } diff --git a/modules/ui/options.js b/modules/ui/options.js index 3990be2a..9aa77a5a 100644 --- a/modules/ui/options.js +++ b/modules/ui/options.js @@ -108,35 +108,51 @@ function showSupporters() { $("#alert").dialog({resizable: false, title: "Patreon Supporters", width: "54vw", position: {my: "center", at: "center", of: "svg"}}); } +// on any option or dialog change +document.getElementById("options").addEventListener("change", checkIfStored); +document.getElementById("dialogs").addEventListener("change", checkIfStored); +document.getElementById("options").addEventListener("input", updateOutputToFollowInput); +document.getElementById("dialogs").addEventListener("input", updateOutputToFollowInput); + +function checkIfStored(ev) { + if (ev.target.dataset.stored) lock(ev.target.dataset.stored); +} + +function updateOutputToFollowInput(ev) { + const id = ev.target.id; + const value = ev.target.value; + + // specific cases + if (id === "manorsInput") return (manorsOutput.value = value == 1000 ? "auto" : value); + + // generic case + if (id.slice(-5) === "Input") { + const output = document.getElementById(id.slice(0, -5) + "Output"); + if (output) output.value = value; + } else if (id.slice(-6) === "Output") { + const input = document.getElementById(id.slice(0, -6) + "Input"); + if (input) input.value = value; + } +} + // Option listeners const optionsContent = document.getElementById("optionsContent"); optionsContent.addEventListener("input", function (event) { - const id = event.target.id, - value = event.target.value; + const id = event.target.id; + const value = event.target.value; if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange(); else if (id === "pointsInput") changeCellsDensity(+value); - else if (id === "culturesInput") culturesOutput.value = value; - else if (id === "culturesOutput") culturesInput.value = value; else if (id === "culturesSet") changeCultureSet(); else if (id === "regionsInput" || id === "regionsOutput") changeStatesNumber(value); - else if (id === "provincesInput") provincesOutput.value = value; - else if (id === "provincesOutput") provincesOutput.value = value; - else if (id === "provincesOutput") powerOutput.value = value; - else if (id === "powerInput") powerOutput.value = value; - else if (id === "powerOutput") powerInput.value = value; - else if (id === "neutralInput") neutralOutput.value = value; - else if (id === "neutralOutput") neutralInput.value = value; - else if (id === "manorsInput") changeBurgsNumberSlider(value); - else if (id === "religionsInput") religionsOutput.value = value; else if (id === "emblemShape") changeEmblemShape(value); else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value); else if (id === "transparencyInput") changeDialogsTransparency(value); }); optionsContent.addEventListener("change", function (event) { - if (event.target.dataset.stored) lock(event.target.dataset.stored); - const id = event.target.id, - value = event.target.value; + const id = event.target.id; + const value = event.target.value; + if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value); else if (id === "optionsSeed") generateMapWithSeed(); else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value); @@ -332,8 +348,8 @@ function changeCellsDensity(value) { const cells = convert(value); pointsInput.setAttribute("data-cells", cells); - pointsOutput.value = cells / 1000 + "K"; - pointsOutput.style.color = cells > 50000 ? "#b12117" : cells !== 10000 ? "#dfdf12" : "#053305"; + pointsOutput_formatted.value = cells / 1000 + "K"; + pointsOutput_formatted.style.color = cells > 50000 ? "#b12117" : cells !== 10000 ? "#dfdf12" : "#053305"; } function changeCultureSet() { @@ -384,16 +400,11 @@ function changeEmblemShape(emblemShape) { } function changeStatesNumber(value) { - regionsInput.value = regionsOutput.value = value; regionsOutput.style.color = +value ? null : "#b12117"; burgLabels.select("#capitals").attr("data-size", Math.max(rn(6 - value / 20), 3)); labels.select("#countries").attr("data-size", Math.max(rn(18 - value / 6), 4)); } -function changeBurgsNumberSlider(value) { - manorsOutput.value = value == 1000 ? "auto" : value; -} - function changeUIsize(value) { if (isNaN(+value) || +value < 0.5) return; @@ -410,7 +421,6 @@ function getUImaxSize() { } function changeTooltipSize(value) { - tooltipSizeInput.value = tooltipSizeOutput.value = value; tooltip.style.fontSize = `calc(${value}px + 0.5vw)`; } @@ -448,8 +458,9 @@ function applyStoredOptions() { if (localStorage.getItem("heightUnit")) applyOption(heightUnit, localStorage.getItem("heightUnit")); for (let i = 0; i < localStorage.length; i++) { - const stored = localStorage.key(i), - value = localStorage.getItem(stored); + const stored = localStorage.key(i); + const value = localStorage.getItem(stored); + if (stored === "speakerVoice") continue; const input = document.getElementById(stored + "Input") || document.getElementById(stored); const output = document.getElementById(stored + "Output"); diff --git a/modules/ui/style.js b/modules/ui/style.js index 161636b6..44605bcc 100644 --- a/modules/ui/style.js +++ b/modules/ui/style.js @@ -92,9 +92,9 @@ function selectStyleElement() { if (sel === "terrs") { styleHeightmap.style.display = "block"; styleHeightmapScheme.value = terrs.attr("scheme"); - styleHeightmapTerracing.value = styleHeightmapTerracingOutput.value = terrs.attr("terracing"); - styleHeightmapSkip.value = styleHeightmapSkipOutput.value = terrs.attr("skip"); - styleHeightmapSimplification.value = styleHeightmapSimplificationOutput.value = terrs.attr("relax"); + styleHeightmapTerracingInput.value = styleHeightmapTerracingOutput.value = terrs.attr("terracing"); + styleHeightmapSkipInput.value = styleHeightmapSkipOutput.value = terrs.attr("skip"); + styleHeightmapSimplificationInput.value = styleHeightmapSimplificationOutput.value = terrs.attr("relax"); styleHeightmapCurve.value = terrs.attr("curve"); } @@ -419,20 +419,17 @@ styleHeightmapScheme.addEventListener("change", function () { drawHeightmap(); }); -styleHeightmapTerracing.addEventListener("input", function () { - styleHeightmapTerracingOutput.value = this.value; +styleHeightmapTerracingInput.addEventListener("input", function () { terrs.attr("terracing", this.value); drawHeightmap(); }); -styleHeightmapSkip.addEventListener("input", function () { - styleHeightmapSkipOutput.value = this.value; +styleHeightmapSkipInput.addEventListener("input", function () { terrs.attr("skip", this.value); drawHeightmap(); }); -styleHeightmapSimplification.addEventListener("input", function () { - styleHeightmapSimplificationOutput.value = this.value; +styleHeightmapSimplificationInput.addEventListener("input", function () { terrs.attr("relax", this.value); drawHeightmap(); }); diff --git a/modules/ui/units-editor.js b/modules/ui/units-editor.js index 9c47a0ef..fe12ecf9 100644 --- a/modules/ui/units-editor.js +++ b/modules/ui/units-editor.js @@ -15,16 +15,15 @@ function editUnits() { document.getElementById("distanceUnitInput").addEventListener("change", changeDistanceUnit); document.getElementById("distanceScaleOutput").addEventListener("input", changeDistanceScale); document.getElementById("distanceScaleInput").addEventListener("change", changeDistanceScale); - document.getElementById("areaUnit").addEventListener("change", () => lock("areaUnit")); document.getElementById("heightUnit").addEventListener("change", changeHeightUnit); document.getElementById("heightExponentInput").addEventListener("input", changeHeightExponent); document.getElementById("heightExponentOutput").addEventListener("input", changeHeightExponent); document.getElementById("temperatureScale").addEventListener("change", changeTemperatureScale); - document.getElementById("barSizeOutput").addEventListener("input", changeScaleBarSize); - document.getElementById("barSize").addEventListener("input", changeScaleBarSize); - document.getElementById("barLabel").addEventListener("input", changeScaleBarLabel); - document.getElementById("barPosX").addEventListener("input", changeScaleBarPosition); - document.getElementById("barPosY").addEventListener("input", changeScaleBarPosition); + document.getElementById("barSizeOutput").addEventListener("input", drawScaleBar); + document.getElementById("barSizeInput").addEventListener("input", drawScaleBar); + document.getElementById("barLabel").addEventListener("input", drawScaleBar); + document.getElementById("barPosX").addEventListener("input", fitScaleBar); + document.getElementById("barPosY").addEventListener("input", fitScaleBar); document.getElementById("barBackOpacity").addEventListener("input", changeScaleBarOpacity); document.getElementById("barBackColor").addEventListener("input", changeScaleBarColor); @@ -42,7 +41,7 @@ function editUnits() { function changeDistanceUnit() { if (this.value === "custom_name") { - prompt("Provide a custom name for a distance unit", {default:""}, custom => { + prompt("Provide a custom name for a distance unit", {default: ""}, custom => { this.options.add(new Option(custom, custom, false, true)); lock("distanceUnit"); drawScaleBar(); @@ -51,114 +50,55 @@ function editUnits() { return; } - lock("distanceUnit"); drawScaleBar(); calculateFriendlyGridSize(); } function changeDistanceScale() { - const scale = +this.value; - if (!scale || isNaN(scale) || scale < 0) { - tip("Distance scale should be a positive number", false, "error"); - this.value = document.getElementById("distanceScaleInput").dataset.value; - return; - } - - document.getElementById("distanceScaleOutput").value = scale; - document.getElementById("distanceScaleInput").value = scale; - document.getElementById("distanceScaleInput").dataset.value = scale; - lock("distanceScale"); - drawScaleBar(); calculateFriendlyGridSize(); } function changeHeightUnit() { - if (this.value === "custom_name") { - prompt("Provide a custom name for a height unit", {default:""}, custom => { - this.options.add(new Option(custom, custom, false, true)); - lock("heightUnit"); - }); - return; - } + if (this.value !== "custom_name") return; - lock("heightUnit"); + prompt("Provide a custom name for a height unit", {default: ""}, custom => { + this.options.add(new Option(custom, custom, false, true)); + lock("heightUnit"); + }); } function changeHeightExponent() { - document.getElementById("heightExponentInput").value = this.value; - document.getElementById("heightExponentOutput").value = this.value; calculateTemperatures(); if (layerIsOn("toggleTemp")) drawTemp(); - lock("heightExponent"); } function changeTemperatureScale() { - lock("temperatureScale"); if (layerIsOn("toggleTemp")) drawTemp(); } - function changeScaleBarSize() { - document.getElementById("barSize").value = this.value; - document.getElementById("barSizeOutput").value = this.value; - drawScaleBar(); - lock("barSize"); - } - - function changeScaleBarPosition() { - lock("barPosX"); - lock("barPosY"); - fitScaleBar(); - } - - function changeScaleBarLabel() { - lock("barLabel"); - drawScaleBar(); - } - function changeScaleBarOpacity() { scaleBar.select("rect").attr("opacity", this.value); - lock("barBackOpacity"); } function changeScaleBarColor() { scaleBar.select("rect").attr("fill", this.value); - lock("barBackColor"); } function changePopulationRate() { - const rate = +this.value; - if (!rate || isNaN(rate) || rate <= 0) { - tip("Population rate should be a positive number", false, "error"); - this.value = document.getElementById("populationRate").dataset.value; - return; - } - - document.getElementById("populationRateOutput").value = rate; - document.getElementById("populationRate").value = rate; - document.getElementById("populationRate").dataset.value = rate; - lock("populationRate"); + document.getElementById("populationRateOutput").value = this.value; + document.getElementById("populationRate").value = this.value; } function changeUrbanizationRate() { - const rate = +this.value; - if (!rate || isNaN(rate) || rate < 0) { - tip("Urbanization rate should be a number", false, "error"); - this.value = document.getElementById("urbanization").dataset.value; - return; - } - - document.getElementById("urbanizationOutput").value = rate; - document.getElementById("urbanization").value = rate; - document.getElementById("urbanization").dataset.value = rate; - lock("urbanization"); + document.getElementById("urbanizationOutput").value = this.value; + document.getElementById("urbanization").value = this.value; } function restoreDefaultUnits() { // distanceScale document.getElementById("distanceScaleOutput").value = 3; document.getElementById("distanceScaleInput").value = 3; - document.getElementById("distanceScaleInput").dataset.value = 3; unlock("distanceScale"); // units @@ -180,9 +120,9 @@ function editUnits() { calculateTemperatures(); // scale bar - barSizeOutput.value = barSize.value = 2; + barSizeOutput.value = barSizeInput.value = 2; barLabel.value = ""; - barBackOpacity.value = .2; + barBackOpacity.value = 0.2; barBackColor.value = "#ffffff"; barPosX.value = barPosY.value = 99; @@ -203,13 +143,13 @@ function editUnits() { function addRuler() { if (!layerIsOn("toggleRulers")) toggleRulers(); - const pt = document.getElementById('map').createSVGPoint(); - pt.x = graphWidth / 2, pt.y = graphHeight / 4; + const pt = document.getElementById("map").createSVGPoint(); + (pt.x = graphWidth / 2), (pt.y = graphHeight / 4); const p = pt.matrixTransform(viewbox.node().getScreenCTM().inverse()); const dx = graphWidth / 4 / scale; const dy = (rulers.data.length * 40) % (graphHeight / 2); - const from = [p.x-dx | 0, p.y+dy | 0]; - const to = [p.x+dx | 0, p.y+dy | 0]; + const from = [(p.x - dx) | 0, (p.y + dy) | 0]; + const to = [(p.x + dx) | 0, (p.y + dy) | 0]; rulers.create(Ruler, [from, to]).draw(); } @@ -223,23 +163,25 @@ function editUnits() { tip("Draw a curve to measure length. Hold Shift to disallow path optimization", true); unitsBottom.querySelectorAll(".pressed").forEach(button => button.classList.remove("pressed")); this.classList.add("pressed"); - viewbox.style("cursor", "crosshair").call(d3.drag().on("start", function() { - const point = d3.mouse(this); - const opisometer = rulers.create(Opisometer, [point]).draw(); - - d3.event.on("drag", function() { + viewbox.style("cursor", "crosshair").call( + d3.drag().on("start", function () { const point = d3.mouse(this); - opisometer.addPoint(point); - }); + const opisometer = rulers.create(Opisometer, [point]).draw(); - d3.event.on("end", function() { - restoreDefaultEvents(); - clearMainTip(); - addOpisometer.classList.remove("pressed"); - if (opisometer.points.length < 2) rulers.remove(opisometer.id); - if (!d3.event.sourceEvent.shiftKey) opisometer.optimize(); - }); - })); + d3.event.on("drag", function () { + const point = d3.mouse(this); + opisometer.addPoint(point); + }); + + d3.event.on("end", function () { + restoreDefaultEvents(); + clearMainTip(); + addOpisometer.classList.remove("pressed"); + if (opisometer.points.length < 2) rulers.remove(opisometer.id); + if (!d3.event.sourceEvent.shiftKey) opisometer.optimize(); + }); + }) + ); } } @@ -253,40 +195,42 @@ function editUnits() { tip("Draw a curve along routes to measure length. Hold Shift to measure away from roads.", true); unitsBottom.querySelectorAll(".pressed").forEach(button => button.classList.remove("pressed")); this.classList.add("pressed"); - viewbox.style("cursor", "crosshair").call(d3.drag().on("start", function() { - const cells = pack.cells; - const burgs = pack.burgs; - const point = d3.mouse(this); - const c = findCell(point[0], point[1]); - if (cells.road[c] || d3.event.sourceEvent.shiftKey) { - const b = cells.burg[c]; - const x = b ? burgs[b].x : cells.p[c][0]; - const y = b ? burgs[b].y : cells.p[c][1]; - const routeOpisometer = rulers.create(RouteOpisometer, [[x, y]]).draw(); + viewbox.style("cursor", "crosshair").call( + d3.drag().on("start", function () { + const cells = pack.cells; + const burgs = pack.burgs; + const point = d3.mouse(this); + const c = findCell(point[0], point[1]); + if (cells.road[c] || d3.event.sourceEvent.shiftKey) { + const b = cells.burg[c]; + const x = b ? burgs[b].x : cells.p[c][0]; + const y = b ? burgs[b].y : cells.p[c][1]; + const routeOpisometer = rulers.create(RouteOpisometer, [[x, y]]).draw(); - d3.event.on("drag", function () { - const point = d3.mouse(this); - const c = findCell(point[0], point[1]); - if (cells.road[c] || d3.event.sourceEvent.shiftKey) { - routeOpisometer.trackCell(c, true); - } - }); + d3.event.on("drag", function () { + const point = d3.mouse(this); + const c = findCell(point[0], point[1]); + if (cells.road[c] || d3.event.sourceEvent.shiftKey) { + routeOpisometer.trackCell(c, true); + } + }); - d3.event.on("end", function () { + d3.event.on("end", function () { + restoreDefaultEvents(); + clearMainTip(); + addRouteOpisometer.classList.remove("pressed"); + if (routeOpisometer.points.length < 2) { + rulers.remove(routeOpisometer.id); + } + }); + } else { restoreDefaultEvents(); clearMainTip(); addRouteOpisometer.classList.remove("pressed"); - if (routeOpisometer.points.length < 2) { - rulers.remove(routeOpisometer.id); - } - }); - } else { - restoreDefaultEvents(); - clearMainTip(); - addRouteOpisometer.classList.remove("pressed"); - tip("Must start in a cell with a route in it", false, "error"); - } - })); + tip("Must start in a cell with a route in it", false, "error"); + } + }) + ); } } @@ -300,24 +244,25 @@ function editUnits() { tip("Draw a curve to measure its area. Hold Shift to disallow path optimization", true); unitsBottom.querySelectorAll(".pressed").forEach(button => button.classList.remove("pressed")); this.classList.add("pressed"); - viewbox.style("cursor", "crosshair").call(d3.drag().on("start", function() { - const point = d3.mouse(this); - const planimeter = rulers.create(Planimeter, [point]).draw(); - - d3.event.on("drag", function() { + viewbox.style("cursor", "crosshair").call( + d3.drag().on("start", function () { const point = d3.mouse(this); - planimeter.addPoint(point); - }); + const planimeter = rulers.create(Planimeter, [point]).draw(); - d3.event.on("end", function() { - restoreDefaultEvents(); - clearMainTip(); - addPlanimeter.classList.remove("pressed"); - if (planimeter.points.length < 3) rulers.remove(planimeter.id); - else if (!d3.event.sourceEvent.shiftKey) planimeter.optimize(); - }); - })); + d3.event.on("drag", function () { + const point = d3.mouse(this); + planimeter.addPoint(point); + }); + d3.event.on("end", function () { + restoreDefaultEvents(); + clearMainTip(); + addPlanimeter.classList.remove("pressed"); + if (planimeter.points.length < 3) rulers.remove(planimeter.id); + else if (!d3.event.sourceEvent.shiftKey) planimeter.optimize(); + }); + }) + ); } } @@ -326,18 +271,19 @@ function editUnits() { alertMessage.innerHTML = ` Are you sure you want to remove all placed rulers?
If you just want to hide rulers, toggle the Rulers layer off in Menu`; - $("#alert").dialog({resizable: false, title: "Remove all rulers", + $("#alert").dialog({ + resizable: false, + title: "Remove all rulers", buttons: { - Remove: function() { + Remove: function () { $(this).dialog("close"); rulers.undraw(); rulers = new Rulers(); }, - Cancel: function() {$(this).dialog("close");} + Cancel: function () { + $(this).dialog("close"); + } } }); } - - } -