Skip to content

Commit

Permalink
add concentric data watchface
Browse files Browse the repository at this point in the history
  • Loading branch information
novvember committed Nov 17, 2024
1 parent d9a74ce commit bde93e4
Show file tree
Hide file tree
Showing 109 changed files with 1,148 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ To add a new watchface to your device:
| ![](./g-shock/demo.png) | G-Shock | All round watches | ✅ Done |
| ![](./grotesque/demo.png) | Grotesque | All round watches | ✅ Done |
| ![](./time-machine/demo.png) | Time Machine | All round watches | ✅ Done |
| ![](./concentric-data/demo.png) | Concentric Data | All round watches | ✅ Done |
15 changes: 15 additions & 0 deletions concentric-data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.DS_Store
node_modules/**
dist/*
npm-debug.log
yarn-debug.log*
yarn-error.log*
yarn.lock
package-lock.json
selenium-debug.log
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
33 changes: 33 additions & 0 deletions concentric-data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Concentric Data Watchface
Watchface for Amazfit GTR Mini and for other round ZeppOS watch.

![demo](./demo-gtr-mini.png)

## Features

**Main features**
- sliding minutes and seconds
- date and weekday
- step counter
- sleep time or sunrise/sunset time if no sleep data
- heart rate
- battery level


**Model compatibility:** Amazfit GTR Mini, Amazfit GTR 4 and all other round ZeppOS watches

**Note: It requires devices with ZeppOS 2 and higher and is not compatible with older models like the GTR 3 and GTR 3.**

**AOD:** No

**Tap-zones:** No

**Language:** English, Russian

**Inspired:** [Famous Concentric Watchface for Pixel Watches](https://play.google.com/store/apps/details?id=com.watchfacedesigns.Concentric)

## Download ⏬

To install it to your smartwatch:

See instructions [here](https://github.com/novvember/amazfit-watchfaces/blob/main/README.md) to download and install to your watch.
10 changes: 10 additions & 0 deletions concentric-data/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
App({
globalData: {},
onCreate(options) {
console.log('app on create invoke')
},

onDestroy(options) {
console.log('app on destroy invoke')
}
})
58 changes: 58 additions & 0 deletions concentric-data/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"configVersion": "v3",
"app": {
"appId": 1067740,
"appName": "Concentric Data",
"appType": "watchface",
"version": {
"code": 1,
"name": "1.0.0"
},
"icon": "icon.png",
"vender": "novvember",
"cover": [
"cover.png"
],
"description": "Concentric Data watchface. Source code here: https://github.com/novvember/amazfit-watchfaces"
},
"runtime": {
"apiVersion": {
"compatible": "1.0.0",
"target": "1.0.1",
"minVersion": "1.0.0"
}
},
"permissions": [],
"targets": {
"common": {
"module": {
"watchface": {
"path": "watchface/index",
"main": 1,
"editable": 0,
"lockscreen": 1,
"photoscreen": 0
}
},
"platforms": [
{
"st": "r"
}
],
"designWidth": 480
}
},
"i18n": {
"en-US": {
"appName": "Concentric Data"
},
"ru-RU": {
"appName": "Concentric Data"
},
"uk-UA": {
"appName": "Concentric Data"
}
},
"defaultLanguage": "en-US",
"debug": false
}
Binary file added concentric-data/assets/common.r/cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/data/dot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added concentric-data/assets/common.r/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/%.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/a.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/b.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/c.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/colon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/e.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/f.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/g.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/h.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/i.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/j.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added concentric-data/assets/common.r/text_chars/k.png
Binary file added concentric-data/assets/common.r/text_chars/l.png
Binary file added concentric-data/assets/common.r/text_chars/m.png
Binary file added concentric-data/assets/common.r/text_chars/n.png
Binary file added concentric-data/assets/common.r/text_chars/o.png
Binary file added concentric-data/assets/common.r/text_chars/p.png
Binary file added concentric-data/assets/common.r/text_chars/q.png
Binary file added concentric-data/assets/common.r/text_chars/r.png
Binary file added concentric-data/assets/common.r/text_chars/s.png
Binary file added concentric-data/assets/common.r/text_chars/space.png
Binary file added concentric-data/assets/common.r/text_chars/t.png
Binary file added concentric-data/assets/common.r/text_chars/u.png
Binary file added concentric-data/assets/common.r/text_chars/v.png
Binary file added concentric-data/assets/common.r/text_chars/w.png
Binary file added concentric-data/assets/common.r/text_chars/x.png
Binary file added concentric-data/assets/common.r/text_chars/y.png
Binary file added concentric-data/assets/common.r/text_chars/z.png
Binary file added concentric-data/assets/common.r/text_chars/а.png
Binary file added concentric-data/assets/common.r/text_chars/б.png
Binary file added concentric-data/assets/common.r/text_chars/в.png
Binary file added concentric-data/assets/common.r/text_chars/г.png
Binary file added concentric-data/assets/common.r/text_chars/д.png
Binary file added concentric-data/assets/common.r/text_chars/е.png
Binary file added concentric-data/assets/common.r/text_chars/ж.png
Binary file added concentric-data/assets/common.r/text_chars/з.png
Binary file added concentric-data/assets/common.r/text_chars/и.png
Binary file added concentric-data/assets/common.r/text_chars/й.png
Binary file added concentric-data/assets/common.r/text_chars/к.png
Binary file added concentric-data/assets/common.r/text_chars/л.png
Binary file added concentric-data/assets/common.r/text_chars/м.png
Binary file added concentric-data/assets/common.r/text_chars/н.png
Binary file added concentric-data/assets/common.r/text_chars/о.png
Binary file added concentric-data/assets/common.r/text_chars/п.png
Binary file added concentric-data/assets/common.r/text_chars/р.png
Binary file added concentric-data/assets/common.r/text_chars/с.png
Binary file added concentric-data/assets/common.r/text_chars/т.png
Binary file added concentric-data/assets/common.r/text_chars/у.png
Binary file added concentric-data/assets/common.r/text_chars/ф.png
Binary file added concentric-data/assets/common.r/text_chars/х.png
Binary file added concentric-data/assets/common.r/text_chars/ц.png
Binary file added concentric-data/assets/common.r/text_chars/ч.png
Binary file added concentric-data/assets/common.r/text_chars/ш.png
Binary file added concentric-data/assets/common.r/text_chars/щ.png
Binary file added concentric-data/assets/common.r/text_chars/ъ.png
Binary file added concentric-data/assets/common.r/text_chars/ы.png
Binary file added concentric-data/assets/common.r/text_chars/ь.png
Binary file added concentric-data/assets/common.r/text_chars/э.png
Binary file added concentric-data/assets/common.r/text_chars/ю.png
Binary file added concentric-data/assets/common.r/text_chars/я.png
Binary file added concentric-data/assets/common.r/text_chars/ё.png
Binary file added concentric-data/assets/common.r/text_chars/▲.png
Binary file added concentric-data/assets/common.r/text_chars/☀.png
Binary file added concentric-data/assets/common.r/text_chars/☼.png
Binary file added concentric-data/assets/common.r/text_chars/✱.png
Binary file added concentric-data/assets/common.r/text_chars/❤.png
Binary file added concentric-data/assets/common.r/time/frame.png
Binary file added concentric-data/assets/common.r/time/minute.png
Binary file added concentric-data/assets/common.r/time/second.png
Binary file added concentric-data/demo-balance.png
Binary file added concentric-data/demo-gtr-3-pro.png
Binary file added concentric-data/demo-gtr-4.png
Binary file added concentric-data/demo-gtr-mini.png
Binary file added concentric-data/demo-t-rex-2.png
Binary file added concentric-data/demo.png
Binary file added concentric-data/preview.png
88 changes: 88 additions & 0 deletions concentric-data/utils/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
TEXT_CHAR_HEIGHT,
TEXT_CHAR_WIDTH,
TEXT_CHARS,
} from '../utils/textChars';

const lang = DeviceRuntimeCore.HmUtils.getLanguage();
const isRusLang = ['ru-RU', 'uk-UA'].includes(lang);

const { width, height } = hmSetting.getDeviceInfo();

export const SCREEN = {
width,
height,
centerX: width / 2,
centerY: height / 2,
};

export const COLORS = {
primary: 0xffffff,
secondary: 0xbdbdbd,
tertiary: 0x525457,
};

export const FONTS = {
primary: 'fonts/FiraSansCondensed-Medium.ttf',
secondary: 'fonts/FiraSans-Regular.ttf',
tertiary: 'fonts/FiraSans-Medium.ttf',
};

export const SECOND = {
image: {
src: 'time/second.png',
},
text: {
width: px(30),
height: px(30),
textSize: px(22),
color: COLORS.secondary,
radius: px(224),
},
};

export const MINUTE = {
image: {
src: 'time/minute.png',
},
text: {
width: px(40),
height: px(40),
textSize: px(28),
color: COLORS.secondary,
radius: px(112),
},
};

export const CURRENT_HOUR = {
width: px(140),
height: px(140),
textSize: px(110),
color: COLORS.primary,
};

export const CURRENT_MINUTE = {
width: px(70),
height: px(70),
textSize: px(54),
color: COLORS.primary,
radius: px(100),
};

export const MIN_ANGLE_TO_UPDATE_WHEEL = 0.7;

export const DATA = {
radius: px(186),
circleText: {
charImages: TEXT_CHARS,
imageWidth: TEXT_CHAR_WIDTH,
imageHeight: TEXT_CHAR_HEIGHT,
},
arc: {
width: px(5),
},
};

export const WEEKDAYS = isRusLang
? ['ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ', 'ВС']
: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'];
90 changes: 90 additions & 0 deletions concentric-data/utils/createCircleTextWidget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Converts radian angle value to degrees
* @param {number} rad - radian value
* @returns {number} - degrees value
*/
function radiansToDegrees(rad) {
return (rad * 180) / Math.PI;
}

/**
* Calculates angular length of element
* @param {Number} r - radius of circle, where element is
* @param {Number} length - size of elenet
* @returns {Number} - angle in degrees
*/
function calculateAnglularLength(r, length) {
return radiansToDegrees(Math.acos((2 * r ** 2 - length ** 2) / (2 * r ** 2)));
}

/**
* Builds circle text, where every char is hmUI.widget.IMG widget
* - center of text rotation is the center of the screen of w480 size
* @param {Object} params
* @returns {Objcet}
*/
export function createCircleTextWidget({
maxLength,
text,
angleStart,
radius,
gap,
charImages,
imageWidth,
imageHeight,
isTextReversed,
}) {
const SCREEN_SIZE = px(480);

if (isTextReversed) {
angleStart *= -1;
}

const chars = text
.toLowerCase()
.slice(0, maxLength)
.padEnd(maxLength, ' ')
.split('');
const imageAngle = calculateAnglularLength(radius, imageWidth);
let gapAngle = calculateAnglularLength(radius, gap);

if (gap < 0) {
gapAngle *= -1;
}

const widgets = chars.map((char, i) =>
hmUI.createWidget(hmUI.widget.IMG, {
src: charImages[char] || charImages[' '],
w: SCREEN_SIZE,
h: SCREEN_SIZE,
x: 0,
y: 0,
pos_x: SCREEN_SIZE / 2 - imageWidth / 2,
pos_y: isTextReversed
? SCREEN_SIZE / 2 + radius
: SCREEN_SIZE / 2 - radius - imageHeight,
center_x: SCREEN_SIZE / 2,
center_y: SCREEN_SIZE / 2,
angle: isTextReversed
? angleStart - i * imageAngle - i * gapAngle
: angleStart + i * imageAngle + i * gapAngle,
show_level: hmUI.show_level.ONLY_NORMAL,
}),
);

const updateText = (newText) => {
newText = newText.toLowerCase();

for (let i = 0; i < chars.length; i++) {
if (!newText[i]) newText[i] = ' ';
if (chars[i] === newText[i]) continue;

widgets[i].setProperty(
hmUI.prop.SRC,
charImages[newText[i]] || charImages[' '],
);
}
};

return { updateText };
}
17 changes: 17 additions & 0 deletions concentric-data/utils/degrees.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Converts radian angle value to degrees
* @param {number} rad - radian value
* @returns {number} - degrees value
*/
export function radiansToDegrees(rad) {
return (rad * 180) / Math.PI;
}

/**
* Converts degrees angle value to radian
* @param {number} deg - degrees value
* @returns {number} - radian value
*/
export function degreesToRadians(deg) {
return (deg * Math.PI) / 180;
}
28 changes: 28 additions & 0 deletions concentric-data/utils/getAngleFromTime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Transforms seconds time value to angle of second hand
* @param {Number} seconds
* @returns {Number}
*/
export function getAngleFromSeconds(seconds) {
return seconds * 6;
}

/**
* Transforms minutes ans seconds time value to angle of minute hand
* @param {Number} minutes
* @param {Number} seconds
* @returns {Number}
*/
export function getAngleFromMinutes(minutes, seconds = 0) {
return ((minutes + seconds / 60) * 360) / 60;
}

/**
* Transforms hours time value to angle of hour hand
* @param {Number} hours
* @returns {Number}
*/
export function getAngleFromHours(hours) {
hours = hours % 12;
return (hours * 360) / 12;
}
30 changes: 30 additions & 0 deletions concentric-data/utils/getClosestSunriseSunsetTime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Calculates closest sun time (will it be sunset or sunrise) and its time in minutes
* @param {*} timeSensor - hmSensor.id.TIME
* @param {*} timeSensor - hmSensor.id.WEATHER
* @returns {Object}
*/
export function getClosestSunriseSunsetTime(timeSensor, weatherSensor) {
const { hour, minute } = timeSensor;
const forecastWeather = weatherSensor.getForecastWeather();
const tideData = forecastWeather.tideData;

if (!tideData.count) {
return;
}

const nowMins = hour * 60 + minute;
const { sunrise, sunset } = tideData.data[0] || {};
const sunriseMins = sunrise.hour * 60 + sunrise.minute;
const sunsetMins = sunset.hour * 60 + sunset.minute;

const isDay = nowMins >= sunriseMins && nowMins <= sunsetMins;
const type = isDay ? 'sunset' : 'sunrise';
const obj = isDay ? sunset : sunrise;

return {
type,
hour: obj.hour,
minute: obj.minute,
};
}
Loading

0 comments on commit bde93e4

Please sign in to comment.