diff options
author | Jakob Stendahl <jakob.stendahl@outlook.com> | 2021-02-02 16:54:52 +0100 |
---|---|---|
committer | Jakob Stendahl <jakob.stendahl@outlook.com> | 2021-02-02 16:54:52 +0100 |
commit | a726b288b00cd4e83801bc1ff800b615d6368049 (patch) | |
tree | 392d9aba6e574e780d51afdb64d678d63bbd798c | |
parent | 33df6fc26e63d4e6f0129553ebd30ef9686be39f (diff) | |
download | hoverbit-ble-a726b288b00cd4e83801bc1ff800b615d6368049.tar.gz hoverbit-ble-a726b288b00cd4e83801bc1ff800b615d6368049.zip |
First shot at a redesign of the webapp
-rw-r--r-- | index.html | 59 | ||||
-rw-r--r-- | nipplejs.js | 1 | ||||
-rw-r--r-- | package-lock.json | 5 | ||||
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | script.js | 153 | ||||
-rw-r--r-- | styles.css | 201 |
6 files changed, 145 insertions, 277 deletions
@@ -16,49 +16,46 @@ <link rel="preconnect" href="https://fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css2?family=Kufam&display=swap" rel="stylesheet"> </head> - <body> - - <div class="info"> - <h1>HOVER:BIT Controller</h1> - <div class="info-device"> - <span class="connection"> - <i class="material-icons">bluetooth</i> - </span> - <span class="battery"> - <i class="material-icons">battery_std</i> - <span class="battery-status">0%</span> - </span> - <span class="arm"> - <i class="material-icons">warning</i> - </span> - <span class="ping"> - <i class="material-icons">settings_input_antenna</i> - </span> - </div> + <body class=""> + <!-- <h1>HOVER:BIT Controller</h1> --> + + <div class="statusline-bottom"> + <span class="statusline-item connection"> + <i class="material-icons">bluetooth</i> + </span> + <span class="statusline-item arm"> + <i class="material-icons">warning</i> + </span> + <span class="statusline-item ping"> + <i class="material-icons">settings_input_antenna</i> + </span> + <span class="statusline-item battery"> + <i class="material-icons">battery_std</i> + <span class="battery-status">0%</span> + </span> </div> - <div class="options"> - <button id="btn_connect">Connect</button> - <button id="btn_disconnect">Disconnect</button> - <button id="btn_arm">Arm</button> - <button id="btn_disarm">Disarm</button> - <button id="btn_sticky">Sticky controls</button> + <button class="button-center button-center-top" id="btn_connect">Connect</button> + <button class="button-center button-center-top" id="btn_disconnect">Disconnect</button> + + <div class="acc-string"> + <pre></pre> </div> - <div class="throttle"> - <div class="throttle-thumb"></div> - <div class="throttle-indicator"></div> + <button class="button-center button-center-bottom" id="btn_arm">Arm</button> + <button class="button-center button-center-bottom" id="btn_disarm">Disarm</button> + + <div class="joystick joystick-left"> </div> - <div class="rudder"> - <div class="rudder-thumb"></div> - <div class="rudder-indicator"></div> + <div class="joystick joystick-right"> </div> <div class="log"> <pre id="logEl"></pre> </div> + <script type="text/javascript" src="./nipplejs.js"></script> <script type="text/javascript" src="script.js"></script> </body> </html> diff --git a/nipplejs.js b/nipplejs.js new file mode 100644 index 0000000..5e40ed7 --- /dev/null +++ b/nipplejs.js @@ -0,0 +1 @@ +!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define("nipplejs",[],i):"object"==typeof exports?exports.nipplejs=i():t.nipplejs=i()}(window,function(){return function(t){var i={};function e(o){if(i[o])return i[o].exports;var n=i[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}return e.m=t,e.c=i,e.d=function(t,i,o){e.o(t,i)||Object.defineProperty(t,i,{enumerable:!0,get:o})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,i){if(1&i&&(t=e(t)),8&i)return t;if(4&i&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(e.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&i&&"string"!=typeof t)for(var n in t)e.d(o,n,function(i){return t[i]}.bind(null,n));return o},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},e.p="",e(e.s=0)}([function(t,i,e){"use strict";e.r(i);var o,n=function(t,i){var e=i.x-t.x,o=i.y-t.y;return Math.sqrt(e*e+o*o)},s=function(t){return t*(Math.PI/180)},r=function(t){return t*(180/Math.PI)},d=function(t,i,e){for(var o,n=i.split(/[ ,]+/g),s=0;s<n.length;s+=1)o=n[s],t.addEventListener?t.addEventListener(o,e,!1):t.attachEvent&&t.attachEvent(o,e)},a=function(t,i,e){for(var o,n=i.split(/[ ,]+/g),s=0;s<n.length;s+=1)o=n[s],t.removeEventListener?t.removeEventListener(o,e):t.detachEvent&&t.detachEvent(o,e)},p=function(t){return t.preventDefault(),t.type.match(/^touch/)?t.changedTouches:t},c=function(){return{x:void 0!==window.pageXOffset?window.pageXOffset:(document.documentElement||document.body.parentNode||document.body).scrollLeft,y:void 0!==window.pageYOffset?window.pageYOffset:(document.documentElement||document.body.parentNode||document.body).scrollTop}},h=function(t,i){i.top||i.right||i.bottom||i.left?(t.style.top=i.top,t.style.right=i.right,t.style.bottom=i.bottom,t.style.left=i.left):(t.style.left=i.x+"px",t.style.top=i.y+"px")},l=function(t,i,e){var o=u(t);for(var n in o)if(o.hasOwnProperty(n))if("string"==typeof i)o[n]=i+" "+e;else{for(var s="",r=0,d=i.length;r<d;r+=1)s+=i[r]+" "+e+", ";o[n]=s.slice(0,-2)}return o},u=function(t){var i={};i[t]="";return["webkit","Moz","o"].forEach(function(e){i[e+t.charAt(0).toUpperCase()+t.slice(1)]=""}),i},f=function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t[e]=i[e]);return t},y=function(t,i){if(t.length)for(var e=0,o=t.length;e<o;e+=1)i(t[e]);else i(t)},m=!!("ontouchstart"in window),v=!!window.PointerEvent,g=!!window.MSPointerEvent,b={start:"mousedown",move:"mousemove",end:"mouseup"},x={};function O(){}v?o={start:"pointerdown",move:"pointermove",end:"pointerup, pointercancel"}:g?o={start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}:m?(o={start:"touchstart",move:"touchmove",end:"touchend, touchcancel"},x=b):o=b,O.prototype.on=function(t,i){var e,o=t.split(/[ ,]+/g);this._handlers_=this._handlers_||{};for(var n=0;n<o.length;n+=1)e=o[n],this._handlers_[e]=this._handlers_[e]||[],this._handlers_[e].push(i);return this},O.prototype.off=function(t,i){return this._handlers_=this._handlers_||{},void 0===t?this._handlers_={}:void 0===i?this._handlers_[t]=null:this._handlers_[t]&&this._handlers_[t].indexOf(i)>=0&&this._handlers_[t].splice(this._handlers_[t].indexOf(i),1),this},O.prototype.trigger=function(t,i){var e,o=this,n=t.split(/[ ,]+/g);o._handlers_=o._handlers_||{};for(var s=0;s<n.length;s+=1)e=n[s],o._handlers_[e]&&o._handlers_[e].length&&o._handlers_[e].forEach(function(t){t.call(o,{type:e,target:o},i)})},O.prototype.config=function(t){this.options=this.defaults||{},t&&(this.options=function(t,i){var e={};for(var o in t)t.hasOwnProperty(o)&&i.hasOwnProperty(o)?e[o]=i[o]:t.hasOwnProperty(o)&&(e[o]=t[o]);return e}(this.options,t))},O.prototype.bindEvt=function(t,i){var e=this;return e._domHandlers_=e._domHandlers_||{},e._domHandlers_[i]=function(){"function"==typeof e["on"+i]?e["on"+i].apply(e,arguments):console.warn('[WARNING] : Missing "on'+i+'" handler.')},d(t,o[i],e._domHandlers_[i]),x[i]&&d(t,x[i],e._domHandlers_[i]),e},O.prototype.unbindEvt=function(t,i){return this._domHandlers_=this._domHandlers_||{},a(t,o[i],this._domHandlers_[i]),x[i]&&a(t,x[i],this._domHandlers_[i]),delete this._domHandlers_[i],this};var _=O;function w(t,i){return this.identifier=i.identifier,this.position=i.position,this.frontPosition=i.frontPosition,this.collection=t,this.defaults={size:100,threshold:.1,color:"white",fadeTime:250,dataOnly:!1,restJoystick:!0,restOpacity:.5,mode:"dynamic",zone:document.body,lockX:!1,lockY:!1,shape:"circle"},this.config(i),"dynamic"===this.options.mode&&(this.options.restOpacity=0),this.id=w.id,w.id+=1,this.buildEl().stylize(),this.instance={el:this.ui.el,on:this.on.bind(this),off:this.off.bind(this),show:this.show.bind(this),hide:this.hide.bind(this),add:this.addToDom.bind(this),remove:this.removeFromDom.bind(this),destroy:this.destroy.bind(this),setPosition:this.setPosition.bind(this),resetDirection:this.resetDirection.bind(this),computeDirection:this.computeDirection.bind(this),trigger:this.trigger.bind(this),position:this.position,frontPosition:this.frontPosition,ui:this.ui,identifier:this.identifier,id:this.id,options:this.options},this.instance}w.prototype=new _,w.constructor=w,w.id=0,w.prototype.buildEl=function(t){return this.ui={},this.options.dataOnly?this:(this.ui.el=document.createElement("div"),this.ui.back=document.createElement("div"),this.ui.front=document.createElement("div"),this.ui.el.className="nipple collection_"+this.collection.id,this.ui.back.className="back",this.ui.front.className="front",this.ui.el.setAttribute("id","nipple_"+this.collection.id+"_"+this.id),this.ui.el.appendChild(this.ui.back),this.ui.el.appendChild(this.ui.front),this)},w.prototype.stylize=function(){if(this.options.dataOnly)return this;var t=this.options.fadeTime+"ms",i=function(t,i){var e=u(t);for(var o in e)e.hasOwnProperty(o)&&(e[o]=i);return e}("borderRadius","50%"),e=l("transition","opacity",t),o={};return o.el={position:"absolute",opacity:this.options.restOpacity,display:"block",zIndex:999},o.back={position:"absolute",display:"block",width:this.options.size+"px",height:this.options.size+"px",marginLeft:-this.options.size/2+"px",marginTop:-this.options.size/2+"px",background:this.options.color,opacity:".5"},o.front={width:this.options.size/2+"px",height:this.options.size/2+"px",position:"absolute",display:"block",marginLeft:-this.options.size/4+"px",marginTop:-this.options.size/4+"px",background:this.options.color,opacity:".5"},f(o.el,e),"circle"===this.options.shape&&f(o.back,i),f(o.front,i),this.applyStyles(o),this},w.prototype.applyStyles=function(t){for(var i in this.ui)if(this.ui.hasOwnProperty(i))for(var e in t[i])this.ui[i].style[e]=t[i][e];return this},w.prototype.addToDom=function(){return this.options.dataOnly||document.body.contains(this.ui.el)?this:(this.options.zone.appendChild(this.ui.el),this)},w.prototype.removeFromDom=function(){return this.options.dataOnly||!document.body.contains(this.ui.el)?this:(this.options.zone.removeChild(this.ui.el),this)},w.prototype.destroy=function(){clearTimeout(this.removeTimeout),clearTimeout(this.showTimeout),clearTimeout(this.restTimeout),this.trigger("destroyed",this.instance),this.removeFromDom(),this.off()},w.prototype.show=function(t){var i=this;return i.options.dataOnly?i:(clearTimeout(i.removeTimeout),clearTimeout(i.showTimeout),clearTimeout(i.restTimeout),i.addToDom(),i.restCallback(),setTimeout(function(){i.ui.el.style.opacity=1},0),i.showTimeout=setTimeout(function(){i.trigger("shown",i.instance),"function"==typeof t&&t.call(this)},i.options.fadeTime),i)},w.prototype.hide=function(t){var i=this;return i.options.dataOnly?i:(i.ui.el.style.opacity=i.options.restOpacity,clearTimeout(i.removeTimeout),clearTimeout(i.showTimeout),clearTimeout(i.restTimeout),i.removeTimeout=setTimeout(function(){var e="dynamic"===i.options.mode?"none":"block";i.ui.el.style.display=e,"function"==typeof t&&t.call(i),i.trigger("hidden",i.instance)},i.options.fadeTime),i.options.restJoystick&&i.setPosition(t,{x:0,y:0}),i)},w.prototype.setPosition=function(t,i){var e=this;e.frontPosition={x:i.x,y:i.y};var o=e.options.fadeTime+"ms",n={};n.front=l("transition",["top","left"],o);var s={front:{}};s.front={left:e.frontPosition.x+"px",top:e.frontPosition.y+"px"},e.applyStyles(n),e.applyStyles(s),e.restTimeout=setTimeout(function(){"function"==typeof t&&t.call(e),e.restCallback()},e.options.fadeTime)},w.prototype.restCallback=function(){var t={};t.front=l("transition","none",""),this.applyStyles(t),this.trigger("rested",this.instance)},w.prototype.resetDirection=function(){this.direction={x:!1,y:!1,angle:!1}},w.prototype.computeDirection=function(t){var i,e,o,n=t.angle.radian,s=Math.PI/4,r=Math.PI/2;if(n>s&&n<3*s&&!t.lockX?i="up":n>-s&&n<=s&&!t.lockY?i="left":n>3*-s&&n<=-s&&!t.lockX?i="down":t.lockY||(i="right"),t.lockY||(e=n>-r&&n<r?"left":"right"),t.lockX||(o=n>0?"up":"down"),t.force>this.options.threshold){var d,a={};for(d in this.direction)this.direction.hasOwnProperty(d)&&(a[d]=this.direction[d]);var p={};for(d in this.direction={x:e,y:o,angle:i},t.direction=this.direction,a)a[d]===this.direction[d]&&(p[d]=!0);if(p.x&&p.y&&p.angle)return t;p.x&&p.y||this.trigger("plain",t),p.x||this.trigger("plain:"+e,t),p.y||this.trigger("plain:"+o,t),p.angle||this.trigger("dir dir:"+i,t)}else this.resetDirection();return t};var T=w;function k(t,i){return this.nipples=[],this.idles=[],this.actives=[],this.ids=[],this.pressureIntervals={},this.manager=t,this.id=k.id,k.id+=1,this.defaults={zone:document.body,multitouch:!1,maxNumberOfNipples:10,mode:"dynamic",position:{top:0,left:0},catchDistance:200,size:100,threshold:.1,color:"white",fadeTime:250,dataOnly:!1,restJoystick:!0,restOpacity:.5,lockX:!1,lockY:!1,shape:"circle",dynamicPage:!1},this.config(i),"static"!==this.options.mode&&"semi"!==this.options.mode||(this.options.multitouch=!1),this.options.multitouch||(this.options.maxNumberOfNipples=1),this.updateBox(),this.prepareNipples(),this.bindings(),this.begin(),this.nipples}k.prototype=new _,k.constructor=k,k.id=0,k.prototype.prepareNipples=function(){var t=this.nipples;t.on=this.on.bind(this),t.off=this.off.bind(this),t.options=this.options,t.destroy=this.destroy.bind(this),t.ids=this.ids,t.id=this.id,t.processOnMove=this.processOnMove.bind(this),t.processOnEnd=this.processOnEnd.bind(this),t.get=function(i){if(void 0===i)return t[0];for(var e=0,o=t.length;e<o;e+=1)if(t[e].identifier===i)return t[e];return!1}},k.prototype.bindings=function(){this.bindEvt(this.options.zone,"start"),this.options.zone.style.touchAction="none",this.options.zone.style.msTouchAction="none"},k.prototype.begin=function(){var t=this.options;if("static"===t.mode){var i=this.createNipple(t.position,this.manager.getIdentifier());i.add(),this.idles.push(i)}},k.prototype.createNipple=function(t,i){var e=c(),o={},n=this.options;if(t.x&&t.y)o={x:t.x-(e.x+this.box.left),y:t.y-(e.y+this.box.top)};else if(t.top||t.right||t.bottom||t.left){var s=document.createElement("DIV");s.style.display="hidden",s.style.top=t.top,s.style.right=t.right,s.style.bottom=t.bottom,s.style.left=t.left,s.style.position="absolute",n.zone.appendChild(s);var r=s.getBoundingClientRect();n.zone.removeChild(s),o=t,t={x:r.left+e.x,y:r.top+e.y}}var d=new T(this,{color:n.color,size:n.size,threshold:n.threshold,fadeTime:n.fadeTime,dataOnly:n.dataOnly,restJoystick:n.restJoystick,restOpacity:n.restOpacity,mode:n.mode,identifier:i,position:t,zone:n.zone,frontPosition:{x:0,y:0},shape:n.shape});return n.dataOnly||(h(d.ui.el,o),h(d.ui.front,d.frontPosition)),this.nipples.push(d),this.trigger("added "+d.identifier+":added",d),this.manager.trigger("added "+d.identifier+":added",d),this.bindNipple(d),d},k.prototype.updateBox=function(){this.box=this.options.zone.getBoundingClientRect()},k.prototype.bindNipple=function(t){var i,e=this,o=function(t,o){i=t.type+" "+o.id+":"+t.type,e.trigger(i,o)};t.on("destroyed",e.onDestroyed.bind(e)),t.on("shown hidden rested dir plain",o),t.on("dir:up dir:right dir:down dir:left",o),t.on("plain:up plain:right plain:down plain:left",o)},k.prototype.pressureFn=function(t,i,e){var o=this,n=0;clearInterval(o.pressureIntervals[e]),o.pressureIntervals[e]=setInterval(function(){var e=t.force||t.pressure||t.webkitForce||0;e!==n&&(i.trigger("pressure",e),o.trigger("pressure "+i.identifier+":pressure",e),n=e)}.bind(o),100)},k.prototype.onstart=function(t){var i=this,e=i.options,o=t;t=p(t),i.updateBox();return y(t,function(n){i.actives.length<e.maxNumberOfNipples?i.processOnStart(n):o.type.match(/^touch/)&&(Object.keys(i.manager.ids).forEach(function(e){if(Object.values(o.touches).findIndex(function(t){return t.identifier===e})<0){var n=[t[0]];n.identifier=e,i.processOnEnd(n)}}),i.actives.length<e.maxNumberOfNipples&&i.processOnStart(n))}),i.manager.bindDocument(),!1},k.prototype.processOnStart=function(t){var i,e=this,o=e.options,s=e.manager.getIdentifier(t),r=t.force||t.pressure||t.webkitForce||0,d={x:t.pageX,y:t.pageY},a=e.getOrCreate(s,d);a.identifier!==s&&e.manager.removeIdentifier(a.identifier),a.identifier=s;var p=function(i){i.trigger("start",i),e.trigger("start "+i.id+":start",i),i.show(),r>0&&e.pressureFn(t,i,i.identifier),e.processOnMove(t)};if((i=e.idles.indexOf(a))>=0&&e.idles.splice(i,1),e.actives.push(a),e.ids.push(a.identifier),"semi"!==o.mode)p(a);else{if(!(n(d,a.position)<=o.catchDistance))return a.destroy(),void e.processOnStart(t);p(a)}return a},k.prototype.getOrCreate=function(t,i){var e,o=this.options;return/(semi|static)/.test(o.mode)?(e=this.idles[0])?(this.idles.splice(0,1),e):"semi"===o.mode?this.createNipple(i,t):(console.warn("Coudln't find the needed nipple."),!1):e=this.createNipple(i,t)},k.prototype.processOnMove=function(t){var i=this.options,e=this.manager.getIdentifier(t),o=this.nipples.get(e);if(function(t){return isNaN(t.buttons)?0!==t.pressure:0!==t.buttons}(t)){if(!o)return console.error("Found zombie joystick with ID "+e),void this.manager.removeIdentifier(e);if(i.dynamicPage){var d=c();p=o.el.getBoundingClientRect(),o.position={x:d.x+p.left,y:d.y+p.top}}o.identifier=e;var a=o.options.size/2,p={x:t.pageX,y:t.pageY};i.lockX&&(p.y=o.position.y),i.lockY&&(p.x=o.position.x);var l,u,f,y,m,v,g,b,x=n(p,o.position),O=(l=p,u=o.position,f=u.x-l.x,y=u.y-l.y,r(Math.atan2(y,f))),_=s(O),w=x/a,T={distance:x,position:p};"circle"===o.options.shape?(x=Math.min(x,a),m=o.position,v=x,b={x:0,y:0},g=s(g=O),b.x=m.x-v*Math.cos(g),b.y=m.y-v*Math.sin(g),p=b):(p=function(t,i,e){return{x:Math.min(Math.max(t.x,i.x-e),i.x+e),y:Math.min(Math.max(t.y,i.y-e),i.y+e)}}(p,o.position,a),x=n(p,o.position));var k=p.x-o.position.x,P=p.y-o.position.y;o.frontPosition={x:k,y:P},i.dataOnly||h(o.ui.front,o.frontPosition);var E={identifier:o.identifier,position:p,force:w,pressure:t.force||t.pressure||t.webkitForce||0,distance:x,angle:{radian:_,degree:O},vector:{x:k/a,y:-P/a},raw:T,instance:o,lockX:i.lockX,lockY:i.lockY};(E=o.computeDirection(E)).angle={radian:s(180-O),degree:180-O},o.trigger("move",E),this.trigger("move "+o.id+":move",E)}else this.processOnEnd(t)},k.prototype.processOnEnd=function(t){var i=this,e=i.options,o=i.manager.getIdentifier(t),n=i.nipples.get(o),s=i.manager.removeIdentifier(n.identifier);n&&(e.dataOnly||n.hide(function(){"dynamic"===e.mode&&(n.trigger("removed",n),i.trigger("removed "+n.id+":removed",n),i.manager.trigger("removed "+n.id+":removed",n),n.destroy())}),clearInterval(i.pressureIntervals[n.identifier]),n.resetDirection(),n.trigger("end",n),i.trigger("end "+n.id+":end",n),i.ids.indexOf(n.identifier)>=0&&i.ids.splice(i.ids.indexOf(n.identifier),1),i.actives.indexOf(n)>=0&&i.actives.splice(i.actives.indexOf(n),1),/(semi|static)/.test(e.mode)?i.idles.push(n):i.nipples.indexOf(n)>=0&&i.nipples.splice(i.nipples.indexOf(n),1),i.manager.unbindDocument(),/(semi|static)/.test(e.mode)&&(i.manager.ids[s.id]=s.identifier))},k.prototype.onDestroyed=function(t,i){this.nipples.indexOf(i)>=0&&this.nipples.splice(this.nipples.indexOf(i),1),this.actives.indexOf(i)>=0&&this.actives.splice(this.actives.indexOf(i),1),this.idles.indexOf(i)>=0&&this.idles.splice(this.idles.indexOf(i),1),this.ids.indexOf(i.identifier)>=0&&this.ids.splice(this.ids.indexOf(i.identifier),1),this.manager.removeIdentifier(i.identifier),this.manager.unbindDocument()},k.prototype.destroy=function(){for(var t in this.unbindEvt(this.options.zone,"start"),this.nipples.forEach(function(t){t.destroy()}),this.pressureIntervals)this.pressureIntervals.hasOwnProperty(t)&&clearInterval(this.pressureIntervals[t]);this.trigger("destroyed",this.nipples),this.manager.unbindDocument(),this.off()};var P=k;function E(t){var i,e=this;return e.ids={},e.index=0,e.collections=[],e.config(t),e.prepareCollections(),d(window,"resize",function(t){clearTimeout(i),i=setTimeout(function(){var t,i=c();e.collections.forEach(function(e){e.forEach(function(e){t=e.el.getBoundingClientRect(),e.position={x:i.x+t.left,y:i.y+t.top}})})},100)}),e.collections}E.prototype=new _,E.constructor=E,E.prototype.prepareCollections=function(){var t=this;t.collections.create=t.create.bind(t),t.collections.on=t.on.bind(t),t.collections.off=t.off.bind(t),t.collections.destroy=t.destroy.bind(t),t.collections.get=function(i){var e;return t.collections.every(function(t){return!(e=t.get(i))}),e}},E.prototype.create=function(t){return this.createCollection(t)},E.prototype.createCollection=function(t){var i=new P(this,t);return this.bindCollection(i),this.collections.push(i),i},E.prototype.bindCollection=function(t){var i,e=this,o=function(t,o){i=t.type+" "+o.id+":"+t.type,e.trigger(i,o)};t.on("destroyed",e.onDestroyed.bind(e)),t.on("shown hidden rested dir plain",o),t.on("dir:up dir:right dir:down dir:left",o),t.on("plain:up plain:right plain:down plain:left",o)},E.prototype.bindDocument=function(){this.binded||(this.bindEvt(document,"move").bindEvt(document,"end"),this.binded=!0)},E.prototype.unbindDocument=function(t){Object.keys(this.ids).length&&!0!==t||(this.unbindEvt(document,"move").unbindEvt(document,"end"),this.binded=!1)},E.prototype.getIdentifier=function(t){var i;return t?void 0===(i=void 0===t.identifier?t.pointerId:t.identifier)&&(i=this.latest||0):i=this.index,void 0===this.ids[i]&&(this.ids[i]=this.index,this.index+=1),this.latest=i,this.ids[i]},E.prototype.removeIdentifier=function(t){var i={};for(var e in this.ids)if(this.ids[e]===t){i.id=e,i.identifier=this.ids[e],delete this.ids[e];break}return i},E.prototype.onmove=function(t){return this.onAny("move",t),!1},E.prototype.onend=function(t){return this.onAny("end",t),!1},E.prototype.oncancel=function(t){return this.onAny("end",t),!1},E.prototype.onAny=function(t,i){var e,o=this,n="processOn"+t.charAt(0).toUpperCase()+t.slice(1);i=p(i);return y(i,function(t){e=o.getIdentifier(t),y(o.collections,function(t,i,e){e.ids.indexOf(i)>=0&&(e[n](t),t._found_=!0)}.bind(null,t,e)),t._found_||o.removeIdentifier(e)}),!1},E.prototype.destroy=function(){this.unbindDocument(!0),this.ids={},this.index=0,this.collections.forEach(function(t){t.destroy()}),this.off()},E.prototype.onDestroyed=function(t,i){if(this.collections.indexOf(i)<0)return!1;this.collections.splice(this.collections.indexOf(i),1)};var I=new E;i.default={create:function(t){return I.create(t)},factory:I}}]).default});
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 838b4a7..b57141c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,11 @@ "@types/node": "8.10.40", "@types/web-bluetooth": "~0.0.5" } + }, + "nipplejs": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/nipplejs/-/nipplejs-0.8.7.tgz", + "integrity": "sha512-B3uSKnWIGWHfrd6oDpLW1xiYleY8+ACVIlLNZeVChBBGDeDiKm4YjetVxlP3O2FvS3Fqf24E/9FrjM3Thc6WDg==" } } } diff --git a/package.json b/package.json index ba07630..ceaf86d 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "microbit-web-bluetooth": "^0.6.0" + "microbit-web-bluetooth": "^0.6.0", + "nipplejs": "^0.8.7" } } @@ -1,11 +1,8 @@ +/* Register service worker */ if (navigator.serviceWorker) { navigator.serviceWorker.register('/hoverbit-ble/sw.js', {scope: '/hoverbit-ble/'}); } -let StickyControls = false; -let throttleElement = document.querySelector(".throttle"); -let rudderElement = document.querySelector(".rudder"); - const hoverControlModule = () => { let _throttle = 0; let _throttleAcc = 0; @@ -19,11 +16,9 @@ const hoverControlModule = () => { switch (item.substring(0, 1)) { case "T": _throttleAcc = parseInt(item.substring(1, item.length)); - document.querySelector(".throttle-indicator").style["bottom"] = _throttleAcc + "%"; break; case "R": _rudderAcc = parseInt(item.substring(1, item.length)); - document.querySelector(".rudder-indicator").style.left = (((_rudderAcc+90) * (100)) / (180)) + "%"; break; case "A": _armAcc = parseInt(item.substring(1, item.length)) == 1; @@ -39,6 +34,7 @@ const hoverControlModule = () => { console.log(`Unkown acc: ${item}`); } }); + document.querySelector(".acc-string pre").innerHTML = `T: ${_throttleAcc}, R: ${_rudderAcc}`; } const reset = () => { @@ -52,8 +48,6 @@ const hoverControlModule = () => { if (throttle > 100) { throttle = 100; } if (throttle < 0) { throttle = 0; } _throttle = throttle; - - document.querySelector(".throttle-thumb").style.height = throttle + "%"; } const getThrottle = () => _throttle; @@ -62,15 +56,6 @@ const hoverControlModule = () => { if (rudder > 90) { rudder = 90; } if (rudder < -90) { rudder = -90; } _rudder = rudder; - - let rudderThumb = document.querySelector(".rudder-thumb"); - rudderThumb.style.width = ((Math.abs(_rudder) / (90 / 50))) + "%"; - if (_rudder > 0) { - rudderThumb.style.backgroundColor = "yellow"; - } else { - rudderThumb.style.backgroundColor = "red"; - rudderThumb.style.left = (50 - ((Math.abs(_rudder) / (90 / 50)))) + "%"; - } } const getRudder = () => _rudder; @@ -94,93 +79,43 @@ const hoverControlModule = () => { getArm }; } -let hoverControl = hoverControlModule(); - -window.onload = () => { - addEventListener("touchstart", (touch) => { - addEventListener("touchmove", (touch => { - console.log(touch); - }), true); - }, false); - - // throttleElement.addEventListener('mousedown', on_pointer_hold_throttle,false); - // document.body.addEventListener('mouseup', on_pointer_release_throttle, false); - // - // throttleElement.addEventListener('touchstart', on_pointer_hold_throttle,false); - // document.body.addEventListener('touchend', on_pointer_release_throttle, false); - // - // rudderElement.addEventListener('mousedown', on_pointer_hold_rudder,false); - // document.body.addEventListener('mouseup', on_pointer_release_rudder, false); - // - // rudderElement.addEventListener('touchstart', on_pointer_hold_rudder,false); - // document.body.addEventListener('touchend', on_pointer_release_rudder, false); -}; - -function on_pointer_hold_throttle() { - throttleElement.addEventListener('mousemove',(on_mouse_move_throttle),true); - document.body.addEventListener('mousemove',on_mouse_move_throttle,true); - - throttleElement.addEventListener('touchmove',on_touch_move_throttle,true); - document.body.addEventListener('touchmove',on_touch_move_throttle,true); -} - -function on_mouse_move_throttle(event) { - let throttle = Math.round(100 - (event.clientY) / (throttleElement.clientHeight / 100)); - hoverControl.setThrottle(throttle); -} - -function on_touch_move_throttle(touch) { - let throttle = Math.round(100 - (touch.touches[0].clientY) / (throttleElement.clientHeight / 100)); - hoverControl.setThrottle(throttle); -} - -function on_pointer_release_throttle() { - throttleElement.removeEventListener('mousemove',on_mouse_move_throttle,true); - document.body.removeEventListener('mousemove',on_mouse_move_throttle,true); - - throttleElement.removeEventListener('touchmove',on_touch_move_throttle,true); - document.body.removeEventListener('touchmove',on_touch_move_throttle,true); - - if (!StickyControls) { - hoverControl.setThrottle(0); - } -} - -function on_pointer_hold_rudder() { - rudderElement.addEventListener('mousemove',on_mouse_move_rudder,true); - document.body.addEventListener('mousemove',on_mouse_move_rudder,true); - rudderElement.addEventListener('touchmove',on_touch_move_rudder,true); - document.body.addEventListener('touchmove',on_touch_move_rudder,true); -} - -function on_mouse_move_rudder(event) { - let rudder = Math.round(((event.clientX * (90 - (-90))) / (rudderElement.clientWidth)) + (-90)); - hoverControl.setRudder(rudder); -} +/* Define and initialize things */ +let hoverControl = hoverControlModule(); +let joystickLeft = nipplejs.create({ + zone: document.querySelector(".joystick-left"), + size: 200, + position: {left: '50%', bottom: '50%'}, + mode: "static", + lockX: true +}); +let joystickRight = nipplejs.create({ + zone: document.querySelector(".joystick-right"), + size: 200, + position: {left: '50%', bottom: '50%'}, + mode: "static", + lockY: true +}); +let bDev; -function on_touch_move_rudder(touch) { - let rudder = Math.round(((touch.touches[0].clientX * (90 - (-90))) / (rudderElement.clientWidth)) + (-90)); +/* Setup event_listeners */ +joystickLeft.on("move", (evt, data) => { + rudder = ((data.distance * 90) / 100); + if (data.angle.degree > 90) { rudder = rudder * -1; } hoverControl.setRudder(rudder); -} - -function on_pointer_release_rudder() { - rudderElement.removeEventListener('mousemove',on_mouse_move_rudder,true); - document.body.removeEventListener('mousemove',on_mouse_move_rudder,true); - - rudderElement.removeEventListener('touchmove',on_touch_move_rudder,true); - document.body.removeEventListener('touchmove',on_touch_move_rudder,true); - - if (!StickyControls) { - hoverControl.setRudder(0); - } -} +}); +joystickLeft.on("end", (evt, data) => { + hoverControl.setRudder(0); +}); -const logEl = document.getElementById("logEl"); -const log = (message) => logEl.innerHTML = `${message}\n${logEl.innerHTML}`; -const logJson = (message) => log(JSON.stringify(message, null, 2)); -const eventHandler = event => log(`${event.type}: ${JSON.stringify(event.detail, null, 2)}`); -let bDev; +joystickRight.on("move", (evt, data) => { + throttle = data.distance; + if (data.angle.degree > 90) { throttle = 0; } + hoverControl.setThrottle(throttle); +}); +joystickRight.on("end", (evt, data) => { + hoverControl.setThrottle(0); +}); document.getElementById("btn_arm").addEventListener("click", () => { hoverControl.setArm(true); @@ -190,17 +125,6 @@ document.getElementById("btn_disarm").addEventListener("click", () => { hoverControl.setArm(false); }); -document.getElementById("btn_sticky").addEventListener("click", () => { - StickyControls = !StickyControls; - if (StickyControls) { - document.getElementById("btn_sticky").style.backgroundColor = "green"; - } else { - hoverControl.setThrottle(0); - hoverControl.setRudder(0); - document.getElementById("btn_sticky").style.backgroundColor = null; - } -}); - document.getElementById("btn_connect").onclick = async () => { const device = await microbit.requestMicrobit(window.navigator.bluetooth); bDev = device; @@ -209,12 +133,10 @@ document.getElementById("btn_connect").onclick = async () => { if (device) { if (device.gatt.connected) { document.body.classList.add("connected"); - // document.querySelector(".connection-status").innerHTML = "CONNECTED"; } else { hoverControl.reset(); document.body.classList.remove("connected"); document.body.classList.remove("armed"); - // document.querySelector(".connection-status").innerHTML = "DISCONNECTED"; // clearInterval(connCheckInterval); device.gatt.disconnect(); } @@ -230,10 +152,7 @@ document.getElementById("btn_connect").onclick = async () => { const services = await microbit.getServices(device); document.querySelector("#btn_disconnect").addEventListener("click", () => { - hoverControl.setArm(0); - hoverControl.setThrottle(0); - hoverControl.setRudder(0); - + hoverControl.reset(); device.gatt.disconnect(); }); @@ -10,25 +10,50 @@ html, body { body { margin: 10px; + background-color: #454545; + color: white; } -.info h1 { +h1 { + font-size: 10px; margin: 0; + color: #9c9c9c; } -.info-device { - margin: 0; +.statusline-bottom { + position: absolute; display: flex; + bottom: 0; + left: 0; + height: 30px; + /* padding-left: 5px; */ + width: calc(100%); + font-size: 12px; + margin: 0; align-items: center; + + background-color: #333333; +} + +.statusline-bottom i { + font-size: 12px; +} + +.statusline-item { + display: none; + align-items: flex-start; + margin-left: 5px; + margin-right: 5px; + + color: #b5b5b5; } -.info-device i { - font-size: 18px; +.connected .statusline-item { + display: flex; } .connection { display: flex; - align-items: flex-start; color: #c32222; } @@ -50,23 +75,8 @@ body { text-transform: uppercase; } -.battery { - display: none; - margin-left: 5px; - /* display: flex; */ - align-items: start; - color: #4a4a4a; -} - -.connected .battery { - display: flex; -} - .arm { - display: none; margin-left: 5px; - /* display: flex; */ - align-items: start; color: #c32222; } @@ -80,22 +90,12 @@ body { display: block; } -.connected .arm { - display: flex; -} - .armed .arm { color: #008000; } .ping { - display: none; -} - -.connected .ping { - display: block; - margin-left: 5px; - color: #4a4a4a; + margin-left: auto; } .ping i { @@ -110,125 +110,70 @@ body { 100% { opacity: 0; } } -.options { - position: absolute; - display: flex; - bottom: 60px; - right: 60px; - flex-direction:column-reverse; -} - -.options button { +.acc-string { display: none; - margin-top: 5px; - border: 1px solid black; - background-color: #b5b5b5; - padding: 10px; - width: 120px; + position: absolute; + top: 60px; + left: calc(50% - 50px - 10px); + width: 100px; + text-align: center; + background-color: #272727; + padding: 0 10px; + border-radius: 10px; + font-size: 9px; } -.armed .options button { +.connected .acc-string { display: block; } -#btn_connect { display: block; } -.connected #btn_connect { display: none; } -.connected #btn_disconnect { display: block; } -.connected #btn_arm { display: block; } -.armed #btn_arm { display: none; } - -.throttle { - position: absolute; - top: 10px; - right: 10px; - width: 40px; - height: calc(100% - 70px); - - margin: 0; - background-color: #b5b5b5; - border: 1px solid black; -} - -.throttle-thumb { - width: 40px; - height: 1%; +button { position: absolute; - bottom: 0; - background-color: green; + display: none; + margin-top: 5px; + border: none; + background-color: #333333; + color: #c3c3c3; + padding: 10px; + width: 120px; } -.throttle-indicator { - position: absolute; - width: 40px; - height: 0px; - bottom: 0; - /* border: 4px solid black; */ +.armed button { + display: block; } -.throttle-indicator:before { - content: " "; - background-color: black; - width: 20px; - height: 1px; - position: absolute; - left: 0; +.button-center { + left: calc(50% - 60px); } -.throttle-indicator:after { - content: " "; - background-color: black; - width: 20px; - height: 1px; - position: absolute; - right: 0; +.button-center-bottom { + bottom: 40px; } -.rudder { - position: absolute; - bottom: 10px; - left: 10px; - width: calc(100% - 70px); - height: 40px; - margin: 0; - background-color: #b5b5b5; - border: 1px solid black; +.button-center-top { + top: 10px; } -.rudder-labels { - position: absolute; -} +#btn_connect { display: block; } +.connected #btn_connect { display: none; } +.connected #btn_disconnect { display: block; } +.connected #btn_arm { display: block; } +.armed #btn_arm { display: none; } -.rudder-thumb { - position: absolute; - bottom: 0; - left: 50%; - height: 40px; - background-color: yellow; -} -.rudder-indicator { +.joystick { position: absolute; - width: 0px; - height: 40px; - left: 50%; - bottom: 0; + width: 200px; + height: 200px; + top: calc(50% - 100px - 10px); /* 50% - half height - statusline height */ + /* border: 1px solid pink; */ } -.rudder-indicator:before { - content: " "; - background-color: black; - width: 1px; - height: 20px; - position: absolute; - top: 0; +.joystick-left { + left: calc(25% - 100px); } -.rudder-indicator:after { - content: " "; - background-color: black; - width: 1px; - height: 20px; - position: absolute; - bottom: 0; +.joystick-right { + left: calc(75% - 100px); } |