02-11-2021 12:42
02-11-2021 12:42
I have a basic gradient mask setup where the left side of the screen is HMS and the right is three goal rings with icons. On the simulator, I can see everything perfectly and nothing overlaps. However, when I load the clockface onto my Versa 2, a black rectangle on top of the minutes cuts off part of the hours and a black rectangle on top of the seconds cuts off part of the minutes. See here: https://imgur.com/a/wtOP3Fc. I made a watch with the same spacing but without a mask and there is no overlap at all so this has to be a mask issue. So:
I only have a Versa 2 so I cannot check this on any other watches.
02-24-2021 07:51
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
02-24-2021 07:51
How many masks are you using? Can you try to simplify it and provide a sample?
Best Answer02-24-2021 09:59
02-24-2021 09:59
I've simplified it to just the clock. I am using v4.2 and testing on Versa 2. I have the same index, widgets, and utils for both clocks. The index.gui is only different in that I put my hours, minutes, and seconds in a mask tag and added the gradient tag underneath.
index.js
import clock from "clock";
import document from "document";
import { preferences } from "user-settings";
import * as util from "../common/utils";
// Update the clock every minute
clock.granularity = "seconds";
// Get a handle on the <text> element
const _hours = document.getElementById("clockHours");
const _minutes = document.getElementById("clockMins");
const _seconds = document.getElementById("clockSecs");
// Update the <text> element every tick with the current time
clock.ontick = (evt) => {
let today = evt.date;
let hours = today.getHours();
if (preferences.clockDisplay === "12h") {
// 12h format
hours = hours % 12 || 12;
}
hours = util.monoDigits(hours);
let mins = util.monoDigits(today.getMinutes());
let secs = util.monoDigits(today.getSeconds());
_hours.text = hours;
_minutes.text = mins;
_seconds.text = secs;
}utils.js
export function monoDigits(num, pad = true) {
let monoNum = '';
if (typeof num === 'number') {
num |= 0;
if (pad && num < 10) {
monoNum = c0 + monoDigit(num);
} else {
while (num > 0) {
monoNum = monoDigit(num % 10) + monoNum;
num = (num / 10) | 0;
}
}
} else {
let text = num.toString();
let textLen = text.length;
for (let i = 0; i < textLen; i++) {
monoNum += monoDigit(text.charAt(i));
}
}
return monoNum;
}
const c0 = String.fromCharCode(0x10);
const c1 = String.fromCharCode(0x11);
const c2 = String.fromCharCode(0x12);
const c3 = String.fromCharCode(0x13);
const c4 = String.fromCharCode(0x14);
const c5 = String.fromCharCode(0x15);
const c6 = String.fromCharCode(0x16);
const c7 = String.fromCharCode(0x17);
const c8 = String.fromCharCode(0x18);
const c9 = String.fromCharCode(0x19);
function monoDigit(digit) {
switch (digit) {
case 0: return c0;
case 1: return c1;
case 2: return c2;
case 3: return c3;
case 4: return c4;
case 5: return c5;
case 6: return c6;
case 7: return c7;
case 8: return c8;
case 9: return c9;
case '0': return c0;
case '1': return c1;
case '2': return c2;
case '3': return c3;
case '4': return c4;
case '5': return c5;
case '6': return c6;
case '7': return c7;
case '8': return c8;
case '9': return c9;
default: return digit;
}
}mask: index.gui
<svg class="root" viewport-fill="#000000">
<mask id="mask">
<text id="clockHours" class="Clock-Mask" />
<text id="clockMins" class="Clock-Mask" />
<text id="clockSecs" class="Clock-Mask" />
</mask>
<svg mask="#mask" width="100%" height="100%">
<gradientRect id="gradient" width="100%" height="100%"
gradient-type="linear"
gradient-x1="50" gradient-y1="0"
gradient-x2="100%-50" gradient-y2="0"
gradient-color1="magenta" gradient-color2="red" />
</svg>
</svg>no mask: index.gui
<svg class="root" viewport-fill="#000000">
<text id="clockHours" class="Clock-Mask" />
<text id="clockMins" class="Clock-Mask" />
<text id="clockSecs" class="Clock-Mask" />
</svg>styles.css
.root {
width: 100%;
height: 100%;
}
.Clock-Mask {
fill: red;
x: 50%+5;
font-size: 120;
font-family: SevilleSharp-Regular;
text-length: 32;
}
#clockHours {
y: 17%+42+10;
text-anchor: end;
}
#clockMins {
y: 50%+42;
text-anchor: end;
}
#clockSecs {
y: 83%+42-10;
text-anchor: end;
}widgets.gui
<svg>
<defs>
<link rel="stylesheet" href="styles.css" />
<link rel="import" href="/mnt/sysassets/widgets_common.gui" />
</defs>
</svg>Both look fine on the simulator but I downloaded both to my watch to test again and the margins still overlap when using a mask.
Best Answer02-24-2021 11:48
Gold Fitbit Product Experts share support knowledge on the forums and advocate for the betterment of Fitbit products and services. Learn more
02-24-2021 11:48
I wonder if this could be a font substitution thing. The sim may handle this differently to the watch, and I don't recall that font-family being standard.
Stretching images, or having very large elements, can also result in clipping. At a quick glance, you don't seem to be doing that, but maybe check.
Best Answer02-24-2021 12:06
02-24-2021 12:06
It's not a font issue as far as I can tell. I can't say I've tested all the different fonts but it does the same thing if I use System-Regular instead of SevilleSharp-Regular and regular or monospace digits.
I don't think I'm stretching anything but idk...
Best Answer02-25-2021 03:54
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
02-25-2021 03:54
How about setting width/height on the text elements?
Best Answer02-25-2021 20:50
02-25-2021 20:50
I added heights to the text elements in the index.gui but no change. Looking at the documentation, text doesn't have a height attribute (https://dev.fitbit.com/build/guides/user-interface/svg/#text). Textarea does but specifying the height doesn't fix the issue. I am using font-size: 120 but when I clip the height below 132, the text completely disappears both on the simulator and on my watch.
Best Answer