Skip to content

Instantly share code, notes, and snippets.

@exhuma
Last active March 16, 2018 08:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exhuma/ddfed1da0ba1703cae820894f555be50 to your computer and use it in GitHub Desktop.
Save exhuma/ddfed1da0ba1703cae820894f555be50 to your computer and use it in GitHub Desktop.
Colorise parametric value using Python
from math import pi, cos
from functools import partial
def sinusoidal(v):
'''
Create a sinusoidal easing function.
*v* is assumed to range from 0 to 1. The function will return a new value
from 0 to 1.
>>> sinusoidal(0)
0.0
>>> sinusoidal(1)
1.0
>>> sinusoidal(0.5)
0.5
>>> sinusoidal(0.75)
0.8535533905932737
'''
output = cos(pi * v)
output = (output / 2) + 0.5
output = 1 - output
return output
def squeeze(start, end):
'''
Given a "start" and "end" value, returns slope and intercept coefficients
for a linear function which ranges from 0 to 1 and intercepts x=0 at *start*
and x=1 at *1-end*.
>>> squeeze(0, 0)
(1.0, -0.0)
>>> squeeze(0.2, 0)
(1.25, -0.25)
>>> squeeze(0, 0.2)
(1.25, -0.0)
>>> squeeze(0.2, 0.2)
(1.6666666666666665, -0.3333333333333333)
'''
tan_alpha = 1 / (1-start-end)
slope = tan_alpha
intercept = -(start * (1 / (1-start-end)))
return slope, intercept
def clamped_sinusoidal(v, x1=0.0, x2=0.0):
'''
Applies :py:func:`sinusoidal` only between *start+x1* and *end-x2*.
Returns a sinusoidal function mapping a value in [0..1] to a new value in
from [0..1]. The curve is "squeezed" between *0+start* and *1-end*
effectively ramping up late, and levelling out early.
>>> clamped_sinusoidal(0.5, 0, 0) == sinusoidal(0.5)
True
>>> clamped_sinusoidal(0.1, 0, 0) == sinusoidal(0.1)
True
>>> clamped_sinusoidal(0.9, 0, 0) == sinusoidal(0.9)
True
>>> clamped_sinusoidal(0.5, 0.2, 0.2)
0.4999999999999999
>>> clamped_sinusoidal(0.5, 0, 0.2)
0.6913417161825448
>>> clamped_sinusoidal(0.5, 0.2, 0)
0.3086582838174551
'''
a, b = squeeze(x1, x2)
if x1 and v <= x1:
return 0.0
if x2 and v >= (1-x2):
return 1.0
return sinusoidal(a*v+b)
def percentage_position(percentage, items):
'''
Returns an item from a list by a percentage position.
Example::
>>> percentage_position(0.0, [1, 2, 3])
1
>>> percentage_position(0.5, [1, 2, 3])
2
>>> percentage_position(0.99, [1, 2, 3])
3
'''
position = (len(items)-1) * percentage
return items[round(position)]
def main():
print('Visualising Easing function')
ease = partial(clamped_sinusoidal, x1=0.3, x2=0.2)
print(' Visualising Easing Curve '.center(80, '-'))
for n in range(30):
progress = ease(n/30)
print('%3s' % n, '*'*round((80*(progress))))
print(' Example with fixed pallette '.center(80, '-'))
colors = [
'#ff0000',
'#aaaa00',
'#ffff00',
'#aaff00',
'#00ff00',
]
print('Pallette:', colors)
for n in range(30):
value = ease(n / 30)
out = percentage_position(value, colors)
print('%3s' % n, out)
print(' Example with a smooth transition '.center(80, '-'))
for n in range(30):
value = ease(n / 30)
hue = 120 * value
out = 'hsl(%d%%, 50%%, 50%%)' % round(hue)
print('%3s' % n, out)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment