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

Gradient mask causes elements to overlap

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:

  1. Can I somehow "clip" the mask so it doesn't overlap with my other text?
  2. Is there some other work-around for this?

I only have a Versa 2 so I cannot check this on any other watches.

Best Answer
0 Votes
6 REPLIES 6

How many masks are you using? Can you try to simplify it and provide a sample?

Best Answer
0 Votes

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 Answer
0 Votes

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.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

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 Answer
0 Votes

How about setting width/height on the text elements?

Best Answer
0 Votes

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
0 Votes