function newViewPort () { const CONSOLE_LOG = true let ANIMATION_INCREMENT = 0.25 const TOP_MARGIN = 15 + TOP_SPACE_HEIGHT const BOTTOM_MARGIN = 15 + BOTTOM_SPACE_HEIGHT const LEFT_MARGIN = 50 const RIGHT_MARGIN = 50 const MIN_ZOOM_LEVEL = -28.25 let thisObject = { visibleArea: undefined, eventHandler: undefined, zoomTargetLevel: undefined, zoomLevel: undefined, mousePosition: undefined, newZoomLevel: newZoomLevel, applyZoom: applyZoom, isMinZoom: isMinZoom, zoomFontSize: zoomFontSize, zoomThisPoint: zoomThisPoint, unzoomThisPoint: unzoomThisPoint, isThisPointVisible: isThisPointVisible, fitIntoVisibleArea: fitIntoVisibleArea, displace: displace, displaceTarget: displaceTarget, animate: animate, draw: draw, raiseEvents: raiseEvents, initialize: initialize } let increment = 0.035 var offset = { x: 0, y: 0 } var targetOffset = { x: 0, y: 0 } let offsetIncrement = { x: 0, y: 0 } thisObject.mousePosition = { x: 0, y: 0 } thisObject.eventHandler = newEventHandler() return thisObject function initialize () { thisObject.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 raiseEvents () { let event = { newOffset: offset } thisObject.eventHandler.raiseEvent('Offset Changed', event) } function animate () { if (thisObject.zoomLevel < thisObject.zoomTargetLevel) { if (thisObject.zoomTargetLevel - thisObject.zoomLevel < ANIMATION_INCREMENT) { ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) } thisObject.zoomLevel = thisObject.zoomLevel + ANIMATION_INCREMENT changeZoom(thisObject.zoomLevel - ANIMATION_INCREMENT, thisObject.zoomLevel) } if (thisObject.zoomLevel > thisObject.zoomTargetLevel) { if (thisObject.zoomLevel - thisObject.zoomTargetLevel < ANIMATION_INCREMENT) { ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) } thisObject.zoomLevel = thisObject.zoomLevel - ANIMATION_INCREMENT changeZoom(thisObject.zoomLevel + ANIMATION_INCREMENT, thisObject.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 } thisObject.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 newZoomLevel (level) { thisObject.zoomTargetLevel = level thisObject.zoomLevel = level ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / 3 let event = { newLevel: thisObject.zoomTargetLevel, newOffset: offset, type: undefined } thisObject.eventHandler.raiseEvent('Zoom Changed', event) return true } function isMinZoom () { /* returns true is we are currently at the min zoom level. */ if (thisObject.zoomTargetLevel === MIN_ZOOM_LEVEL) { return true } else { return false } } function applyZoom (amount) { // console.log("applyZoom amount: " + amount); if (amount > 0) { if (thisObject.zoomTargetLevel > -5) { amount = amount * 2 } if (thisObject.zoomTargetLevel > 10) { amount = amount * 3 } if (thisObject.zoomTargetLevel > 15) { amount = amount * 4 } } if (amount < 0) { if (thisObject.zoomTargetLevel > -4) { amount = amount * 2 } if (thisObject.zoomTargetLevel > 13) { amount = amount * 3 } if (thisObject.zoomTargetLevel > 19) { amount = amount * 4 } } if (thisObject.zoomTargetLevel + amount > 1000) { return false } if (thisObject.zoomTargetLevel <= -27 && amount < 0) { amount = amount / 4 } if (thisObject.zoomTargetLevel < -27 && amount > 0) { amount = amount / 4 } if (thisObject.zoomTargetLevel + amount < MIN_ZOOM_LEVEL) { return false } thisObject.zoomTargetLevel = thisObject.zoomTargetLevel + amount ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / 3 let event = { newLevel: thisObject.zoomTargetLevel, newOffset: offset, type: undefined } if (amount > 0) { event.type = 'Zoom In' } else { event.type = 'Zoom Out' } thisObject.eventHandler.raiseEvent('Zoom Changed', event) return true } function changeZoom (oldLevel, newLevel) { let mouseNoZoom = unzoomThisPoint(thisObject.mousePosition, oldLevel) let newMouse = zoomThisPoint(mouseNoZoom, newLevel) offset.x = offset.x - newMouse.x + thisObject.mousePosition.x offset.y = offset.y - newMouse.y + thisObject.mousePosition.y targetOffset.x = offset.x targetOffset.y = offset.y offsetIncrement = { x: 0, y: 0 } } function zoomFontSize (baseSize, level) { let zoomFactor = increment // + increment * thisObject.zoomLevel / 100; if (level === undefined) { baseSize = baseSize * (1 + zoomFactor * thisObject.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 > thisObject.visibleArea.bottomRight.x + 1) { point.x = thisObject.visibleArea.bottomRight.x + 1 } if (point.x < thisObject.visibleArea.topLeft.x - 1) { point.x = thisObject.visibleArea.topLeft.x - 1 } if (point.y > thisObject.visibleArea.bottomRight.y + 1) { point.y = thisObject.visibleArea.bottomRight.y + 1 } if (point.y < thisObject.visibleArea.topLeft.y - 1) { point.y = thisObject.visibleArea.topLeft.y - 1 } return point } function zoomThisPoint (point, level) { let zoomFactor = increment // + increment * thisObject.zoomLevel / 100; if (level === undefined) { point.x = point.x * (1 + zoomFactor * thisObject.zoomLevel) + offset.x point.y = point.y * (1 + zoomFactor * thisObject.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 * thisObject.zoomLevel / 100; if (level === undefined) { pointWithoutZoom = { x: (pointWithZoom.x - offset.x) / (1 + zoomFactor * thisObject.zoomLevel), y: (pointWithZoom.y - offset.y) / (1 + zoomFactor * thisObject.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 = (thisObject.visibleArea.bottomRight.x - thisObject.visibleArea.bottomLeft.x) / step squareWidth = squareWidth + squareWidth * increment * thisObject.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 * thisObject.zoomLevel if (lineWidth < 0.5) { return } if (lineWidth > 2) { lineWidth = 2 } browserCanvasContext.beginPath() for (var i = startingX; i < thisObject.visibleArea.bottomRight.x; i = i + squareWidth) { for (var j = startingY; j < thisObject.visibleArea.bottomRight.y; j = j + squareWidth) { let point1 = { x: thisObject.visibleArea.bottomLeft.x, y: j } let point2 = { x: thisObject.visibleArea.bottomRight.x, y: j } browserCanvasContext.moveTo(point1.x, point1.y) browserCanvasContext.lineTo(point2.x, point2.y) } let point3 = { x: i, y: thisObject.visibleArea.topLeft.y } let point4 = { x: i, y: thisObject.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() } }