diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f69d3d2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Ignore build generated files +build/ +dist/ +dist.zip + +# Ignore waf lock file +.lock-waf* + +# Ignore installed node modules +node_modules/ diff --git a/README.md b/README.md index bbcb19d..695ac85 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,7 @@ This is a Rocky.js reboot of the [Concentricity](https://github.com/pebble-examples/concentricity) example watchface. It makes use of Rocky.js and Canvas APIs `rockyFillRadial` and `fillRect`, as well as demonstrates how to use the `UnobstructedArea` API. +![](screenshots/concentricity_js~emery.png) +![](screenshots/concentricity_js~diorite.png) +![](screenshots/concentricity_js~chalk.png) +![](screenshots/concentricity_js~basalt.png) diff --git a/package.json b/package.json new file mode 100644 index 0000000..cc77eec --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "concentricity_js", + "author": "MakeAwesomeHappen", + "version": "1.0.0", + "keywords": ["pebble-app"], + "private": true, + "dependencies": {}, + "pebble": { + "displayName": "concentricity_js", + "uuid": "e4b999b1-aa83-41cb-b29f-f4b74dc2e483", + "projectType": "rocky", + "sdkVersion": "3", + "enableMultiJS": true, + "watchapp": { + "watchface": true + }, + "resources": { + "media": [] + } + } +} diff --git a/screenshots/concentricity_js~basalt.png b/screenshots/concentricity_js~basalt.png new file mode 100644 index 0000000..0eb458d Binary files /dev/null and b/screenshots/concentricity_js~basalt.png differ diff --git a/screenshots/concentricity_js~chalk.png b/screenshots/concentricity_js~chalk.png new file mode 100644 index 0000000..b9e5317 Binary files /dev/null and b/screenshots/concentricity_js~chalk.png differ diff --git a/screenshots/concentricity_js~diorite.png b/screenshots/concentricity_js~diorite.png new file mode 100644 index 0000000..2ce99b9 Binary files /dev/null and b/screenshots/concentricity_js~diorite.png differ diff --git a/screenshots/concentricity_js~emery.png b/screenshots/concentricity_js~emery.png new file mode 100644 index 0000000..ae18795 Binary files /dev/null and b/screenshots/concentricity_js~emery.png differ diff --git a/src/rocky/index.js b/src/rocky/index.js new file mode 100644 index 0000000..b6446b6 --- /dev/null +++ b/src/rocky/index.js @@ -0,0 +1,42 @@ +// Copyright [2016] Pebble Technology +var rocky = require('rocky'); + +var round = require('./round'); +var rect = require('./rect'); + +function DrawCommand(platform) { + if (platform === 'chalk') { + this.hours = round.drawHours; + this.minutes = round.drawMinutes; + this.seconds = round.drawSeconds; + } else { + this.hours = rect.drawHours; + this.minutes = rect.drawMinutes; + this.seconds = rect.drawSeconds; + } + if (platform === 'diorite') { + this.hourColor = "white"; + this.minuteColor = "white"; + this.secondColor = "white"; + } else { + this.hourColor = "bluemoon"; + this.minuteColor = "vividviolet"; + this.secondColor = "richbrilliantlavender"; + } +} + +var draw = new DrawCommand(rocky.watchInfo.platform); + +rocky.on('draw', function(event) { + var ctx = event.context; + ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight); + + var date = new Date(); + draw.hours(ctx, date.getHours(), draw.hourColor); + draw.minutes(ctx, date.getMinutes(), draw.minuteColor); + draw.seconds(ctx, date.getSeconds(), draw.secondColor); +}); + +rocky.on('secondchange', function(event) { + rocky.requestDraw(); +}); diff --git a/src/rocky/rect.js b/src/rocky/rect.js new file mode 100644 index 0000000..ec20f14 --- /dev/null +++ b/src/rocky/rect.js @@ -0,0 +1,100 @@ +// Copyright [2016] Pebble Technology +var utils = require('./utils'); + +var drawBorder = function(ctx, arcId, segment, totalSegments, color){ + // Calculate x, y, width, height of border + var canvasWidth = ctx.canvas.unobstructedWidth; + var canvasHeight = ctx.canvas.unobstructedHeight; + var centerX = canvasWidth / 2; + var centerY = canvasHeight / 2; + var inset = utils.calculateInset(canvasWidth, arcId); + + var x = centerX - (canvasWidth / 2) + inset; + var y = centerY - (canvasHeight / 2) + inset; + var width = centerX + (canvasWidth / 2) - (inset * 2); + var height = centerY + (canvasHeight / 2) - (inset * 2); + var strokeWidth = utils.getStrokeWidth(canvasWidth); + + // Calculate max no of pixels in perimeter less the size of the border at + // the four corners + var perimeterMax = ((width * 2) + (height * 2)) - (strokeWidth * 4); + + // Calculate the corners + var topRight = width / 2; + var bottomRight = topRight + height - strokeWidth; + var bottomLeft = bottomRight + width - strokeWidth; + var topLeft = bottomLeft + height - strokeWidth; + + // Calculate our current position around the perimeter + var perimeterPosition = (segment * perimeterMax) / totalSegments; + + // Make sure we don't exceed maximum + if (perimeterPosition > perimeterMax) { + perimeterPosition = perimeterMax; + } + + // Set the drawing color + ctx.fillStyle = color; + + // Prefill any completed sides + // Prefill top right + if (perimeterPosition > topRight) { + ctx.fillRect((width / 2) + x, y, width / 2, strokeWidth); + } + + // Prefill right + if (perimeterPosition > bottomRight) { + ctx.fillRect(width - strokeWidth + x, strokeWidth + y, strokeWidth, height - strokeWidth); + } + + // Prefill bottom + if (perimeterPosition > bottomLeft) { + ctx.fillRect(x, height - strokeWidth + y, width - strokeWidth, strokeWidth); + } + + // Fill left + if (perimeterPosition > topLeft) { + ctx.fillRect(x, y, strokeWidth, height - strokeWidth); + } + + // Draw from the last filled side to our current position + if (perimeterPosition >= topLeft) { + // TOP LEFT to TOP MIDDLE + ctx.fillRect(strokeWidth + x, y, perimeterPosition - topLeft, strokeWidth); + } else if (perimeterPosition <= topRight) { + // TOP MIDDLE to TOP RIGHT + ctx.fillRect((width / 2) + x, y, perimeterPosition, strokeWidth); + } else if (perimeterPosition <= bottomRight) { + // TOP RIGHT to BOTTOM RIGHT + ctx.fillRect(width - strokeWidth + x, strokeWidth + y, strokeWidth, perimeterPosition - topRight); + } else if (perimeterPosition <= bottomLeft) { + // BOTTOM RIGHT to BOTTOM LEFT + ctx.fillRect(width - strokeWidth - (perimeterPosition - bottomRight) + x, height - strokeWidth + y, + perimeterPosition - bottomRight, strokeWidth); + } else if (perimeterPosition < topLeft) { + // BOTTOM LEFT to TOP LEFT + ctx.fillRect(x, height - strokeWidth - (perimeterPosition - bottomLeft) + y, + strokeWidth, perimeterPosition - bottomLeft); + } +}; + +// Handle representation for hours +var drawHours = function(ctx, hours, color) { + drawBorder(ctx, 2, hours % 12, 12, color); +}; + +// Handle representation for minutes +var drawMinutes = function(ctx, minutes, color) { + drawBorder(ctx, 1, minutes + 1, 60, color); +}; + +// Handle representation for seconds +var drawSeconds = function(ctx, seconds, color) { + drawBorder(ctx, 0, seconds + 1, 60, color); +}; + +module.exports = { + drawHours: drawHours, + drawMinutes: drawMinutes, + drawSeconds: drawSeconds +}; diff --git a/src/rocky/round.js b/src/rocky/round.js new file mode 100644 index 0000000..ed9052a --- /dev/null +++ b/src/rocky/round.js @@ -0,0 +1,52 @@ +// Copyright [2016] Pebble Technology +var utils = require('./utils'); + +var timeAngle = function(time) { + return time * (2 * Math.PI / 60); +}; +var hourAngle = function(hour) { + return hour * (2 * Math.PI / 12); +}; + +// Draw an arc with given inner/outer radii +var drawArc = function(ctx, arcId, endAngle, color) { + var startAngleOffset = Math.PI / 2; + var canvasWidth = ctx.canvas.unobstructedWidth; + var centerX = canvasWidth / 2; + var centerY = ctx.canvas.unobstructedHeight / 2; + + var strokeWidth = utils.getStrokeWidth(canvasWidth); + var outerRadius = utils.calculateOuterRadius(arcId, canvasWidth); + + // Set the drawing color + ctx.fillStyle = color; + + if (endAngle === 0) { + ctx.rockyFillRadial(centerX, centerY, outerRadius - strokeWidth, outerRadius, + -startAngleOffset, (2 * Math.PI) - startAngleOffset); + } else { + ctx.rockyFillRadial(centerX, centerY, outerRadius - strokeWidth, outerRadius, + -startAngleOffset, endAngle - startAngleOffset); + } +}; + +// Handle representation for hours +var drawHours = function(ctx, hours, color) { + drawArc(ctx, 2, hourAngle(hours % 12), color); +}; + +// Handle representation for minutes +var drawMinutes = function(ctx, minutes, color) { + drawArc(ctx, 1, timeAngle(minutes), color); +}; + +// Handle representation for seconds +var drawSeconds = function(ctx, seconds, color) { + drawArc(ctx, 0, timeAngle(seconds), color); +}; + +module.exports = { + drawHours: drawHours, + drawMinutes: drawMinutes, + drawSeconds: drawSeconds +}; diff --git a/src/rocky/utils.js b/src/rocky/utils.js new file mode 100644 index 0000000..3f8a5a5 --- /dev/null +++ b/src/rocky/utils.js @@ -0,0 +1,22 @@ +// Copyright [2016] Pebble Technology + +var PADDING = 10; +var NUM_ARCS = 3; + +var calculateInset = function(canvasWidth, arcId) { + return (getStrokeWidth(canvasWidth) + PADDING) * arcId; +}; + +var getStrokeWidth = function(canvasWidth) { + return ((canvasWidth / NUM_ARCS) / 2) - PADDING; +}; + +var calculateOuterRadius = function(arcId, canvasWidth) { + return (canvasWidth / 2) - ((getStrokeWidth(canvasWidth) + PADDING) * arcId); +}; + +module.exports = { + getStrokeWidth: getStrokeWidth, + calculateInset: calculateInset, + calculateOuterRadius: calculateOuterRadius +}; \ No newline at end of file diff --git a/wscript b/wscript new file mode 100644 index 0000000..e6b347a --- /dev/null +++ b/wscript @@ -0,0 +1,30 @@ +# +# This file is the default set of rules to compile a Pebble application. +# +# Feel free to customize this to your needs. +# +top = '.' +out = 'build' + + +def options(ctx): + ctx.load('pebble_sdk') + + +def configure(ctx): + """ + This method is used to configure your build. ctx.load(`pebble_sdk`) automatically configures + a build for each valid platform in `targetPlatforms`. Platform-specific configuration: add your + change after calling ctx.load('pebble_sdk') and make sure to set the correct environment first. + Universal configuration: add your change prior to calling ctx.load('pebble_sdk'). + """ + ctx.load('pebble_sdk') + + +def build(ctx): + ctx.load('pebble_sdk') + ctx.pbl_bundle(js=ctx.path.ant_glob(['src/pkjs/**/*.js', + 'src/pkjs/**/*.json', + 'src/common/**/*.js']), + js_entry_file='src/pkjs/index.js', + bin_type='rocky')