Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Create a line chart on the watch itself

 

I wanted to share something I put together that allows us to create a line chart from data on the watch itself without using a companion app.  You can use it to track heartbeat, pauses, exercise, button presses, etc.   You'd just need to add a redraw function when you add new data. This graph will auto scale.  You can add as many data points for as many line segments you put in the index.gui.  

 

Here's what the barebones graph looks like on your watchface as you add data in: 

Screen Shot 2020-08-08 at 2.57.56 PM.png

 

What other creative ways are there to get around the current limitations to create graphs and charts on the fitbit and do you have any suggestions to make the graph better? 

 

 

 

Here is the index.gui:

<svg>
  <line id="1" class="line" />
  <line id="2" class="line" />
  <line id="3" class="line" />
  <line id="4" class="line" />
  <line id="5" class="line" />
  <line id="6" class="line" />
  <line id="7" class="line" />
  <line id="8" class="line" />
  <line id="9" class="line" />
  <line id="10" class="line" />
  <line id="11" class="line" />
  <line id="12" class="line" />
  <line id="13" class="line" />
  <line id="14" class="line" />
  <line id="15" class="line" />
  <line id="16" class="line" />
  <line id="17" class="line" />
  <line id="18" class="line" />
  <line id="19" class="line" />
  <line id="20" class="line" />
</svg>

 

And here is the index.js code

import document from "document";

let lines = [];
let xOffset = 25;
let yOffset = 25;
let data = [
1.1, 1.2, 1.45, 2.3, 3.56,
4,   4.2, 4.5,  5.3, 5.4,
5.3, 4.9, 3.4,  3.1, 2.9];
let len = data.length;
let xAxisInt = (325-xOffset*2)/len;
let dataMin = min(data);
let dataMax = max(data);

setup(data);

for(let i = 0; i < data.length-1; i++){
  lines[i].style.display = "inline";
  lines[i+1].style.display = "inline";
  lines[i].x1 = xOffset+i*xAxisInt;
  lines[i].x2 = xOffset+(i+1)*xAxisInt;
  lines[i].y1 = mapY(data[i], dataMin, dataMax, 275,25);
  lines[i].y2 = mapY(data[i+1], dataMin, dataMax, 275,25);
}


function setup(data){
  for (let i = 0; i < data.length; i++){
    let index = (i+1).toString();
    lines.push(document.getElementById(index));
    lines[i].style.display = "none";
    lines[i].fill="red";
  }
}

function max(array){
  let max = -Infinity;
  for(let i = 0; i < array.length;i++){
    if(array[i]>max){
      max = array[i]
    }
  }
  return max
}

function min(array){
  let min = Infinity;
  for(let i = 0; i < array.length;i++){
    if(array[i]<min){
      min = array[i]
    }
  }
  return min
}

function mapY(y, in_min, in_max, out_min, out_max) {
  return (y - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

 

And finally heres the styles.css

.line {
  fill: grey;
  stroke-width: 5;
}

 

Best Answer
5 REPLIES 5

I think that will be very useful for a lot of people.

 

I've developed a few clockfaces and apps that display bar charts using a similar method. Here's a free one that can be zoomed and panned, with labels on the axes. The screenshots are a bit misleading because they're based on fake data.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Interesting, I'm assuming instead of blank line tags, you used black rect tags and then calculate the y and height values based on the data. I really like the ability to switch from one metric to another.  

Best Answer
0 Votes

That's right.

You might also consider getElementsByClassName, which can make it quicker to scoop up all the segments in one go. It may not help much in your case, though.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Thanks for this! My standard clock face since I got my versa has been this heart rate monitor

But it has gained some visual glitches since the 4.2 firmware update (semi-transparent elements are now rendering as fully opaque).

 

I'm fairly sure the developer has abandoned Fitbit development so I'm going to have a go at creating something similar myself. Your example will help get me started.

Best Answer
0 Votes

Cool. Here is what my graphs look like on the Sentinel clockface.

 

The graph area is actually a button and hitting it cycles through 30min (6 points), 1hr (12 points), 2hr(24 points) graphs of blood-glucose data for up to 3 people (so up to 72 points and the associated 69 lines. Plus I have 6 floating numbers per person. The graph normalizes to the size of the button area. It took a while for me to get it right. 

FB_IMG_1599282719933.jpg

 

Best Answer