For this example we'll be making a simple color picker that's powered by python.
import math
import purly
To set things up we'll need to stand up our model server. By default the server has a max refresh rate of 25
hertz. However for this example to be convincingly smooth we'll want to bump that up to about 60
. If you want to unlock the refresh rate set refresh=None
. We'll then hook up a layout object to a model resource (see the introductory example or read the docs if this doesn't make sense).
from example_utils import localhost
# increase model server refresh cap to 60 hertz.
purly.state.Machine(refresh=60).run()
# name the layout resource "color-wheel" and connect to the update stream
websocket_url = localhost('ws', 8000) + '/model/color-wheel/stream'
layout = purly.Layout(websocket_url)
To do this we'll need a simple function that will create an HSL (hue, saturation, and lightness) color string. The function will accept the radius of the color picker wheel, and the x-y position of the mouse in order to select a color based on the angle around the circle, and distance from the center.
def hsl(radius, x, y):
"""Return an HSL color string."""
x -= radius
y -= radius
unit_radius = int((x ** 2 + y **2) ** 0.5) / radius
degrees = int(math.atan2(x, y) * 180 / math.pi)
return "hsl(%s, 100%%, %s%%)" % (degrees, unit_radius * 100)
Next we'll need style up the the color wheel, and a selection indicator.
radius = 50
wheel = layout.html('div')
wheel.style.update(
height="%spx" % (radius * 2),
width="%spx" % (radius * 2),
backgroundColor="hsl(120, 100%, 50%)",
borderRadius="50%",
)
selection = layout.html('div')
selection.style.update(
height="20px",
width="20px",
backgroundColor="hsl(120, 100%, 50%)",
)
layout.children.append(wheel)
layout.children.append(selection)
layout.sync()
layout
You should now see the color wheel and selector indicator in the output above!
However when you mouse over the wheel nothing happens, so we'll need to hook into some mouse events to make the display animate. To do that requires the onMouseMove
and onClick
events which can be captures via the on
decorator of the wheel
element. The underlying logic of each is actually pretty simple:
onMouseMove
: if the mouse moves over the color wheel, then set the color wheel to the HSL color that corresponds to its x-y position.onClick
: if the mouse clicks on the wheel, set the selection indicator to the corresponding HSL color.@wheel.on('MouseMove')
def cause_color_change(offsetX, offsetY):
wheel.style["backgroundColor"] = hsl(50, offsetX, offsetY)
@wheel.on("Click")
def cause_color_select(offsetX, offsetY):
selection.style["backgroundColor"] = hsl(50, offsetX, offsetY)
Finally we'll need to serve up our event handlers in order to animate.
layout.serve()
Now mouse over the wheel and try selecting a color!