fitbit-widget-template

This project provides a framework that can be used to create reusable visual components ('widgets') for Fitbit OS clockfaces and apps.

Places where the code needs to be customised are marked with TODO code comments. A suggested sequence is given below.

The project also includes sample code that demonstrates how to populate the framework to create a widget, and how to use such a widget in a host project. Such code is provided in comment blocks marked with EXAMPLE. The capabilities (eg, API) implemented in the example code is documented below.

Files

Files that need to be customised to create your widget:

  • app/widgets/my-widget-type/index.js
  • resources/widgets/my-widget-type/index.view
  • resources/widgets/my-widget-type/styles.css (optional)

File that needs to be distributed with your widget, but which shouldn't need to be customised:

  • app/widgets/construct-widgets.js

Files that are not a part of your widget but which demonstrate how to host and use a widget:

  • app/index.js
  • resources/index.view
  • resources/styles.css
  • resources/widget.defs

Suggested Approach

Before coding, decide:

  • what visual SVG elements are needed
  • what attributes you want to be able to define in SVG (.view) and CSS (you don't need to consider standard attributes that can be applied directly to the <use> element)
  • what properties and methods (ie, API) you'll need to allow manipulation of the widget in JavaScript at runtime (you don't need to consider standard properties and methods that can be applied directly to GraphicsElement objects because widget objects already implement that interface).

Populate the framework provided here with code for your widget. Here's a suggested order (numbers correspond to TODO comments):

  • 01 Rename my-widget-type (directory names and all references in code files) to something appropriate for your widget.
  • 02 Rename myWidgetType (in all code files) to something appropriate for your widget.
  • 03 Add class="widget-manual" to the symbol if you don't want widget instances to be constructed automatically (see note below).
  • 04 Declare one or more SVG elements. They can be different element types.
  • 05 Don't include a config element unless you need it for SVG/CSS declarations.
  • 06 Don't import parseConfig if you don't use a config element in your widget.
  • 07 If your widget doesn't use config, remove the call to parseConfig().
  • 08 If your widget doesn't include any default styles, delete the link to its CSS file.
  • 09 Define default styles (if any) for your widget.
  • 10 Define private variables and functions, and public properties and methods, for your widget.
  • 11 If you use config, define cases to handle the attributes.
  • 12 Perform any other necessary initialisation; eg, responding to SVG/CSS attributes/styles.

To test the widget or host one or more instances of it in a clockface/app:

  • 13 In your <svg>, declare <use> elements for every instance of the widget that you need.
  • 14 Widget styles can be defined or over-ridden in the clockface/app .css.
  • 15 Unless your widgets are static, include code in your clockface/app .js to manipulate them.

Widget Construction and the widget-manual Style

Before they can be used, widgets need to be constructed (see app/widgets/my-widget-type/index.js).

The framework provided here normally initiates construction of all widget instances when the clockface/app starts. This is usually preferable and allows widgets to be used very similarly to built-in Fitbit SVG elements and components.

Automatic construction may be undesirable if the SVG document is large and/or if different SVG documents are dynamically loaded at runtime. Including the style widget-manual in the widget template or instances will prevent automatic construction. At present, no method is provided to perform on-demand widget construction (coming soon).

config Element

The Fitbit build process does not allow the use of custom element data attributes in SVG or CSS. Moreover, many predefined attribute names (eg, text) can't be applied to the <use> element that specifies widget instances in .view files.

To get around these limitations, this framework includes an optional config text element that can be used to specify attributes with arbitary names. While the syntax for this is a bit ugly (although related to the HTML style attribute), it provides great flexibility. config can be used in .view and .css files; examples are included in this repository.

If you don't need to use config, all code associated with it can be removed.

Example Capabilities

The EXAMPLE code (commented out) implements the capabilities described in this section.

Most of the widget's code is for style interfaces for the widget and its child elements. This could be simplified, but the goal was to make the widget as simple as possible to use (ie, as consistent as possible with standard Fitbit SVG elements). API members that affect the whole widget are implemented by the widget object itself, whereas members that only affect one child element are implemented by that element. Closures are used to limit access to private variables, which reduces the likelihood of non-widget code breaking the widget.

Attributes applicable to <use> element in .view and .css:

  • x, y and other members of GraphicsElement
  • font-family
  • font-size

Attributes applicable to config element in .view and .css:

  • text
  • text-anchor
  • letter-spacing

Properties and method applicable to widget object in .js:

  • x, y and other members of GraphicsElement
  • text
  • textAnchor
  • letterSpacing
  • style
  • main
  • shadow
  • getBBox()

Properties applicable to widget .style object in .js:

  • opacity
  • display
  • fontFamily
  • fontSize

Property and method applicable to widget .main object in .js:

  • style
  • getBBox()

Properties applicable to widget .shadow object in .js:

  • x, y
  • style

Properties applicable to widget .main.style and .shadow.style objects in .js:

  • opacity
  • display
  • fill

Distribution

If you develop a widget that's free for other developers to use, please consider submitting it to Fitbit's ossapps repo. Note that there's a specific section for widgets.

Support

For help with widget development, post in the Fitbit SDK forum or Discord.

Acknowledgements and Other Examples

The approach to widget creation presented here was developed collaboratively between BarbWire and Gondwana Software, with input from Sergio Morchón Poveda.

The template and example code in this repository is based on BarbWire's fitbit-3D-text repository. That repository provides a more detailed example.

Other examples of widgets that use a similar approach: