diff --git a/.vs/AAWeb/v15/.suo b/.vs/AAWeb/v15/.suo index c983a5706..4db55183e 100644 Binary files a/.vs/AAWeb/v15/.suo and b/.vs/AAWeb/v15/.suo differ diff --git a/FloatingSpace/Bubble.js b/FloatingSpace/Bubble.js new file mode 100644 index 000000000..86ad215af --- /dev/null +++ b/FloatingSpace/Bubble.js @@ -0,0 +1,148 @@ + +function newBubble() { + + var thisObject = { + + drawBackground: drawBackground, + drawForeground: drawForeground, + initialize: initialize + + }; + + return thisObject; + + function initialize(callBackFunction) { + + callBackFunction(); + + } + + function drawBackground(pFloatingObject) { + + if (pFloatingObject.currentRadius > 1) { + + /* Target Line */ + + browserCanvasContext.beginPath(); + browserCanvasContext.moveTo(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y); + browserCanvasContext.lineTo(pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.x, pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.y); + browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)'; + browserCanvasContext.setLineDash([4, 2]); + browserCanvasContext.lineWidth = 1; + browserCanvasContext.stroke(); + browserCanvasContext.setLineDash([0, 0]); + + } + + if (pFloatingObject.currentRadius > 0.5) { + + /* Target Spot */ + + var radius = 1; + + browserCanvasContext.beginPath(); + browserCanvasContext.arc(pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.x, pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].position.y, radius, 0, Math.PI * 2, true); + browserCanvasContext.closePath(); + browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)'; + browserCanvasContext.fill(); + + } + } + + function drawForeground(pFloatingObject) { + + if (pFloatingObject.currentRadius > 5) { + + /* Contourn */ + + browserCanvasContext.beginPath(); + browserCanvasContext.arc(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y, pFloatingObject.currentRadius, 0, Math.PI * 2, true); + browserCanvasContext.closePath(); + browserCanvasContext.strokeStyle = 'rgba(30, 30, 30, 0.75)'; + browserCanvasContext.lineWidth = 1; + browserCanvasContext.stroke(); + + } + + if (pFloatingObject.currentRadius > 0.5) { + + /* Main FloatingObject */ + + var alphaA; + + if (pFloatingObject.currentRadius < 3) { + alphaA = 1; + } else { + alphaA = 0.75; + } + + alphaA = 0.75; + + browserCanvasContext.beginPath(); + browserCanvasContext.arc(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y, pFloatingObject.currentRadius, 0, Math.PI * 2, true); + browserCanvasContext.closePath(); + + browserCanvasContext.fillStyle = pFloatingObject.fillStyle; + + browserCanvasContext.fill(); + + } + + /* Image */ + + if (pFloatingObject.payload.profile.imageId !== undefined) { + + let image = document.getElementById(pFloatingObject.payload.profile.imageId); + + if (image !== null) { + + browserCanvasContext.drawImage(image, pFloatingObject.currentPosition.x - pFloatingObject.currentImageSize / 2, pFloatingObject.currentPosition.y - pFloatingObject.currentImageSize / 2, pFloatingObject.currentImageSize, pFloatingObject.currentImageSize); + + } + } + + /* Label Text */ + + if (pFloatingObject.currentRadius > 6) { + + browserCanvasContext.strokeStyle = pFloatingObject.labelStrokeStyle; + + let labelPoint; + let fontSize = 10; + + browserCanvasContext.font = fontSize + 'px Courier New'; + + let label; + + label = pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].title; + + if (label !== undefined) { + + labelPoint = { + x: pFloatingObject.currentPosition.x - label.length / 2 * fontSize * 0.60, + y: pFloatingObject.currentPosition.y - pFloatingObject.currentImageSize / 2 - fontSize * 0.60 - 5 + }; + + browserCanvasContext.font = fontSize + 'px Courier New'; + browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle; + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y); + + } + + label = pFloatingObject.payload.bubbles[pFloatingObject.payload.bubbleIndex].body; + + if (label !== undefined) { + + labelPoint = { + x: pFloatingObject.currentPosition.x - label.length / 2 * fontSize * 0.60, + y: pFloatingObject.currentPosition.y + pFloatingObject.currentImageSize / 2 + fontSize * 0.60 + 10 + }; + + browserCanvasContext.font = fontSize + 'px Courier New'; + browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle; + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y); + + } + } + } +} diff --git a/FloatingSpace/BubbleSets.js b/FloatingSpace/BubbleSets.js index a43fcb350..770f2243a 100644 --- a/FloatingSpace/BubbleSets.js +++ b/FloatingSpace/BubbleSets.js @@ -14,7 +14,6 @@ function newBubbleSets() { }; let bubbleSets = []; - let floatingLayer; return thisObject; @@ -36,17 +35,118 @@ function newBubbleSets() { } } - function createBubbleSet(pPlotterBubbles) { + function createBubbleSet(pPayload, pEventHandler, callBackFunction) { let bubbleSet = { + imageId: pPayload.profile.imageId, floatingBubbles: [], - plotterBubbles: pPlotterBubbles, + payload: pPayload, handle: Math.floor((Math.random() * 10000000) + 1) }; bubbleSets.push(bubbleSet); - return bubbleSet.handle; + pEventHandler.listenToEvent("Bubbles Changed", onBubblesChanged, bubbleSets.length - 1) + + callBackFunction(GLOBAL.CUSTOM_OK_RESPONSE, bubbleSet.handle); + + function onBubblesChanged(pEvent, pBubbleSetIndex) { + + let bubbleSet = bubbleSets[pBubbleSetIndex]; + + /* First we add the new bubbles. */ + + let newFloatingBubbles = []; // We will create a new array of Floating Bubbles as a result of this operation. + + for (let i = 0; i < bubbleSet.payload.bubbles.length; i++) { + + let plotterBubble = bubbleSet.payload.bubbles[i]; + let plotterBubbleKey = plotterBubble.date.toString() + plotterBubble.rate.toString(); + let found = false; + + for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) { + + let floatingBubble = bubbleSet.floatingBubbles[j]; + let floatingBubbleKey = floatingBubble.date.toString() + floatingBubble.rate.toString(); + + if (plotterBubbleKey === floatingBubbleKey) { + + found = true; + break; + + } + } + + if (found === false) { + + let floatingObject = newFloatingObject(); + floatingObject.initialize("Bubble", onInitialized); + + function onInitialized(err) { + + floatingObject.payload = bubbleSet.payload; + floatingObject.payload.bubbleIndex = i; + floatingObject.payload.profile.imageId = bubbleSet.imageId; + + //floatingObject.container = pContainer; + + floatingObject.friction = .995; + + floatingObject.initializeMass(100); + floatingObject.initializeRadius(30); + floatingObject.initializeImageSize(50); + + floatingObject.fillStyle = 'rgba(255, 255, 255, 0.5)'; + floatingObject.labelStrokeStyle = 'rgba(60, 60, 60, 0.50)'; + + floatingLayer.addFloatingObject(floatingObject); + plotterBubble.floatingHandle = floatingObject.handle; + + } + + } + + newFloatingBubbles.push(plotterBubble); + + } + + bubbleSet.floatingBubbles = newFloatingBubbles; + + /* Second we remove the old bubbles. */ + + newFloatingBubbles = []; // We will create a new array of Floating Bubbles as a result of this operation. + + for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) { + + let floatingBubble = bubbleSet.floatingBubbles[j]; + let floatingBubbleKey = floatingBubble.date.toString() + floatingBubble.rate.toString(); + + for (let i = 0; i < bubbleSet.payload.bubbles.length; i++) { + + let plotterBubble = bubbleSet.payload.bubbles[i]; + let plotterBubbleKey = plotterBubble.date.toString() + plotterBubble.rate.toString(); + let found = false; + + if (plotterBubbleKey === floatingBubbleKey) { + + found = true; + break; + + } + } + + if (found === false) { + + floatingLayer.removeFloatingObject(floatingBubble.floatingHandle); + + } else { + + newFloatingBubbles.push(floatingBubble); + } + } + + bubbleSet.floatingBubbles = newFloatingBubbles; + } } function destroyBubbleSet(pHandle) { @@ -56,6 +156,14 @@ function newBubbleSets() { let bubbleSet = bubbleSets[i]; if (bubbleSet.handle === pHandle) { + + for (let j = 0; j < bubbleSet.floatingBubbles.length; j++) { + + let floatingBubble = bubbleSet.floatingBubbles[j]; + + floatingLayer.removeFloatingObject(floatingBubble.floatingHandle); + } + bubbleSets.splice(i, 1); // Delete item from array. return; } diff --git a/FloatingSpace/FloatingLayer.js b/FloatingSpace/FloatingLayer.js index cbe088afa..d3ca1a75c 100644 --- a/FloatingSpace/FloatingLayer.js +++ b/FloatingSpace/FloatingLayer.js @@ -79,13 +79,38 @@ function newFloatingLayer() { // Gives a minimun speed towards their taget. - if (floatingObject.currentPosition.x < floatingObject.input.position.x) { + let payload = { + position: undefined, + visible: false + }; + + switch (floatingObject.type) { + + case "Profile Ball": { + + payload.position = floatingObject.payload.profile.position; + payload.visible = floatingObject.payload.profile.visible; + break; + } + case "Bubble": { + + payload.position = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].position; + payload.visible = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].visible; + break; + } + default: { + + break; + } + } + + if (floatingObject.currentPosition.x < payload.position.x) { floatingObject.currentSpeed.x = floatingObject.currentSpeed.x + .005; } else { floatingObject.currentSpeed.x = floatingObject.currentSpeed.x - .005; } - if (floatingObject.currentPosition.y < floatingObject.input.position.y) { + if (floatingObject.currentPosition.y < payload.position.y) { floatingObject.currentSpeed.y = floatingObject.currentSpeed.y + .005; } else { floatingObject.currentSpeed.y = floatingObject.currentSpeed.y - .005; @@ -142,7 +167,7 @@ function newFloatingLayer() { repulsionForce(i); - gravityForce(floatingObject); + gravityForce(floatingObject, payload); } @@ -164,11 +189,36 @@ function newFloatingLayer() { let floatingObject = innactiveFloatingObjects[i]; - if (floatingObject.input.visible === true) { + let payload = { + position: undefined, + visible: false + }; + + switch (floatingObject.type) { + + case "Profile Ball": { + + payload.position = floatingObject.payload.profile.position; + payload.visible = floatingObject.payload.profile.visible; + break; + } + case "Bubble": { + + payload.position = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].position; + payload.visible = floatingObject.payload.bubbles[floatingObject.payload.bubbleIndex].visible; + break; + } + default: { + + break; + } + } + + if (payload.visible === true) { /* The first time that the floatingObject becomes visible, we need to do this. */ - floatingObject.radomizeCurrentPosition(floatingObject.input.position); + floatingObject.radomizeCurrentPosition(payload.position); floatingObject.radomizeCurrentSpeed(); thisObject.floatingObjects.push(floatingObject); @@ -179,14 +229,14 @@ function newFloatingLayer() { } } - function gravityForce(floatingObject) { + function gravityForce(floatingObject, payload) { /* We simulate a kind of gravity towards the target point of each floatingObject. This force will make the floatingObject to keep pushing to reach that point. */ const coulomb = .00001; const minForce = 0.01; - var d = Math.sqrt(Math.pow(floatingObject.input.position.x - floatingObject.currentPosition.x, 2) + Math.pow(floatingObject.input.position.y - floatingObject.currentPosition.y, 2)); // ... we calculate the distance ... + var d = Math.sqrt(Math.pow(payload.position.x - floatingObject.currentPosition.x, 2) + Math.pow(payload.position.y - floatingObject.currentPosition.y, 2)); // ... we calculate the distance ... var force = coulomb * d * d / floatingObject.currentMass; // In this case the mass of the floatingObject affects the gravity force that it receives, that gives priority to target position to bigger floatingObjects. @@ -200,8 +250,8 @@ function newFloatingLayer() { }; var pos2 = { - x: floatingObject.input.position.x, - y: floatingObject.input.position.y + x: payload.position.x, + y: payload.position.y }; var posDiff = { // Next we need the vector resulting from the 2 positions. diff --git a/FloatingSpace/FloatingObject.js b/FloatingSpace/FloatingObject.js index 433375ed7..fd9dba610 100644 --- a/FloatingSpace/FloatingObject.js +++ b/FloatingSpace/FloatingObject.js @@ -3,7 +3,9 @@ function newFloatingObject() { var thisObject = { - input: undefined, // This object contains information needed to draw the floating object, but also referenced from outside, so as to have control of the basics of the floating object. + payload: undefined, // This is a reference to an object controlled by a Plotter. The plotter can change its internal value and we will see them from here. + type: undefined, // Currently there are two types of Floating Objects: Profile Balls, and Bubbles. + physicsEnabled: false, initializeMass: initializeMass, @@ -67,6 +69,13 @@ function newFloatingObject() { } case "Bubble": { + underlayingObject = newBubble(); + underlayingObject.initialize(onInitialized); + + function onInitialized(err) { + + + } break; } default: { @@ -75,6 +84,8 @@ function newFloatingObject() { } } + thisObject.type = pType; + callBackFunction(); } diff --git a/FloatingSpace/ProfileBall.js b/FloatingSpace/ProfileBall.js index dbfa706b5..87b1d30be 100644 --- a/FloatingSpace/ProfileBall.js +++ b/FloatingSpace/ProfileBall.js @@ -25,7 +25,7 @@ function newProfileBall() { browserCanvasContext.beginPath(); browserCanvasContext.moveTo(pFloatingObject.currentPosition.x, pFloatingObject.currentPosition.y); - browserCanvasContext.lineTo(pFloatingObject.input.position.x, pFloatingObject.input.position.y); + browserCanvasContext.lineTo(pFloatingObject.payload.profile.position.x, pFloatingObject.payload.profile.position.y); browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)'; browserCanvasContext.setLineDash([4, 2]); browserCanvasContext.lineWidth = 1; @@ -41,7 +41,7 @@ function newProfileBall() { var radius = 1; browserCanvasContext.beginPath(); - browserCanvasContext.arc(pFloatingObject.input.position.x, pFloatingObject.input.position.y, radius, 0, Math.PI * 2, true); + browserCanvasContext.arc(pFloatingObject.payload.profile.position.x, pFloatingObject.payload.profile.position.y, radius, 0, Math.PI * 2, true); browserCanvasContext.closePath(); browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)'; browserCanvasContext.fill(); @@ -90,9 +90,9 @@ function newProfileBall() { /* Image */ - if (pFloatingObject.input.imageId !== undefined) { + if (pFloatingObject.payload.profile.imageId !== undefined) { - let image = document.getElementById(pFloatingObject.input.imageId); + let image = document.getElementById(pFloatingObject.payload.profile.imageId); if (image !== null) { @@ -114,7 +114,7 @@ function newProfileBall() { let label; - label = pFloatingObject.input.upLabel; + label = pFloatingObject.payload.profile.upLabel; if (label !== undefined) { @@ -129,7 +129,7 @@ function newProfileBall() { } - label = pFloatingObject.input.downLabel; + label = pFloatingObject.payload.profile.downLabel; if (label !== undefined) { diff --git a/FloatingSpace/ProfileBalls.js b/FloatingSpace/ProfileBalls.js index 205a535fc..c6e7b0986 100644 --- a/FloatingSpace/ProfileBalls.js +++ b/FloatingSpace/ProfileBalls.js @@ -42,14 +42,14 @@ function newProfileBalls() { } } - function createNewProfileBall(pInput, pContainer, callBackFunction) { + function createNewProfileBall(pPayload, pContainer, callBackFunction) { let floatingObject = newFloatingObject(); floatingObject.initialize("Profile Ball", onInitialized); function onInitialized(err) { - floatingObject.input = pInput; + floatingObject.payload = pPayload; floatingObject.container = pContainer; diff --git a/Project.njsproj b/Project.njsproj index b3022b5c5..3f168d3f7 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -32,6 +32,9 @@ + + Code + Code diff --git a/TimelineChart.js b/TimelineChart.js index e02aac988..6f68f278f 100644 --- a/TimelineChart.js +++ b/TimelineChart.js @@ -307,27 +307,33 @@ /* Create The Profie Picture FloatingObject */ - if (productPlotter.plotter.profile !== undefined) { + if (productPlotter.plotter.payload !== undefined) { let imageId = pProductCard.bot.devTeam + "." + pProductCard.bot.profilePicture; - productPlotter.plotter.profile.upLabel = pProductCard.product.shortDisplayName; - productPlotter.plotter.profile.downLabel = pProductCard.bot.displayName; - productPlotter.plotter.profile.imageId = imageId; + productPlotter.plotter.payload.profile.upLabel = pProductCard.product.shortDisplayName; + productPlotter.plotter.payload.profile.downLabel = pProductCard.bot.displayName; + productPlotter.plotter.payload.profile.imageId = imageId; - canvas.floatingSpace.profileBalls.createNewProfileBall(productPlotter.plotter.profile, thisObject.container, onProfileBallCreated) + canvas.floatingSpace.profileBalls.createNewProfileBall(productPlotter.plotter.payload, thisObject.container, onProfileBallCreated) function onProfileBallCreated(err, pProfileHandle) { productPlotter.profile = pProfileHandle; } + + /* Create the Text Bubbles */ + + canvas.floatingSpace.bubbleSets.createBubbleSet(productPlotter.plotter.payload, productPlotter.plotter.container.eventHandler, onBubbleSetCreated); + + function onBubbleSetCreated(err, pBubbleSetHandle) { + + productPlotter.bubbleSet = pBubbleSetHandle; + + } } - /* Create the Text Bubbles */ - - productPlotter.bubbleSet = canvas.floatingSpace.bubbleSets.createBubbleSet(productPlotter.plotter.bubbles); - /* Add the new Active Protter to the Array */ productPlotters.push(productPlotter); diff --git a/index.html b/index.html index e26d9397b..2d7969acf 100644 --- a/index.html +++ b/index.html @@ -44,6 +44,7 @@ +