mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
v1.5.04 - Emblems auto-hide and hightlighting
This commit is contained in:
parent
56b6eb2a13
commit
32c4566aa7
9 changed files with 125 additions and 54 deletions
|
|
@ -21,7 +21,7 @@ function clicked() {
|
|||
const p = d3.mouse(this);
|
||||
const i = findCell(p[0], p[1]);
|
||||
|
||||
if (parent.id === "emblems") editEmblem();
|
||||
if (grand.id === "emblems") editEmblem();
|
||||
else if (parent.id === "rivers") editRiver();
|
||||
else if (grand.id === "routes") editRoute();
|
||||
else if (el.tagName === "tspan" && grand.parentNode.parentNode.id === "labels") editLabel();
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@ function editEmblem(type, id, el) {
|
|||
if (customization) return;
|
||||
|
||||
if (!id && d3.event) {
|
||||
const data = d3.event.target.__data__;
|
||||
type = data.type;
|
||||
id = data.id;
|
||||
el = data.el;
|
||||
const parent = d3.event.target.parentNode;
|
||||
const [g, t] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] :
|
||||
parent.id === "provinceEmblems" ? [pack.provinces, "province"] :
|
||||
[pack.states, "state"];
|
||||
const i = +d3.event.target.dataset.i;
|
||||
type = t;
|
||||
id = type+"COA"+i;
|
||||
el = g[i];
|
||||
}
|
||||
|
||||
emblems.selectAll(":scope > use").call(d3.drag().on("drag", dragEmblem)).classed("draggable", true);
|
||||
|
|
@ -31,6 +35,7 @@ function editEmblem(type, id, el) {
|
|||
emblemStates.addEventListener("input", selectState);
|
||||
emblemProvinces.addEventListener("input", selectProvince);
|
||||
emblemBurgs.addEventListener("input", selectBurg);
|
||||
document.getElementById("emblemsFocus").addEventListener("click", showArea);
|
||||
|
||||
function updateElementSelectors(type, id, el) {
|
||||
let state = 0, province = 0, burg = 0;
|
||||
|
|
@ -132,6 +137,10 @@ function editEmblem(type, id, el) {
|
|||
});
|
||||
}
|
||||
|
||||
function showArea() {
|
||||
highlightEmblemElement(type, el);
|
||||
}
|
||||
|
||||
function closeEmblemEditor() {
|
||||
emblems.selectAll(":scope > use").call(d3.drag().on("drag", null)).attr("class", null);
|
||||
}
|
||||
|
|
@ -94,11 +94,18 @@ function showMapTooltip(point, e, i, g) {
|
|||
tip(e.target.parentNode.dataset.name + ". Click to edit");
|
||||
return;
|
||||
}
|
||||
if (group === "emblems" && e.target.__data__?.el) {
|
||||
const el = d3.select(e.target);
|
||||
el.raise();
|
||||
const name = el.datum().el.fullName || el.datum().el.name || "";
|
||||
const type = el.datum().type || "";
|
||||
if (group === "emblems") {
|
||||
const parent = e.target.parentNode;
|
||||
const [g, type] = parent.id === "burgEmblems" ? [pack.burgs, "burg"] :
|
||||
parent.id === "provinceEmblems" ? [pack.provinces, "province"] :
|
||||
[pack.states, "state"];
|
||||
const i = +e.target.dataset.i;
|
||||
highlightEmblemElement(type, g[i]);
|
||||
|
||||
d3.select(e.target).raise();
|
||||
d3.select(parent).raise();
|
||||
|
||||
const name = g[i].fullName || g[i].name;
|
||||
tip(`${name} ${type} emblem. Click to edit`);
|
||||
return;
|
||||
}
|
||||
|
|
@ -289,6 +296,32 @@ function getPopulationTip(i) {
|
|||
return `Cell population: ${si(rural+urban)}; Rural: ${si(rural)}; Urban: ${si(urban)}`;
|
||||
}
|
||||
|
||||
function highlightEmblemElement(type, el) {
|
||||
if (emblems.selectAll("line, circle").size()) return;
|
||||
const i = el.i, cells = pack.cells;
|
||||
const animation = d3.transition().duration(1000).ease(d3.easeSinIn);
|
||||
|
||||
if (type === "burg") {
|
||||
const {x, y} = el;
|
||||
emblems.append("circle").attr("cx", x).attr("cy", y).attr("r", 0)
|
||||
.attr("fill", "none").attr("stroke", "#d0240f").attr("stroke-width", 1).attr("opacity", 1)
|
||||
.transition(animation).attr("r", 20).attr("opacity", .1).attr("stroke-width", 0).remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const [x, y] = el.pole;
|
||||
const obj = type === "state" ? cells.state : cells.province;
|
||||
const borderCells = cells.i.filter(id => obj[id] === i && cells.c[id].some(n => obj[n] !== i));
|
||||
const data = Array.from(borderCells).filter((c, i) => !(i%2)).map(i => cells.p[i]).map(i => [i[0], i[1], Math.hypot(i[0]-x, i[1]-y)]);
|
||||
|
||||
emblems.selectAll("line").data(data).enter().append("line")
|
||||
.attr("x1", x).attr("y1", y).attr("x2", d => d[0]).attr("y2", d => d[1])
|
||||
.attr("stroke", "#d0240f").attr("stroke-width", .5).attr("opacity", .2)
|
||||
.attr("stroke-dashoffset", d => d[2]).attr("stroke-dasharray", d => d[2])
|
||||
.transition(animation).attr("stroke-dashoffset", 0).attr("opacity", 1)
|
||||
.transition(animation).delay(1000).attr("stroke-dashoffset", d => d[2]).attr("opacity", 0).remove();
|
||||
}
|
||||
|
||||
// assign lock behavior
|
||||
document.querySelectorAll("[data-locked]").forEach(function(e) {
|
||||
e.addEventListener("mouseover", function(event) {
|
||||
|
|
|
|||
|
|
@ -1230,7 +1230,7 @@ function toggleZones(event) {
|
|||
function toggleEmblems(event) {
|
||||
if (!layerIsOn("toggleEmblems")) {
|
||||
turnButtonOn("toggleEmblems");
|
||||
if (!emblems.selectAll("*").size()) drawEmblems();
|
||||
if (!emblems.selectAll("use").size()) drawEmblems();
|
||||
$('#emblems').fadeIn();
|
||||
if (event && isCtrlClick(event)) editStyle("emblems");
|
||||
} else {
|
||||
|
|
@ -1242,19 +1242,14 @@ function toggleEmblems(event) {
|
|||
|
||||
function drawEmblems() {
|
||||
TIME && console.time("drawEmblems");
|
||||
const {states, provinces, burgs, cells} = pack;
|
||||
|
||||
// const sizeBurgs = +emblems.attr("size-burgs") || 15;
|
||||
// burgs.filter(b => b.i && !b.removed && b.coa).forEach(burg => {
|
||||
// const {x, y} = burg;
|
||||
// COArenderer.trigger("burgCOA"+burg.i, burg.coa);
|
||||
// svg += `<use x=${x-sizeBurgs/2} y=${y-sizeBurgs/2} width=${sizeBurgs} height=${sizeBurgs} href="#burgCOA${burg.i}"></use>`;
|
||||
// });
|
||||
const {states, provinces, burgs} = pack;
|
||||
|
||||
const validStates = states.filter(s => s.i && !s.removed && s.coa);
|
||||
const validProvinces = provinces.filter(p => p.i && !p.removed && p.coa);
|
||||
const validBurgs = burgs.filter(b => b.i && !b.removed && b.coa);
|
||||
|
||||
const sizeMod = +emblems.attr("size-modifier") || 1;
|
||||
|
||||
const getStateEmblemsSize = () => {
|
||||
const startSize = (graphHeight + graphWidth) / 40;
|
||||
const statesMod = (1 + validStates.length / 100) - (15 - validStates.length) / 200; // states number modifier
|
||||
|
|
@ -1265,36 +1260,47 @@ function drawEmblems() {
|
|||
const getProvinceEmblemsSize = () => {
|
||||
const startSize = (graphHeight + graphWidth) / 80;
|
||||
const provincesMod = (1 + validProvinces.length / 1000) - (115 - validProvinces.length) / 1000; // states number modifier
|
||||
const size = rn(startSize / provincesMod * sizeMod); // target size ~50px on 1536x754 map with 15 states
|
||||
const size = rn(startSize / provincesMod * sizeMod); // target size ~26px on 1536x754 map with 115 provinces
|
||||
return Math.min(Math.max(size, 5), 75);
|
||||
}
|
||||
|
||||
const getBurgEmblemSize = () => {
|
||||
const startSize = (graphHeight + graphWidth) / 150;
|
||||
const burgsMod = (1 + validBurgs.length / 1000) - (450 - validBurgs.length) / 1000; // states number modifier
|
||||
const size = rn(startSize / burgsMod * sizeMod); // target size ~10px on 1536x754 map with 450 burgs
|
||||
return Math.min(Math.max(size, 5), 50);
|
||||
}
|
||||
|
||||
const sizeBurgs = getBurgEmblemSize();
|
||||
const burgCOAs = validBurgs.map(burg => {
|
||||
const {x, y} = burg;
|
||||
return {type: "burg", i: burg.i, x, y, size: sizeBurgs};
|
||||
});
|
||||
|
||||
const sizeProvinces = getProvinceEmblemsSize();
|
||||
const provinceCOAs = validProvinces.map(province => {
|
||||
if (!province.pole) getProvincesVertices();
|
||||
const [x, y] = province.pole;
|
||||
COArenderer.trigger("provinceCOA"+province.i, province.coa);
|
||||
return {type: "province", id: "provinceCOA"+province.i, x, y, size: sizeProvinces, el: province};
|
||||
return {type: "province", i: province.i, x, y, size: sizeProvinces};
|
||||
});
|
||||
|
||||
const sizeStates = getStateEmblemsSize();
|
||||
const stateCOAs = validStates.map(state => {
|
||||
const [x, y] = state.pole;
|
||||
COArenderer.trigger("stateCOA"+state.i, state.coa);
|
||||
return {type: "state", id: "stateCOA"+state.i, x, y, size: sizeStates, el: state};
|
||||
return {type: "state", i: state.i, x, y, size: sizeStates};
|
||||
});
|
||||
|
||||
const nodes = provinceCOAs.concat(stateCOAs);
|
||||
const nodes = burgCOAs.concat(provinceCOAs).concat(stateCOAs);
|
||||
const simulation = d3.forceSimulation(nodes)
|
||||
.alphaMin(.6).alphaDecay(.2).velocityDecay(.6)
|
||||
.force('collision', d3.forceCollide().radius(d => d.size/2))
|
||||
.stop();
|
||||
|
||||
debug.attr("fill", "#fff").attr("stroke", "#000")
|
||||
.selectAll("circle").data(nodes).join("circle")
|
||||
.attr("cx", d => d.x)
|
||||
.attr("cy", d => d.y)
|
||||
.attr("r", 2);
|
||||
// debug.attr("fill", "#fff").attr("stroke", "#000")
|
||||
// .selectAll("circle").data(nodes).join("circle")
|
||||
// .attr("cx", d => d.x)
|
||||
// .attr("cy", d => d.y)
|
||||
// .attr("r", 2);
|
||||
|
||||
d3.timeout(function() {
|
||||
const n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay()));
|
||||
|
|
@ -1302,12 +1308,20 @@ function drawEmblems() {
|
|||
simulation.tick();
|
||||
}
|
||||
|
||||
emblems.selectAll("use").data(nodes).join("use")
|
||||
.attr("href", d => "#"+d.id)
|
||||
.attr("x", d => d.x - d.size / 2)
|
||||
.attr("y", d => d.y - d.size / 2)
|
||||
.attr("width", d => d.size + "em")
|
||||
.attr("height", d => d.size + "em");
|
||||
emblems.select("#burgEmblems").attr("font-size", sizeBurgs)
|
||||
.selectAll("use").data(nodes.filter(node => node.type === "burg")).join("use")
|
||||
.attr("x", d => d.x - d.size / 2).attr("y", d => d.y - d.size / 2)
|
||||
.attr("width", "1em").attr("height", "1em").attr("data-i", d => d.i);
|
||||
|
||||
emblems.select("#provinceEmblems").attr("font-size", sizeProvinces)
|
||||
.selectAll("use").data(nodes.filter(node => node.type === "province")).join("use")
|
||||
.attr("x", d => d.x - d.size / 2).attr("y", d => d.y - d.size / 2)
|
||||
.attr("width", "1em").attr("height", "1em").attr("data-i", d => d.i);
|
||||
|
||||
emblems.select("#stateEmblems").attr("font-size", sizeStates)
|
||||
.selectAll("use").data(nodes.filter(node => node.type === "state")).join("use")
|
||||
.attr("x", d => d.x - d.size / 2).attr("y", d => d.y - d.size / 2)
|
||||
.attr("width", "1em").attr("height", "1em").attr("data-i", d => d.i);
|
||||
|
||||
invokeActiveZooming();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -795,7 +795,7 @@ function applyDefaultStyle() {
|
|||
labels.select("#addedLabels").attr("fill", "#3e3e4b").attr("opacity", 1).attr("stroke", "#3a3a3a").attr("stroke-width", 0).attr("font-family", "Almendra SC").attr("data-font", "Almendra+SC").attr("font-size", 18).attr("data-size", 18).attr("filter", null);
|
||||
|
||||
fogging.attr("opacity", .98).attr("fill", "#30426f");
|
||||
emblems.attr("opacity", .9).attr("font-size", 1).attr("size-modifier", 1).attr("filter", null)
|
||||
emblems.attr("opacity", .9).attr("size-modifier", 1).attr("filter", null)
|
||||
}
|
||||
|
||||
// apply style settings in JSON
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue