Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Suuuuuuuuuuuuuper Simple Color Picker

edited September 2015 in Code Sharing Posts: 557

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.

Tagged:

Comments

  • edited September 2015 Posts: 557

    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!

Sign In or Register to comment.