It looks like you're new here. If you want to get involved, click one of these buttons!
Want a super-simple color picker that won't clutter your UI? Try this!
It's the SwipeColorPicker, and here's how it works. It draws a circle on the screen, which can be resized and repositioned as you like. The circle shows a solid color. If you touch inside the circle and drag in any direction, you can change the color. Dragging vertically changes saturation and brightness, and dragging horizontally changes hue. That's it! Place this one circle anywhere in your UI, at any visible size, and you've got yourself a color picker.
It's not the best color picker, but it'll get you up and running in under a minute, and save you a lot of time re-inventing the wheel.
Many thanks to @SkyTheCoder for sharing the hsv-to-rgb conversion method on these forums. And if you want a better color picker, check his out: http://codea.io/talk/discussion/3285/color-chooser. Just be sure to skip the long argument over pentagons vs. circles.
Here's my widget:
--# Main
-- SwipeColorPicker
-- Use this function to perform your initial setup
function setup()
swiper = SwipeColorPicker()
end
-- This function gets called once every frame
function draw()
background(12, 12, 12, 255)
swiper:draw()
end
function touched(touch)
swiper:touched(touch)
end
--# SwipeColorPicker
SwipeColorPicker = class()
function SwipeColorPicker:init(x)
self.hsv = vec4(0.5,1.0,1.0,1.0)
self.color = self:updateRGB()
self.size = 80
self.position = vec2(200,200)
self.strokeSize = 3
self.active = false
self.sizePickerMode = false
end
function SwipeColorPicker:swipeHorizontal(amount)
amount = amount / WIDTH
self:hsvShift(amount, 0)
end
function SwipeColorPicker:hsvShift(h,v)
self.hsv.x = self.hsv.x + h
if self.hsv.y < 1 then
self.hsv.y = self.hsv.y - v
if self.hsv.y < 0 then
self.hsv.y = 0
end
if self.hsv.y > 1 then
self.hsv.z = self.hsv.z - math.fmod(self.hsv.y, 1)
self.hsv.y = 1
end
else
self.hsv.z = self.hsv.z + v
if self.hsv.z > 1 then
self.hsv.y = self.hsv.y - math.fmod(self.hsv.z, 1)
self.hsv.z = 1
end
end
self:updateRGB()
end
function SwipeColorPicker:swipeVertical(amount)
amount = amount / HEIGHT * 3
self:hsvShift(0, amount)
end
function SwipeColorPicker:draw()
-- Codea does not automatically call this method
-- background(self.color)
pushStyle()
ellipseMode(CENTER)
if self.active then
fill(197, 167, 167, 109)
ellipse(self.position.x, self.position.y-0.5, self.size+6)
ellipse(self.position.x, self.position.y+1.5, self.size+6)
end
-- the bezels
fill(self.color)
ellipse(self.position.x, self.position.y + 2, self.size)
fill(0, 0, 0, 179)
ellipse(self.position.x, self.position.y + 2, self.size)
fill(self.color)
ellipse(self.position.x, self.position.y - 2, self.size)
fill(255, 255, 255, 145)
ellipse(self.position.x, self.position.y - 2, self.size)
-- the color
fill(self.color)
ellipse(self.position.x, self.position.y, self.size)
if self.sizePickerMode then
stroke(self.color)
strokeWidth(self.strokeSize)
line(self.position.x - 20,self.position.y + self.size - (self.size / 3),
self.position.x + 20,self.position.y + self.size - (self.size / 3))
strokeWidth(0)
end
popStyle()
end
function SwipeColorPicker:touched(touch)
local insideCircle
if touch.state == BEGAN then
local radius = self.size * 0.5
local closeEnoughX = math.abs(touch.x-self.position.x) < radius
local closeEnoughY = math.abs(touch.y-self.position.y) < radius
if closeEnoughX and closeEnoughY then
self.active = true
end
end
if self.active then
if touch.tapCount == 2 and self.sizePickerMode == false then
self.sizePickerMode = true
end
if self.sizePickerMode then
self.strokeSize = self.strokeSize + touch.deltaY
if self.strokeSize < 0.5 then
self.strokeSize = 0.5
end
else
if math.abs(touch.deltaX) > math.abs(touch.deltaY) then
self:swipeHorizontal(touch.deltaX)
else
self:swipeVertical(touch.deltaY)
end
end
if touch.state == ENDED then
self.active = false
self.sizePickerMode = false
end
end
end
function SwipeColorPicker:updateRGB()
self.color = color(self:hsvToRGB(self.hsv.x, self.hsv.y,self.hsv.z))
return self.color
end
function SwipeColorPicker:hsvToRGB(h, s, v)
--thanks to SkyTheCoder on the Codea forums
local r, g, b
local i = math.floor(h * 6)
local f = h * 6 - i
local p = v * (1 - s)
local q = v * (1 - f * s)
local t = v * (1 - (1 - f) * s)
local switch = i % 6
if switch == 0 then
r = v
g = t
b = p
elseif switch == 1 then
r = q
g = v
b = p
elseif switch == 2 then
r = p
g = v
b = t
elseif switch == 3 then
r = p
g = q
b = v
elseif switch == 4 then
r = t
g = p
b = v
elseif switch == 5 then
r = v
g = p
b = q
end
return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255)
end
While it is a complete solution, should anyone feel so inspired, I think it could use a better-looking bezel and a better "active state" indicator.
Comments
edit
I updated the code above: it now includes a stroke-size setter. If you double-tap the swath, a line appears above it. Then dragging up or down changes the stroke size. Letting go reverts back to color-choosing mode.
It's less easily configurable now, because the stroke preview position will have to be adjusted depending on screen placement, but that wouldn't be too hard. Still a lot of bang for the buck!