diff --git a/index.html b/index.html index c0f17592..e4f782ed 100644 --- a/index.html +++ b/index.html @@ -8107,5 +8107,6 @@ + diff --git a/modules/renderers/draw-emblems.js b/modules/renderers/draw-emblems.js new file mode 100644 index 00000000..43cf61dc --- /dev/null +++ b/modules/renderers/draw-emblems.js @@ -0,0 +1,111 @@ +"use strict"; + +function drawEmblems() { + TIME && console.time("drawEmblems"); + const {states, provinces, burgs} = pack; + + const validStates = states.filter(s => s.i && !s.removed && s.coa && s.coa.size !== 0); + const validProvinces = provinces.filter(p => p.i && !p.removed && p.coa && p.coa.size !== 0); + const validBurgs = burgs.filter(b => b.i && !b.removed && b.coa && b.coa.size !== 0); + + const getStateEmblemsSize = () => { + const startSize = minmax((graphHeight + graphWidth) / 40, 10, 100); + const statesMod = 1 + validStates.length / 100 - (15 - validStates.length) / 200; // states number modifier + const sizeMod = +emblems.select("#stateEmblems").attr("data-size") || 1; + return rn((startSize / statesMod) * sizeMod); // target size ~50px on 1536x754 map with 15 states + }; + + const getProvinceEmblemsSize = () => { + const startSize = minmax((graphHeight + graphWidth) / 100, 5, 70); + const provincesMod = 1 + validProvinces.length / 1000 - (115 - validProvinces.length) / 1000; // states number modifier + const sizeMod = +emblems.select("#provinceEmblems").attr("data-size") || 1; + return rn((startSize / provincesMod) * sizeMod); // target size ~20px on 1536x754 map with 115 provinces + }; + + const getBurgEmblemSize = () => { + const startSize = minmax((graphHeight + graphWidth) / 185, 2, 50); + const burgsMod = 1 + validBurgs.length / 1000 - (450 - validBurgs.length) / 1000; // states number modifier + const sizeMod = +emblems.select("#burgEmblems").attr("data-size") || 1; + return rn((startSize / burgsMod) * sizeMod); // target size ~8.5px on 1536x754 map with 450 burgs + }; + + const sizeBurgs = getBurgEmblemSize(); + const burgCOAs = validBurgs.map(burg => { + const {x, y} = burg; + const size = burg.coa.size || 1; + const shift = (sizeBurgs * size) / 2; + return {type: "burg", i: burg.i, x: burg.coa.x || x, y: burg.coa.y || y, size, shift}; + }); + + const sizeProvinces = getProvinceEmblemsSize(); + const provinceCOAs = validProvinces.map(province => { + const [x, y] = province.pole || pack.cells.p[province.center]; + const size = province.coa.size || 1; + const shift = (sizeProvinces * size) / 2; + return {type: "province", i: province.i, x: province.coa.x || x, y: province.coa.y || y, size, shift}; + }); + + const sizeStates = getStateEmblemsSize(); + const stateCOAs = validStates.map(state => { + const [x, y] = state.pole || pack.cells.p[state.center]; + const size = state.coa.size || 1; + const shift = (sizeStates * size) / 2; + return {type: "state", i: state.i, x: state.coa.x || x, y: state.coa.y || y, size, shift}; + }); + + const nodes = burgCOAs.concat(provinceCOAs).concat(stateCOAs); + const simulation = d3 + .forceSimulation(nodes) + .alphaMin(0.6) + .alphaDecay(0.2) + .velocityDecay(0.6) + .force( + "collision", + d3.forceCollide().radius(d => d.shift) + ) + .stop(); + + d3.timeout(function () { + const n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); + for (let i = 0; i < n; ++i) { + simulation.tick(); + } + + const burgNodes = nodes.filter(node => node.type === "burg"); + const burgString = burgNodes + .map( + d => + `` + ) + .join(""); + emblems.select("#burgEmblems").attr("font-size", sizeBurgs).html(burgString); + + const provinceNodes = nodes.filter(node => node.type === "province"); + const provinceString = provinceNodes + .map( + d => + `` + ) + .join(""); + emblems.select("#provinceEmblems").attr("font-size", sizeProvinces).html(provinceString); + + const stateNodes = nodes.filter(node => node.type === "state"); + const stateString = stateNodes + .map( + d => + `` + ) + .join(""); + emblems.select("#stateEmblems").attr("font-size", sizeStates).html(stateString); + + invokeActiveZooming(); + }); + + TIME && console.timeEnd("drawEmblems"); +} diff --git a/modules/renderers/draw-scalebar.js b/modules/renderers/draw-scalebar.js index bdca799a..1eb25da2 100644 --- a/modules/renderers/draw-scalebar.js +++ b/modules/renderers/draw-scalebar.js @@ -1,24 +1,12 @@ "use strict"; function drawScaleBar(scaleBar, scaleLevel) { - TIME && console.time("drawScaleBar"); - if (!scaleBar.size() || scaleBar.style("display") === "none") return; const unit = distanceUnitInput.value; const size = +scaleBar.attr("data-bar-size"); - const length = (function () { - const init = 100; - let val = (init * size * distanceScale) / scaleLevel; // 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 length = (val * scaleLevel) / distanceScale; // actual length in pixels on this scale - return length; - })(); - + const length = getLength(scaleLevel, size); scaleBar.select("#scaleBarContent").remove(); // redraw content every time const content = scaleBar.append("g").attr("id", "scaleBarContent"); @@ -85,8 +73,19 @@ function drawScaleBar(scaleBar, scaleLevel) { .attr("width", bbox.width + paddingRight) .attr("height", bbox.height + paddingBottom); } +} - TIME && console.timeEnd("drawScaleBar"); +function getLength(scaleLevel) { + const init = 100; + + const size = +scaleBar.attr("data-bar-size"); + let val = (init * size * distanceScale) / scaleLevel; // 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 length = (val * scaleLevel) / distanceScale; // actual length in pixels on this scale + return length; } function fitScaleBar(scaleBar, fullWidth, fullHeight) { diff --git a/modules/ui/layers.js b/modules/ui/layers.js index 842223ea..4894cc54 100644 --- a/modules/ui/layers.js +++ b/modules/ui/layers.js @@ -935,116 +935,6 @@ function toggleEmblems(event) { } } -function drawEmblems() { - TIME && console.time("drawEmblems"); - const {states, provinces, burgs} = pack; - - const validStates = states.filter(s => s.i && !s.removed && s.coa && s.coa.size !== 0); - const validProvinces = provinces.filter(p => p.i && !p.removed && p.coa && p.coa.size !== 0); - const validBurgs = burgs.filter(b => b.i && !b.removed && b.coa && b.coa.size !== 0); - - const getStateEmblemsSize = () => { - const startSize = minmax((graphHeight + graphWidth) / 40, 10, 100); - const statesMod = 1 + validStates.length / 100 - (15 - validStates.length) / 200; // states number modifier - const sizeMod = +emblems.select("#stateEmblems").attr("data-size") || 1; - return rn((startSize / statesMod) * sizeMod); // target size ~50px on 1536x754 map with 15 states - }; - - const getProvinceEmblemsSize = () => { - const startSize = minmax((graphHeight + graphWidth) / 100, 5, 70); - const provincesMod = 1 + validProvinces.length / 1000 - (115 - validProvinces.length) / 1000; // states number modifier - const sizeMod = +emblems.select("#provinceEmblems").attr("data-size") || 1; - return rn((startSize / provincesMod) * sizeMod); // target size ~20px on 1536x754 map with 115 provinces - }; - - const getBurgEmblemSize = () => { - const startSize = minmax((graphHeight + graphWidth) / 185, 2, 50); - const burgsMod = 1 + validBurgs.length / 1000 - (450 - validBurgs.length) / 1000; // states number modifier - const sizeMod = +emblems.select("#burgEmblems").attr("data-size") || 1; - return rn((startSize / burgsMod) * sizeMod); // target size ~8.5px on 1536x754 map with 450 burgs - }; - - const sizeBurgs = getBurgEmblemSize(); - const burgCOAs = validBurgs.map(burg => { - const {x, y} = burg; - const size = burg.coa.size || 1; - const shift = (sizeBurgs * size) / 2; - return {type: "burg", i: burg.i, x: burg.coa.x || x, y: burg.coa.y || y, size, shift}; - }); - - const sizeProvinces = getProvinceEmblemsSize(); - const provinceCOAs = validProvinces.map(province => { - const [x, y] = province.pole || pack.cells.p[province.center]; - const size = province.coa.size || 1; - const shift = (sizeProvinces * size) / 2; - return {type: "province", i: province.i, x: province.coa.x || x, y: province.coa.y || y, size, shift}; - }); - - const sizeStates = getStateEmblemsSize(); - const stateCOAs = validStates.map(state => { - const [x, y] = state.pole || pack.cells.p[state.center]; - const size = state.coa.size || 1; - const shift = (sizeStates * size) / 2; - return {type: "state", i: state.i, x: state.coa.x || x, y: state.coa.y || y, size, shift}; - }); - - const nodes = burgCOAs.concat(provinceCOAs).concat(stateCOAs); - const simulation = d3 - .forceSimulation(nodes) - .alphaMin(0.6) - .alphaDecay(0.2) - .velocityDecay(0.6) - .force( - "collision", - d3.forceCollide().radius(d => d.shift) - ) - .stop(); - - d3.timeout(function () { - const n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); - for (let i = 0; i < n; ++i) { - simulation.tick(); - } - - const burgNodes = nodes.filter(node => node.type === "burg"); - const burgString = burgNodes - .map( - d => - `` - ) - .join(""); - emblems.select("#burgEmblems").attr("font-size", sizeBurgs).html(burgString); - - const provinceNodes = nodes.filter(node => node.type === "province"); - const provinceString = provinceNodes - .map( - d => - `` - ) - .join(""); - emblems.select("#provinceEmblems").attr("font-size", sizeProvinces).html(provinceString); - - const stateNodes = nodes.filter(node => node.type === "state"); - const stateString = stateNodes - .map( - d => - `` - ) - .join(""); - emblems.select("#stateEmblems").attr("font-size", sizeStates).html(stateString); - - invokeActiveZooming(); - }); - - TIME && console.timeEnd("drawEmblems"); -} - function toggleVignette(event) { if (!layerIsOn("toggleVignette")) { turnButtonOn("toggleVignette");