04-30-2021 15:34
04-30-2021 15:34
I have no coding experience, learning what I can from forums like this.
I made a simple watch face that shows the time. date and heart rate for the fitbit since. Works perfectly.
Wanted to make it just a tad more unique by having the back ground change based on the heart rate. After digging and trial and error, this is what I came up with and yes....it doesn't work.
In my Index.js file I have the following, the addition is the "background = function(evt) "
if (HeartRateSensor) {
const hrm = new HeartRateSensor({ frequency: 1 });
hrm.addEventListener("reading", () => {
hrmData.text = `HR: ${hrm.heartRate}`;
});
sensors.push(hrm);
hrm.start();
} else {
hrmLabel.style.display = "none";
hrmData.style.display = "none";
}
background = function(evt) {
if (hrm.heartRate < 84){
show = "BG1";
} else if (hrm.heartRate > 84){
show = "BG2";
}
}
Then in the Index.view file I have:
<svg class="background">
<svg id="BG1" display="inline">
<image href="img1.png" />
<text id="myclock"></text>
<text id="myDate" />
<text id="hrm-data" class="sensor-data"></text>
</svg>
<svg id="BG2" display="inline">
<image href="img2.png" />
<text id="myclock"></text>
<text id="myDate" />
<text id="hrm-data" class="sensor-data"></text>
</svg>
</svg>
I was figuring based on the if statement in index.js it would switch which SVG portion to view. but to no avail.
If there is an easier way what is the base code and in which files do I put what?
04-30-2021 19:17
04-30-2021 19:17
Try something like this:
if (HeartRateSensor) {
const hrm = new HeartRateSensor({ frequency: 1 });
hrm.addEventListener("reading", () => {
hrmData.text = `HR: ${hrm.heartRate}`;
if (hrm.heartRate < 84){
BG2.style.display = 'none';
BG1.style.display = 'inline';
} else if (hrm.heartRate > 84){
BG2.style.display = 'inline';
BG1.style.display = 'none';
}
});
sensors.push(hrm);
hrm.start();
} else {
hrmLabel.style.display = "none";
hrmData.style.display = "none";
}
Use BG.style.display = 'inline' or 'none'.
Also I got rid of background = function(evt) {, and I moved the if statement into the function where the heart rate is being read.
Hope it helps!
04-30-2021 19:42
04-30-2021 19:42
I added it, but it wants me to define the bg1 and bg2. also what do I do in the image.view file? I downloaded it and made it sharable via google drive if you want to take a look.
https://drive.google.com/file/d/1SimQS2EHIu04msgEmcYM0zXUBekF69hH/view?usp=sharing
04-30-2021 20:10
04-30-2021 20:10
I will take a look at this tomorrow.
05-01-2021 06:03
05-01-2021 06:03
Ok, so in the index.view file, you can leave it as it is. Everything looked fine there. But it is wanting you to define them because you haven't declared them as variables yet. So at the top of your code, not in any functions, put these two lines.
let BG1 = document.getElementById('BG1');
let BG2 = document.getElementById('BG2');
the word "let' is just making a variable, and then we name the variable with BG1 or BG2. Then the document.getElementById is a javascript function that can take something that you have made in the index.view file and let you modify it in javascript. So we need to tell it what ID the object that we want has. That is what is in parenthesis. <svg id="BG2" display="inline"> So in this line of code, the id of this object is BG2, so we name the variable that, and also you put that in the parenthesis.
I hope that helps you understand. I know that it took me a few months for it to make sense.
05-01-2021 07:54
05-01-2021 07:54
Awesome that worked. but now when the HRM is greater than 84, the BG2 pops up, but the Clock/Date/HRM disappears. like it's putting the BG2 as an overlay instead of a BG. Im thinking is due to my image.view file. Screenshots below, and my image.view file in the code box below.
*Side note, I know the BG2 image is blurry, I will be adding a better one soon, just using for testing.
Before 84HRM
https://drive.google.com/file/d/1aCo1uSrWEKwO6Tm3GU-jZBn-DrIBQ4IW/view?usp=sharing
After 84HRM
https://drive.google.com/file/d/1zVqJ9VC-C-J18kOPwmfO5Rx4hDu_JA1u/view?usp=sharing
<svg class="background">
<svg id="BG1">
<image href="BG1.png" />
<text id="myclock"></text>
<text id="myDate" />
<text id="hrm-data" class="sensor-data"></text>
</svg>
<svg id="BG2">
<image href="BG2.png" />
<text id="myclock"></text>
<text id="myDate" />
<text id="hrm-data" class="sensor-data"></text>
</svg>
</svg>
05-01-2021 07:55
05-01-2021 07:55
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import * as util from "../common/utils";
import { display } from "display";
import { HeartRateSensor } from "heart-rate";
const myclock = document.getElementById("myclock");
const hrmData = document.getElementById("hrm-data");
const myDate = document.getElementById("myDate");
const sensors = [];
clock.granularity = "minutes";
clock.ontick = (evt) => {
let today = evt.date;
let hours = today.getHours();
let monthnum = today.getMonth();
let day = today.getDate();
if (preferences.clockDisplay === "12h") {
// 12h format
hours = hours % 12 || 12;
} else {
// 24h format
hours = util.zeroPad(hours);
}
let mins = util.zeroPad(today.getMinutes());
myclock.text = `${hours}:${mins}`;
var month = new Array();
month[0] = "01";
month[1] = "02";
month[2] = "03";
month[3] = "04";
month[4] = "05";
month[5] = "06";
month[6] = "07";
month[7] = "08";
month[8] = "09";
month[9] = "10";
month[10] = "11";
month[11] = "12";
let monthname = month[monthnum];
myDate.text = `${monthname}-${day}`;
}
let BG1 = document.getElementById('BG1');
let BG2 = document.getElementById('BG2');
if (HeartRateSensor) {
const hrm = new HeartRateSensor({ frequency: 1 });
hrm.addEventListener("reading", () => {
hrmData.text = `HR: ${hrm.heartRate}`;
if (hrm.heartRate < 84){
BG2.style.display = 'none';
BG1.style.display = 'inline';
} else if (hrm.heartRate > 84){
BG2.style.display = 'inline';
BG1.style.display = 'none';
}
});
sensors.push(hrm);
hrm.start();
} else {
hrmLabel.style.display = "none";
hrmData.style.display = "none";
}
display.addEventListener("change", () => {
// Automatically stop all sensors when the screen is off to conserve battery
display.on ? sensors.map(sensor => sensor.start()) : sensors.map(sensor => sensor.stop());
});
05-01-2021 07:56
05-01-2021 07:56
Also for the date. is there an easier way to do the leading zero in the month and day?
05-01-2021 11:15 - edited 05-01-2021 11:18
05-01-2021 11:15 - edited 05-01-2021 11:18
Ok, I think I will need to restructure your index.view file.
<svg class="background">
<image id = 'BG1' href="BG1.png" />
<image id = 'BG2' href="BG2.png" />
<text id="myclock"></text>
<text id="myDate" />
<text id="hrm-data" class="sensor-data"></text>
</svg>
The reason it wasn't working (I hope 😉) is because you were giving the clock, data, and heartrate labels the same id twice. So I cut the svg in half, but redid it so it should work this time.
About getting the month easier: You seem to be doing it the same way that I do. It is fine.
05-03-2021 11:47
05-03-2021 11:47
Awesome, got it all to work.
Updated the background images. and it works great until I ran into a bug.
It seems when I go to an app on the watch, or Alexa, the background image will just disappear completely, and unless I swipe around a lot or reset it the background image will not come back.
Here is the full build:
https://drive.google.com/file/d/16hQlXlSkDSXw4OiCXYnWdjC6VRBzZU32/view?usp=sharing
Index.js
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import * as util from "../common/utils";
import { display } from "display";
import { HeartRateSensor } from "heart-rate";
const myClock = document.getElementById("myClock");
const hrmData = document.getElementById("hrm-data");
const myDate = document.getElementById("myDate");
const sensors = [];
let days = ["Sun", "Mon", "Tue", "Wen", "Thu", "Fri", "Sat"];
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
clock.granularity = "minutes";
clock.ontick = (evt) => {
let today = evt.date;
let dayName = days[today.getDay()];
let hours = today.getHours();
let month = util.zeroPad(today.getMonth() + 1);
let monthName = months[today.getMonth()];
let dayNumber = util.zeroPad(today.getDate());
if (preferences.clockDisplay === "12h") {
// 12h format
hours = hours % 12 || 12;
} else {
// 24h format
hours = util.zeroPad(hours);
}
let mins = util.zeroPad(today.getMinutes());
myClock.text = `${hours}:${mins}`;
myDate.text = `${dayName}, ${monthName}-${dayNumber}`;
}
let BG1 = document.getElementById('BG1');
let BG2 = document.getElementById('BG2');
if (HeartRateSensor) {
const hrm = new HeartRateSensor({ frequency: 1 });
hrm.addEventListener("reading", () => {
hrmData.text = `${hrm.heartRate}`;
if (hrm.heartRate <= 100){
BG2.style.display = 'none';
BG1.style.display = 'inline';
} else if (hrm.heartRate > 100){
BG2.style.display = 'inline';
BG1.style.display = 'none';
}
});
sensors.push(hrm);
hrm.start();
} else {
hrmLabel.style.display = "none";
hrmData.style.display = "none";
}
display.addEventListener("change", () => {
// Automatically stop all sensors when the screen is off to conserve battery
display.on ? sensors.map(sensor => sensor.start()) : sensors.map(sensor => sensor.stop());
});
Common > Utils.js
// Add zero in front of numbers < 10
export function zeroPad(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
Resources > Index.view
<svg class="background">
<svg>
<image id = 'BG1' href="AllioredBanners.png" />
<image id = 'BG2' href="WarMode.png" />
<text id="myClock"></text>
<text id="myDate"></text>
<text id="hrm-data" class="sensor-data"></text>
</svg>
</svg>
Resources > Style.css
#myDate {
font-size: 35;
font-family: System-Bold;
text-length: 32;
text-anchor: middle;
x: 130;
y: 210;
fill: white;
}
#myClock {
font-size: 40;
font-family: System-Bold;
text-length: 32;
text-anchor: middle;
x: 180;
y: 103;
fill: white;
}
#hrm-data {
font-size: 20;
font-family: System-Bold;
text-length: 32;
text-anchor: middle;
x: 262;
y: 285;
fill: white;
}
05-03-2021 18:40
05-03-2021 18:40
That is strange. I would maybe try setting image 1 to inline and image 2 to none outside of the function as well as in the function. So here is the index.js how I would suggest:
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import * as util from "../common/utils";
import { display } from "display";
import { HeartRateSensor } from "heart-rate";
const myClock = document.getElementById("myClock");
const hrmData = document.getElementById("hrm-data");
const myDate = document.getElementById("myDate");
const sensors = [];
let days = ["Sun", "Mon", "Tue", "Wen", "Thu", "Fri", "Sat"];
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
//THE TWO LINES BELOW THIS ARE WHAT I ADDED
BG2.style.display = 'none';
BG1.style.display = 'inline';
clock.granularity = "minutes";
clock.ontick = (evt) => {
let today = evt.date;
let dayName = days[today.getDay()];
let hours = today.getHours();
let month = util.zeroPad(today.getMonth() + 1);
let monthName = months[today.getMonth()];
let dayNumber = util.zeroPad(today.getDate());
if (preferences.clockDisplay === "12h") {
// 12h format
hours = hours % 12 || 12;
} else {
// 24h format
hours = util.zeroPad(hours);
}
let mins = util.zeroPad(today.getMinutes());
myClock.text = `${hours}:${mins}`;
myDate.text = `${dayName}, ${monthName}-${dayNumber}`;
}
let BG1 = document.getElementById('BG1');
let BG2 = document.getElementById('BG2');
if (HeartRateSensor) {
const hrm = new HeartRateSensor({ frequency: 1 });
hrm.addEventListener("reading", () => {
hrmData.text = `${hrm.heartRate}`;
if (hrm.heartRate <= 100){
BG2.style.display = 'none';
BG1.style.display = 'inline';
} else if (hrm.heartRate > 100){
BG2.style.display = 'inline';
BG1.style.display = 'none';
}
});
sensors.push(hrm);
hrm.start();
} else {
hrmLabel.style.display = "none";
hrmData.style.display = "none";
}
display.addEventListener("change", () => {
// Automatically stop all sensors when the screen is off to conserve battery
display.on ? sensors.map(sensor => sensor.start()) : sensors.map(sensor => sensor.stop());
});