Coder Social home page Coder Social logo

bobboteck / joystick Goto Github PK

View Code? Open in Web Editor NEW
332.0 332.0 91.0 42 KB

A simple JoyStick that use HTML5, Canvas and Vanilla JavaScript, for touch and mouse interfaces (no JQuery required), preview at:

Home Page: https://bobboteck.github.io/joy/joy.html

License: MIT License

HTML 29.51% JavaScript 70.49%
html5 javascript joystick touchscreen vanilla-javascript

joystick's Introduction

Hi there 👋

Completed in the year 2021

  • Version 2.0.0 of my JoyStick
  • Released on Arduino Library registry my CWLibrary to send Morse message

🔧 I'm currently working on

  • a version 2.1.0 of my JoyStick
  • A simple HF beacon
  • A Direct Conversion Receiver

💡 I'm currently learnig to

  • build my first HF Transceiver 📻
  • use serial port on Javascript

🤔 I’m looking for help to design and build my first HF Transceiver

💬 Ask me about my Vanilla Javascript JoyStick project

📺 On my YouTube Channel you can find some video about my Robots and other projects

joystick's People

Contributors

amjadah avatar bobboteck avatar brollin avatar codacy-badger avatar gitter-badger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

joystick's Issues

Allow AddListener/Callback

Currently, you have to use setTimout. Is there a way to do this with listeners/callbacks, and if there isn't could you add the ability? This would be greatly appreciated.

Option to stop returning to center

Hi this is a brilliant script. But I was wondering if you could stop it from returning to zero. I would like to do this myself but I don’t know js and have only adapted it for flask. Thanks

More robust calculation of touch/click position relative to canvas

Hi @bobboteck , thanks for this library.

While trying it inside a page with a complex layout, using canvas.offsetParent.offsetLeft (and Top) inside of onTouchMove() and onMouseMove() reported (correctly) the offsets for the closest positioned parent element.

However, its offsetTop was 0 but the event.pageY was something like 400 and that made the Y axis of the joystick unusable.

|-------------------------------------|
|    offsetParent with offsetTop=0    |  
|                                     |  
|                                     |
|    |---------------------------|    |  
|    |  joy div, top ~ 400       |    |  
|    |                           |    |  
|    |   ---------------------   |    |  
|    |   |   joy canvas      |   |    |  
|    |   |                   |   |    |  
|    |   |                   |   |    |  
|    |   |-------------------|   |    |  
|    |                           |    |  
|    |---------------------------|    |  
|                                     |
|-------------------------------------|

Nowadays most browsers support the clientX and clientY properties on events that report the desired value (see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX and related)

We ended up patching the methods like:

  function onMouseMove(event) 
  {
    if(pressed === 1)
    {
      movedX = event.offsetX;
      movedY = event.offsetY;
      // Delete canvas
      context.clearRect(0, 0, canvas.width, canvas.height);
      // Redraw object
      drawExternal();
      drawInternal();
    }
  }

  function onTouchMove(event)
  {
    // Prevent the browser from doing its default thing (scroll, zoom)
    event.preventDefault();
    if(pressed === 1 && event.targetTouches[0].target === canvas)
    {
      movedX = event.targetTouches[0].offsetX;
      movedY = event.targetTouches[0].offsetY;
      // Delete canvas
      context.clearRect(0, 0, canvas.width, canvas.height);
      // Redraw object
      drawExternal();
      drawInternal();
    }
  } 

and that made it work like a charm.
I don't know if you had other reason for the original code but this is related to issues like #10, #11 and #12.

Thanks

Error with different css-positions

When working with a CSS position other than the default, the joystick can not be moved correctly.
I suspect, this is an issue with the calculation of the movement.
I suggest to calculate the movement based on the last and the current position.

Issue with multiple joysticks

Describe the bug
the "touchend" event should be listening to "canvas" rather than "document", as in my webapp, when i want to have 2 joysticks, and I let go of one of them, the "touchend" event gets fired on both of the joysticks.

To Reproduce
Steps to reproduce the behavior:

  1. add 2 joysticks
  2. touch 2 at the same time
  3. let go of one
  4. "touchend" will be fired for both joysticks, rather than just the one.

Expected behavior
touchend fired on the joystick that actually initialised it, rather than both

Screenshots
ezgif-5-5020b8eb2b

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6] ALL DEVICES
  • OS: [e.g. iOS8.1] ALL OS's
  • Browser [e.g. stock browser, safari] ALL BROWSERS
  • Version [e.g. 22] ALL

Additional context
None

The joystick does not move to the left (moves to the right) after I add position: fixed; top: 0; to the CSS grid div CSS (HTML provided)

Hello, I want to use your library for a mobile site. The layout is however for some reason a bit taller than the view port in the landscape orientation and full screen mode. So I want to disable scrolling with position: fixed; top: 0; That however produces the following result: the joystick can't be moved left and is moved right when I move my mouse to the left.

<html>
<head>
<meta charset="utf-8">

<script type="text/javascript" src="joy.js"></script>
<style type="text/css">

	.wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 200px 200px;
    grid-gap: 20px;
	}
	.joy3Posizione{
		display: none;
	}
	.popisek{
		font-family: Helvetica;padding-top:9px;font-weight: 600;
	}
    .c{
    	background-color: grey;
    }
    th, td {
	  padding-left:5px;padding-right: 5px
	}

   .plyn {
   	transform: rotate(-90deg);
	  -webkit-appearance: none;
	  width: 100%;
	  height: 25px;
	  background: #d3d3d3;
	  outline: none;
	  opacity: 0.7;
	  -webkit-transition: .2s;
	  transition: opacity .2s;
	  tran: 0px;
	}

	.plyn:hover {
	  opacity: 1;
	}

	.plyn::-webkit-slider-thumb {
	  -webkit-appearance: none;
	  appearance: none;
	  width: 25px;
	  height: 25px;
	  background: #04AA6D;
	  cursor: pointer;
	}

	.plyn::-moz-range-thumb {
	  width: 25px;
	  height: 25px;
	  background: #04AA6D;
	  cursor: pointer;
	}
	.wrapper{
	    position: fixed;
        top: 0;
	}
	#IP{
		width: 230px;
	}
	#confirm{
	    width: 60px;
	}
</style>
</head>
<body>

<div class="wrapper">
	<!-- Example of FIXED or ABSOLUTE position -->
	<div class="c" id="containe"> <!-- style="width:200px;height:200px"> -->
		<div style="display: inline"> <!-- style="position:fixed;bottom:125px;left:750px;" -->

		<input class="joy3Posizione" type="text"> <!-- to tam musí být -->
		<input class="joy3Posizione" type="text">
		Y :<input class="t" id="joy3Y" type="text">
	    <p class="popisek">text</p>
		</div>
		<div style="width:200px;height:200px;display: block;margin: 0 auto;">
			 <input type="range" min="1" max="100" value="50" class="plyn">
		</div>
	</div>
	<div class="c">
		<center class="popisek">text:
		<table style="font-family: Helvetica;">
		<tr>
		    <th>text</th>
		    <th>text</th> 
		  </tr>
			<tr>
		    <td>text</td>
		    <td>100%</td>
			</tr>
			<tr>
		    <td>text</td>
		    <td>100%</td>
			</tr>
		</table>
			<input type="button" value="Pause" id="siesta">
		  <input type="button" value="Action" id="Action">
		</center>
	</div>
    
    <div class="c" id="containe"> <!-- style="width:200px;height:200px" -->
		<div style="display: inline"> <!-- style="position:fixed;bottom:125px;left:750px;" -->

		<input class="joy3Posizione" type="text"> <!-- to tam musí být -->
		<input class="joy3Posizione" type="text">
		X :<input id="joy4X" class="t" type="text"><br>
		Y :<input id="joy4Y" class="t" type="text">
	    <center class="popisek">text</center>
		</div>
		<div id='container' style="width:200px;height:200px;display: block;margin: 0 auto;"></div>
	</div>

	<div style="padding-top: 100px">
	 IP: <input  id="IP" type="text"> <input type="button" id="confirm" value="OK">
         <input type="button" id="clear" value="Clear">
	 
	 <input id="IP_default" type="button" value="Výchozí">
	 <p id="received data">
	  <p id="adress">
	</div>
</div>
<script type="text/javascript">

	var joy3 = new JoyStick('container'); //směr

	var joy3X = document.getElementById("joy4X");
	var joy3Y = document.getElementById("joy4Y");
	var joy4Y = document.getElementById("joy3Y"); //

	//document.getElementByClassName("plyn")[0];
  document.getElementById("IP_default").addEventListener("click",function(e){
  	document.getElementById("IP").value = "http://127.0.0.1:8000/";
  	 sendTo = "http://127.0.0.1:8000/";
  });
  
  document.getElementById("confirm").addEventListener("click",function(e){
      sendTo = document.getElementById("IP").value;
  });

	document.getElementById("clear").addEventListener("click",function(e){
	      document.getElementById("IP_default").click();
	      document.getElementById("IP").value = "";
				document.documentElement.requestFullscreen();
				screen.orientation.lock("landscape");
});
</script>
<!-- <script type="text/javascript" src="posilac.js"></script> -->
</body>
</html>

4 directions

Is there a way to eliminate NE, SE, SW & NW, so it is only N, E, S & W (& C)?

Two sticks in a row

I am trying to place two sticks in a row. I tried putting them in a table but there is something wrong with the input then since the movements are not correct. I suppose the canvas coordinates might be messed up.

So my question is how can I do what I want to do? It works placing them in div that ends up in two different blocks. Making the divs inline or using span instead of div and it does not work.

Integration in third-party application

Hi Roberto (@bobboteck),

Thanks for sharing this library!
I would like to integrate your widget into an open-source application (as child of a DIV element...), but I have some questions about this:

  • Is it possible to show only the canvas and not the other widgets?
  • Is there also an NPM package available?

Happy christmas!
Bart

No integrated direction buttons?

Hello, your virtual joystick is very good.

However, why is there no integrated direction button?

Because it is also a joystick and a direction key, it will be more convenient for many games.

Doesn’t Scale if elements are % (or vw/vh)

Describe the bug
if docs are % (or vw/vh), the elements should scale when window resized.

To Reproduce
Steps to reproduce the behavior:
<!— 2 divs —>

// JS

var modxy1 = new JoyStick('xy1', {
    internalFillColor:'#db3236',
    internalStrokeColor:'#db3236',
    externalStrokeColor:'rgba(0,0,0,0)',
    //internalLineWidth:0,
    externalLineWidth:4,
}, function(stickData) {xy1_dir = stickData.cardinalDirection});
var modxy2 = new JoyStick('xy2', {
    internalFillColor:'#4885ed',
    internalStrokeColor:'#4885ed',
    externalStrokeColor:'rgba(0,0,0,0)',
    //internalLineWidth:0,
    externalLineWidth:4,
}, function(stickData) {xy2_dir = stickData.cardinalDirection});

Expected behavior
Should scale elements and re-center circle
Screenshot 2022-09-09 at 13 55 02
Screenshot 2022-09-09 at 13 55 15

Issues with position: fixed; in CSS(again)

Hello again. I've seen last update of joystick that added support for position: absolute; and position: fixed; CSS attributes. I downloaded the latest version, extracted joy.js to my HTML folder, and... nothing. Still doesn't work. If you need, here is the repo (site is in HTML folder): https://github.com/GGorAA/GLaDOS.

How to fix this issue?

When using large non-square width and heights (especially width) the joystick has very little movement in one axis

Laptop 1980x1200, desktop chrome full size, setting size of div to 60vw 60vh, results in a short wide box, and the joystick movement space is very limited in vertical direction. I've made this change, and also set a Max and Min on the returned X and Y.

I changed the calculation for internalRadius and all is well:

var smallestDimension = Math.min(canvas.width,canvas.height);
var internalRadius = (smallestDimension-((smallestDimension/2)+10))/2;

This is the minor change to X / Y to be capped at +/-100

/**
* @desc Normalizzed value of X move of stick
* @return Integer from -100 to +100
*/
this.GetX = function ()
{
    return Math.max(-100,Math.min(100, (100*((movedX - centerX)/maxMoveStick)))).toFixed();
};

/**
* @desc Normalizzed value of Y move of stick
* @return Integer from -100 to +100
*/
this.GetY = function ()
{
    return Math.max(-100,Math.min(100, ((100*((movedY - centerY)/maxMoveStick))*-1))).toFixed();
};

Issues with position: absolute;

Hi. I use your JoyStick project for controlling my robot over internet, just by opening web page. Issue is: I can't place joy at the bottom of the screen using:

position: relative;
bottom: 0;

because it starts to behave not normal. Without this, controller won't be usable (technically usable, you can click on buttons and move joy, but they will be sitting on top of the screen, which is uncomfortable)

x and y coordinates outside the range of (-100, 100)

Inside my callback function, I'm seeing values for X and Y that are occasionally below -100 and above 100.

To see this, I added the following code to my HTML document:

<div id="joydiv" style="width: 200px; height: 200px; margin: 50px;"></div>
<script>
var joy = new JoyStick("joydiv", {"title": "Head", "width": 200, "height":200, "autoReturnToCenter": false}, function(joydata) {
  console.log(joydata);
});
</script>

When I drag the joystick, I see the X and Y values in the console. As I move from the center to the right edge of the joystick control, the x value increases as expected, but peaks at 110, and then drops to 100, as shown here:

Object { xPosition: 148, yPosition: 98, x: "96", y: "4", cardinalDirection: "E" }
Object { xPosition: 151, yPosition: 98, x: "102", y: "4", cardinalDirection: "E" } <=====
Object { xPosition: 155, yPosition: 98, x: "110", y: "4", cardinalDirection: "E" } <=====
Object { xPosition: 150, yPosition: 98, x: "100", y: "4", cardinalDirection: "E" }

Moving the joystick in other directions causes similar results.

X and Y should never be below -100 or above 100.

I suspect the issue is in the drawInterval() function where movedX and movedY are clipped. internalRadius should be replaced by maxMoveStick in these statements.

I'm seeing this in version 2.0.0 of joy.js on Firefox 97 on Windows 10.

Provide a reset or recenter function

While the parameter autoReturnToCenter=false is handy for preserving the joystick position, I would like the ability to force the joystick to return to center, or even to a specific position. I am using a joystick to control multiple robot joints, one at a time (as there isn't enough real estate to display multiple joysticks), and would like to restore the joystick position after switching the joint the joystick is controlling.

I would like to see a function (or more) called reset(), returnToCenter(), or setPosition(x,y) that would set the joystick to the initial (center) position or a specific position. I would call such a function when switching controls.

Since the joystick position is read-only, there is no way to change it. I could destroy the joystick and recreate it, but that seems wasteful, I could also use hidden elements for multiple joysticks, but just complicates the user interface.

Hosting on GitHub Pages would be helpful

I wanted to use this library without adding joy.js to my website (it is kind of a pain)

If this repo was hosted on GitHub pages it would easy to use by just saying:
<script src="https://bobboteck.github.io/JoyStick/joy.js"></script>

For now I forked the repo and am using:
<script src="https://williamsokol.github.io/JoyStick/joy.js"></script>
But it'd be nice for new people if they did not have to fork it.

Size scalability not working properly

When changing the div sizes (width / height) to e.g. 600x600, the Joystick gets too big, thus cannot be moved further than X=20 and Y=20. This is due to a hardcoded number ("50") in the .js code in the calculation for the internalRadius variable.
Maybe you could consider changing the calculation to something more generous.

Here you can see how I fixed it for my project:
https://github.com/vanslipon/JoyStick/blob/vanslipon-patch-1/joy.js
I simply changed the line:
var internalRadius = (canvas.width-((50*2)+10))/2;
to
var internalRadius = (canvas.width-(((canvas.width/4)*2)+10))/2;

Like this, the joystick circle scales completely fine and everything works as expected again, since other variables like externalRadius are using the internalRadius.

Nevertheless, very nice code and good work! Thx for the cool Joystick :) I'm also using it to control my robot.

Greetings from germany and stay healthy!

Bug when working with two joysticks

I have two joysticks which are supposed to control movement and camera for a vehicle simulation respectively, and they are positioned next to each other in the html document. The first joystick works as expected, but the second uses the first joysticks center as its center, opposeed to using its own center.
This is my html code fro the joysticks:

And here is the JS:
var joy = new JoyStick('vehicle_joy',{
title: 'vehicle_joystick',
width: 100,
height: 100,
internalFillColor: '#00000F',
internalLineWidth: 2,
internalStrokeColor: '#00000F',
externalLineWidth: 2,
externalStrokeColor: '#00000F',
autoReturnToCenter: true
});

(The second joystick is the same only with a name change)

Steps to reproduce the behavior:

  1. Create html and js documents with the code before
  2. Try to move the second joystick. It moves as if its center was the one from the first joystick

I expected, as it should be natural, for each joystick to move respectively to thir own center.

  • OS: Windows 11
  • Browser: Chrome
  • Version 120.0.6099.130

joystick cant be reloaded when change the view

Im using this code to change the view

var showView = function (id) {
        var view = document.getElementById(id);
        var all_views = document.querySelectorAll('view');
        // Hide all containers
        for (var i = 0; i < all_views.length; i++) {
            all_views[i].style.display = 'none';
        }

        // Show container
        view.style.display = 'block';
    };

in the body, the joystick is defined two times

<body onload="window.app = new App()">
    <!-- Add your HTML elements here -->
    <div id="loading_view" class="view">Loading ...</div>
    <div id="ingame_attack" class="view">
        <div id="pass-button" ontouchstart="window.app.sendMessageToScreen('pass')"></div>
        <div id="shoot-button" ontouchstart="window.app.sendMessageToScreen('shoot')"></div>
        <div id="joyDiv"></div>
    </div>
    <div id="ingame_defense" class="view">
        <div id="change-button" ontouchstart="window.app.sendMessageToScreen('pass')"></div>
        <div id="tackle-button" ontouchstart="window.app.sendMessageToScreen('shoot')"></div>
        <div id="joyDiv"></div>
    </div>
</body>

in css i defined the joystick this way

#joyDiv {
            position: absolute;
            top: 0%;
            left: 0%;
            width: 80%;
            height: 80%;
            background-size: contain;
            background-repeat: no-repeat;
        }

the first time i call showView('ingame_attack'); the joystick works fine
the problem is when i change in the middle of the game to "ingame_defense", the joystick stop moving

im developing an AirConsole game with Unity 2019.4,
for this code, i followed this tutorial
https://franzeus.medium.com/the-airconsole-controller-your-smartphone-is-the-gamepad-588875f944d7#.zfhidyi4j

i tried with a joyDiv2 in the css, body and showview (adding "joy = new JoyStick('joyDiv2');"), but the old joystick remains in the place, and anytime i call showview, a new joystick appear

Touch mode not activating in Chrome

Hello, and thank you for the great work!

First off, this is on Google Chrome, on a Windows 10 touchscreen laptop (Dell Inspiron 3505),
Google Chrome Version 105.0.5195.127 (Official Build) (64-bit)

Out of the box, everything worked perfect when manipulating with the mouse, but it didn't respond to touch.

Took a quick look in the code and putting an (... || true) in the below pictured if statement (ln 119) got me the functionality I was after but now the mouse is unresponsive. I'm not sure if there is a reason to make these mutually exclusive but for my purpose I want to be able to use both. So, I commented out the if structure and it works as I was hoping for!

image

I don't understand the ("ontouchstart" in document.documentElement) method, but it never returns true for me, while using "onclick" does... odd, but I can confirm that the touch listeners are working for me regardless of this test method.

Personally I would prefer the listeners to be able to be activated / deactivated with a parameter input, then it either works or it doesn't, but that's just me.

Best Regards!
-Matt

Add one dimensional joysticks (X or Y axis)

I want to make a drone controller out of this, so I need a joystick, which moves up and down for gas. I could read only x axis from a regular joystick, but it moves to the sides too. Thanks for making a great library!

CSS breaks the script

Your joystick code works perfectly until I try to position it on the screen using CSS. Let me give a code example.

Your HTML code reads
<div id="joyDiv" style="width:200px;height:200px;margin-bottom:20px;"></div>

and everything works just fine.

BUT, if you move the div to the left of the screen

<div id="joyDiv" style="position:absolute; width:200px;height:200px;margin-bottom:20px;left:1000px;"></div>

then the 'middle' of the joystick jerks to the right on mousedown event. On my screen I'm guessing the green centre moves around 50px to the right immediately on a click!

I think the problem lies with this function, but my JS isn't good enough to fix the bug :-(

function onMouseMove(event)
{
    if(pressed==1)
    {
        movedX=event.pageX;
        movedY=event.pageY;
        // Manage offset
        movedX-=canvas.offsetLeft;
        movedY-=canvas.offsetTop;
        // Delete canvas
        context.clearRect(0, 0, canvas.width, canvas.height);
        // Redraw object
        drawExternal();
        drawInternal();
    }

wrong direction

The direction east is never shown.
So please change the code:
...
if(orizontal>directionHorizontalLimitPos)
{
if(result=="C")
{
result = "E";
}
else
{
result += "E";
}
}
...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.