-
Notifications
You must be signed in to change notification settings - Fork 1.3k
spotrem: add volume knob gesture #3847
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
597a47e
5f91cf8
2966051
8a78873
09ee996
0b693cd
3df424b
915546d
732c633
7be4771
068675e
0696b12
d99f528
be7c1de
4d8ff49
9af1e6a
e7b0af4
656294b
0d7fb84
9445bf4
807add0
08e23d8
b4bcc6f
15ceb23
5ed691b
d5f5b22
ea1a716
cb82231
9adab33
902bbf8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
function Dial(cb, options) { | ||
"ram"; | ||
const SCREEN_W = g.getWidth(); | ||
const SCREEN_H = g.getHeight(); | ||
|
||
options = Object.assign( | ||
{ stepsPerWholeTurn : 7, // 7 chosen as it felt the best in use. | ||
dialRect : { | ||
x: 0, | ||
y: 0, | ||
w: SCREEN_W, | ||
h: SCREEN_H, | ||
}, | ||
}, options); | ||
|
||
const DIAL_RECT = options.dialRect; | ||
|
||
const CENTER = { | ||
x: DIAL_RECT.x + DIAL_RECT.w / 2, | ||
y: DIAL_RECT.y + DIAL_RECT.h / 2, | ||
}; | ||
|
||
const BASE_SCREEN_W = 176; | ||
const STEPS_PER_TURN = options.stepsPerWholeTurn; | ||
const BASE_THRESHOLD = 50; | ||
const THRESHOLD = | ||
BASE_THRESHOLD * | ||
(10 / STEPS_PER_TURN) * | ||
(DIAL_RECT.w / BASE_SCREEN_W); | ||
|
||
let cumulative = 0; | ||
|
||
function onDrag(e) { | ||
"ram"; | ||
|
||
if ( | ||
e.x < DIAL_RECT.x || | ||
e.x > DIAL_RECT.x+DIAL_RECT.w-1 || | ||
e.y < DIAL_RECT.y || | ||
e.y > DIAL_RECT.y+DIAL_RECT.h-1 | ||
) { | ||
return; | ||
} | ||
|
||
if (e.y < CENTER.y) { | ||
cumulative += e.dx; | ||
} else { | ||
cumulative -= e.dx; | ||
} | ||
|
||
if (e.x < CENTER.x) { | ||
cumulative -= e.dy; | ||
} else { | ||
cumulative += e.dy; | ||
} | ||
|
||
function stepHandler(step) { | ||
cumulative -= THRESHOLD * step; | ||
cb(step); | ||
} | ||
|
||
while (cumulative > THRESHOLD) { | ||
stepHandler(1); | ||
} | ||
while (cumulative < -THRESHOLD) { | ||
stepHandler(-1); | ||
} | ||
|
||
E.stopEventPropagation(); | ||
} | ||
|
||
return onDrag; | ||
} | ||
|
||
exports = Dial; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
Bangle.js Dial Library | ||
====================== | ||
|
||
> Take a look at README.md for hints on developing with this library. | ||
|
||
Usage | ||
----- | ||
|
||
```JS | ||
var Dial = require("Dial"); | ||
var dial = new Dial(cb, options) | ||
Bangle.on("drag", dial); | ||
|
||
or | ||
|
||
var dial = require("Dial")(cb, options); | ||
Bangle.on("drag", dial); | ||
``` | ||
|
||
For example: | ||
|
||
```JS | ||
let cb = (plusOrMinusOne)=>{print(plusOrMinusOne)}; | ||
let options = { | ||
stepsPerWholeTurn : 6, | ||
dialRect : { | ||
x: 0, | ||
y: 0, | ||
w: g.getWidth()/2, | ||
h: g.getHeight()/2, | ||
} | ||
} | ||
|
||
let dial = require("Dial")(cb, options); | ||
Bangle.on("drag", dial); | ||
``` | ||
|
||
`cb` (first argument) is a callback function that should expect either `+1` or `-1` as argument when called. | ||
|
||
`options` (second argument) (optional) is an object containing: | ||
|
||
`stepsPerWholeTurn` - how many steps there are in one complete turn of the dial. | ||
`dialRect` - decides the area of the screen the dial is set up on. | ||
|
||
Defaults: | ||
```js | ||
{ stepsPerWholeTurn : 7 | ||
dialRect : { | ||
x: 0, | ||
y: 0, | ||
w: g.getWidth(), | ||
h: g.getHeight(), | ||
}, | ||
} | ||
``` | ||
|
||
Notes | ||
----- | ||
|
||
A complementary library for drawing graphics is provided in the Dial_Display module. |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,59 @@ | ||||||||||
let dialDisplayGenerator = function(options) { | ||||||||||
"ram"; | ||||||||||
const SCREEN_W = g.getWidth(); | ||||||||||
const SCREEN_H = g.getHeight(); | ||||||||||
|
||||||||||
options = Object.assign( | ||||||||||
{ stepsPerWholeTurn : 7, // 7 chosen as it felt the best in use. | ||||||||||
dialRect : { | ||||||||||
x: 0, | ||||||||||
y: 0, | ||||||||||
w: SCREEN_W, | ||||||||||
h: SCREEN_H, | ||||||||||
}, | ||||||||||
}, options); | ||||||||||
|
||||||||||
const DIAL_RECT = options.dialRect; | ||||||||||
|
||||||||||
const CENTER = { | ||||||||||
x: DIAL_RECT.x + DIAL_RECT.w / 2, | ||||||||||
y: DIAL_RECT.y + DIAL_RECT.h / 2, | ||||||||||
}; | ||||||||||
|
||||||||||
let dialDisplay = function(step, value, isReinit) { | ||||||||||
let prevValue = this.value; | ||||||||||
if (value!==undefined) this.value = value; | ||||||||||
if (!this.value) this.value = 0; | ||||||||||
if (this.isFirstDraw===undefined || isReinit) this.isFirstDraw = true; | ||||||||||
this.value += step; | ||||||||||
//g.setFont("Vector:30"); | ||||||||||
//g.drawString(this.value); | ||||||||||
|
||||||||||
let drawCircle = (value, R, G, B, rad, isFill)=>{ | ||||||||||
let x = CENTER.x+27*Math.sin(value*(2*Math.PI/options.stepsPerWholeTurn)); | ||||||||||
let y = CENTER.y-27*Math.cos(value*(2*Math.PI/options.stepsPerWholeTurn)); | ||||||||||
g.setColor(R,G,B) | ||||||||||
if (!isFill) g.drawCircle(x, y, rad); | ||||||||||
if (isFill) g.fillCircle(x, y, rad); | ||||||||||
Comment on lines
+36
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole |
||||||||||
} | ||||||||||
if (this.isFirstDraw) { | ||||||||||
g.setColor(0,0,0).fillCircle(CENTER.x, CENTER.y, 25); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the radii for the drawing operations should not be hardcoded to 25, 23, 9 etc but depend on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe adding a additional There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think this is ok for now but we could have a follow-up PR which infers a radius from the rect? Or like you say, adds a setting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, lets leave it as is for now :) |
||||||||||
g.setColor(1,1,1).drawCircle(CENTER.x, CENTER.y, 25); | ||||||||||
for (let i=0; i<options.stepsPerWholeTurn; i++) { | ||||||||||
drawCircle(i, 1, 1, 1, 1, true); | ||||||||||
} | ||||||||||
this.isFirstDraw = false; | ||||||||||
} | ||||||||||
|
||||||||||
//drawCircle(this.value, 1, 1, 1, 2, false); | ||||||||||
//drawCircle(prevValue, 0, 0, 0, 2, false); | ||||||||||
g.setColor(0,0,0).drawLine(CENTER.x, CENTER.y, CENTER.x+23*Math.sin(prevValue*(2*Math.PI/options.stepsPerWholeTurn)), CENTER.y-23*Math.cos(prevValue*(2*Math.PI/options.stepsPerWholeTurn))); | ||||||||||
g.setColor(1,1,1).drawLine(CENTER.x, CENTER.y, CENTER.x+23*Math.sin(this.value*(2*Math.PI/options.stepsPerWholeTurn)), CENTER.y-23*Math.cos(this.value*(2*Math.PI/options.stepsPerWholeTurn))); | ||||||||||
g.setColor(0,0,0).fillCircle(CENTER.x, CENTER.y, 9); | ||||||||||
|
||||||||||
return this.value; | ||||||||||
} | ||||||||||
return dialDisplay; | ||||||||||
} | ||||||||||
|
||||||||||
exports = dialDisplayGenerator; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
Bangle.js Dial Display Library | ||
====================== | ||
|
||
|
||
> Take a look at README.md for hints on developing with this library. | ||
|
||
Usage | ||
----- | ||
|
||
```JS | ||
var DialDisplay = require("Dial_Display"); | ||
var dialDisplay = new DialDisplay(options); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same again (as the other comment), but here I think we'll want to change to make it more class-like, or alter how For example, in the IDE: > cb
=function (step) { ... }
>cb(1)
=undefined
>cb(1)
=undefined
// the dial renders successfully
// `this` variables are written to the global:
>isFirstDraw
=false
>value
=14 Happy to go through a few suggestions for it, if you like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Please do! Fun with a learning opportunity :) Feel free to commit to this PR. |
||
var value = dialDisplay(-1, 0, true) | ||
``` | ||
|
||
For example in use with the Dial module: | ||
|
||
```JS | ||
var options = { | ||
stepsPerWholeTurn : 6, | ||
dialRect : { | ||
x: 0, | ||
y: 0, | ||
w: g.getWidth()/2, | ||
h: g.getHeight()/2, | ||
} | ||
} | ||
|
||
var DialDisplay = require("Dial_Display"); | ||
var dialDisplay = new DialDisplay(options); | ||
|
||
var cb = (step)=>{ | ||
var value = dialDisplay(step, undefined, true); | ||
}; | ||
|
||
var Dial = require("Dial"); | ||
var dial = new Dial(cb, options) | ||
Bangle.on("drag", dial); | ||
``` | ||
|
||
`options` (first argument) (optional) is an object containing: | ||
|
||
`stepsPerWholeTurn` - how many steps there are in one complete turn of the dial. | ||
`dialRect` - decides the area of the screen the dial is set up on. | ||
|
||
Defaults: | ||
```js | ||
{ stepsPerWholeTurn : 7 | ||
dialRect : { | ||
x: 0, | ||
y: 0, | ||
w: g.getWidth(), | ||
h: g.getHeight(), | ||
}, | ||
} | ||
``` | ||
|
||
The generated function takes three arguments: | ||
`step` - +1 or -1 | ||
`value` - the previous value the step acts on. | ||
`isReinit` - true/false, whether to draw all of the dial or just the indicator. | ||
|
||
Notes: | ||
====== | ||
- It would be nice to choose what colors are used. Something for the future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use
Dial
here as a constructor (nothis
and it returns an object explicitly) so thenew
(while it works) might confuse users. What about:(suggested lowercase
dial
as it's no longer a class too, don't mind if you prefer it Titlecase though)Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - if that makes more sense I'm all for it.
I looked at the Layout module for inspiration when developing
and taking a quick look now I fail to see how they differ in this regard. Out of interest, do they?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I think I get what you mean now!