This week and possibly much of next I’m concentrating on updating the fixed content of my website, which means I’m only going to be doing small increments on this project. I’ve decided that the next item to work on is panning a zooming because of something I want to demonstrate in the fixed content. To that end I installed the simplest possible commands to pan the 2D display around within certain limits. Mostly I wanted to verify that I’d added the base x- and y-origins for the viewable area of the screen were added to all of the drawing commands properly.
Here’s the relevant code from the DisplayElement
object. It shows how the drawing locations now include the offsets I’ve defined (globalBaseX
and globalBaseY
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
this.drawBasic = function() { var borderColor; if (this.parent.getExclusive()) { if (this.parent.getOpenStatus()) { borderColor = this.readyColor; } else { borderColor = this.waitingColor; } } else { borderColor = this.neutralColor; } //if (this.parent.getComponentType() != "Path") { if (this.isJourney) { globalCTX.strokeStyle = borderColor; globalCTX.beginPath(); if (this.innode) { globalCTX.moveTo(this.x1-5-globalBaseX+0.5,this.y1-5-globalBaseY+0.5); globalCTX.lineTo(this.x1+4-globalBaseX+0.5,this.y1-5-globalBaseY+0.5); globalCTX.lineTo(this.x1+4-globalBaseX+0.5,this.y1+4-globalBaseY+0.5); globalCTX.lineTo(this.x1-5-globalBaseX+0.5,this.y1+4-globalBaseY+0.5); globalCTX.lineTo(this.x1-5-globalBaseX+0.5,this.y1-5-globalBaseY+0.5); } else { //outnode globalCTX.moveTo(this.x2-5-globalBaseX+0.5,this.y2-5-globalBaseY+0.5); globalCTX.lineTo(this.x2+4-globalBaseX+0.5,this.y2-5-globalBaseY+0.5); globalCTX.lineTo(this.x2+4-globalBaseX+0.5,this.y2+4-globalBaseY+0.5); globalCTX.lineTo(this.x2-5-globalBaseX+0.5,this.y2+4-globalBaseY+0.5); globalCTX.lineTo(this.x2-5-globalBaseX+0.5,this.y2-5-globalBaseY+0.5); } globalCTX.stroke(); //do nothing } else if (!this.isPath) { var runningHeight = 15; globalCTX.strokeStyle = borderColor; globalCTX.beginPath(); globalCTX.moveTo(this.x1-globalBaseX+0.5,this.y1-globalBaseY+0.5); globalCTX.lineTo(this.x2-globalBaseX+0.5,this.y1-globalBaseY+0.5); globalCTX.lineTo(this.x2-globalBaseX+0.5,this.y2-globalBaseY+0.5); globalCTX.lineTo(this.x1-globalBaseX+0.5,this.y2-globalBaseY+0.5); globalCTX.lineTo(this.x1-globalBaseX+0.5,this.y1-globalBaseY+0.5); globalCTX.stroke(); globalCTX.font = "12px Arial"; globalCTX.fillStyle = this.labelColor; globalCTX.textAlign = "center"; globalCTX.fillText(this.label,this.x1+this.nodexi-globalBaseX,this.y1+runningHeight-globalBaseY); runningHeight += 12; if (this.traverse) { globalCTX.textAlign = "right"; var waitChar = "P:"; if (this.parent.getComponentType() == "Queue") { waitChar = "T:"; } else if (this.parent.getComponentType() == "Process") { waitChar = "P:"; } globalCTX.fillText(waitChar,x1-globalBaseX+15,this.y1-globalBaseY+runningHeight); globalCTX.fillStyle = this.valueColor; globalCTX.textAlign = "left"; globalCTX.fillText(this.traverseValue,x1-globalBaseX+17,this.y1-globalBaseY+runningHeight); runningHeight += 12; } if (this.count) { globalCTX.fillStyle = this.labelColor; globalCTX.textAlign = "right"; globalCTX.fillText("Q:",x1-globalBaseX+15,this.y1-globalBaseY+runningHeight); globalCTX.fillStyle = this.valueColor; globalCTX.textAlign = "left"; globalCTX.fillText(this.countValue,x1-globalBaseX+17,this.y1-globalBaseY+runningHeight); runningHeight += 12; } } else { globalCTX.strokeStyle = borderColor; globalCTX.beginPath(); globalCTX.moveTo(this.x1-globalBaseX+0.5,this.y1-globalBaseY+0.5); globalCTX.lineTo(this.x2-globalBaseX+0.5,this.y2-globalBaseY+0.5); globalCTX.stroke(); } }; this.drawNodes = function() { //if (this.parent.getComponentType() != "Path") { if (this.isJourney) { if (this.innode) { drawNode(this.x1-globalBaseX,this.y1-globalBaseY,3,this.nodeColor); } if (this.outnode) { drawNode(this.x2-globalBaseX,this.y2-globalBaseY,3,this.nodeColor); } } else if (!this.isPath) { if (this.innode) { drawNode(this.x1+this.nodexi-globalBaseX,this.y1+this.nodeyi-globalBaseY,3,this.nodeColor); } if (this.outnode) { drawNode(this.x1+this.nodexo-globalBaseX,this.y1+this.nodeyo-globalBaseY,3,this.nodeColor); } } else { if (this.parent.previousComponent.getComponentType() == "Path") { drawNode(this.x1-globalBaseX,this.y1-globalBaseY,3,this.nodeColor); } if (this.parent.nextComponent.getComponentType() == "Path") { drawNode(this.x2-globalBaseX,this.y2-globalBaseY,3,this.nodeColor); } } }; this.drawEntities = function() { var i; var drawCount; var drawColor; var xx; var yy; var qCount; //if (this.parent.getComponentType() == "Path") { if (this.isPath) { drawCount = this.parent.entityQueue.length; for (i=0; i<drawCount; i++) { var location = this.parent.entityQueue[i].getLocation(); drawNode(location.x-globalBaseX,location.y-globalBaseY,5,this.readyColor); drawNode(location.x-globalBaseX,location.y-globalBaseY,3,this.parent.entityQueue[i].getEntityColor()) } } else if (this.parent.getComponentType() == "Bag") { drawCount = this.parent.maxCapacity; //should be < this.entityLocs.length drawColor = this.waitingColor; for (i=0; i<drawCount; i++) { if (this.parent.entityQueue[i] != null) { xx = this.entityLocs[0][i].x-globalBaseX; yy = this.entityLocs[0][i].y-globalBaseY; drawNode(this.x1+xx,this.y1+yy,5,drawColor); drawNode(this.x1+xx,this.y1+yy,3,this.parent.entityQueue[i].getEntityColor()); if (this.parent.subEntityQueue[i] != null) { drawNode(this.x1+xx+3,this.y1+yy-3,5,drawColor); drawNode(this.x1+xx+3,this.y1+yy-3,3,this.parent.subEntityQueue[i].getEntityColor()); } } } drawCount = this.entityLocs[0].length - this.parent.maxCapacity; if (this.parent.exitQueue.length < drawCount) { drawCount = this.parent.exitQueue.length; } drawColor = this.readyColor; for (i=0; i<drawCount; i++) { //locs for exit queue in order from maxCapacity xx = this.entityLocs[0][this.parent.maxCapacity + i].x-globalBaseX; yy = this.entityLocs[0][this.parent.maxCapacity + i].y-globalBaseY; drawNode(this.x1+xx,this.y1+yy,5,drawColor); //exit queue items in reverse order drawNode(this.x1+xx,this.y1+yy,3,this.parent.exitQueue[this.parent.exitQueue.length-1-i].getEntityColor()); } } else if (this.parent.getComponentType()== "Combined") { //var locs = this.entityLocs.length; qCount = this.countValue - this.traverseValue; //drawCount = locs - this.parent.processCapacity; drawCount = this.locsCount[0] - this.parent.processCapacity; if (this.parent.entityQueue.length < drawCount) { drawCount = this.parent.entityQueue.length; } for (i=0; i<drawCount; i++) { if (i < qCount) { drawColor = this.readyColor; } else { drawColor = this.waitingColor; } xx = this.entityLocs[0][i].x-globalBaseX; yy = this.entityLocs[0][i].y-globalBaseY; drawNode(this.x1+xx,this.y1+yy,5,drawColor); drawNode(this.x1+xx,this.y1+yy,3,this.parent.entityQueue[i].getEntityColor()); } var pCount = this.parent.countInProcessQueue - this.parent.countInProcess; drawCount = this.parent.countInProcessQueue; //start from end of entityLocs for (i=0; i<drawCount; i++) { if (i < pCount) { drawColor = this.readyColor; } else { drawColor = this.waitingColor; } xx = this.entityLocs[0][this.locsCount[0]-i-1].x-globalBaseX; yy = this.entityLocs[0][this.locsCount[0]-i-1].y-globalBaseY; drawNode(this.x1+xx,this.y1+yy,5,drawColor); drawNode(this.x1+xx,this.y1+yy,3,this.parent.processQueue[drawCount-i-1].getEntityColor()); } } else if (this.parent.getComponentType() != "Arrivals") { if (this.parent.componentName == "Q0") { dummy1 = 6; } qCount = this.countValue - this.traverseValue; if (this.countValue > this.locsCount[0]) { drawCount = this.locsCount[0]; } else { drawCount = this.countValue; } for (i=0; i<drawCount; i++) { if (i < qCount) { drawColor = this.readyColor; } else { drawColor = this.waitingColor; } xx = this.entityLocs[0][i].x-globalBaseX; yy = this.entityLocs[0][i].y-globalBaseY; drawNode(this.x1+xx,this.y1+yy,5,drawColor); drawNode(this.x1+xx,this.y1+yy,3,this.parent.entityQueue[i].getEntityColor()); } } }; |
Here’s the code that does the basic pan. It picks up keystrokes and changes the base x- and y-axis panning origins within limits. When the code is running in its own window there are times when higher priority events consume the messages for the up and down arrow keys, namely when the entire page wants to scroll. When I embed this in an iframe on the website it doesn’t seem to have this problem. However, when it’s in the iframe (like you see it here) you need to click on the canvas to give it the focus. The arrow keys move the display and the home key restore the origin point to its original value. There’s no provision for panning on a mobile device, either, but at least I know the offsets are in correctly.
You may also notice that these calls update the graphics when the simulation is not running, but don’t need to do so when the simulation is running, though the panning action will be much more slow and choppy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
var xPanMin = -200; //globalBaseX var xPanMax = 200; var xPanInc = 2; var yPanMin = -200; //globalBaseY var yPanMax = 200; var yPanInc = 2; function panUp() { globalBaseY += yPanInc; if (globalBaseY > yPanMax) { globalBaseY = yPanMax; } if (!running) { drawModel(); } } function panDown() { globalBaseY -= yPanInc; if (globalBaseY < yPanMin) { globalBaseY = yPanMin; } if (!running) { drawModel(); } } function panRight() { globalBaseX += xPanInc; if (globalBaseX > xPanMax) { globalBaseX = xPanMax; } if (!running) { drawModel(); } } function panLeft() { globalBaseX -= xPanInc; if (globalBaseX < xPanMin) { globalBaseX = xPanMin; } if (!running) { drawModel(); } } function resetPan() { globalBaseX = 0; globalBaseY = 0; if (!running) { drawModel(); } } document.onkeydown = checkKey; function checkKey(e) { e = e || window.event; //up 38 down 40 if (e.keyCode == '37') { //left arrow panLeft(); } else if (e.keyCode == '39') { //right arrow panRight(); } else if (e.keyCode == '38') { //up arrow panUp(); } else if (e.keyCode == '40') { //down arrow panDown(); } else if (e.keyCode == '66') { //b key } else if (e.keyCode == '70') { //f key } else if (e.keyCode == '36') { //home key resetPan(); } } |