diff --git a/TODO.md b/TODO.md
index b0816dd51..418877434 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,8 +1,9 @@
# TODO
- https://github.com/sledilnik/website/issues/770
- - tooltips
- try using different colors
+ - using color mixing function
+ - tooltips
- new OWID export
- return back the official URL, once it has been pushed to production
diff --git a/src/visualizations/App.fsproj b/src/visualizations/App.fsproj
index 4a6f7d157..0113b32e7 100644
--- a/src/visualizations/App.fsproj
+++ b/src/visualizations/App.fsproj
@@ -9,6 +9,7 @@
+
diff --git a/src/visualizations/Colors.fs b/src/visualizations/Colors.fs
new file mode 100644
index 000000000..cd2467c50
--- /dev/null
+++ b/src/visualizations/Colors.fs
@@ -0,0 +1,37 @@
+module Colors
+
+type RgbaColor = uint32
+
+let inline r(color: RgbaColor) = byte (color >>> 24)
+let inline g(color: RgbaColor) = byte (color >>> 16)
+let inline b(color: RgbaColor) = byte (color >>> 8)
+let inline a(color: RgbaColor) = byte color
+
+///
+/// Constructs the from R, G, B and alpha
+/// components.
+///
+let inline rgbaColor (r: byte) (g: byte) (b: byte) (a: byte): RgbaColor =
+ (uint32 r <<< 24) ||| (uint32 g <<< 16) ||| (uint32 b <<< 8) ||| (uint32 a)
+
+let inline mixColors colorA colorB mixRatio =
+ let mixByteValues (v1:byte) (v2: byte): byte =
+ let v1Float = float v1
+ let mixedFloat = (float v2 - v1Float) * mixRatio + v1Float
+ byte mixedFloat
+
+ match mixRatio with
+ | 0. -> colorA
+ | 1. -> colorB
+ | _ ->
+ rgbaColor
+ (mixByteValues (r colorA) (r colorB))
+ (mixByteValues (g colorA) (g colorB))
+ (mixByteValues (b colorA) (b colorB))
+ (mixByteValues (a colorA) (a colorB))
+
+let inline toHex(color: RgbaColor): string =
+ let alpha = a color
+ match alpha with
+ | 0xffuy -> sprintf "#%02x%02x%02x" (r color) (g color) (b color)
+ | _ -> sprintf "#%02x%02x%02x%02x" alpha (r color) (g color) (b color)