413 lines
10 KiB
JavaScript
413 lines
10 KiB
JavaScript
|
|
function newViewPort() {
|
|
|
|
let ANIMATION_INCREMENT = 0.25;
|
|
const TOP_MARGIN = 15;
|
|
const BOTTOM_MARGIN = 0;
|
|
const LEFT_MARGIN = 0;
|
|
const RIGHT_MARGIN = 50;
|
|
|
|
let viewPort = {
|
|
visibleArea: undefined,
|
|
eventHandler: undefined,
|
|
zoomLevel: INITIAL_ZOOM_LEVEL,
|
|
mousePosition: undefined,
|
|
applyZoom: applyZoom,
|
|
zoomFontSize: zoomFontSize,
|
|
zoomThisPoint: zoomThisPoint,
|
|
unzoomThisPoint: unzoomThisPoint,
|
|
isThisPointVisible: isThisPointVisible,
|
|
fitIntoVisibleArea: fitIntoVisibleArea,
|
|
displace: displace,
|
|
displaceTarget: displaceTarget,
|
|
animate: animate,
|
|
draw: draw,
|
|
initialize: initialize
|
|
};
|
|
|
|
zoomTargetLevel = INITIAL_ZOOM_LEVEL;
|
|
|
|
let increment = 0.035;
|
|
|
|
var offset = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
var targetOffset = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
let offsetIncrement = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
viewPort.mousePosition = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
viewPort.eventHandler = newEventHandler();
|
|
|
|
return viewPort;
|
|
|
|
function initialize() {
|
|
|
|
viewPort.visibleArea = {
|
|
topLeft: { x: LEFT_MARGIN, y: TOP_MARGIN },
|
|
topRight: { x: browserCanvas.width - RIGHT_MARGIN , y: TOP_MARGIN },
|
|
bottomRight: { x: browserCanvas.width - RIGHT_MARGIN, y: browserCanvas.height - BOTTOM_MARGIN},
|
|
bottomLeft: { x: LEFT_MARGIN, y: browserCanvas.height - BOTTOM_MARGIN}
|
|
};
|
|
|
|
}
|
|
|
|
function animate() {
|
|
|
|
if (viewPort.zoomLevel < zoomTargetLevel) {
|
|
if (zoomTargetLevel - viewPort.zoomLevel < ANIMATION_INCREMENT) {
|
|
ANIMATION_INCREMENT = Math.abs(zoomTargetLevel - viewPort.zoomLevel);
|
|
}
|
|
viewPort.zoomLevel = viewPort.zoomLevel + ANIMATION_INCREMENT;
|
|
changeZoom(viewPort.zoomLevel - ANIMATION_INCREMENT, viewPort.zoomLevel);
|
|
}
|
|
|
|
if (viewPort.zoomLevel > zoomTargetLevel) {
|
|
if (viewPort.zoomLevel - zoomTargetLevel < ANIMATION_INCREMENT) {
|
|
ANIMATION_INCREMENT = Math.abs(zoomTargetLevel - viewPort.zoomLevel);
|
|
}
|
|
viewPort.zoomLevel = viewPort.zoomLevel - ANIMATION_INCREMENT;
|
|
changeZoom(viewPort.zoomLevel + ANIMATION_INCREMENT, viewPort.zoomLevel);
|
|
}
|
|
|
|
/*
|
|
if (offsetIncrement.x !== 0) {
|
|
|
|
if (Math.trunc(Math.abs(targetOffset.x - offset.x) * 1000) >= Math.trunc(Math.abs(offsetIncrement.x) * 1000)) {
|
|
offset.x = offset.x + offsetIncrement.x;
|
|
} else {
|
|
offsetIncrement.x = 0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (offsetIncrement.y !== 0) {
|
|
|
|
if (Math.trunc(Math.abs(targetOffset.y - offset.y) * 1000) >= Math.trunc(Math.abs(offsetIncrement.y) * 1000)) {
|
|
offset.y = offset.y + offsetIncrement.y;
|
|
|
|
//console.log("offset.y changed to " + offset.y)
|
|
|
|
} else {
|
|
offsetIncrement.y = 0;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
function displace(displaceVector) {
|
|
|
|
offset.x = offset.x + displaceVector.x;
|
|
offset.y = offset.y + displaceVector.y;
|
|
|
|
let event = {
|
|
newOffset: offset
|
|
};
|
|
|
|
viewPort.eventHandler.raiseEvent("Offset Changed", event);
|
|
|
|
//console.log("displace produced new Offset x = " + offset.x + " y = " + offset.y);
|
|
|
|
}
|
|
|
|
function displaceTarget(displaceVector) {
|
|
|
|
|
|
targetOffset.x = targetOffset.x + displaceVector.x;
|
|
targetOffset.y = targetOffset.y + displaceVector.y;
|
|
|
|
|
|
offsetIncrement = {
|
|
x: (targetOffset.x - offset.x) / 10,
|
|
y: (targetOffset.y - offset.y) / 10
|
|
};
|
|
|
|
//console.log("displaceTarget x = " + targetOffset.x + " y = " + targetOffset.y);
|
|
|
|
}
|
|
|
|
function applyZoom(amount) {
|
|
|
|
//console.log("applyZoom amount: " + amount);
|
|
|
|
if (amount > 0) {
|
|
|
|
|
|
if (zoomTargetLevel > -5) {
|
|
amount = amount * 2;
|
|
}
|
|
|
|
if (zoomTargetLevel > 10) {
|
|
amount = amount * 3;
|
|
}
|
|
|
|
if (zoomTargetLevel > 15) {
|
|
amount = amount * 4;
|
|
}
|
|
}
|
|
|
|
if (amount < 0) {
|
|
|
|
if (zoomTargetLevel > -4) {
|
|
amount = amount * 2;
|
|
}
|
|
|
|
if (zoomTargetLevel > 13) {
|
|
amount = amount * 3;
|
|
}
|
|
|
|
if (zoomTargetLevel > 19) {
|
|
amount = amount * 4;
|
|
}
|
|
}
|
|
|
|
if (zoomTargetLevel + amount > 1000) {
|
|
return false;
|
|
}
|
|
|
|
if (zoomTargetLevel <= -27 && amount < 0) {
|
|
amount = amount / 4;
|
|
}
|
|
|
|
if (zoomTargetLevel < -27 && amount > 0) {
|
|
amount = amount / 4;
|
|
}
|
|
|
|
if (zoomTargetLevel + amount < -28.25) {
|
|
return false;
|
|
}
|
|
|
|
zoomTargetLevel = zoomTargetLevel + amount;
|
|
|
|
ANIMATION_INCREMENT = Math.abs(zoomTargetLevel - viewPort.zoomLevel) / 3;
|
|
|
|
let event = {
|
|
newLevel: zoomTargetLevel,
|
|
newOffset: offset,
|
|
type: undefined
|
|
};
|
|
|
|
if (amount > 0) {
|
|
event.type = "Zoom In";
|
|
} else {
|
|
event.type = "Zoom Out";
|
|
}
|
|
|
|
//console.log("Zoom Changed > " + event.newLevel);
|
|
|
|
viewPort.eventHandler.raiseEvent("Zoom Changed", event);
|
|
return true;
|
|
}
|
|
|
|
|
|
function changeZoom(oldLevel, newLevel) {
|
|
|
|
let mouseNoZoom = unzoomThisPoint(viewPort.mousePosition, oldLevel);
|
|
let newMouse = zoomThisPoint(mouseNoZoom, newLevel);
|
|
|
|
offset.x = offset.x - newMouse.x + viewPort.mousePosition.x;
|
|
offset.y = offset.y - newMouse.y + viewPort.mousePosition.y;
|
|
|
|
//console.log("changeZoom produced new Offset x = " + offset.x + " y = " + offset.y);
|
|
|
|
targetOffset.x = offset.x
|
|
targetOffset.y = offset.y ;
|
|
|
|
offsetIncrement = {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
|
|
}
|
|
|
|
|
|
function zoomFontSize(baseSize, level) {
|
|
|
|
let zoomFactor = increment; // + increment * viewPort.zoomLevel / 100;
|
|
|
|
if (level === undefined) {
|
|
|
|
baseSize = baseSize * (1 + zoomFactor * viewPort.zoomLevel);
|
|
|
|
} else {
|
|
|
|
baseSize = baseSize * (1 + zoomFactor * level);
|
|
|
|
}
|
|
|
|
return baseSize;
|
|
}
|
|
|
|
function fitIntoVisibleArea(point) {
|
|
|
|
|
|
/* Here we check the boundaries of the resulting points, so they dont go out of the visible area. */
|
|
|
|
if (point.x > viewPort.visibleArea.bottomRight.x + 1) {
|
|
point.x = viewPort.visibleArea.bottomRight.x + 1;
|
|
}
|
|
|
|
if (point.x < viewPort.visibleArea.topLeft.x - 1) {
|
|
point.x = viewPort.visibleArea.topLeft.x - 1;
|
|
}
|
|
|
|
if (point.y > viewPort.visibleArea.bottomRight.y + 1) {
|
|
point.y = viewPort.visibleArea.bottomRight.y + 1;
|
|
}
|
|
|
|
if (point.y < viewPort.visibleArea.topLeft.y - 1) {
|
|
point.y = viewPort.visibleArea.topLeft.y - 1;
|
|
}
|
|
|
|
return point;
|
|
}
|
|
|
|
|
|
function zoomThisPoint(point, level) {
|
|
|
|
let zoomFactor = increment; // + increment * viewPort.zoomLevel / 100;
|
|
|
|
if (level === undefined) {
|
|
|
|
point.x = point.x * (1 + zoomFactor * viewPort.zoomLevel) + offset.x;
|
|
point.y = point.y * (1 + zoomFactor * viewPort.zoomLevel) + offset.y;
|
|
|
|
} else {
|
|
|
|
point.x = point.x * (1 + zoomFactor * level) + offset.x;
|
|
point.y = point.y * (1 + zoomFactor * level) + offset.y;
|
|
|
|
}
|
|
|
|
return point;
|
|
}
|
|
|
|
function unzoomThisPoint(pointWithZoom, level) {
|
|
|
|
let pointWithoutZoom;
|
|
let zoomFactor = increment; // + increment * viewPort.zoomLevel / 100;
|
|
|
|
if (level === undefined) {
|
|
|
|
pointWithoutZoom = {
|
|
x: (pointWithZoom.x - offset.x) / (1 + zoomFactor * viewPort.zoomLevel),
|
|
y: (pointWithZoom.y - offset.y) / (1 + zoomFactor * viewPort.zoomLevel)
|
|
};
|
|
|
|
} else {
|
|
|
|
pointWithoutZoom = {
|
|
x: (pointWithZoom.x - offset.x) / (1 + zoomFactor * level),
|
|
y: (pointWithZoom.y - offset.y) / (1 + zoomFactor * level)
|
|
};
|
|
|
|
}
|
|
return pointWithoutZoom;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isThisPointVisible(point) {
|
|
|
|
if (visibleArea === undefined) {
|
|
|
|
getVisibleArea();
|
|
|
|
}
|
|
|
|
if (point.x < visibleArea.topLeft.x || point.x > visibleArea.bottomRight.x || point.y < visibleArea.topLeft.y || point.y > visibleArea.bottomRight.y) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
function draw() {
|
|
/*
|
|
drawGrid(10);
|
|
drawGrid(1);
|
|
drawGrid(0.1);
|
|
*/
|
|
}
|
|
|
|
function drawGrid(step) {
|
|
|
|
let squareWidth = (viewPort.visibleArea.bottomRight.x - viewPort.visibleArea.bottomLeft.x) / step;
|
|
squareWidth = squareWidth + squareWidth * increment * viewPort.zoomLevel;
|
|
|
|
let startingX = offset.x - Math.trunc(offset.x / squareWidth) * squareWidth;
|
|
let startingY = offset.y - Math.trunc(offset.y / squareWidth) * squareWidth;
|
|
let lineWidth = 10 / step + 10 / step * increment * viewPort.zoomLevel;
|
|
|
|
if (lineWidth < 0.5) {
|
|
return;
|
|
}
|
|
|
|
if (lineWidth > 2) {
|
|
lineWidth = 2;
|
|
}
|
|
|
|
browserCanvasContext.beginPath();
|
|
|
|
for (var i = startingX; i < viewPort.visibleArea.bottomRight.x; i = i + squareWidth) {
|
|
|
|
for (var j = startingY; j < viewPort.visibleArea.bottomRight.y; j = j + squareWidth) {
|
|
|
|
let point1 = {
|
|
x: viewPort.visibleArea.bottomLeft.x,
|
|
y: j
|
|
};
|
|
|
|
let point2 = {
|
|
x: viewPort.visibleArea.bottomRight.x,
|
|
y: j
|
|
};
|
|
|
|
browserCanvasContext.moveTo(point1.x, point1.y);
|
|
browserCanvasContext.lineTo(point2.x, point2.y);
|
|
}
|
|
|
|
let point3 = {
|
|
x: i,
|
|
y: viewPort.visibleArea.topLeft.y
|
|
};
|
|
|
|
let point4 = {
|
|
x: i,
|
|
y: viewPort.visibleArea.bottomLeft.y
|
|
};
|
|
|
|
browserCanvasContext.moveTo(point3.x, point3.y);
|
|
browserCanvasContext.lineTo(point4.x, point4.y);
|
|
}
|
|
browserCanvasContext.closePath();
|
|
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 0.' + Math.trunc(lineWidth + 1) + ')';
|
|
|
|
browserCanvasContext.lineWidth = lineWidth;
|
|
|
|
browserCanvasContext.stroke();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|