331 lines
16 KiB
HTML
331 lines
16 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
<title>SVG Layout Generator</title>
|
||
|
<style>
|
||
|
body {
|
||
|
font-family: Arial, sans-serif;
|
||
|
/* background-color: #334173; */
|
||
|
color: white;
|
||
|
margin: 0;
|
||
|
display: flex;
|
||
|
justify-content: center;
|
||
|
align-items: center;
|
||
|
height: 100vh;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="svgContainer"></div>
|
||
|
|
||
|
<script>
|
||
|
const screenWidth = screen.width || window.innerWidth || document.documentElement.clientWidth;
|
||
|
const screenHeight = screen.height || window.innerHeight || document.documentElement.clientHeight;
|
||
|
const screenPpi = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight) / Math.sqrt(screen.width * screen.width + screen.height * screen.height) * 96;
|
||
|
const paper_size = "A3";
|
||
|
|
||
|
if (paper_size == "A4") {
|
||
|
heigth = 210 * screenPpi / 25.4;
|
||
|
width = 297 * screenPpi / 25.4;
|
||
|
} else if (paper_size == "A3") {
|
||
|
height = 297 * screenPpi / 25.4;
|
||
|
width = 420 * screenPpi / 25.4;
|
||
|
}
|
||
|
|
||
|
function createSVG() {
|
||
|
const svgNS = "http://www.w3.org/2000/svg";
|
||
|
|
||
|
// Create the SVG element
|
||
|
const svg = document.createElementNS(svgNS, "svg");
|
||
|
svg.setAttribute("width", width);
|
||
|
svg.setAttribute("height", height);
|
||
|
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
|
||
|
|
||
|
|
||
|
const backgroundRect = document.createElementNS(svgNS, "rect");
|
||
|
backgroundRect.setAttribute("x", "0");
|
||
|
backgroundRect.setAttribute("y", "0");
|
||
|
backgroundRect.setAttribute("width", width);
|
||
|
backgroundRect.setAttribute("height", height);
|
||
|
backgroundRect.setAttribute("fill", "#334173");
|
||
|
svg.appendChild(backgroundRect);
|
||
|
|
||
|
// Header
|
||
|
const headerHeight = height * 0.15;
|
||
|
const path_width = width * 0.5;
|
||
|
const headerGroup = document.createElementNS(svgNS, "g");
|
||
|
|
||
|
const headerPath = document.createElementNS(svgNS, "path");
|
||
|
const pathData = `
|
||
|
M 0 0
|
||
|
H ${path_width}
|
||
|
C ${path_width * 0.75} 0 ${path_width * 0.75} ${headerHeight} ${path_width * 0.6} ${headerHeight * 0.95}
|
||
|
H 0
|
||
|
Z
|
||
|
`;
|
||
|
headerPath.setAttribute("d", pathData);
|
||
|
headerPath.setAttribute("fill", "#ffffff");
|
||
|
|
||
|
// Header text inside the path
|
||
|
const headerTextInside = document.createElementNS(svgNS, "text");
|
||
|
headerTextInside.setAttribute("x", `${path_width * 0.07}`);
|
||
|
headerTextInside.setAttribute("y", `${headerHeight * 0.6}`);
|
||
|
headerTextInside.setAttribute("fill", "#000");
|
||
|
headerTextInside.setAttribute("font-size", `${headerHeight * 0.38}`);
|
||
|
headerTextInside.textContent = "PVV fadderuke";
|
||
|
|
||
|
// Header text outside the path, tilted
|
||
|
const headerTextOutside = document.createElementNS(svgNS, "text");
|
||
|
headerTextOutside.setAttribute("x", `${path_width * 0.9}`);
|
||
|
headerTextOutside.setAttribute("y", `${headerHeight * 0.7}`);
|
||
|
headerTextOutside.setAttribute("fill", "#fff");
|
||
|
headerTextOutside.setAttribute("font-size", `${headerHeight * 0.3}`);
|
||
|
headerTextOutside.textContent = "Åpent for alle!";
|
||
|
const textCenterX = path_width * 0.8;
|
||
|
const textCenterY = headerHeight * 1.1;
|
||
|
headerTextOutside.setAttribute("transform", `rotate(-7 ${textCenterX},${textCenterY})`);
|
||
|
|
||
|
// Year text
|
||
|
const yearText = document.createElementNS(svgNS, "text");
|
||
|
yearText.setAttribute("x", `${width - headerHeight * 3}`);
|
||
|
yearText.setAttribute("y", `${headerHeight * 0.7}`);
|
||
|
yearText.setAttribute("fill", "#fff");
|
||
|
yearText.setAttribute("font-size", `${headerHeight * 0.56}`);
|
||
|
yearText.textContent = "2024";
|
||
|
|
||
|
// Invert the colors of the logo filter
|
||
|
const filter = document.createElementNS(svgNS, "filter");
|
||
|
filter.setAttribute("id", "invert");
|
||
|
const feColorMatrix = document.createElementNS(svgNS, "feColorMatrix");
|
||
|
feColorMatrix.setAttribute("type", "matrix");
|
||
|
feColorMatrix.setAttribute("values", "-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0");
|
||
|
filter.appendChild(feColorMatrix);
|
||
|
svg.appendChild(filter);
|
||
|
|
||
|
const headerLogo = document.createElementNS(svgNS, "image");
|
||
|
headerLogo.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "logo_black_thicc.svg");
|
||
|
headerLogo.setAttribute("x", `${width - headerHeight * 1.2}`);
|
||
|
headerLogo.setAttribute("y", "0");
|
||
|
headerLogo.setAttribute("width", `${headerHeight}`);
|
||
|
headerLogo.setAttribute("height", `${headerHeight}`);
|
||
|
headerLogo.setAttribute("filter", "url(#invert)");
|
||
|
|
||
|
// Append elements to the header group
|
||
|
headerGroup.appendChild(headerPath);
|
||
|
headerGroup.appendChild(headerTextInside);
|
||
|
headerGroup.appendChild(headerTextOutside);
|
||
|
headerGroup.appendChild(yearText);
|
||
|
headerGroup.appendChild(headerLogo);
|
||
|
|
||
|
svg.appendChild(headerGroup);
|
||
|
|
||
|
//Start of middle Event part.
|
||
|
const eventHeight = height * 0.7;
|
||
|
const eventHeightStart = headerHeight;
|
||
|
// Events and icons
|
||
|
const events = [
|
||
|
{ name: "Åpen dag", date: "12.08", icon: "ikoner/åpendag.svg" },
|
||
|
{ name: "Åpen dag /\nBrettspill", date: "13.08", icon: "ikoner/brettspill.svg" },
|
||
|
{ name: "Filmkveld", date: "14.08", icon: "ikoner/movie.svg" },
|
||
|
{ name: "Hackekveld", date: "15.08", icon: "ikoner/hackekveld.svg" },
|
||
|
{ name: "AbeLAN", date: "16.08", icon: "ikoner/abellan.svg" },
|
||
|
{ name: "Anime", date: "17.08", icon: "ikoner/anime.svg" },
|
||
|
{ name: "Guide &\nBBQ", date: "18.08", icon: "ikoner/grill1.svg" },
|
||
|
{ name: "Quiz", date: "19.08", icon: "ikoner/quiz.svg" },
|
||
|
{ name: "Brettspill", date: "20.08", icon: "ikoner/brettspill3.svg" },
|
||
|
{ name: "Anime", date: "21.08", icon: "ikoner/anime2.svg" },
|
||
|
{ name: "Bowling", date: "22.08", icon: "ikoner/bowling.jpg" },
|
||
|
{ name: "D&D", date: "23.08", icon: "ikoner/dnd.svg" },
|
||
|
{ name: "Hackekveld /\nSkaperfest", date: "24.08", icon: "ikoner/hackekveld.svg" },
|
||
|
{ name: "Avslutning", date: "25.08", icon: "ikoner/avslutning.svg" }
|
||
|
];
|
||
|
|
||
|
const eventGroup = document.createElementNS(svgNS, "g");
|
||
|
const padding = width / ((events.length * 2)*1.5);
|
||
|
console.log(padding);
|
||
|
const eventHeightPadding = eventHeight / 50;
|
||
|
const circleRadius = (eventHeight / 7.5) - eventHeightPadding;
|
||
|
|
||
|
// Draw the lines connecting the circles
|
||
|
const line_stroke_width = "8";
|
||
|
const line = document.createElementNS(svgNS, "line");
|
||
|
line.setAttribute("x1", padding);
|
||
|
line.setAttribute("y1", eventHeightStart + circleRadius*2);
|
||
|
line.setAttribute("x2", padding + (events.length - 1) % 7 * (circleRadius * 2 + padding) + circleRadius);
|
||
|
line.setAttribute("y2", eventHeightStart + circleRadius*2);
|
||
|
line.setAttribute("stroke", "#ffffff");
|
||
|
line.setAttribute("stroke-width", line_stroke_width);
|
||
|
eventGroup.appendChild(line);
|
||
|
|
||
|
//end on first line, a dotted line after the last event to show that there are more events, This goes to the right, one more circle radius than the last circle
|
||
|
const line_end = document.createElementNS(svgNS, "line");
|
||
|
line_end.setAttribute("x1", padding + (events.length - 1) % 7 * (circleRadius * 2 + padding) + circleRadius);
|
||
|
line_end.setAttribute("y1", eventHeightStart + circleRadius*2);
|
||
|
line_end.setAttribute("x2", padding + (events.length - 1) % 7 * (circleRadius * 2 + padding) + circleRadius*2.5);
|
||
|
line_end.setAttribute("y2", eventHeightStart + circleRadius*2);
|
||
|
line_end.setAttribute("stroke", "#ffffff");
|
||
|
line_end.setAttribute("stroke-width", line_stroke_width);
|
||
|
line_end.setAttribute("stroke-dasharray", "10,10");
|
||
|
eventGroup.appendChild(line_end);
|
||
|
|
||
|
|
||
|
//dotted line start befor the second row, for a circle radius from the left
|
||
|
const line_start = document.createElementNS(svgNS, "line");
|
||
|
line_start.setAttribute("x1", padding*2);
|
||
|
line_start.setAttribute("y1", eventHeightStart + circleRadius*6);
|
||
|
line_start.setAttribute("x2", padding*2 - circleRadius*2);
|
||
|
line_start.setAttribute("y2", eventHeightStart + circleRadius*6);
|
||
|
line_start.setAttribute("stroke", "#ffffff");
|
||
|
line_start.setAttribute("stroke-width", line_stroke_width);
|
||
|
line_start.setAttribute("stroke-dasharray", "10,10");
|
||
|
eventGroup.appendChild(line_start);
|
||
|
|
||
|
const line2 = document.createElementNS(svgNS, "line");
|
||
|
line2.setAttribute("x1", padding*2);
|
||
|
line2.setAttribute("y1", eventHeightStart + circleRadius*6);
|
||
|
line2.setAttribute("x2", padding + (events.length - 8) % 7 * (circleRadius * 2 + padding) + circleRadius);
|
||
|
line2.setAttribute("y2", eventHeightStart + circleRadius*6);
|
||
|
line2.setAttribute("stroke", "#ffffff");
|
||
|
line2.setAttribute("stroke-width", line_stroke_width);
|
||
|
eventGroup.appendChild(line2);
|
||
|
|
||
|
events.forEach((event, index) => {
|
||
|
const cx = padding + circleRadius + index % 7 * (circleRadius * 2 + padding);
|
||
|
const cy = eventHeightStart + circleRadius*2 + Math.floor(index / 7) * (circleRadius*4);
|
||
|
|
||
|
const circle = document.createElementNS(svgNS, "circle");
|
||
|
circle.setAttribute("cx", cx);
|
||
|
circle.setAttribute("cy", cy);
|
||
|
circle.setAttribute("r", circleRadius);
|
||
|
circle.setAttribute("fill", "#ffffff");
|
||
|
|
||
|
const textName = document.createElementNS(svgNS, "text");
|
||
|
textName.setAttribute("x", cx);
|
||
|
textName.setAttribute("y", cy - circleRadius - padding);
|
||
|
textName.setAttribute("fill", "#ffffff");
|
||
|
textName.setAttribute("font-size", padding / 1.5);
|
||
|
textName.setAttribute("text-anchor", "middle");
|
||
|
textName.setAttribute("font-weight", "bold");
|
||
|
|
||
|
const lines = event.name.split('\n');
|
||
|
lines.forEach((line, index) => {
|
||
|
const tspan = document.createElementNS(svgNS, "tspan");
|
||
|
tspan.setAttribute("x", cx);
|
||
|
tspan.setAttribute("dy", index === 0 ? 0 : "1.2em"); // Adjust dy for subsequent lines
|
||
|
tspan.textContent = line;
|
||
|
textName.appendChild(tspan);
|
||
|
});
|
||
|
|
||
|
const textDate = document.createElementNS(svgNS, "text");
|
||
|
textDate.setAttribute("x", cx);
|
||
|
textDate.setAttribute("y", cy + circleRadius + padding);
|
||
|
textDate.setAttribute("fill", "#ffffff");
|
||
|
textDate.setAttribute("font-size", padding);
|
||
|
textDate.setAttribute("text-anchor", "middle");
|
||
|
textName.setAttribute("font-weight", "bold");
|
||
|
textDate.textContent = event.date;
|
||
|
|
||
|
const iconImage = document.createElementNS(svgNS, "image");
|
||
|
iconImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", event.icon);
|
||
|
iconImage.setAttribute("x", cx - circleRadius/2);
|
||
|
iconImage.setAttribute("y", cy - circleRadius/2);
|
||
|
iconImage.setAttribute("width", circleRadius);
|
||
|
iconImage.setAttribute("height", circleRadius);
|
||
|
|
||
|
eventGroup.appendChild(circle);
|
||
|
eventGroup.appendChild(iconImage);
|
||
|
eventGroup.appendChild(textName);
|
||
|
eventGroup.appendChild(textDate);
|
||
|
});
|
||
|
|
||
|
svg.appendChild(eventGroup);
|
||
|
|
||
|
// Footer
|
||
|
const footerHeight = height * 0.2;
|
||
|
const footerHeightStart = height - footerHeight;
|
||
|
|
||
|
const footerGroup = document.createElementNS(svgNS, "g");
|
||
|
const footerRect = document.createElementNS(svgNS, "rect");
|
||
|
footerRect.setAttribute("x", "0");
|
||
|
footerRect.setAttribute("y", footerHeightStart);
|
||
|
footerRect.setAttribute("width", width);
|
||
|
footerRect.setAttribute("height", footerHeight);
|
||
|
footerRect.setAttribute("fill", "#334173");
|
||
|
|
||
|
footerGroup.appendChild(footerRect);
|
||
|
|
||
|
const qrCodeDiscord = document.createElementNS(svgNS, "image");
|
||
|
qrCodeDiscord.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "ikoner/discord-qr-code.svg");
|
||
|
qrCodeDiscord.setAttribute("x", footerHeight * 0.1);
|
||
|
qrCodeDiscord.setAttribute("y", footerHeightStart);
|
||
|
qrCodeDiscord.setAttribute("width", footerHeight * 0.9);
|
||
|
qrCodeDiscord.setAttribute("height", footerHeight * 0.9);
|
||
|
|
||
|
const qrCodeMap = document.createElementNS(svgNS, "image");
|
||
|
qrCodeMap.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "ikoner/mazemap-qr-code.svg");
|
||
|
qrCodeMap.setAttribute("x", footerHeight * 1.1);
|
||
|
qrCodeMap.setAttribute("y", footerHeightStart);
|
||
|
qrCodeMap.setAttribute("width", footerHeight * 0.9);
|
||
|
qrCodeMap.setAttribute("height", footerHeight * 0.9);
|
||
|
|
||
|
// Location text
|
||
|
const locationText = document.createElementNS(svgNS, "text");
|
||
|
locationText.setAttribute("x", width * 0.6);
|
||
|
locationText.setAttribute("y", footerHeightStart + footerHeight * 0.5);
|
||
|
locationText.setAttribute("fill", "#ffffff");
|
||
|
locationText.setAttribute("font-size", `${footerHeight * 0.2}`);
|
||
|
locationText.setAttribute("text-anchor", "start");
|
||
|
const locationLines = "Oppredningen\nRom 247".split('\n');
|
||
|
locationLines.forEach((line, index) => {
|
||
|
const tspan = document.createElementNS(svgNS, "tspan");
|
||
|
tspan.setAttribute("x", width * 0.3);
|
||
|
tspan.setAttribute("dy", index === 0 ? 0 : "1.2em"); // Adjust dy for subsequent lines
|
||
|
tspan.textContent = line;
|
||
|
locationText.appendChild(tspan);
|
||
|
});
|
||
|
footerGroup.appendChild(locationText);
|
||
|
|
||
|
// English/Norwegian info text
|
||
|
const infoText = document.createElementNS(svgNS, "text");
|
||
|
infoText.setAttribute("x", width * 0.6);
|
||
|
infoText.setAttribute("y", footerHeightStart + footerHeight * 0.5);
|
||
|
infoText.setAttribute("fill", "#ffffff");
|
||
|
infoText.setAttribute("font-size", `${footerHeight * 0.2}`);
|
||
|
infoText.setAttribute("text-anchor", "middle");
|
||
|
const infoLines = "Mer info på /\nMore info at".split('\n');
|
||
|
infoLines.forEach((line, index) => {
|
||
|
const tspan = document.createElementNS(svgNS, "tspan");
|
||
|
tspan.setAttribute("x", width * 0.6);
|
||
|
tspan.setAttribute("dy", index === 0 ? 0 : "1.2em"); // Adjust dy for subsequent lines
|
||
|
tspan.textContent = line;
|
||
|
infoText.appendChild(tspan);
|
||
|
});
|
||
|
|
||
|
footerGroup.appendChild(infoText);
|
||
|
|
||
|
// URL text
|
||
|
const urlText = document.createElementNS(svgNS, "text");
|
||
|
urlText.setAttribute("x", width * 0.7);
|
||
|
urlText.setAttribute("y", footerHeightStart + footerHeight * 0.65);
|
||
|
urlText.setAttribute("fill", "#ffffff");
|
||
|
urlText.setAttribute("font-size", `${footerHeight * 0.4}`);
|
||
|
urlText.textContent = "pvv.ntnu.no";
|
||
|
footerGroup.appendChild(urlText);
|
||
|
|
||
|
footerGroup.appendChild(qrCodeDiscord);
|
||
|
footerGroup.appendChild(qrCodeMap);
|
||
|
// footerGroup.appendChild(footerText);
|
||
|
|
||
|
svg.appendChild(footerGroup);
|
||
|
|
||
|
document.getElementById("svgContainer").appendChild(svg);
|
||
|
}
|
||
|
|
||
|
// Call the function to create the SVG
|
||
|
createSVG();
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|