diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000..0ba8230 --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,43 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: '.' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 295e3a4..d8cca6a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A simple **JoyStick** for web application that use HTML5, Canvas and JavaScript. You can simply add a JoyStick in your HTML5 page, base configuration is ready for use it. -The JoyStick can be used either on touch devices, or on devices that use mouse, touchpads or similar pointing systems. +The JoyStick can be used either on touch devices, or on devices that use a mouse, touchpad or similar pointing systems. Developed for Web Remote Control of Robot, the JoyStick can be used for all other scope. > **Note:** the code not use JQuery, or other framework, but only pure Vanilla JavaScript. @@ -90,24 +90,30 @@ But if you want see the JoyStick in action go to this [link](http://bobboteck.gi All configuration parameters are optional, must be passed in JSON format, therefore it is sufficient to indicate only the parameters for which you want to provide a configuration other than the Default value. * **title {String} (optional)** - The ID of canvas (Default value is 'joystick') -* **width {Int} (optional)** - The width of canvas, if not specified is setted at width of container object (Default value is the width of container object) -* **height {Int} (optional)** - The height of canvas, if not specified is setted at height of container object (Default value is the height of container object) +* **width {Int} (optional)** - The width of canvas, if not specified is set to width of container object (Default value is the width of container object) +* **height {Int} (optional)** - The height of canvas, if not specified is set to width of container object (Default value is the height of container object) * **internalFillColor {String} (optional)** - Internal color of Stick (Default value is '#00AA00') * **internalLineWidth {Int} (optional)** - Border width of Stick (Default value is 2) * **internalStrokeColor {String}(optional)** - Border color of Stick (Default value is '#003300') -* **externalLineWidth {Int} (optional)** - External reference circonference width (Default value is 2) -* **externalStrokeColor {String} (optional)** - External reference circonference color (Default value is '#008000') +* **internalDrawArrows {Bool} (optional)** - Draws X and Y arrows on the centre of the Stick (if axisOnlyX=true only X arrow is draw, if axisOnlyY=true only Y is arrow draw) +* **externalLineWidth {Int} (optional)** - External reference circumference width (Default value is 2) +* **externalStrokeColor {String} (optional)** - External reference circumference color (Default value is '#008000') * **autoReturnToCenter {Bool} (optional)** - Sets the behavior of the stick, whether or not, it should return to zero position when released (Default value is True and return to zero) +* **axisOnlyX {Bool} (optional)** - Stick only moves in the X direction, y is set to 0 (ignored if both axisOnlyX and axisOnlyY are set to true) +* **axisOnlyY {Bool} (optional)** - Stick only moves in the Y direction, x is set to 0 (ignored if both axisOnlyX and axisOnlyY are set to true) ## Tips & Tricks -The ***title*** parameter, that have as default value 'joystick', is used to set the ID of Canvas elemente that contains the JoyStick, you can use this to define custom CSS style for the canvas. For example in the ***[joy.html](http://bobboteck.github.io/joy/joy.html)*** file the CSS style is used to set the border of Canvas with this row of code: +The ***title*** parameter, that have as default value 'joystick', is used to set the ID of Canvas element that contains the JoyStick, you can use this to define custom CSS style for the canvas. For example in the ***[joy.html](http://bobboteck.github.io/joy/joy.html)*** file the CSS style is used to set the border of Canvas with this row of code: ```css #joystick { border: 1px solid #9C9898; } ``` +The ***axisOnlyX*** and ***axisOnlyY*** parameters can be used to make the stick only move in the X or Y directions. If using either of these, it is also useful to use the ***internalDrawArrows*** parameter as this will draw an arrow on the stick showing the direction of the allowed (X or Y) movement. See example ***[joy-axis.html](https://kenloveday.github.io/JoyStick/joy-axis.html)***. + +[joystick-axis](https://kenloveday.github.io/JoyStick/joy-axis.html) ## Share your experience diff --git a/joy-axis.html b/joy-axis.html new file mode 100644 index 0000000..822957c --- /dev/null +++ b/joy-axis.html @@ -0,0 +1,92 @@ + + + + + JoyStick Axis + + + + + + +

JoyStick XY Axis Options

+ +
+
+
Parameters:
{'internalDrawArrows': true, 'axisOnlyX': true}
+
+
+
+
+
Parameters:
{'internalDrawArrows': true, 'axisOnlyY': true}
+
+
+
+
+
Parameters:
{'internalDrawArrows': true}
+
+
+
+
+
Parameters:
{}
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/joy.js b/joy.js index 09608c4..b28f595 100644 --- a/joy.js +++ b/joy.js @@ -45,7 +45,7 @@ * SOFTWARE. */ -let StickStatus = +var StickStatus = { xPosition: 0, yPosition: 0, @@ -56,32 +56,38 @@ let StickStatus = /** * @desc Principal object that draw a joystick, you only need to initialize the object and suggest the HTML container - * @costructor - * @param container {String} - HTML object that contains the Joystick + * @constructor + * @param container {String} - HTML object that contains the Joystick * @param parameters (optional) - object with following keys: - * title {String} (optional) - The ID of canvas (Default value is 'joystick') - * width {Int} (optional) - The width of canvas, if not specified is setted at width of container object (Default value is the width of container object) - * height {Int} (optional) - The height of canvas, if not specified is setted at height of container object (Default value is the height of container object) - * internalFillColor {String} (optional) - Internal color of Stick (Default value is '#00AA00') - * internalLineWidth {Int} (optional) - Border width of Stick (Default value is 2) - * internalStrokeColor {String}(optional) - Border color of Stick (Default value is '#003300') - * externalLineWidth {Int} (optional) - External reference circonference width (Default value is 2) - * externalStrokeColor {String} (optional) - External reference circonference color (Default value is '#008000') - * autoReturnToCenter {Bool} (optional) - Sets the behavior of the stick, whether or not, it should return to zero position when released (Default value is True and return to zero) - * @param callback {StickStatus} - + * title {String} (optional) - The ID of canvas (Default value is 'joystick') + * width {Int} (optional) - The width of canvas, if not specified is set to width of container object (Default value is the width of container object) + * height {Int} (optional) - The height of canvas, if not specified is set to height of container object (Default value is the height of container object) + * internalFillColor {String} (optional) - Internal color of Stick (Default value is '#00AA00') + * internalLineWidth {Int} (optional) - Border width of Stick (Default value is 2) + * internalStrokeColor {String} (optional) - Border color of Stick (Default value is '#003300') + * internalDrawArrows {Bool} (optional) - Draws X and Y arrows on the centre of the Stick (if axisOnlyX=true only X arrow is draw, if axisOnlyY=true only Y is arrow draw) + * externalLineWidth {Int} (optional) - External reference circumference width (Default value is 2) + * externalStrokeColor {String} (optional) - External reference circumference color (Default value is '#008000') + * autoReturnToCenter {Bool} (optional) - Sets the behavior of the stick, whether or not, it should return to zero position when released (Default value is True and return to zero) + * axisOnlyX {Bool} (optional) - Stick only moves in the X direction, y is set to 0 (ignored if both axisOnlyX and axisOnlyY are set to true) + * axisOnlyY {Bool} (optional) - Stick only moves in the Y direction, x is set to 0 (ignored if both axisOnlyX and axisOnlyY are set to true) + * @param callback {StickStatus} */ var JoyStick = (function(container, parameters, callback) { parameters = parameters || {}; - var title = (typeof parameters.title === "undefined" ? "joystick" : parameters.title), - width = (typeof parameters.width === "undefined" ? 0 : parameters.width), - height = (typeof parameters.height === "undefined" ? 0 : parameters.height), - internalFillColor = (typeof parameters.internalFillColor === "undefined" ? "#00AA00" : parameters.internalFillColor), - internalLineWidth = (typeof parameters.internalLineWidth === "undefined" ? 2 : parameters.internalLineWidth), + var title = (typeof parameters.title === "undefined" ? "joystick" : parameters.title), + width = (typeof parameters.width === "undefined" ? 0 : parameters.width), + height = (typeof parameters.height === "undefined" ? 0 : parameters.height), + internalFillColor = (typeof parameters.internalFillColor === "undefined" ? "#00AA00" : parameters.internalFillColor), + internalLineWidth = (typeof parameters.internalLineWidth === "undefined" ? 2 : parameters.internalLineWidth), internalStrokeColor = (typeof parameters.internalStrokeColor === "undefined" ? "#003300" : parameters.internalStrokeColor), - externalLineWidth = (typeof parameters.externalLineWidth === "undefined" ? 2 : parameters.externalLineWidth), - externalStrokeColor = (typeof parameters.externalStrokeColor === "undefined" ? "#008000" : parameters.externalStrokeColor), - autoReturnToCenter = (typeof parameters.autoReturnToCenter === "undefined" ? true : parameters.autoReturnToCenter); + internalDrawArrows = (typeof parameters.internalDrawArrows === "undefined" ? false : parameters.internalDrawArrows == true), + externalLineWidth = (typeof parameters.externalLineWidth === "undefined" ? 2 : parameters.externalLineWidth), + externalStrokeColor = (typeof parameters.externalStrokeColor === "undefined" ? "#008000" : parameters.externalStrokeColor), + autoReturnToCenter = (typeof parameters.autoReturnToCenter === "undefined" ? true : parameters.autoReturnToCenter == true), + axisOnlyX = (typeof parameters.axisOnlyX === "undefined" ? false : parameters.axisOnlyX == true), + axisOnlyY = (typeof parameters.axisOnlyY === "undefined" ? false : parameters.axisOnlyY == true); callback = callback || function(StickStatus) {}; @@ -115,6 +121,13 @@ var JoyStick = (function(container, parameters, callback) var movedX=centerX; var movedY=centerY; + // Don't allow axisOnlyX and axisOnlyY to both be set + // as this would mean the stick would not move + if(axisOnlyX && axisOnlyY){ + axisOnlyX = false; + axisOnlyY = false; + } + // Check if the device support the touch or not if("ontouchstart" in document.documentElement) { @@ -131,6 +144,7 @@ var JoyStick = (function(container, parameters, callback) // Draw the object drawExternal(); drawInternal(); + drawInternalArrows(); /****************************************************** * Private methods @@ -172,10 +186,85 @@ var JoyStick = (function(container, parameters, callback) context.stroke(); } + /** + * @desc Draw the internal arrows (if required from parameters) + */ + function drawInternalArrows(){ + + if(!internalDrawArrows) + { + return; + } + + arrowLength = internalRadius/2; // Make arrow length half stick width + + // Arrow colour and width (for simplicity make same as internal stick) + context.strokeStyle = internalStrokeColor; // Arrow colour + context.lineWidth = internalLineWidth; // Arrow line width + + if(!axisOnlyY) + { + drawArrow(context, movedX - arrowLength, movedY, + movedX + arrowLength, movedY, true); + } + if(!axisOnlyX) + { + drawArrow(context, movedX, movedY - arrowLength, + movedX, movedY + arrowLength, true); + } + } + + /** + * @desc Draws arrows on canvas + */ + function drawArrow(context, fromX, fromY, toX, toY, doubleHeaded) { + + // Arrow head settings + arrowHeadSize = 0.2; // Arrow head size as fraction of arrow length + context.lineCap = "round"; + + // Calculate arrow head length + dx = toX - fromX; + dy = toY - fromY; + headLength = Math.sqrt(dx*dx + dy*dy) * arrowHeadSize; + + // Draw arrow line + context.beginPath(); + context.moveTo(fromX, fromY); + context.lineTo(toX, toY); + context.stroke(); + + // Draw arrow head (at end of line) + angle = Math.atan2(dy, dx); + context.beginPath(); + context.moveTo(toX - headLength * Math.cos( angle - Math.PI / 6), + toY - headLength * Math.sin( angle - Math.PI / 6)); + context.lineTo(toX, toY); + context.lineTo(toX - headLength * Math.cos( angle + Math.PI / 6), + toY - headLength * Math.sin( angle + Math.PI / 6)); + context.stroke(); + + // See if we want a double headed arrow + if(!doubleHeaded) + { + return; + } + + // Draw arrow head (at beginning of line) + angle = Math.atan2(-dy, -dx); + context.beginPath(); + context.moveTo(fromX - headLength * Math.cos( angle - Math.PI / 6), + fromY - headLength * Math.sin( angle - Math.PI / 6)); + context.lineTo(fromX, fromY); + context.lineTo(fromX - headLength * Math.cos( angle + Math.PI / 6), + fromY - headLength * Math.sin( angle + Math.PI / 6)); + context.stroke(); + } + /** * @desc Events for manage touch */ - let touchId = null; + var touchId = null; function onTouchStart(event) { pressed = 1; @@ -199,11 +288,22 @@ var JoyStick = (function(container, parameters, callback) movedX -= canvas.offsetParent.offsetLeft; movedY -= canvas.offsetParent.offsetTop; } + + if(axisOnlyY) + { + movedX = centerX; + } + if(axisOnlyX) + { + movedY = centerY; + } + // Delete canvas context.clearRect(0, 0, canvas.width, canvas.height); // Redraw object drawExternal(); drawInternal(); + drawInternalArrows(); // Set attribute of callback StickStatus.xPosition = movedX; @@ -217,7 +317,10 @@ var JoyStick = (function(container, parameters, callback) function onTouchEnd(event) { - if (event.changedTouches[0].identifier !== touchId) return; + if (event.changedTouches[0].identifier !== touchId) + { + return; + } pressed = 0; // If required reset position store variable @@ -226,11 +329,13 @@ var JoyStick = (function(container, parameters, callback) movedX = centerX; movedY = centerY; } + // Delete canvas context.clearRect(0, 0, canvas.width, canvas.height); // Redraw object drawExternal(); drawInternal(); + drawInternalArrows(); // Set attribute of callback StickStatus.xPosition = movedX; @@ -249,7 +354,7 @@ var JoyStick = (function(container, parameters, callback) pressed = 1; } - /* To simplify this code there was a new experimental feature here: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX , but it present only in Mouse case not metod presents in Touch case :-( */ + // To simplify this code there was a new experimental feature here: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX, but it present only in Mouse case not method presents in Touch case :-( function onMouseMove(event) { if(pressed === 1) @@ -267,11 +372,22 @@ var JoyStick = (function(container, parameters, callback) movedX -= canvas.offsetParent.offsetLeft; movedY -= canvas.offsetParent.offsetTop; } + + if(axisOnlyY) + { + movedX = centerX; + } + if(axisOnlyX) + { + movedY = centerY; + } + // Delete canvas context.clearRect(0, 0, canvas.width, canvas.height); // Redraw object drawExternal(); drawInternal(); + drawInternalArrows(); // Set attribute of callback StickStatus.xPosition = movedX; @@ -292,11 +408,13 @@ var JoyStick = (function(container, parameters, callback) movedX = centerX; movedY = centerY; } + // Delete canvas context.clearRect(0, 0, canvas.width, canvas.height); // Redraw object drawExternal(); drawInternal(); + drawInternalArrows(); // Set attribute of callback StickStatus.xPosition = movedX; @@ -309,9 +427,9 @@ var JoyStick = (function(container, parameters, callback) function getCardinalDirection() { - let result = ""; - let orizontal = movedX - centerX; - let vertical = movedY - centerY; + var result = ""; + var horizontal = movedX - centerX; + var vertical = movedY - centerY; if(vertical >= directionVerticalLimitNeg && vertical <= directionVerticalLimitPos) { @@ -326,7 +444,7 @@ var JoyStick = (function(container, parameters, callback) result = "S"; } - if(orizontal < directionHorizontalLimitNeg) + if(horizontal < directionHorizontalLimitNeg) { if(result === "C") { @@ -337,7 +455,7 @@ var JoyStick = (function(container, parameters, callback) result += "W"; } } - if(orizontal > directionHorizontalLimitPos) + if(horizontal > directionHorizontalLimitPos) { if(result === "C") { @@ -393,7 +511,7 @@ var JoyStick = (function(container, parameters, callback) }; /** - * @desc Normalizzed value of X move of stick + * @desc Normalized value of X move of stick * @return Integer from -100 to +100 */ this.GetX = function () @@ -402,7 +520,7 @@ var JoyStick = (function(container, parameters, callback) }; /** - * @desc Normalizzed value of Y move of stick + * @desc Normalized value of Y move of stick * @return Integer from -100 to +100 */ this.GetY = function () diff --git a/joy.min.js b/joy.min.js index 98c4e7f..9320da5 100644 --- a/joy.min.js +++ b/joy.min.js @@ -44,4 +44,4 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -let StickStatus={xPosition:0,yPosition:0,x:0,y:0,cardinalDirection:"C"};var JoyStick=function(t,e,i){var o=void 0===(e=e||{}).title?"joystick":e.title,n=void 0===e.width?0:e.width,a=void 0===e.height?0:e.height,r=void 0===e.internalFillColor?"#00AA00":e.internalFillColor,c=void 0===e.internalLineWidth?2:e.internalLineWidth,s=void 0===e.internalStrokeColor?"#003300":e.internalStrokeColor,d=void 0===e.externalLineWidth?2:e.externalLineWidth,u=void 0===e.externalStrokeColor?"#008000":e.externalStrokeColor,h=void 0===e.autoReturnToCenter||e.autoReturnToCenter;i=i||function(t){};var S=document.getElementById(t);S.style.touchAction="none";var f=document.createElement("canvas");f.id=o,0===n&&(n=S.clientWidth),0===a&&(a=S.clientHeight),f.width=n,f.height=a,S.appendChild(f);var l=f.getContext("2d"),k=0,g=2*Math.PI,x=(f.width-(f.width/2+10))/2,v=x+5,P=x+30,m=f.width/2,C=f.height/2,p=f.width/10,y=-1*p,w=f.height/10,L=-1*w,F=m,E=C;function W(){l.beginPath(),l.arc(m,C,P,0,g,!1),l.lineWidth=d,l.strokeStyle=u,l.stroke()}function T(){l.beginPath(),Ff.width&&(F=f.width-v),Ef.height&&(E=f.height-v),l.arc(F,E,x,0,g,!1);var t=l.createRadialGradient(m,C,5,m,C,200);t.addColorStop(0,r),t.addColorStop(1,s),l.fillStyle=t,l.fill(),l.lineWidth=c,l.strokeStyle=s,l.stroke()}function D(){let t="",e=F-m,i=E-C;return i>=L&&i<=w&&(t="C"),iw&&(t="S"),ep&&("C"===t?t="E":t+="E"),t}"ontouchstart"in document.documentElement?(f.addEventListener("touchstart",function(t){k=1},!1),document.addEventListener("touchmove",function(t){1===k&&t.targetTouches[0].target===f&&(F=t.targetTouches[0].pageX,E=t.targetTouches[0].pageY,"BODY"===f.offsetParent.tagName.toUpperCase()?(F-=f.offsetLeft,E-=f.offsetTop):(F-=f.offsetParent.offsetLeft,E-=f.offsetParent.offsetTop),l.clearRect(0,0,f.width,f.height),W(),T(),StickStatus.xPosition=F,StickStatus.yPosition=E,StickStatus.x=((F-m)/v*100).toFixed(),StickStatus.y=((E-C)/v*100*-1).toFixed(),StickStatus.cardinalDirection=D(),i(StickStatus))},!1),document.addEventListener("touchend",function(t){k=0,h&&(F=m,E=C);l.clearRect(0,0,f.width,f.height),W(),T(),StickStatus.xPosition=F,StickStatus.yPosition=E,StickStatus.x=((F-m)/v*100).toFixed(),StickStatus.y=((E-C)/v*100*-1).toFixed(),StickStatus.cardinalDirection=D(),i(StickStatus)},!1)):(f.addEventListener("mousedown",function(t){k=1},!1),document.addEventListener("mousemove",function(t){1===k&&(F=t.pageX,E=t.pageY,"BODY"===f.offsetParent.tagName.toUpperCase()?(F-=f.offsetLeft,E-=f.offsetTop):(F-=f.offsetParent.offsetLeft,E-=f.offsetParent.offsetTop),l.clearRect(0,0,f.width,f.height),W(),T(),StickStatus.xPosition=F,StickStatus.yPosition=E,StickStatus.x=((F-m)/v*100).toFixed(),StickStatus.y=((E-C)/v*100*-1).toFixed(),StickStatus.cardinalDirection=D(),i(StickStatus))},!1),document.addEventListener("mouseup",function(t){k=0,h&&(F=m,E=C);l.clearRect(0,0,f.width,f.height),W(),T(),StickStatus.xPosition=F,StickStatus.yPosition=E,StickStatus.x=((F-m)/v*100).toFixed(),StickStatus.y=((E-C)/v*100*-1).toFixed(),StickStatus.cardinalDirection=D(),i(StickStatus)},!1)),W(),T(),this.GetWidth=function(){return f.width},this.GetHeight=function(){return f.height},this.GetPosX=function(){return F},this.GetPosY=function(){return E},this.GetX=function(){return((F-m)/v*100).toFixed()},this.GetY=function(){return((E-C)/v*100*-1).toFixed()},this.GetDir=function(){return D()}}; \ No newline at end of file +var StickStatus={xPosition:0,yPosition:0,x:0,y:0,cardinalDirection:"C"},JoyStick=function(t,e,i){var n=void 0===(e=e||{}).title?"joystick":e.title,o=void 0===e.width?0:e.width,a=void 0===e.height?0:e.height,r=void 0===e.internalFillColor?"#00AA00":e.internalFillColor,h=void 0===e.internalLineWidth?2:e.internalLineWidth,d=void 0===e.internalStrokeColor?"#003300":e.internalStrokeColor,s=void 0!==e.internalDrawArrows&&1==e.internalDrawArrows,c=void 0===e.externalLineWidth?2:e.externalLineWidth,u=void 0===e.externalStrokeColor?"#008000":e.externalStrokeColor,l=void 0===e.autoReturnToCenter||1==e.autoReturnToCenter,S=void 0!==e.axisOnlyX&&1==e.axisOnlyX,f=void 0!==e.axisOnlyY&&1==e.axisOnlyY;i=i||function(t){};var g=document.getElementById(t);g.style.touchAction="none";var k=document.createElement("canvas");k.id=n,0===o&&(o=g.clientWidth),0===a&&(a=g.clientHeight),k.width=o,k.height=a,g.appendChild(k);var x=k.getContext("2d"),v=0,P=2*Math.PI,L=(k.width-(k.width/2+10))/2,y=L+5,w=L+30,m=k.width/2,M=k.height/2,C=k.width/10,T=-1*C,p=k.height/10,F=-1*p,E=m,W=M;function D(){x.beginPath(),x.arc(m,M,w,0,P,!1),x.lineWidth=c,x.strokeStyle=u,x.stroke()}function I(){x.beginPath(),Ek.width&&(E=k.width-y),Wk.height&&(W=k.height-y),x.arc(E,W,L,0,P,!1);var t=x.createRadialGradient(m,M,5,m,M,200);t.addColorStop(0,r),t.addColorStop(1,d),x.fillStyle=t,x.fill(),x.lineWidth=h,x.strokeStyle=d,x.stroke()}function G(){s&&(arrowLength=L/2,x.strokeStyle=d,x.lineWidth=h,f||Y(x,E-arrowLength,W,E+arrowLength,W,!0),S||Y(x,E,W-arrowLength,E,W+arrowLength,!0))}function Y(t,e,i,n,o,a){arrowHeadSize=.2,t.lineCap="round",dx=n-e,dy=o-i,headLength=Math.sqrt(dx*dx+dy*dy)*arrowHeadSize,t.beginPath(),t.moveTo(e,i),t.lineTo(n,o),t.stroke(),angle=Math.atan2(dy,dx),t.beginPath(),t.moveTo(n-headLength*Math.cos(angle-Math.PI/6),o-headLength*Math.sin(angle-Math.PI/6)),t.lineTo(n,o),t.lineTo(n-headLength*Math.cos(angle+Math.PI/6),o-headLength*Math.sin(angle+Math.PI/6)),t.stroke(),a&&(angle=Math.atan2(-dy,-dx),t.beginPath(),t.moveTo(e-headLength*Math.cos(angle-Math.PI/6),i-headLength*Math.sin(angle-Math.PI/6)),t.lineTo(e,i),t.lineTo(e-headLength*Math.cos(angle+Math.PI/6),i-headLength*Math.sin(angle+Math.PI/6)),t.stroke())}S&&f&&(S=!1,f=!1),"ontouchstart"in document.documentElement?(k.addEventListener("touchstart",(function(t){v=1,R=t.targetTouches[0].identifier}),!1),document.addEventListener("touchmove",(function(t){1===v&&t.targetTouches[0].target===k&&(E=t.targetTouches[0].pageX,W=t.targetTouches[0].pageY,"BODY"===k.offsetParent.tagName.toUpperCase()?(E-=k.offsetLeft,W-=k.offsetTop):(E-=k.offsetParent.offsetLeft,W-=k.offsetParent.offsetTop),f&&(E=m),S&&(W=M),x.clearRect(0,0,k.width,k.height),D(),I(),G(),StickStatus.xPosition=E,StickStatus.yPosition=W,StickStatus.x=((E-m)/y*100).toFixed(),StickStatus.y=((W-M)/y*100*-1).toFixed(),StickStatus.cardinalDirection=O(),i(StickStatus))}),!1),document.addEventListener("touchend",(function(t){if(t.changedTouches[0].identifier!==R)return;v=0,l&&(E=m,W=M);x.clearRect(0,0,k.width,k.height),D(),I(),G(),StickStatus.xPosition=E,StickStatus.yPosition=W,StickStatus.x=((E-m)/y*100).toFixed(),StickStatus.y=((W-M)/y*100*-1).toFixed(),StickStatus.cardinalDirection=O(),i(StickStatus)}),!1)):(k.addEventListener("mousedown",(function(t){v=1}),!1),document.addEventListener("mousemove",(function(t){1===v&&(E=t.pageX,W=t.pageY,"BODY"===k.offsetParent.tagName.toUpperCase()?(E-=k.offsetLeft,W-=k.offsetTop):(E-=k.offsetParent.offsetLeft,W-=k.offsetParent.offsetTop),f&&(E=m),S&&(W=M),x.clearRect(0,0,k.width,k.height),D(),I(),G(),StickStatus.xPosition=E,StickStatus.yPosition=W,StickStatus.x=((E-m)/y*100).toFixed(),StickStatus.y=((W-M)/y*100*-1).toFixed(),StickStatus.cardinalDirection=O(),i(StickStatus))}),!1),document.addEventListener("mouseup",(function(t){v=0,l&&(E=m,W=M);x.clearRect(0,0,k.width,k.height),D(),I(),G(),StickStatus.xPosition=E,StickStatus.yPosition=W,StickStatus.x=((E-m)/y*100).toFixed(),StickStatus.y=((W-M)/y*100*-1).toFixed(),StickStatus.cardinalDirection=O(),i(StickStatus)}),!1)),D(),I(),G();var R=null;function O(){var t="",e=E-m,i=W-M;return i>=F&&i<=p&&(t="C"),ip&&(t="S"),eC&&("C"===t?t="E":t+="E"),t}this.GetWidth=function(){return k.width},this.GetHeight=function(){return k.height},this.GetPosX=function(){return E},this.GetPosY=function(){return W},this.GetX=function(){return((E-m)/y*100).toFixed()},this.GetY=function(){return((W-M)/y*100*-1).toFixed()},this.GetDir=function(){return O()}}; \ No newline at end of file