New to Bangle.js and Espruino. Need help with graphics

Posted on
Page
of 2
Prev
/ 2
  • Updated CGauge prototype/'class' which shows begin-tick, end-tick and - if defined - 0-tick. Code in post #13 is left alone to preserve line numbers used in text of past posts.

    Temporary, updated code also included the option to draw only the value-arg... but it became pretty quickly complicated to render cleanly. Choosing the (black) background color for the fill color yields the same look, just less efficiently ... :<

    Screenshots attached.

    This will it be for a while... the filling can wait...

    // cgauge.js - circular gauge
    // allObjects - forum.espruiono.com
    // 2020-11-27
    
    // left/top = x/y = 0/0
    
    // Circular Gauge cg0:
    // - visual: 270 degree clock-wise gauge starting mid left bottom quadrant
    // - graphics: ...starting mid 2nd quadrant ending mid 1st quadrant
    // - showing values from 0..300 clockwise with initial value of 100
    
    var cg0
      , cg1,cg1c,cg1f,cg1t,cg1h
      , cg2,cg2c,cg2f,cg2t,cg2h
      , cg3,cg3c,cg3f,cg3t,cg3h
      , cg4
      , b1w,b2w,b3w
      ;
    function run() {
      halt();
      cg0=new CGauge("cg0",0,0,300,[0,1,0],[1  ,0  ,0  ],135,270,null,120,140,100,96);
      cg1=new CGauge("cg1",0,0, 30,[1,1,0],[0  ,1  ,1  ],180,180,null, 80,212, 16,13);
      cg2=new CGauge("cg2",0,0, 60,[1,1,1],[0.5,0.5,0.5], 90,360,null,120,180, 22, 1);
      cg3=new CGauge("cg3",0,0, 30,[1,0,1],[0  ,0  ,1  ],180,180,null,160,212, 16, 0);
      cg4=new CGauge("cg4",0,0, 40,[1,0,1],[0.6,0.6,0.6],120,-60,null,12­0,  8, 70,64);
      cg0.setVal(100,-1);
      cg1.setVal( 20,-1);
      cg2.setVal(108,-1);
      cg3.setVal( 15,-1);
      cg4.setVal( 10,-1);
      drawAll();
      cg1c=2; cg1f=function(){ if (!cg1.setVal(cg1.val+cg1c)) cg1c=-cg1c; };
      cg1t=750;
      cg2c=1; cg2f=function(){ if (!cg2.setVal(cg2.val+cg2c)) cg2c=-cg2c; };
      cg2t=1000;
      cg3c=5; cg3f=function(){ if (!cg3.setVal(cg3.val+cg3c)) cg3c=-cg3c; };
      cg3t=1700;
      if (!b1w) b1w=setWatch(cg1f,BTN1,{edge:"rising",re­peat:true});
      if (!b2w) b2w=setWatch(cg2f,BTN2,{edge:"rising",re­peat:true});
      if (!b3w) b3w=setWatch(cg3f,BTN3,{edge:"rising",re­peat:true});
      cont();
    }
    function cont() {
       cg1h=setInterval(cg1f,cg1t);
       cg2h=setInterval(cg2f,cg2t);
       cg3h=setInterval(cg3f,cg3t);
    }
    function halt() {
      if (cg1h) cg1h=clearInterval(cg1h);
      if (cg2h) cg2h=clearInterval(cg2h);
      if (cg3h) cg3h=clearInterval(cg3h);
    }
    
    function drawAll() { 
      g.clear(); setTimeout(function() {
          cg0.draw(1); cg1.draw(1); cg2.draw(1); cg3.draw(1); cg4.draw(1); }
        , 1000); }
    
    var p; // temp for prototype references
    function CGauge(id,val,minV,maxV,color,fColor,beg­Deg,degs,deg0,x,y,rOuter,rInner) {
      var _=0||this;
      _.mxXY=239;    // x, y max graph coord - defaults for BangleJS Graphics
      _.pps=2;       // 'pixel per segment'/jaggedness/graphical precision/resolution
      _.tikL=6;      // tick-length (set to 0 post construction for no ticks drawing)
      _.id=id;       // id of the circular gauge
      _.val=null;    // temporary, set at end of construction
      _.minV=minV;   // minimum value (arc all in fColor)
      _.maxV=maxV;   // maximum value (arc all in color)
      _.clr=color;   // color - as required by Graphics - for the value arc
      _.fClr=fColor; // color - as required by Graphics - for to complete the arc
      _.begD=begDeg; // 0 degrees: +x-Axis
      _.degs=degs;   // gauge full arc in degrees -/+ = counter/clockwise
      _.deg0=(deg0)?deg0:begDeg; // for 0/center value mark; falsy defaults to begDeg
      _.x=x;         // center x
      _.y=y;         // center y
      _.rOut=rOuter; // radius outer
      _.rIn=rInner;  // radius inner (optional)
      _.begR=_.rad(_.begD);                              // begin radian
      _.arcR=(_.degs==360)?Math.PI*2:_.rad(_.d­egs);      // arc rad used for sCnt only
      _.segR=(Math.PI/(4/_.pps)/_.rOut)*((degs­>0)?1:-1); // segment radian
      _.sCnt=Math.round(Math.abs(_.arcR/_.segR­));        // segment count in arc
      _.cUp=[];                                          // clean up vertices 
      _.setVal(val,-1); // set value only
    } p=CGauge.prototype;
    p.setVal=function(v,opt) { // --- set min/max adj'd val, draw != && opt=0 || opt>0; 
      var chd = (v=(v<this.minV)?this.minV:(v>this.maxV)­?this.maxV:v)!=this.val; // ret
      if (opt<0) { this.val=v; // update value only, NO drawing
      } else if (v!=this.val||opt>0) { this.val=v; this.draw(opt); }
      return chd; };
    p.draw=function(o) { // --- draw circular gauge (o-pt w/ extras, such as 0-tick)
      var s=this.sCnt,v=Math.round(s/(this.maxV-th­is.minV)*this.val),h=!!this.rIn,vs;
      if (o) { if (this.tikL) this.drawTicks(h); } // console.log(this.id,this.val,v,s,this.cU­p);
      g.setColor(0,0,0); while (this.cUp.length) g.drawLine.apply(g,this.cUp.pop());
      if (v<s) g.setColor.apply(g,this.fClr).drawPoly(t­his._pvs(v,s,0),h);
      vs=this._pvs(0,v,1);
      g.setColor.apply(g,this.clr).drawPoly(vs­,h); };
    p.drawTicks=function(h) { // --- draw ticks, begin and end and 0-tick
      var x=this.x,y=this.y,rTO=(h)?this.rIn:this.­rOut,rTI=rTO-this.tikL,bR=this.begR
        , eR=bR+this.sCnt*this.segR,rTS=((rTI<0)?0­:rTI)/rTO; // console.log(this.id,rTO,rTI,rTS);
      this.drawTick(x,y,rTO,rTS,eR,this.fClr);­this.drawTick(x,y,rTO,rTS,bR,this.clr);
      if (this.deg0!=this.begD) this.drawTick(x,y,rTO,rTS,bR,this.clr); };
    p.drawTick=function(x,y,t,s,r,c) { // --- draw tick;
      var vX=t*Math.cos(r),vY=t*Math.sin(r); g.setColor.apply(g,c); g.drawLine(
        Math.round(x+vX),Math.round(y+vY),Math.r­ound(x+vX*s),Math.round(y+vY*s)); };
    p._pvs=function(f,t,c) { // --- calc polygon vertices from..to
      var x=this.x, y=this.y, rO=this.rOut, rI=this.rIn, bR=this.begR, sR=this.segR
        , l=(t-f+1)*2*((rI)?2:1) // len of array for vertices (double w/ inner radius
        , v=((this.mxXY<=355) ? new Uint8Array(l) : new Uint16Array(l)) // vertices array
        , s=f-1  // segment index 
        , i=-1,j // vertices array index (running and 'turn around'/last outer)
        , r      // radian
        ; // console.log(x,y,rO,rI,bR,sR,f,t,s,i);
      while(++s<=t) { r=bR+s*sR;
        v[++i]=Math.round(x+rO*Math.cos(r));
        v[++i]=Math.round(y+rO*Math.sin(r)); } // console.log(this.id,s,r,v[i-1],v[i]); }
      if (rI) { j=i;
        while (--s>=f) { r=bR+s*sR;
          v[++i]=Math.round(x+rI*Math.cos(r));
          v[++i]=Math.round(y+rI*Math.sin(r)); }
        this.cUp.push((c)?v.slice(j-1,j+3):v.sli­ce(0,2).concat(v.slice(-2)));
      } // console.log(this.id,c,j,v.slice(0,4),thi­s.cUp); }
      return v; };
    p.rad=function(degrs) { return 2*Math.PI*(degrs%360)/360; }; // radian <-- degrees
    // p.v=function(x,y,r,rO,ri) { // <--- vertice
    //  return [
    
    function r() { run(); }
    function h() { halt(); }
    function c() { cont(); }
    
    setTimeout(run,999);
    

    1 Attachment

    • CGaugesWithTicks.png
  • @Gordon,

    me keeping going on on this subject does not mean you have to get distracted from your priorities. For me, this conversation became some personal exploring of the problem and possible solution space (and next UI component after having done the vertical/horizontal bar / slider as UI component in UI Framework for microcontrollers... Looks like I have to add the same visuals to those pages as are available in the conversation covering the first comprehensive documentation of Modular and extensible UI framework and ui elements. ).

  • Hello All,
    Am back with continuation of this thread :)
    For a recap- I had this (pic attached) built with steps value as 2,500 which was a static value, a constant.
    I have to now color the semicircle green depending on value (got at run time, it would keep changing).

    I went through this entire thread once again. And looks like there is a lot that has been experimented.
    Thanks a lot once again for all your help.
    I am now going to start looking through the code you all have shared here.
    Just had one query because I am not sure if I understood it correctly(after looking at the watch face example) - Is a feature like this now being provided by bangle.js? Or, else I will start working on my code (as suggested in #17)

    Thanks a lot once again!


    1 Attachment

    • 2021-01-25 (3).png
  • Nice, clean layout.

  • Cool, maybe you could use scaled fixed font for date and day rather than vector.

  • I built the daisy clock. To get a decent looking ring I did it with a series of fixed images. The resolution of the screen is too course to get non pixellated curves drawn. We really need a 360x360 screen.

  • After 2 years, @NewAtEspruino might not be new at espruino anymore :) As for drawing rings, there is now a graphics_utils library for that extracted from https://espruino.github.io/BangleApps/?q­=choozi.

  • Nice!
    @Gordon: should this go into firmware or module?

  • Yes, the module is at https://github.com/espruino/BangleApps/b­lob/master/modules/graphics_utils.js

    Well, realistically if there were to be a fillArc function internally it'd be best to do it with something a bit more clever (like some kind of bresenham thing). If someone wanted to contribute it I'd merge though (albeit probably only on devices that weren't too constrained).

    The nice thing about the library is if it ever does get implemented we can just make the library use the internal version instead

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

New to Bangle.js and Espruino. Need help with graphics

Posted by Avatar for NewAtEspruino @NewAtEspruino

Actions