atlas/web/_js/main.js

468 lines
10 KiB
JavaScript
Raw Normal View History

/*
========================================================================
The /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
artwork of the canvas provided by the community.
Copyright (C) 2017 Roland Rytz <roland@draemm.li>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
========================================================================
*/
var innerContainer = document.getElementById("innerContainer");
var container = document.getElementById("container");
var canvas = document.getElementById("highlightCanvas");
var context = canvas.getContext("2d");
var zoom = 1;
if(window.devicePixelRatio){
zoom = 1/window.devicePixelRatio;
}
var maxZoom = 128;
var minZoom = 0.1;
var zoomOrigin = [0, 0];
var scaleZoomOrigin = [0, 0];
var dragging = false;
var lastPosition = [0, 0];
var viewportSize = [0, 0];
document.getElementById("donateButton").addEventListener("click", function(e){
document.getElementById("bitcoinQR").src = "./_img/bitcoinQR.png?from=index";
document.getElementById("donateOverlay").style.display = "flex";
});
document.getElementById("closeBitcoinButton").addEventListener("click", function(e){
document.getElementById("donateOverlay").style.display = "none";
});
function applyView(){
2017-04-10 12:25:04 +02:00
2017-04-10 15:16:34 +02:00
//console.log(zoomOrigin, scaleZoomOrigin);
2017-04-10 16:28:22 +02:00
//console.log(scaleZoomOrigin[0]);
scaleZoomOrigin[0] = Math.max(-1000, Math.min(1000, scaleZoomOrigin[0]));
scaleZoomOrigin[1] = Math.max(-1000, Math.min(1000, scaleZoomOrigin[1]));
2017-04-10 16:28:22 +02:00
zoomOrigin = [scaleZoomOrigin[0]*zoom, scaleZoomOrigin[1]*zoom];
innerContainer.style.height = (~~(zoom*2000))+"px";
innerContainer.style.width = (~~(zoom*2000))+"px";
innerContainer.style.left = ~~(container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft)+"px";
innerContainer.style.top = ~~(container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop)+"px";
2017-04-09 02:08:35 +02:00
}
2022-04-05 11:48:15 +02:00
var atlas = null;
init();
2022-04-05 11:48:15 +02:00
async function init(){
2022-04-05 21:26:54 +02:00
let resp = await fetch("./atlas.json");
2022-04-05 11:48:15 +02:00
atlas = await resp.json();
atlas.sort(function (a, b) {
if (a.center[1] < b.center[1]) {
return -1;
}
if (a.center[1] > b.center[1]) {
return 1;
}
// a must be equal to b
return 0;
});
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);
zoomOrigin = [0, 0];
applyView();
var initialPinchDistance = 0;
var initialPinchZoom = 0;
var initialPinchZoomOrigin = [0, 0];
var desiredZoom;
var zoomAnimationFrame;
var mode = "view";
var args = window.location.search;
if(args){
mode = args.split("mode=")[1];
if(mode){
mode = mode.split("&")[0];
} else {
mode = "view";
}
}
if(mode == "view"){
2017-04-06 11:44:50 +02:00
wrapper.className = wrapper.className.replace(/ drawMode/g, "");
initView();
} else if(mode=="draw"){
wrapper.className += " draw";
initDraw();
} else if(mode=="about"){
window.location = "./about.html";
} else if(mode=="overlap"){
wrapper.className = wrapper.className.replace(/ drawMode/g, "");
if(initOverlap){
initOverlap();
}
}
2022-04-06 10:30:04 +02:00
function changeOverlapMode(){
console.log(mode)
switch(mode){
case "overlap":
window.location.href = "?mode=explore"
break;
case "explore":
window.location.href = "?"
break;
default:
window.location.href = "?mode=overlap"
break;
}
return false;
}
const modeMap = {
"view": "Overlap",
"overlap": "Explore",
"explore": "Atlas"
}
const toggleMode = document.getElementById("toggleMode");
toggleMode.onclick = changeOverlapMode;
toggleMode.innerHTML = modeMap[mode];
2017-04-10 17:57:13 +02:00
document.getElementById("loading").style.display = "none";
document.getElementById("zoomInButton").addEventListener("click", function(e){
2017-04-10 12:25:04 +02:00
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame);
2017-04-10 12:25:04 +02:00
}*/
var x = container.clientWidth/2;
var y = container.clientHeight/2;
initialPinchZoomOrigin = [
scaleZoomOrigin[0],
scaleZoomOrigin[1]
];
initialPinchZoom = zoom;
lastPosition = [x, y];
2017-04-10 12:25:04 +02:00
zoom = zoom * 2;
zoom = Math.max(minZoom, Math.min(maxZoom, zoom));
2017-04-10 12:25:04 +02:00
applyZoom(x, y, zoom);
2017-04-05 00:53:10 +02:00
});
document.getElementById("zoomOutButton").addEventListener("click", function(e){
2017-04-10 12:25:04 +02:00
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame);
2017-04-10 12:25:04 +02:00
}*/
var x = container.clientWidth/2;
var y = container.clientHeight/2;
initialPinchZoomOrigin = [
scaleZoomOrigin[0],
scaleZoomOrigin[1]
];
initialPinchZoom = zoom;
lastPosition = [x, y];
2017-04-10 12:25:04 +02:00
zoom = zoom / 2;
zoom = Math.max(minZoom, Math.min(maxZoom, zoom));
2017-04-10 12:25:04 +02:00
applyZoom(x, y, zoom);
2017-04-05 00:53:10 +02:00
});
document.getElementById("zoomResetButton").addEventListener("click", function(e){
zoom = 1;
zoomOrigin = [0, 0];
2017-04-10 15:16:34 +02:00
scaleZoomOrigin = [0, 0];
2017-04-09 02:08:35 +02:00
updateLines();
2017-04-05 00:53:10 +02:00
applyView();
});
container.addEventListener("dblclick", function(e){
2017-04-10 12:25:04 +02:00
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame);
2017-04-10 12:25:04 +02:00
}*/
2017-04-10 12:25:04 +02:00
var x = e.clientX - container.offsetLeft;
var y = e.clientY - container.offsetTop;
initialPinchZoomOrigin = [
scaleZoomOrigin[0],
scaleZoomOrigin[1]
];
initialPinchZoom = zoom;
lastPosition = [x, y];
if(e.ctrlKey){
2017-04-10 12:25:04 +02:00
zoom = zoom / 2;
} else {
2017-04-10 12:25:04 +02:00
zoom = zoom * 2;
}
2017-04-10 12:25:04 +02:00
zoom = Math.max(minZoom, Math.min(maxZoom, zoom));
applyZoom(x, y, zoom);
e.preventDefault();
});
container.addEventListener("wheel", function(e){
2017-04-10 12:25:04 +02:00
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame);
2017-04-10 12:25:04 +02:00
}*/
2017-04-10 12:25:04 +02:00
var x = e.clientX - container.offsetLeft;
var y = e.clientY - container.offsetTop;
initialPinchZoomOrigin = [
scaleZoomOrigin[0],
scaleZoomOrigin[1]
];
initialPinchZoom = zoom;
lastPosition = [x, y];
if(e.deltaY > 0){
2017-04-10 12:25:04 +02:00
zoom = zoom / 2;
} else if(e.deltaY < 0){
2017-04-10 12:25:04 +02:00
zoom = zoom * 2;
}
2017-04-10 12:25:04 +02:00
zoom = Math.max(minZoom, Math.min(maxZoom, zoom));
applyZoom(x, y, zoom);
e.preventDefault();
});
2017-04-10 12:25:04 +02:00
/*function setDesiredZoom(x, y, target){
zoom = (zoom*2 + target)/3;
2017-04-10 12:25:04 +02:00
//console.log(zoom);
if(Math.abs(1 - zoom/target) <= 0.01){
zoom = target;
}
applyZoom(x, y, zoom);
if(zoom != target){
zoomAnimationFrame = window.requestAnimationFrame(function(){
setDesiredZoom(x, y, target);
});
}
2017-04-10 12:25:04 +02:00
}*/
container.addEventListener("mousedown", function(e){
mousedown(e.clientX, e.clientY);
e.preventDefault();
});
container.addEventListener("touchstart", function(e){
if(e.touches.length == 2){
e.preventDefault();
}
touchstart(e);
});
function mousedown(x, y){
lastPosition = [x, y];
dragging = true;
}
function touchstart(e){
if(e.touches.length == 1){
mousedown(e.touches[0].clientX, e.touches[0].clientY);
} else if(e.touches.length == 2){
initialPinchDistance = Math.sqrt(
Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2)
+ Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2)
);
initialPinchZoom = zoom;
initialPinchZoomOrigin = [
scaleZoomOrigin[0],
scaleZoomOrigin[1]
];
mousedown(
(e.touches[0].clientX + e.touches[1].clientX)/2,
(e.touches[0].clientY + e.touches[1].clientY)/2
);
}
}
window.addEventListener("mousemove", function(e){
2017-04-09 02:08:35 +02:00
updateLines();
mousemove(e.clientX, e.clientY);
if(dragging){
e.preventDefault();
}
});
window.addEventListener("touchmove", function(e){
if(e.touches.length == 2 || e.scale > 1){
e.preventDefault();
}
touchmove(e);
},
{passive: false}
);
function mousemove(x, y){
if(dragging){
var deltaX = x - lastPosition[0];
var deltaY = y - lastPosition[1];
lastPosition = [x, y];
zoomOrigin[0] += deltaX;
zoomOrigin[1] += deltaY;
scaleZoomOrigin[0] += deltaX/zoom;
scaleZoomOrigin[1] += deltaY/zoom;
2017-04-10 16:28:22 +02:00
previousZoomOrigin = [zoomOrigin[0], zoomOrigin[1]];
previousScaleZoomOrigin = [scaleZoomOrigin[0], scaleZoomOrigin[1]];
2017-04-09 02:08:35 +02:00
updateLines();
applyView();
}
}
function touchmove(e){
2017-04-09 02:08:35 +02:00
updateLines();
if(e.touches.length == 1){
mousemove(e.touches[0].clientX, e.touches[0].clientY);
} else if(e.touches.length == 2){
var newPinchDistance = Math.sqrt(
Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2)
+ Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2)
);
zoom = initialPinchZoom * newPinchDistance / initialPinchDistance;
var x = (e.touches[0].clientX + e.touches[1].clientX)/2 - container.offsetLeft;
var y = (e.touches[0].clientY + e.touches[1].clientY)/2 - container.offsetTop;
applyZoom(x, y, zoom);
}
}
function applyZoom(x, y, zoom){
var deltaX = x - lastPosition[0];
var deltaY = y - lastPosition[1];
var pinchTranslateX = (x - container.clientWidth/2 - deltaX);
var pinchTranslateY = (y - container.clientHeight/2 - deltaY);
scaleZoomOrigin[0] = initialPinchZoomOrigin[0] + deltaX/zoom + pinchTranslateX/zoom - pinchTranslateX/initialPinchZoom;
scaleZoomOrigin[1] = initialPinchZoomOrigin[1] + deltaY/zoom + pinchTranslateY/zoom - pinchTranslateY/initialPinchZoom;
zoomOrigin[0] = scaleZoomOrigin[0]*zoom;
zoomOrigin[1] = scaleZoomOrigin[1]*zoom;
applyView();
updateLines();
}
window.addEventListener("mouseup", function(e){
if(dragging){
e.preventDefault();
}
mouseup(e.clientX, e.clientY);
});
window.addEventListener("touchend", touchend);
function mouseup(x, y){
if(dragging){
dragging = false;
}
}
function touchend(e){
if(e.touches.length == 0){
mouseup();
} else if(e.touches.length == 1){
initialPinchZoom = zoom;
lastPosition = [e.touches[0].clientX, e.touches[0].clientY];
}
}
window.addEventListener("resize", function(){
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);
applyView();
});
}