Skip to content

Instantly share code, notes, and snippets.

@kfl
Last active January 2, 2016 05:59
Show Gist options
  • Save kfl/8260281 to your computer and use it in GitHub Desktop.
Save kfl/8260281 to your computer and use it in GitHub Desktop.
Building a pie chart using ThreePenny HTML canvas.

Building a pie chart

  1. Get Pie.hs and pie.cabal from this gist and put them in a directory pie

  2. Get ThreePenny develop branch

     git clone https://github.com/HeinrichApfelmus/threepenny-gui.git
     cd threepenny-gui
     git checkout develop
     cd ..
    
  3. cd pie

  4. cabal sandbox init

  5. cabal sandbox add-source ../threepenny-gui

  6. cabal install --dependencies-only

  7. cabal build

  8. ./dist/build/pie/pie

-- Initial pie.cabal generated by cabal init. For further documentation,
-- see http://haskell.org/cabal/users-guide/
name: pie
version: 0.1.0.0
synopsis: Drawing a pie chart using threepenny-gui canvas
-- description:
license: MIT
license-file: LICENSE
author: Ken Friis Larsen
maintainer: ken@friislarsen.net
build-type: Simple
cabal-version: >=1.10
executable pie
main-is: Pie.hs
build-depends: base >=4.6 && <4.7, threepenny-gui >=0.5
default-language: Haskell2010
import Control.Monad
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core
{-----------------------------------------------------------------------------
Main
------------------------------------------------------------------------------}
main :: IO ()
main = startGUI defaultConfig setup
-- A data set that conveniently sum to 360, and have labels that can be used as colors
dataset = [(100, "#1f77b4"), (45, "#ff7f0e"), (80, "#2ca02c"), (10, "#d62728")
,(105,"#9467bd"), (20,"#8c564b")]
canvasSide = 416
center = (fromIntegral canvasSide / 2, fromIntegral canvasSide / 2)
radius = 100
radian angle = angle * pi / 180
setup :: Window -> UI ()
setup window = do
return window # set title "Pie Chart"
canvas <- UI.canvas
# set UI.height canvasSide
# set UI.width canvasSide
# set style [("border", "solid black 1px"), ("background", "lightgrey")]
# set UI.lineWidth 2
# set UI.strokeStyle "white"
makePie <- UI.button #+ [string "Must have pie!"]
clear <- UI.button #+ [string "Clear the canvas."]
getBody window #+ [column
[element canvas]
,element makePie, element clear
]
let drawSlice start end col = do
canvas # set' UI.fillStyle col
canvas # UI.beginPath
canvas # UI.arc center radius start end
canvas # UI.lineTo center
canvas # UI.closePath
canvas # UI.fill
canvas # UI.stroke
on UI.click makePie $ const $
foldM (\start (delta, col) -> do
let end = start+delta
drawSlice (radian start) (radian end) col
return end) 0 dataset
on UI.click clear $ const $
UI.clearCanvas canvas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment