Browse Source

Initial commit

master
Skyweb 2 months ago
parent
commit
d549a7da2d
  1. 7
      README.md
  2. 367
      css/reset.css
  3. 81
      css/styles.css
  4. 17
      getMap.php
  5. 39
      index.html
  6. 234
      js/scripts.js

7
README.md

@ -1,3 +1,8 @@
# SovTimeline
System sovereignty timeline viewer for EVE Online
System sovereignty timeline viewer for EVE Online
## Quick setup
1. Download images from verite (https://www.verite.space/maps/influence/) to a new folder "maps"
2. Run on your favourite php enabled webserver

367
css/reset.css

@ -0,0 +1,367 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0-modified | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* make sure to set some focus styles for accessibility */
:focus {
outline: 0;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none;
}
input[type=search] {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
textarea {
overflow: auto;
vertical-align: top;
resize: vertical;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
max-width: 100%;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
html,
button,
input,
select,
textarea {
color: #222;
}
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
img {
vertical-align: middle;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}

81
css/styles.css

@ -0,0 +1,81 @@
body {
font-family: 'Poppins', sans-serif;
color: white;
}
.contentcontainer {
height: 100vh;
background-color: black;
}
.content {
display: grid;
grid-template-rows: 1fr 30px 30px;
height: 100%;
}
.mapcontainer {
grid-row: 1/3;
text-align: center;
}
#map {
object-fit: contain;
max-height: 100%;
max-width: 100%;
}
.text {
margin: auto;
text-align: center;
display: inline-block;
vertical-align: middle;
}
span {
display: inline;
}
.slidecontainer {
height: 30px;
display: grid;
grid-template-columns: 130px auto 80px;
}
.slider {
width: 100%;
}
.controlcontainer {
height: 23px;
display: grid;
grid-template-columns: auto 20px 120px 20px 100px auto;
font-size: 20px;
padding-bottom: 20px;
}
#zoom {
position: fixed;
width: 200px;
height: 200px;
border: 1px solid white;
pointer-events: none;
opacity: 0;
}
.img-zoom-lens {
position: absolute;
width: 80px;
height: 80px;
}
#previous,
#next,
#playpause {
cursor: pointer;
}
.playpausecontainer {
width: 100%;
text-align: center;
}

17
getMap.php

@ -0,0 +1,17 @@
<?php
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
http_response_code(405);
die();
}
date_default_timezone_set('UTC');
$date = date("Ymd", mktime(0, 0, 0, 8, 10, 2007) + 86400 * $_POST["index"]);
$fileName = "maps/" . $date . ".png";
if (file_exists(__DIR__ . "/" . $fileName)){
echo $fileName;
} else {
http_response_code(404);
die();
}

39
index.html

@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sov Timeline</title>
<meta name="description" content="Sov Timeline">
<meta name="author" content="Skyweb">
<link rel="stylesheet" href="css/reset.css?v=1.0">
<link rel="stylesheet" href="css/styles.css?v=1.0">
</head>
<body>
<div class="contentcontainer">
<div class="content">
<div class="mapcontainer">
<img class="map" id="map" />
</div>
<div class="slidecontainer">
<div class="text"><span>2007-08-09</span></div>
<input type="range" min="1" max="50" class="slider" id="date">
<div class="text"><span>Now</span></div>
</div>
<div class="controlcontainer">
<div></div>
<span class="text" id="previous"></span>
<span class="text" id="dateLabel"></span>
<span class="text" id="next"></span>
<div class="playpausecontainer"><span class="text" id="playpause">play</span></div>
<div></div>
</div>
</div>
</div>
<div id="zoom"></div>
<script src="js/scripts.js"></script>
</body>
</html>

234
js/scripts.js

@ -0,0 +1,234 @@
function daysBetween(startDate, endDate) {
var millisecondsPerDay = 24 * 60 * 60 * 1000;
return Math.round((endDate - startDate) / millisecondsPerDay);
}
Date.prototype.addDays = function(days) {
var result = new Date(this.valueOf());
result.setDate(result.getDate() + days);
return result;
}
var slider = document.getElementById("date");
var map = document.getElementById("map");
var dateLabel = document.getElementById("dateLabel");
var playpause = document.getElementById("playpause");
var previous = document.getElementById("previous");
var next = document.getElementById("next");
var zoom = document.getElementById("zoom");
var beginDate = new Date(2007, 7, 09); // lmao august is the 7th month of the year
var endDate = new Date(2021, 7, 15);
var indexArray = [];
slider.min = 0;
slider.max = daysBetween(beginDate, endDate) - 3;
slider.value = slider.max;
var lens = document.createElement("DIV");
map.parentElement.insertBefore(lens, map);
lens.setAttribute("class", "img-zoom-lens");
getMap(slider.value);
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var playspeed = 0.3;
var playing = false;
async function playmap() {
while (playing) {
current = parseInt(slider.value);
if (current + 1 > slider.max) {
playing = false;
playpause.innerHTML = "play";
return;
}
slider.value = current + 1
getMap(slider.value);
await sleep(playspeed * 1000);
}
}
playpause.onclick = function() {
playing = !playing;
if (slider.value === slider.max) {
slider.value = 0;
}
if (playing) {
zoom.style.opacity = 0;
playpause.innerHTML = "pause";
playmap();
} else {
playpause.innerHTML = "play";
}
};
previous.onclick = function() {
if (playing) {
playpause.onclick();
}
slider.value = parseInt(slider.value) - 1
getMap(slider.value);
};
next.onclick = function() {
if (playing) {
playpause.onclick();
}
slider.value = parseInt(slider.value) + 1
getMap(slider.value);
};
function getMap(index) {
if (indexArray[index] === undefined) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "getMap.php");
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function(e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
map.src = xhr.responseText;
zoom.style.backgroundImage = "url('" + xhr.responseText + "')";
indexArray[index] = xhr.responseText;
} else {
console.error(xhr.statusText);
indexArray[index] = "404";
}
}
};
xhr.onerror = function(e) {
indexArray[index] = "404";
console.error(xhr.statusText);
};
xhr.send("index=" + index);
} else {
if (indexArray[index] !== "404") {
map.src = indexArray[index];
zoom.style.backgroundImage = "url('" + indexArray[index] + "')";
}
}
var currentDate = new Date(beginDate.addDays(1 + parseInt(index)));
dateLabel.innerHTML = currentDate.getFullYear() + "-" + String(currentDate.getMonth() + 1).padStart(2, '0') + "-" + String(currentDate.getDate()).padStart(2, '0');
}
slider.oninput = function() {
if (playing) {
playpause.onclick();
}
getMap(slider.value);
}
function imageZoom(imgID, resultID, e = false) {
var img, result, cx, cy;
img = document.getElementById(imgID);
result = document.getElementById(resultID);
/* Calculate the ratio between result DIV and lens: */
cx = zoom.offsetWidth / lens.offsetWidth;
cy = zoom.offsetHeight / lens.offsetHeight;
/* Set background properties for the result DIV */
result.style.backgroundSize = (img.offsetWidth * cx) + "px " + (img.offsetHeight * cy) + "px";
/* Execute a function when someone moves the cursor over the image, or the lens: */
lens.addEventListener("mousemove", moveLens);
img.addEventListener("mousemove", moveLens);
/* And also for touch screens: */
lens.addEventListener("touchmove", moveLens);
img.addEventListener("touchmove", moveLens);
if (e) {
moveLens(e);
}
function moveLens(e) {
var pos, x, y;
/* Prevent any other actions that may occur when moving over the image */
e.preventDefault();
/* Get the cursor's x and y positions: */
pos = getCursorPos(e);
/* Calculate the position of the lens: */
x = pos.x - (lens.offsetWidth / 2);
y = pos.y - (lens.offsetHeight / 2);
/* Prevent the lens from being positioned outside the image: */
if (x > img.width - lens.offsetWidth) { x = img.width - lens.offsetWidth; }
if (x < 0) { x = 0; }
if (y > img.height - lens.offsetHeight) { y = img.height - lens.offsetHeight; }
if (y < 0) { y = 0; }
/* Set the position of the lens: */
lens.style.left = x + "px";
lens.style.top = y + "px";
var zoomx, zoomy;
zoomx = e.pageX - 100;
zoomy = e.pageY - 100;
if (e.pageX > window.innerWidth - 100) { zoomx = window.innerWidth - 200; }
if (e.pageY > window.innerHeight - 173) { zoomy = window.innerHeight - 273; }
if (zoomx < 0) { zoomx = 0; }
if (zoomy < 0) { zoomy = 0; }
result.style.left = zoomx + "px";
result.style.top = zoomy + "px";
/* Display what the lens "sees": */
result.style.backgroundPosition = "-" + (x * cx) + "px -" + (y * cy) + "px";
}
function getCursorPos(e) {
var a, x = 0,
y = 0;
e = e || window.event;
/* Get the x and y positions of the image: */
a = img.getBoundingClientRect();
/* Calculate the cursor's x and y coordinates, relative to the image: */
x = e.pageX - a.left;
y = e.pageY - a.top;
/* Consider any page scrolling: */
x = x - window.pageXOffset;
y = y - window.pageYOffset;
return { x: x, y: y };
}
}
map.onmouseover = function() {
if (!playing) {
zoom.style.opacity = 1;
}
};
map.onmouseout = function() {
zoom.style.opacity = 0;
};
lensZoom = 80;
lens.style.width = lensZoom + "px";
lens.style.height = lensZoom + "px";
function scrollevent(event) {
if (playing) {
return;
}
event.preventDefault();
if (event.deltaY > 0) {
lensZoom += 10;
} else {
if (lensZoom !== 10) {
lensZoom -= 10;
}
}
lens.style.width = lensZoom + "px";
lens.style.height = lensZoom + "px";
imageZoom("map", "zoom", event);
}
map.onwheel = scrollevent;
function resizeEvent() {
lens.style.left = "0px";
lens.style.top = "0px";
result.style.left = "0px";
result.style.top = "0px";
imageZoom("map", "zoom");
}
window.onresize = resizeEvent;
map.onload = function() {
imageZoom("map", "zoom");
}
Loading…
Cancel
Save