Bangle.js 2: Color wheel

Posted on
Page
of 2
/ 2
Next
  • In the last few days, the thread Graphics Color questions has been hijacked for several small example programs related to several..."graphics color questions".

    In order to simplify finding more specific solutions, I've started a new thread for the following example, namely:

    a small color wheel using colors with "full" (0 and 1) and "half" (0.5) values

      let ColorList = [
        '#0000FF', '#8000FF', '#FF00FF', '#FF0080', '#FF0000', '#FF8000',
        '#FFFF00', '#80FF00', '#00FF00', '#00FF80', '#00FFFF', '#0080FF'
      ];
    
      let ScreenWidth  = g.getWidth(),  CenterX = ScreenWidth/2;
      let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
      
      let outerRadius = Math.min(CenterX,CenterY) * 0.9;
      let innerRadius = outerRadius*0.5;
      
      let sin = Math.sin, cos = Math.cos;
      let twoPi = 2*Math.PI;
      
      let DeltaPhi = twoPi/72;
      let Epsilon  = 0.001;
    
      g.clear();
      
      g.setColor(0,0,0);
      g.fillRect(0,0, ScreenWidth,ScreenHeight);
    
      for (let i = 0; i < 12; i++) {
        let Phi0 = i * twoPi/12, Phi1 = (i+1) * twoPi/12;
        
        let Polygon = [];
          for (let Phi = Phi0; Phi <= Phi1+Epsilon; Phi += DeltaPhi) {
            Polygon.push(CenterX + outerRadius * sin(Phi));
            Polygon.push(CenterY - outerRadius * cos(Phi));
          }
        
          for (let Phi = Phi1; Phi >= Phi0-Epsilon; Phi -= DeltaPhi) {
            Polygon.push(CenterX + innerRadius * sin(Phi));
            Polygon.push(CenterY - innerRadius * cos(Phi));
          }
        g.setColor(ColorList[i]);
        g.fillPoly(Polygon);
      }
    

    Hopefully it will help you finding proper good-looking colors


    1 Attachment

    • BangleJS2-ColorWheel.png
  • ...and here is the same in a touchable version:

    //--------------------------------------­--------------------------------------//­
    //--          ColorWheel - draws a "wheel" of good looking colors           --//
    //--------------------------------------­--------------------------------------//­
    
      let ColorList = [
        '#0000FF', '#8000FF', '#FF00FF', '#FF0080', '#FF0000', '#FF8000',
        '#FFFF00', '#80FF00', '#00FF00', '#00FF80', '#00FFFF', '#0080FF'
      ];
    
      let ScreenWidth  = g.getWidth(),  CenterX = ScreenWidth/2;
      let ScreenHeight = g.getHeight(), CenterY = ScreenHeight/2;
    
      let outerRadius = Math.min(CenterX,CenterY) * 0.9;
      let innerRadius = outerRadius*0.5;
    
      let sin = Math.sin, cos = Math.cos;
      let twoPi = 2*Math.PI, halfPi = Math.PI/2;
    
      let DeltaPhi = twoPi/72;
      let Epsilon  = 0.001;
    
      g.clear();
    
      g.setColor(0,0,0);
      g.fillRect(0,0, ScreenWidth,ScreenHeight);
    
      for (let i = 0; i < 12; i++) {
        let Phi0 = i * twoPi/12, Phi1 = (i+1) * twoPi/12;
    
        let Polygon = [];
          for (let Phi = Phi0; Phi <= Phi1+Epsilon; Phi += DeltaPhi) {
            Polygon.push(CenterX + outerRadius * sin(Phi));
            Polygon.push(CenterY - outerRadius * cos(Phi));
          }
    
          for (let Phi = Phi1; Phi >= Phi0-Epsilon; Phi -= DeltaPhi) {
            Polygon.push(CenterX + innerRadius * sin(Phi));
            Polygon.push(CenterY - innerRadius * cos(Phi));
          }
        g.setColor(ColorList[i]);
        g.fillPoly(Polygon);
      }
    
      g.setColor(1,1,1);
      g.fillCircle(CenterX,CenterY, innerRadius);
    
      g.setFont12x20();
      g.setFontAlign(0,0);
      g.setColor(0,0,0);
    
      g.drawString('Tap',   CenterX,CenterY-20);
      g.drawString('on',    CenterX,CenterY);
      g.drawString('Color', CenterX,CenterY+20);
    
      Bangle.on('touch', function (Button,Position) {
        Bangle.buzz();
    
        let dx = Position.x - CenterX;
        let dy = Position.y - CenterY;
    
        let Radius = Math.sqrt(dx*dx + dy*dy);
    
        let Color;
          switch (true) {
            case (Radius > outerRadius): Color = '#000000'; break;
            case (Radius < innerRadius): Color = '#FFFFFF'; break;
            default:
              let Phi = Math.atan2(dy,dx) + halfPi;
              if (Phi < 0)     { Phi += twoPi; }
              if (Phi > twoPi) { Phi -= twoPi; }
    
              let Index = Math.floor(12*Phi/twoPi);
              Color = ColorList[Index];
          }
        g.setColor(1,1,1);
        g.fillCircle(CenterX,CenterY, innerRadius);
    
        g.setColor(0,0,0);
        g.drawString(Color, CenterX,CenterY);
      });
    

    2 Attachments

    • BangleJS2-ColorWheel-2.png
    • BangleJS2-ColorWheel-3.png
  • ...now available on my personal App Loader (look for "ColorWheel") and - hopefully - soon on the official one as well.

  • Awesome. If there was a props button I'd be spamming it - I could not get my head around 3 bit colour when I cracked open my first app.

  • I've started documenting my Bangle.js 2 "activities" on GitHub - this may be a better place for small code snippets than this forum...

  • This forum is a very good place to get attention of the community though, I liked seeing this idea :)

  • I like this version.

    Note you only need 3 hex digits. #8F0 instead of #80FF00.

  • Are you going to do a pull request to the main repository?

  • Yes, I know, but I prefer the long notation.

  • It's already available in my personal app store - just look for the tool "Color Wheel" - and will hopefully be merged as soon as Gordon will return

  • It's interesting to watch the experiments! It's a good idea to document them ;)

  • @Andreas_Rozek - I tried out the colour wheel from your loader.

    My only comments would be I think the design would look more attractive with a black centre and white text for the Hex digits. The advantage of going to a 3 digits hex format would be that the text can be larger and easier to read.

    I also tried out your various analogue clocks. Really good. I like the the fact that you have done a really basic one. I can see you have been really busy.

    I'm really interested to see if its possible to get the hollow hands or altimeter hands look and hands that have a bolt in the middle.


    4 Attachments

    • hollow_hands2.png
    • hollow_hands.png
    • ana_hands.png
    • altimeter_hands.png
  • Hollow hands are trivial: simply replace fillPoly by drawPoly in my code. For the hands shown in the fotos, you'll have to displace the polygons and add a short line from the center. The bolt in the middle is trivial again.

    However, I'll probably won't find the time to implement them today/this year - you'll have to wait til tomorrow/next year.

  • I found a few minutes and just wrote rounded and hollow hands - code and documentation will follow by tomorrow


    2 Attachments

    • roundedHands.png
    • hollowHands.png
  • Hi @Andreas_Rozek - thanks for sharing your code and posts. I'm really enjoying them and find them useful.

    The example hands are a bit more complicated than simple rectangles. The ends are rounded, they start with short spindles etc. The resulting outline by changing to drawPoly will be very weedy. But I am sure it is possible with a lot of tinkering and trial and error with two polygons, one for the ouside and another to hollow it out. I'll probably have a go at this at some point, but suspect its about 4-8 hours of trial and error. But I think it will be worth doing inthe long run as it will enable better looking clocks.

    I had a play with your simple_clock code - many thanks for sharing. I dont thing you need to draw the widgets. I managed to get the widgets to draw and take up the current theme correctly using the code snippets below.

    // at the top of the file
    g.clear();
    Bangle.loadWidgets();
    Bangle.drawWidgets();
    
    const w = g.getWidth();
    const h = g.getHeight();
    const cx = (w/2);
    const cy = (h/2) + (Bangle.appRect.y/2); 
    const outerRadius = (h - Bangle.appRect.y)/2;
    

    Note Bangle.appRect gives you the usable space for the app. Here I am just taking into account if there are widgets on the top, but the approach could be adjusted for the bottom as well taking into account Bangle.appRect.h. Bangle.appRect adjusts depending on if widgets are displayed at the top and bottom - I dont think it is documented - it was introduced in one of the threads a while back.

    In the draw() function I g.fillRect(Bangle.appRect); And leave the drawing of the widgets to the widgets.

    function draw() {
      g.setColor(g.theme.bg);
      g.fillRect(Bangle.appRect);
    
      drawNumbers();
      drawHands();
      queueDraw();  // see Anton clock etc
    }
    

    And at the end I have.

    Bangle.setUI('clock');
    draw();
    

    The rest of the code is the same as yours but without the 80 or so lines that form updateClockFaceSize () and the code to override Bangle.drawWidgets().

  • Wow - you've been busy.

  • Good morning (and all the best for 2022)!

    As promised, I've (fine tuned what I wrote yesterday evening and) published the sources for rounded and hollow hands at the usual place (i.e., on GitHub)

    The new implementations now also contain some "bolts" in the center.

    I really appreciate the sheer performance of the new Bangle.js 2 compared to the first incarnation of that watch!


    2 Attachments

    • hollowHands.png
    • roundedHands.png
  • Concerning your remarks:

    I'm sorry, it's been my fault: I did not remember that I published a simplified version of the simple hands only (and that version drew rectangles rather than rounded rectangles)

    Concerning Bangle.appRect: well, I know that feature but I refuse to sacrifice 24 (or even 48) pixel lines of the extremely precious screen, as soon as even the smallest widget has appeared. For that reason, I used a little geometry to see if a circular clock face could fit into the empty space between widgets in the screen corners - or reduced the clock face radius as little as possible!

  • don't worry - it will soon come to an end when lecture time starts again...

  • The "rounded hands" are now those drawn by my "minimal clock" (see my personal app store)

  • Thank goodness, you're having all the fun and making it easy for the rest of us! :D

  • Great work @Andreas_Rozek, very nice. I'm looking forward to your pull requests.
    I'll scan your personal loader again and give them a go.
    Really like the bolted hands. This is really useful stuff as it will build a set of examples that many will include in fture analogue clocks.

    don't worry - it will soon come to an end when lecture time starts again...

    Shame about the lectures. Assume you are doing a CS degree ?
    You have obviously spotted how addictive fiddling on with a Bangle JS is.
    I'd been looking for years for a watch like this.

  • Concerning Bangle.appRect: well, I know that feature but I refuse to sacrifice 24 (or even 48) pixel >lines of the extremely precious screen, as soon as even the smallest widget has appeared. For that >reason, I used a little geometry to see if a circular clock face could fit into the empty space between >widgets in the screen corners - or reduced the clock face radius as little as possible!

    Sure but in practice its not making very much difference.

    In the example below I am using the Lock, Pedometer, and Battery Widget (themed).
    The line for the 12 digits were coming out as 23.9. My calculation just goes for 24.

    I printed out the values of CentreX, CentreY, outerRadius in both versions and the difference is less than 1 pixel. The presence of one widget on the top line results in the top of the 12 being written at Y = 23.9.

    The advantage of your code is that it will adjust as a person's config changes as they go from no widgets, some top widgets, some bottom widgets etc. So no matter what the config is, your approach will always attempt to maximise the size of the clock face.

    My working example is at:
    https://github.com/hughbarney/bangle_bit­s/blob/master/anaclock/simplest.basic.ap­p.js


    1 Attachment

    • download.png
  • Well,

    Shame about the lectures. Assume you are doing a CS degree ?

    not to misunderstand each other: I give lectures (I made my diploma in physics more than three decades ago). And right now (i.e. during the Corona pandemic), Arduinos (and Espruinos), RasPis and Bangle.js's help me motivating my students and showing them what they could do if they only would have the courage and start doing...

  • Personally, I use very few widgets only - and in such a case, my code may probably reserve the whole screen for an (analog) clock

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Bangle.js 2: Color wheel

Posted by Avatar for Andreas_Rozek @Andreas_Rozek

Actions