Dash O'Clock: Drawing Dash

Drawing Dash for the Flutter Clock Challenge

Dash O’Clock showing 10:10

Flutter announced the Flutter Clock Challenge on the 18th of November 2019. The deadline for submitting the entries for the contest was the 20th of January 2020.

I submitted my entry a few days before the deadline and on 25th of February 2020 - the judgment day it didn’t make it to the top.

There were plenty of gorgeous entries that I’ve seen and liked on Twitter so I didn’t have my hopes too high.

If you’re interested to find out more about the challenge you can do that here.

Why Dash?

My choice of clock face was done somewhere in December when I was researching interesting clock faces that I was capable of creating.

I stumbled upon the Eyeclock designed by Mike Mak:

Eyeclock by Mike Mak

This is quite nice, easy to implement and suitable for the landscape rectangular layout specification of the challenge. So I decided to go on with this concept.

Using Dash was a quite obvious choice considering its the mascot of Dart, the programming language that powers Flutter. Also, it was a choice to set my entry apart, making it a pleasant children theme. The Lenovo Smart Clock is a small cute clock, suitable for a children’s room and its current themes, although are colorful, are generic.

Dash, Dart’s mascot

Also, Dart has some sparkles in its eyes that make them perfect to act as clock handles.

Putting Dash together

I looked around other takes on drawing Dash. I got inspired by some 2D representations.

My goal was to draw Dash by "hand" using simple paths. I used Adobe Animate CC in order to draw Dash as vectors on a fixed size canvas.

I knew that I had to draw the full Dash in order to get it right on other devices not only on the Lenovo Smart Clock.

The first step was to break Dash in several parts:

Dash in simple parts

The EYE part was broken into the eye, eye sparkle, and eye socket (only the eye moving to act as minutes and hours clock handles).

After putting all together Dash looked like this:

Dash in simple lines

After adding some color and removing the lines Dash looked more colorful:

Dash in simple colors

The color palette was kept in those of Dart and Flutter logos. There is a slight addition of green as eye contours to get closer to the actual Dash fluffy mascot.

That was the final piece that I moved with from Animate to Visual Studio Code in order to use the drawing APIs to draw Dash. If you want a fast intro into the drawing world of Flutter you can read this.

Drawing Dash

The canvas that I used was a similar size of that of the Dash body and legs bounding box: 970px x 855px. The viewport that I was after was that of 800px x 480px with an offset of 85px x 100px inside the canvas.

To get a view of what I am saying you can see the canvas box in red and the viewport box in green bellow:

Canvas and viewport for Dash O’Clock

The viewport is the exact size of the Lenovo Smart Clock screen, the "canvas" proposed for this challenge.

Moving into some code, in my flutter_clock clone, I created the dash folder. There I first created the dash_parts.dart class with some static paths that are actually the equivalent of the above-illustrated parts:

import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';class DashParts {
// cache all Dash parts
static final Path dashBody;
static final Path dashFace;
static final Path dashEyeSocketsContours;
static final Path dashEyeSockets;
static final Path dashEyes;
static final Path dashEyeSparkle;
static final Path dashBelly;
static final Path dashWing;
static final Path dashLeftWing;
static final Path dashRightWing;
static final Path dashLeg;
static final Path dashLeftLeg;
static final Path dashRightLeg;
static final Path dashHair;
static final Path dashNoseBase;
static final Path dashNose;
static final Path dashNoseLeft;
static final Path dashNoseRight;
}

I’ll go through with the explanation on only one part of Dash that will illustrate how the rest is composed and that is the hair:

import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';class DashParts {
// cache Dash parts
static final Path dashLeg = _dashLeg;
static final Path dashHair = _dashHair;
static Path get _dashLeg {
return Path()
..addOval(
Rect.fromPoints(
Offset(0.0, 0.0),
Offset(50.0, 95.0),
),
)
..addOval(
Rect.fromPoints(
Offset(33.0, 0.0),
Offset(33.0 + 50.0, 95.0),
),
)
..addOval(
Rect.fromPoints(
Offset(66.0, 0.0),
Offset(66.0 + 50.0, 95.0),
),
);
}
static Path get _dashHair {
Matrix4 m = Matrix4.identity()..translate(426.5, -80.0);
List l = m.storage.toList();
return dashLeg.transform(Float64List.fromList(l));
}
}

I’ve setup a caching mechanism so that the paths are drawn only once and then reused as static members of the DashParts.dart class.

A Dash leg is made up of 3 overlapped ovals and you can see how that is formed in the private _dashLeg getter. This getter returns a Path, which you can view as a mathematical representation of what gets painted on screen (the instructions for painting). These can be reused as they are or modified before use.

As you can see the dashLeg is reused and transformed into Dash hair. We create that hair using the _dashHair getter and there a simple translation happens. This translation places the Path at the right place within the canvas:

The process of adding some hair for Dash

The dashLeg Path is the green overlapped ovals in the top left corner of the canvas. The translations to 426.5px on the X-axis and -80.0px on the Y-axis are represented with the red dotted line. The resulting Path is the blue overlapped ovals that sit nicely on Dash’s head/body. That’s the hair.

The above example would be true if the hair would be the last thing we add to Dash.

The other components follow almost the same process of composition. Some are a bit more difficult to draw (they require the use of Bézier curves or rotations next to the translation transform).

When creating Dash from all these parts there was the need to add some color to the empty Paths. That was done using the dash_paint_bucket.dart

import 'package:flutter/material.dart';class DashPaintBucket {  // Dash hair&body color
static final Paint lightBluePaint = Paint()
..color = const Color(0xFF40c4ff)
..style = PaintingStyle.fill;

}

To draw the Dash we’ll need a CustomPainter where the Paths meet their color. I’ve created 2 such custom painters: a static one and an animated one.

An example of painting only the hair would be:

import 'dart:ui';import 'package:flutter/material.dart';import 'dash_paint_bucket.dart';
import 'dash_parts.dart';
class DashStatic extends CustomPainter {
static final Offset viewportOffset = Offset(85.0, 100.0);
static final Offset referenceSize = Offset(970.0, 855.0);
@override
void paint(Canvas canvas, Size size) {
canvas.drawPath(DashParts.dashHair, DashPaintBucket.lightBluePaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}

Adding all elements together the painted result inside the Lenovo Smart Clock would be:

Dash O’Clock showing 10:10

The Git repository with the entire code can be seen here.

The actual code is the best I could do at that particular moment and in my spare time. I was still in the Dart age, regarding my Flutter skills. Although I have some skills with animation from Adobe Animate and ActionScript, animation within the Flutter world is something I am still to master.

The web demo of the clock is also available here.

Unfortunately, it’s not possible to actually place a custom clock face on the little clock made by Lenovo, other than through Photoshop.

The challenge aims to add extra clock face options to their users, though they will be chosen and delivered by Lenovo so my Dash O’Clock might never get to show time on this device.

Tha(nk|t’)s all!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store