├── .gitignore ├── .editorconfig ├── elm-package.json ├── src ├── Chart.elm ├── ScatterPlot.elm ├── BarChart.elm └── LineChart.elm ├── examples └── Example.elm ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # elm-package generated files 2 | elm-stuff/ 3 | # elm-repl generated files 4 | repl-temp-* 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.2", 3 | "summary": "A pure Elm Chart library", 4 | "repository": "https://github.com/wuct/elm-charts.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "src" 8 | ], 9 | "exposed-modules": [ 10 | "Chart", 11 | "BarChart", 12 | "LineChart", 13 | "ScatterPlot" 14 | ], 15 | "dependencies": { 16 | "elm-lang/core": "5.1.1 <= v < 6.0.0", 17 | "elm-lang/svg": "2.0.0 <= v < 3.0.0" 18 | }, 19 | "elm-version": "0.18.0 <= v < 0.19.0" 20 | } 21 | -------------------------------------------------------------------------------- /src/Chart.elm: -------------------------------------------------------------------------------- 1 | module Chart exposing (Datum, Data, Scale, ChartProps) 2 | 3 | {-| 4 | 5 | # Type 6 | @docs Datum, Data, Scale, ChartProps 7 | 8 | -} 9 | 10 | 11 | import Svg exposing (Attribute) 12 | 13 | 14 | {-| The first value is x-coordinate and the second value is y-coordinate. 15 | The third value is a list of customized svg attributes. 16 | -} 17 | type alias Datum msg = (Float, Float, List (Svg.Attribute msg)) 18 | 19 | 20 | {-| List of Datum. 21 | 22 | import Svg.Attributes exposing (opacity) 23 | import Chart exposing (Data) 24 | import BarChart exposing (color) 25 | 26 | 27 | data : Data msg 28 | data = 29 | [ 30 | (1, 22.2, []), 31 | (2, 34, []), 32 | (3, 56, [opacity "0.3"]), 33 | (4, 62, [color "#7F91B8"]), 34 | (5, 77, []) 35 | ] 36 | 37 | -} 38 | type alias Data msg = List (Datum msg) 39 | 40 | 41 | {-| A function which maps a coordinate to a actual position in ``. 42 | -} 43 | type alias Scale = Float -> Float 44 | 45 | 46 | {-| Props of charts. 47 | -} 48 | type alias ChartProps msg = 49 | { data : Data msg 50 | , xScale : Scale 51 | , yScale: Scale 52 | } 53 | -------------------------------------------------------------------------------- /examples/Example.elm: -------------------------------------------------------------------------------- 1 | import Svg exposing (svg) 2 | import Svg.Attributes exposing (width, height) 3 | import Chart exposing (Scale, Data) 4 | import BarChart exposing (barChart, color, width) 5 | import LineChart exposing (lineChart, color, width) 6 | import ScatterPlot exposing (scatterPlot, color, size) 7 | 8 | 9 | data : Data msg 10 | data = 11 | [ 12 | (1, 22.2, []), 13 | (2, 34, []), 14 | (3, 56, [BarChart.color "#AF86B4", ScatterPlot.size "10"]), 15 | (4, 62, []), 16 | (5, 77, []) 17 | ] 18 | 19 | 20 | xScale : Scale 21 | xScale x = 22 | 20 + x * 100 23 | 24 | 25 | yScale : Scale 26 | yScale y = 27 | 600 - y * 3 28 | 29 | 30 | main = 31 | svg 32 | [ 33 | Svg.Attributes.width "800", 34 | Svg.Attributes.height "600" 35 | ] 36 | [ 37 | barChart 38 | [ 39 | BarChart.color "#F4BDBC", 40 | BarChart.width "20" 41 | ] 42 | { data = data 43 | , xScale = xScale 44 | , yScale = yScale 45 | }, 46 | lineChart 47 | [ 48 | LineChart.color "#7E94C7", 49 | LineChart.width "4" 50 | ] 51 | { data = data 52 | , xScale = xScale 53 | , yScale = (\y -> 500 - y * 4) 54 | }, 55 | scatterPlot 56 | [ 57 | ScatterPlot.size "6", 58 | ScatterPlot.color "#D5B545" 59 | ] 60 | { data = data 61 | , xScale = xScale 62 | , yScale = (\y -> 400 - y * 4) 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, CT Wu 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /src/ScatterPlot.elm: -------------------------------------------------------------------------------- 1 | module ScatterPlot exposing 2 | (scatterPlot, size, color) 3 | 4 | {-| 5 | 6 | # Scatter Plot 7 | @docs scatterPlot 8 | 9 | # Attributes 10 | @docs size, color 11 | 12 | -} 13 | 14 | 15 | import List exposing (map) 16 | import Svg exposing (Svg, Attribute, g, circle) 17 | import Svg.Attributes exposing (fill, cx, cy, r) 18 | import Chart exposing (Data, Scale, ChartProps) 19 | 20 | 21 | type alias DotProps = 22 | { x : Float 23 | , y : Float 24 | } 25 | 26 | 27 | {-| Set dot size. 28 | -} 29 | size : String -> Svg.Attribute msg 30 | size = 31 | Svg.Attributes.r 32 | 33 | 34 | {-| Set dot color. 35 | -} 36 | color : String -> Svg.Attribute msg 37 | color = 38 | Svg.Attributes.fill 39 | 40 | 41 | dot : List (Svg.Attribute msg) -> DotProps -> Svg msg 42 | dot attrs { x, y } = 43 | Svg.circle 44 | ([ 45 | Svg.Attributes.cx (toString x), 46 | Svg.Attributes.cy (toString y), 47 | size "4", 48 | color "grey" 49 | ] ++ attrs) 50 | [] 51 | 52 | 53 | {-| Create a scatter plot. 54 | 55 | import Svg exposing (svg) 56 | import Svg.Attributes exposing (width, height) 57 | import Chart exposing (Scale, Data) 58 | import ScatterPlot exposing (scatterPlot, color, size) 59 | 60 | 61 | data : Data msg 62 | data = 63 | [ 64 | (1, 22.2, []), 65 | (2, 34, []), 66 | (3, 56, []), 67 | (4, 62, []), 68 | (5, 77, []) 69 | ] 70 | 71 | 72 | xScale : Scale 73 | xScale x = 74 | 20 + x * 20 75 | 76 | 77 | yScale : Scale 78 | yScale y = 79 | 400 - y * 3 80 | 81 | 82 | main = 83 | svg 84 | [ 85 | Svg.Attributes.width "600", 86 | Svg.Attributes.height "400" 87 | ] 88 | [ 89 | scatterPlot 90 | [ 91 | ScatterPlot.color "#9F7088", 92 | ScatterPlot.size "4" 93 | ] 94 | { data = data 95 | , xScale = xScale 96 | , yScale = yScale 97 | } 98 | ] 99 | 100 | -} 101 | scatterPlot : List (Svg.Attribute msg) -> (ChartProps msg) -> Svg msg 102 | scatterPlot attrs { data, xScale, yScale } = 103 | g [] 104 | ( 105 | map 106 | (\(x, y, dotAttrs) -> dot (attrs ++ dotAttrs) { x = xScale(x), y = yScale(y) }) 107 | data 108 | ) 109 | -------------------------------------------------------------------------------- /src/BarChart.elm: -------------------------------------------------------------------------------- 1 | module BarChart exposing 2 | (barChart, width, color) 3 | 4 | {-| 5 | 6 | # Bar Chart 7 | @docs barChart 8 | 9 | # Attributes 10 | @docs width, color 11 | 12 | -} 13 | 14 | import List exposing (map) 15 | import Svg exposing (Svg, Attribute, g, line) 16 | import Svg.Attributes exposing (strokeWidth, stroke, x1, x2, y1, y2) 17 | import Chart exposing (Data, Scale, ChartProps) 18 | 19 | 20 | type alias BarProps = 21 | { x : Float 22 | , y1 : Float 23 | , y2 : Float 24 | } 25 | 26 | 27 | {-| Set bar width. 28 | -} 29 | width : String -> Svg.Attribute msg 30 | width = 31 | Svg.Attributes.strokeWidth 32 | 33 | 34 | {-| Set bar color. 35 | -} 36 | color : String -> Svg.Attribute msg 37 | color = 38 | Svg.Attributes.stroke 39 | 40 | 41 | bar : List (Svg.Attribute msg) -> BarProps -> Svg msg 42 | bar attrs { x, y1, y2 } = 43 | Svg.line 44 | ([ 45 | Svg.Attributes.x1 (toString x), 46 | Svg.Attributes.x2 (toString x), 47 | Svg.Attributes.y1 (toString y1), 48 | Svg.Attributes.y2 (toString y2), 49 | width "10", 50 | color "grey" 51 | ] ++ attrs) 52 | [] 53 | 54 | 55 | {-| Create a bar chart. 56 | 57 | import Svg exposing (svg) 58 | import Svg.Attributes exposing (width, height) 59 | import Chart exposing (Scale, Data) 60 | import BarChart exposing (barChart, color, width) 61 | 62 | 63 | data : Data msg 64 | data = 65 | [ 66 | (1, 22.2, []), 67 | (2, 34, []), 68 | (3, 56, []), 69 | (4, 62, []), 70 | (5, 77, []) 71 | ] 72 | 73 | 74 | xScale : Scale 75 | xScale x = 76 | 20 + x * 20 77 | 78 | 79 | yScale : Scale 80 | yScale y = 81 | 400 - y * 3 82 | 83 | 84 | main = 85 | svg 86 | [ 87 | Svg.Attributes.width "600", 88 | Svg.Attributes.height "400" 89 | ] 90 | [ 91 | barChart 92 | [ 93 | BarChart.color "#9F7088", 94 | BarChart.width "10" 95 | ] 96 | { data = data 97 | , xScale = xScale 98 | , yScale = yScale 99 | } 100 | ] 101 | 102 | -} 103 | barChart : List (Svg.Attribute msg) -> (ChartProps msg) -> Svg msg 104 | barChart attrs { data, xScale, yScale } = 105 | g [] 106 | ( 107 | map 108 | (\(x, y, barAttrs) -> bar (attrs ++ barAttrs) { x = xScale(x), y1 = yScale(0), y2 = yScale(y) }) 109 | data 110 | ) 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-charts 2 | A pure Elm chart library 3 | 4 | [![GitHub tag](https://img.shields.io/github/tag/wuct/elm-charts.svg)](http://package.elm-lang.org/packages/wuct/elm-charts) 5 | 6 | __This project is still in alpha. APIs might change heavily in the future.__ 7 | 8 | 9 | - [__Demo__](https://wuct.github.io/elm-charts/) 10 | - [__API Documentation__](http://package.elm-lang.org/packages/wuct/elm-charts/latest/) 11 | 12 | ## To Try 13 | 14 | 1. `git clone https://github.com/wuct/elm-charts.git` 15 | 2. `cd elm-charts` 16 | 3. `elm package install` 17 | 4. `elm reactor` 18 | 5. go to [http://localhost:8000/examples/Example.elm]() 19 | 20 | 21 | ## To Install 22 | 23 | `elm package install wuct/elm-charts` 24 | 25 | ## Update to Elm >= 0.18 26 | 27 | Run 28 | 29 | ` 30 | elm-package install elm-lang/svg 2.0.0 31 | elm-package install elm-lang/core 5.1.1 32 | ` 33 | 34 | Or update existing packages 35 | 36 | 37 | 38 | ## Quick Example 39 | 40 | 41 | ```Elm 42 | import Svg exposing (svg) 43 | import Svg.Attributes exposing (width, height) 44 | import Chart exposing (Scale, Data) 45 | import BarChart exposing (barChart, color, width) 46 | import LineChart exposing (lineChart, color, width) 47 | import ScatterPlot exposing (scatterPlot, color, size) 48 | 49 | 50 | data : Data msg 51 | data = 52 | [ 53 | (1, 22.2, []), 54 | (2, 34, []), 55 | (3, 56, [BarChart.color "yellowgreen"]), 56 | (4, 62, []), 57 | (5, 77, []) 58 | ] 59 | 60 | 61 | xScale : Scale 62 | xScale x = 63 | 20 + x * 20 64 | 65 | 66 | yScale : Scale 67 | yScale y = 68 | 600 - y * 3 69 | 70 | 71 | main = 72 | svg 73 | [ 74 | Svg.Attributes.width "1000", 75 | Svg.Attributes.height "600" 76 | ] 77 | [ 78 | barChart 79 | [ 80 | BarChart.color "pink", 81 | BarChart.width "10" 82 | ] 83 | { data = data 84 | , xScale = xScale 85 | , yScale = yScale 86 | }, 87 | lineChart 88 | [ 89 | LineChart.color "#7E94C7" 90 | ] 91 | { data = data 92 | , xScale = xScale 93 | , yScale = (\y -> 500 - y * 3) 94 | }, 95 | scatterPlot 96 | [] 97 | { data = data 98 | , xScale = xScale 99 | , yScale = (\y -> 400 - y * 3) 100 | } 101 | ] 102 | ``` 103 | 104 | 105 | ## To Contribute 106 | 107 | 1. Fork it 108 | 2. Create your feature branch (`git checkout -b my-new-feature`) 109 | 3. Commit your changes (`git commit -am 'Add some feature'`) 110 | 4. Push to the branch (`git push origin my-new-feature`) 111 | 5. Create new Pull Request 112 | -------------------------------------------------------------------------------- /src/LineChart.elm: -------------------------------------------------------------------------------- 1 | module LineChart exposing 2 | (lineChart, width, color) 3 | 4 | {-| 5 | 6 | # Line Chart 7 | @docs lineChart 8 | 9 | # Attributes 10 | @docs width, color 11 | 12 | -} 13 | 14 | import List exposing (map, foldl) 15 | import String exposing (dropRight) 16 | import Svg exposing (Svg, g, path) 17 | import Svg.Attributes exposing (strokeWidth, stroke, d, fill) 18 | import Chart exposing (Data, Scale, ChartProps) 19 | 20 | 21 | {-| Set line width. 22 | -} 23 | width : String -> Svg.Attribute msg 24 | width = 25 | Svg.Attributes.strokeWidth 26 | 27 | 28 | {-| Set line color. 29 | -} 30 | color : String -> Svg.Attribute msg 31 | color = 32 | Svg.Attributes.stroke 33 | 34 | 35 | creatPath : List (Float, Float) -> String 36 | creatPath = 37 | List.foldl 38 | (\(x, y) path -> path ++ (toString x) ++ "," ++ (toString y) ++ "L") 39 | "M" 40 | >> String.dropRight 1 41 | 42 | 43 | transformDataToCoordinatesByScale : Scale -> Scale -> Data msg -> List (Float, Float) 44 | transformDataToCoordinatesByScale xScale yScale = 45 | List.map(\(x, y, _) -> (xScale(x), yScale(y))) 46 | 47 | 48 | convertDataToPathByScale : Scale -> Scale -> Data msg -> String 49 | convertDataToPathByScale xScale yScale data = 50 | transformDataToCoordinatesByScale xScale yScale data |> creatPath 51 | 52 | 53 | {-| Create a line chart. 54 | 55 | import Svg exposing (svg) 56 | import Svg.Attributes exposing (width, height) 57 | import Chart exposing (Scale, Data) 58 | import LineChart exposing (lineChart, color, width) 59 | 60 | 61 | data : Data msg 62 | data = 63 | [ 64 | (1, 22.2, []), 65 | (2, 34, []), 66 | (3, 56, []), 67 | (4, 62, []), 68 | (5, 77, []) 69 | ] 70 | 71 | 72 | xScale : Scale 73 | xScale x = 74 | 20 + x * 20 75 | 76 | 77 | yScale : Scale 78 | yScale y = 79 | 400 - y * 3 80 | 81 | 82 | main = 83 | svg 84 | [ 85 | Svg.Attributes.width "600", 86 | Svg.Attributes.height "400" 87 | ] 88 | [ 89 | lineChart 90 | [ 91 | LineChart.color "#9F7088", 92 | LineChart.width "10" 93 | ] 94 | { data = data 95 | , xScale = xScale 96 | , yScale = yScale 97 | } 98 | ] 99 | 100 | -} 101 | lineChart : List (Svg.Attribute msg) -> (ChartProps msg) -> Svg msg 102 | lineChart attrs { data, xScale, yScale } = 103 | g [] 104 | [ 105 | path 106 | ([ 107 | Svg.Attributes.d (convertDataToPathByScale xScale yScale data), 108 | Svg.Attributes.fill "transparent", 109 | width "2", 110 | color "grey" 111 | ] ++ attrs) 112 | [] 113 | ] 114 | --------------------------------------------------------------------------------