├── images ├── dots1.png ├── dots2.png ├── dots3.png ├── dots4.png ├── junk.png ├── space.png ├── Example1.png ├── Example2.png ├── Example3.png ├── colors.png ├── legends1.png ├── legends2.png ├── legends3.png ├── legends4.png ├── legends5.png ├── ranges.png ├── ranges2.png ├── ranges3.png ├── ranges4.png ├── shapes.png ├── tooltip1.png ├── tooltip2.png ├── chartarea.png ├── linechart1.png ├── linechart2.png ├── linechart3.png ├── linechart4.png ├── linechart5.png ├── linechart6.png ├── linechart7.png ├── intersection.png ├── intersection1.png ├── interpolation2.png ├── interpolation3.png └── interpolation4.png ├── docs ├── assets │ ├── favicon.ico │ ├── favicon.png │ └── main.css ├── src │ └── Random │ │ └── Pipeline.elm ├── index.html └── highlight │ ├── terezka.css │ └── LICENSE ├── .gitignore ├── examples ├── Docs │ ├── LineChart │ │ ├── Example1.elm │ │ ├── Example2.elm │ │ ├── Example3.elm │ │ ├── Example4.elm │ │ ├── Example5.elm │ │ ├── Example6.elm │ │ ├── Example7.elm │ │ ├── Example9.elm │ │ └── Example8.elm │ ├── Dots │ │ ├── Example1.elm │ │ ├── Example2.elm │ │ ├── Example5.elm │ │ ├── Example3.elm │ │ ├── Example4.elm │ │ └── Example6.elm │ ├── Line │ │ ├── Example1.elm │ │ └── Example2.elm │ ├── Container │ │ ├── Example1.elm │ │ ├── Example4.elm │ │ ├── Example2.elm │ │ └── Example3.elm │ ├── Legends │ │ ├── Example2.elm │ │ ├── Example1.elm │ │ └── Example3.elm │ ├── Axis │ │ ├── Example1.elm │ │ ├── Example2.elm │ │ ├── Example5.elm │ │ ├── Example4.elm │ │ ├── Example3.elm │ │ └── Example6.elm │ ├── Colors │ │ └── Example1.elm │ ├── Intersection │ │ └── Example1.elm │ ├── Junk │ │ ├── Example3.elm │ │ └── Example1.elm │ ├── Events │ │ ├── Example2.elm │ │ ├── Example1.elm │ │ ├── Example3.elm │ │ └── Example4.elm │ ├── Values │ │ └── Example3.elm │ └── Range │ │ └── Example1.elm ├── Simple.elm ├── elm.json ├── Lines.elm ├── Size.elm ├── Explanation │ ├── Intersections.elm │ ├── ChartArea.elm │ └── SvgAndDataSpace.elm ├── Area.elm ├── Interpolation.elm ├── Line.elm ├── Grid.elm ├── Intersection.elm ├── Container.elm ├── Dots.elm ├── Events3.elm ├── Events2.elm ├── Tooltip1.elm ├── Tooltip3.elm ├── BrokenData.elm ├── LotsOfData.elm └── Legends.elm ├── src ├── Internal │ ├── Data.elm │ ├── Axis │ │ ├── Intersection.elm │ │ ├── Title.elm │ │ ├── Line.elm │ │ ├── Range.elm │ │ ├── Ticks.elm │ │ └── Tick.elm │ ├── Area.elm │ ├── Grid.elm │ ├── Container.elm │ └── Coordinate.elm └── LineChart │ ├── Grid.elm │ ├── Interpolation.elm │ ├── Area.elm │ ├── Axis │ ├── Intersection.elm │ ├── Line.elm │ └── Title.elm │ ├── Colors.elm │ └── Line.elm ├── tests ├── elm-package.json └── Coordinate.elm ├── README.md ├── elm.json └── LICENSE /images/dots1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/dots1.png -------------------------------------------------------------------------------- /images/dots2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/dots2.png -------------------------------------------------------------------------------- /images/dots3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/dots3.png -------------------------------------------------------------------------------- /images/dots4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/dots4.png -------------------------------------------------------------------------------- /images/junk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/junk.png -------------------------------------------------------------------------------- /images/space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/space.png -------------------------------------------------------------------------------- /images/Example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/Example1.png -------------------------------------------------------------------------------- /images/Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/Example2.png -------------------------------------------------------------------------------- /images/Example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/Example3.png -------------------------------------------------------------------------------- /images/colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/colors.png -------------------------------------------------------------------------------- /images/legends1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/legends1.png -------------------------------------------------------------------------------- /images/legends2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/legends2.png -------------------------------------------------------------------------------- /images/legends3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/legends3.png -------------------------------------------------------------------------------- /images/legends4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/legends4.png -------------------------------------------------------------------------------- /images/legends5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/legends5.png -------------------------------------------------------------------------------- /images/ranges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/ranges.png -------------------------------------------------------------------------------- /images/ranges2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/ranges2.png -------------------------------------------------------------------------------- /images/ranges3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/ranges3.png -------------------------------------------------------------------------------- /images/ranges4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/ranges4.png -------------------------------------------------------------------------------- /images/shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/shapes.png -------------------------------------------------------------------------------- /images/tooltip1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/tooltip1.png -------------------------------------------------------------------------------- /images/tooltip2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/tooltip2.png -------------------------------------------------------------------------------- /images/chartarea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/chartarea.png -------------------------------------------------------------------------------- /images/linechart1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart1.png -------------------------------------------------------------------------------- /images/linechart2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart2.png -------------------------------------------------------------------------------- /images/linechart3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart3.png -------------------------------------------------------------------------------- /images/linechart4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart4.png -------------------------------------------------------------------------------- /images/linechart5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart5.png -------------------------------------------------------------------------------- /images/linechart6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart6.png -------------------------------------------------------------------------------- /images/linechart7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/linechart7.png -------------------------------------------------------------------------------- /docs/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/docs/assets/favicon.ico -------------------------------------------------------------------------------- /docs/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/docs/assets/favicon.png -------------------------------------------------------------------------------- /images/intersection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/intersection.png -------------------------------------------------------------------------------- /images/intersection1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/intersection1.png -------------------------------------------------------------------------------- /images/interpolation2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/interpolation2.png -------------------------------------------------------------------------------- /images/interpolation3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/interpolation3.png -------------------------------------------------------------------------------- /images/interpolation4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terezka/line-charts/HEAD/images/interpolation4.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # elm-package generated files 2 | elm-stuff 3 | # elm-repl generated files 4 | repl-temp-* 5 | documentation.json 6 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | 7 | 8 | main : Html.Html msg 9 | main = 10 | chart 11 | 12 | 13 | type alias Point = 14 | { x : Float, y : Float } 15 | 16 | 17 | chart : Html.Html msg 18 | chart = 19 | LineChart.view1 .x .y 20 | [ Point 1 2, Point 5 5, Point 10 10 ] 21 | -------------------------------------------------------------------------------- /docs/src/Random/Pipeline.elm: -------------------------------------------------------------------------------- 1 | module Random.Pipeline exposing (generate, with, send) 2 | 3 | 4 | {-| Random pipeline helpers -} 5 | 6 | 7 | import Random 8 | 9 | 10 | {-| -} 11 | generate : a -> Random.Generator a 12 | generate f = 13 | Random.map (\_ -> f) Random.bool 14 | 15 | 16 | {-| -} 17 | with : Random.Generator a -> Random.Generator (a -> b) -> Random.Generator b 18 | with = 19 | Random.map2 (|>) 20 | 21 | 22 | {-| -} 23 | send : (a -> msg) -> (Random.Generator a) -> Cmd msg 24 | send = 25 | Random.generate 26 | -------------------------------------------------------------------------------- /src/Internal/Data.elm: -------------------------------------------------------------------------------- 1 | module Internal.Data exposing (..) 2 | 3 | {-| -} 4 | 5 | import Internal.Coordinate exposing (..) 6 | 7 | 8 | 9 | {-| -} 10 | type alias Data data = 11 | { user : data 12 | , point : Point 13 | , isReal : Bool 14 | } 15 | 16 | 17 | {-| -} 18 | type alias Point = 19 | { x : Float 20 | , y : Float 21 | } 22 | 23 | 24 | {-| -} 25 | isWithinRange : System -> Point -> Bool 26 | isWithinRange system point = 27 | clamp system.x.min system.x.max point.x == point.x && 28 | clamp system.y.min system.y.max point.y == point.y 29 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example2 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | 7 | 8 | main : Html.Html msg 9 | main = 10 | chart 11 | 12 | 13 | type alias Human = 14 | { age : Float 15 | , weight : Float 16 | , height : Float 17 | , income : Float 18 | } 19 | 20 | 21 | chart : Html.Html msg 22 | chart = 23 | LineChart.view1 .age .weight -- Try changing to .height or bmi 24 | [ Human 4 24 0.94 0 25 | , Human 25 75 1.73 25000 26 | , Human 43 83 1.75 40000 27 | ] 28 | 29 | 30 | bmi : Human -> Float 31 | bmi human = 32 | human.weight / human.height ^ 2 33 | -------------------------------------------------------------------------------- /tests/elm-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "summary": "Test Suites", 4 | "repository": "https://github.com/user/project.git", 5 | "license": "BSD3", 6 | "source-directories": [ 7 | "../src", 8 | "." 9 | ], 10 | "exposed-modules": [], 11 | "dependencies": { 12 | "eeue56/elm-html-test": "5.0.1 <= v < 6.0.0", 13 | "elm-community/elm-test": "4.0.0 <= v < 5.0.0", 14 | "elm-lang/core": "5.1.1 <= v < 6.0.0", 15 | "elm-lang/html": "2.0.0 <= v < 3.0.0", 16 | "elm-lang/svg": "2.0.0 <= v < 3.0.0" 17 | }, 18 | "elm-version": "0.18.0 <= v < 0.19.0" 19 | } 20 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example3 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | 7 | 8 | main : Html.Html msg 9 | main = 10 | chart 11 | 12 | 13 | type alias Data = 14 | { age : Float 15 | , weight : Float 16 | , height : Float 17 | , income : Float 18 | } 19 | 20 | 21 | chart : Html.Html msg 22 | chart = 23 | LineChart.view2 .age .weight alice chuck 24 | 25 | 26 | alice : List Data 27 | alice = 28 | [ Data 4 24 0.94 0 29 | , Data 25 75 1.73 25000 30 | , Data 43 83 1.75 40000 31 | ] 32 | 33 | 34 | chuck : List Data 35 | chuck = 36 | [ Data 4 21 0.98 0 37 | , Data 25 89 1.83 85000 38 | , Data 43 95 1.84 120000 39 | ] 40 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example4.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example4 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | 7 | 8 | main : Html.Html msg 9 | main = 10 | chart 11 | 12 | 13 | chart : Html.Html msg 14 | chart = 15 | LineChart.view3 .age .weight alice bobby chuck 16 | 17 | 18 | 19 | -- DATA 20 | 21 | 22 | type alias Data = 23 | { age : Float 24 | , weight : Float 25 | , height : Float 26 | , income : Float 27 | } 28 | 29 | 30 | alice : List Data 31 | alice = 32 | [ Data 4 24 0.94 0 33 | , Data 25 75 1.73 25000 34 | , Data 43 83 1.75 40000 35 | ] 36 | 37 | 38 | bobby : List Data 39 | bobby = 40 | [ Data 4 22 1.01 0 41 | , Data 25 75 1.87 28000 42 | , Data 43 77 1.87 52000 43 | ] 44 | 45 | 46 | chuck : List Data 47 | chuck = 48 | [ Data 4 21 0.98 0 49 | , Data 25 89 1.83 85000 50 | , Data 43 95 1.84 120000 51 | ] 52 | -------------------------------------------------------------------------------- /examples/Simple.elm: -------------------------------------------------------------------------------- 1 | module Simple exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | 8 | 9 | main : Html.Html msg 10 | main = 11 | Html.div 12 | [ class "container" ] 13 | [ chart1, chart2, chart3 ] 14 | 15 | 16 | chart1 : Html.Html msg 17 | chart1 = 18 | LineChart.view1 .x .y data1 19 | 20 | 21 | chart2 : Html.Html msg 22 | chart2 = 23 | LineChart.view2 .x .y data1 data2 24 | 25 | 26 | chart3 : Html.Html msg 27 | chart3 = 28 | LineChart.view3 .x .y data1 data2 data3 29 | 30 | 31 | 32 | -- DATA 33 | 34 | 35 | type alias Point = 36 | { x : Float, y : Float } 37 | 38 | 39 | data1 : List Point 40 | data1 = 41 | [ Point 1 2, Point 6 4, Point 10 10 ] 42 | 43 | 44 | data2 : List Point 45 | data2 = 46 | [ Point 1 5, Point 6 9, Point 10 7 ] 47 | 48 | 49 | data3 : List Point 50 | data3 = 51 | [ Point 1 3, Point 6 2, Point 10 11 ] 52 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example5.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example5 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Dots as Dots 8 | 9 | 10 | main : Html.Html msg 11 | main = 12 | chart 13 | 14 | 15 | chart : Html.Html msg 16 | chart = 17 | LineChart.view .age .height 18 | [ LineChart.line Colors.purple Dots.cross "Alice" alice 19 | , LineChart.line Colors.blue Dots.square "Bobby" bobby 20 | , LineChart.line Colors.cyan Dots.circle "Chuck" chuck 21 | ] 22 | 23 | 24 | 25 | -- DATA 26 | 27 | 28 | type alias Data = 29 | { age : Float 30 | , weight : Float 31 | , height : Float 32 | , income : Float 33 | } 34 | 35 | 36 | alice : List Data 37 | alice = 38 | [ Data 4 24 0.94 0 39 | , Data 25 75 1.73 25000 40 | , Data 43 83 1.75 40000 41 | ] 42 | 43 | 44 | bobby : List Data 45 | bobby = 46 | [ Data 4 22 1.01 0 47 | , Data 25 75 1.87 28000 48 | , Data 43 77 1.87 52000 49 | ] 50 | 51 | 52 | chuck : List Data 53 | chuck = 54 | [ Data 4 21 0.98 0 55 | , Data 25 89 1.83 85000 56 | , Data 43 95 1.84 120000 57 | ] 58 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example6.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example6 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Dots as Dots 8 | 9 | 10 | main : Html.Html msg 11 | main = 12 | chart 13 | 14 | 15 | chart : Html.Html msg 16 | chart = 17 | LineChart.view .age .height 18 | [ LineChart.line Colors.pinkLight Dots.plus "Alice" alice 19 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 20 | , LineChart.line Colors.blueLight Dots.square "Chuck" chuck 21 | ] 22 | 23 | 24 | 25 | -- DATA 26 | 27 | 28 | type alias Data = 29 | { age : Float 30 | , weight : Float 31 | , height : Float 32 | , income : Float 33 | } 34 | 35 | 36 | alice : List Data 37 | alice = 38 | [ Data 4 24 0.94 0 39 | , Data 25 75 1.73 25000 40 | , Data 43 83 1.75 40000 41 | ] 42 | 43 | 44 | bobby : List Data 45 | bobby = 46 | [ Data 4 22 1.01 0 47 | , Data 25 75 1.87 28000 48 | , Data 43 77 1.87 52000 49 | ] 50 | 51 | 52 | chuck : List Data 53 | chuck = 54 | [ Data 4 21 0.98 0 55 | , Data 25 89 1.83 85000 56 | , Data 43 95 1.84 120000 57 | ] 58 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | terezka | line-charts 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | ".", 5 | "../src" 6 | ], 7 | "elm-version": "0.19.0", 8 | "dependencies": { 9 | "direct": { 10 | "avh4/elm-color": "1.0.0", 11 | "debois/elm-dom": "1.3.0", 12 | "elm/browser": "1.0.1", 13 | "elm/core": "1.0.2", 14 | "elm/html": "1.0.0", 15 | "elm/json": "1.1.2", 16 | "elm/random": "1.0.0", 17 | "elm/svg": "1.0.1", 18 | "elm/time": "1.0.0", 19 | "justinmimbs/time-extra": "1.1.0", 20 | "myrho/elm-round": "1.0.4", 21 | "noahzgordon/elm-color-extra": "1.0.1", 22 | "ryannhg/date-format": "2.2.0" 23 | }, 24 | "indirect": { 25 | "elm/parser": "1.1.0", 26 | "elm/regex": "1.0.0", 27 | "elm/url": "1.0.0", 28 | "elm/virtual-dom": "1.0.2", 29 | "elm-explorations/test": "1.2.0", 30 | "fredcy/elm-parseint": "2.0.1", 31 | "justinmimbs/date": "3.1.2" 32 | } 33 | }, 34 | "test-dependencies": { 35 | "direct": {}, 36 | "indirect": {} 37 | } 38 | } -------------------------------------------------------------------------------- /src/Internal/Axis/Intersection.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Intersection exposing 2 | ( Config 3 | , default, atOrigin, at, custom 4 | -- INTERNAL 5 | , getX, getY 6 | ) 7 | 8 | import Internal.Coordinate as Coordinate 9 | import Internal.Data as Data 10 | 11 | 12 | 13 | {-| -} 14 | type Config = 15 | Config (Coordinate.System -> Data.Point) 16 | 17 | 18 | {-| -} 19 | default : Config 20 | default = 21 | custom .min .min 22 | 23 | 24 | {-| -} 25 | atOrigin : Config 26 | atOrigin = 27 | custom towardsZero towardsZero 28 | 29 | 30 | {-| -} 31 | at : Float -> Float -> Config 32 | at x y = 33 | custom (always x) (always y) 34 | 35 | 36 | {-| -} 37 | custom : (Coordinate.Range -> Float) -> (Coordinate.Range -> Float) -> Config 38 | custom toX toY = 39 | Config <| \{ x, y } -> 40 | Data.Point (toX x) (toY y) 41 | 42 | 43 | 44 | -- HELPER 45 | 46 | 47 | towardsZero : Coordinate.Range -> Float 48 | towardsZero { max, min } = 49 | clamp min max 0 50 | 51 | 52 | 53 | -- INTERNAL 54 | 55 | 56 | {-| -} 57 | getX : Config -> Coordinate.System -> Float 58 | getX (Config func) = 59 | .x << func 60 | 61 | 62 | {-| -} 63 | getY : Config -> Coordinate.System -> Float 64 | getY (Config func) = 65 | .y << func 66 | -------------------------------------------------------------------------------- /examples/Lines.elm: -------------------------------------------------------------------------------- 1 | module Lines exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import Color 9 | 10 | 11 | main : Html.Html msg 12 | main = 13 | Html.div 14 | [ class "container" ] 15 | [ chart ] 16 | 17 | 18 | chart : Html.Html msg 19 | chart = 20 | LineChart.view .age .height 21 | [ LineChart.line Color.red Dots.diamond "Alice" alice 22 | , LineChart.line Color.blue Dots.circle "Bobby" bobby 23 | , LineChart.line Color.green Dots.plus "Chuck" chuck 24 | ] 25 | 26 | 27 | 28 | -- DATA 29 | 30 | 31 | type alias Info = 32 | { age : Float 33 | , weight : Float 34 | , height : Float 35 | , income : Float 36 | } 37 | 38 | 39 | alice : List Info 40 | alice = 41 | [ Info 10 34 1.34 0 42 | , Info 16 42 1.62 3000 43 | , Info 25 75 1.73 25000 44 | , Info 43 83 1.75 40000 45 | ] 46 | 47 | 48 | bobby : List Info 49 | bobby = 50 | [ Info 10 38 1.32 0 51 | , Info 17 69 1.75 2000 52 | , Info 25 75 1.87 32000 53 | , Info 43 77 1.87 52000 54 | ] 55 | 56 | 57 | chuck : List Info 58 | chuck = 59 | [ Info 10 42 1.35 0 60 | , Info 15 72 1.72 1800 61 | , Info 25 89 1.83 85000 62 | , Info 43 95 1.84 120000 63 | ] 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Line Charts 2 | 3 | This library is deprecated in favor of [elm-charts](https://github.com/terezka/elm-charts). 4 | 5 | An library for plotting line charts in SVG. Written in all Elm. See [demo.](https://terezka.github.io/line-charts/) 6 | 7 | ## Installation 8 | 9 | Run the following command in the root of your project 10 | 11 | ```shell 12 | $ elm install terezka/line-charts 13 | ``` 14 | 15 | and import the library in an elm file like this 16 | 17 | ```elm 18 | import LineChart 19 | ``` 20 | 21 | See the documentation for more information on usage! 22 | 23 | ## Documentation 24 | 25 | Find the documentation on [Elm's package website](http://package.elm-lang.org/packages/terezka/line-charts/latest). 26 | 27 | ## Development 28 | 29 | ### Setup 30 | 31 | ```shell 32 | $ cd examples 33 | $ elm package install 34 | $ elm reactor 35 | ``` 36 | 37 | and open [examples](https://localhost:8000). 38 | 39 | ### Tests 40 | 41 | Tests are written with [elm-test](https://github.com/elm-community/elm-test). 42 | For further information on elm-test check the documentation. 43 | All required dependencies are downloaded and installed when initially running the command. 44 | 45 | ```shell 46 | $ elm test 47 | ``` 48 | 49 | ### Compile the Docs 50 | 51 | ```shell 52 | $ elm live docs/src/Main.elm --output=docs/assets/main.js 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/highlight/terezka.css: -------------------------------------------------------------------------------- 1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 2 | 3 | /* Tomorrow Comment */ 4 | .hljs-comment, 5 | .hljs-quote { 6 | color: #8e908c; 7 | } 8 | 9 | /* Tomorrow Red */ 10 | .hljs-variable, 11 | .hljs-template-variable, 12 | .hljs-tag, 13 | .hljs-name, 14 | .hljs-selector-id, 15 | .hljs-selector-class, 16 | .hljs-regexp, 17 | .hljs-deletion { 18 | color: rgb(0, 229, 255); 19 | } 20 | 21 | /* Tomorrow Orange */ 22 | .hljs-number { 23 | color: rgb(156, 39, 176); 24 | } 25 | 26 | /* Tomorrow Orange */ 27 | .hljs-built_in, 28 | .hljs-builtin-name, 29 | .hljs-literal, 30 | .hljs-type, 31 | .hljs-params, 32 | .hljs-meta, 33 | .hljs-link { 34 | color: rgb(245, 105, 215); 35 | } 36 | 37 | /* Tomorrow Yellow */ 38 | .hljs-attribute { 39 | color: #eab700; 40 | } 41 | 42 | /* Tomorrow Green */ 43 | .hljs-string, 44 | .hljs-symbol, 45 | .hljs-bullet, 46 | .hljs-addition { 47 | color: rgb(205, 145, 60); 48 | } 49 | 50 | /* Tomorrow Blue */ 51 | .hljs-title, 52 | .hljs-section { 53 | color: #4271ae; 54 | } 55 | 56 | /* Tomorrow Purple */ 57 | .hljs-keyword, 58 | .hljs-selector-tag { 59 | color: rgb(3, 169, 244); 60 | } 61 | 62 | .hljs { 63 | display: block; 64 | overflow-x: auto; 65 | color: rgb(100, 100, 100); 66 | } 67 | 68 | .hljs-emphasis { 69 | font-style: italic; 70 | } 71 | 72 | .hljs-strong { 73 | font-weight: bold; 74 | } 75 | -------------------------------------------------------------------------------- /src/LineChart/Grid.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Grid exposing (Config, default, dots, lines) 2 | 3 | {-| 4 | 5 | @docs Config, default, dots, lines 6 | 7 | # How do I change where the grid lines/dots are placed? 8 | 9 | By default there is a grid by every tick. If you want to change 10 | the position of the grid or remove it all together, alter your tick 11 | configuration of your axis. 12 | 13 | The path to the tick in the configuration does through the `x` or `y` 14 | property for vertical and horizontal grids respectively and then in the 15 | `axis` property. 16 | 17 | See `LineChart.Axis` -> `LineChart.Axis.Ticks` -> `LineChart.Axis.Tick`. 18 | 19 | -} 20 | 21 | import Internal.Grid as Grid 22 | import Color 23 | 24 | 25 | {-| Use in the `LineChart.Config` passed to `LineChart.viewCustom`. 26 | 27 | chartConfig : LineChart.Config Data msg 28 | chartConfig = 29 | { ... 30 | , grid = Grid.default 31 | , ... 32 | } 33 | 34 | -} 35 | type alias Config = 36 | Grid.Config 37 | 38 | 39 | {-| Gets you some vague gray grid lines. 40 | -} 41 | default : Config 42 | default = 43 | Grid.default 44 | 45 | 46 | {-| Gets you a grid dots of a given radius and color. 47 | -} 48 | dots : Float -> Color.Color -> Config 49 | dots = 50 | Grid.dots 51 | 52 | 53 | {-| Gets you grid lines of a given width and color. 54 | -} 55 | lines : Float -> Color.Color -> Config 56 | lines = 57 | Grid.lines 58 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Dots as Dots 8 | import LineChart.Colors as Colors 9 | 10 | 11 | 12 | 13 | main : Html.Html msg 14 | main = 15 | chart 16 | 17 | 18 | chart : Html.Html msg 19 | chart = 20 | LineChart.view .age .income 21 | [ LineChart.line Colors.gold Dots.circle "Alice" alice 22 | -- ^^^^^^^^^^^ 23 | , LineChart.line Colors.blue Dots.square "Bobby" bobby 24 | -- ^^^^^^^^^^^ 25 | , LineChart.line Colors.pink Dots.diamond "Chuck" chuck 26 | -- ^^^^^^^^^^^^ 27 | ] 28 | 29 | 30 | 31 | -- DATA 32 | 33 | 34 | type alias Data = 35 | { age : Float 36 | , weight : Float 37 | , height : Float 38 | , income : Float 39 | } 40 | 41 | 42 | alice : List Data 43 | alice = 44 | [ Data 4 24 0.94 0 45 | , Data 25 75 1.73 25000 46 | , Data 43 83 1.75 40000 47 | ] 48 | 49 | 50 | bobby : List Data 51 | bobby = 52 | [ Data 4 22 1.01 0 53 | , Data 25 75 1.87 28000 54 | , Data 43 77 1.87 52000 55 | ] 56 | 57 | 58 | chuck : List Data 59 | chuck = 60 | [ Data 4 21 0.98 0 61 | , Data 25 89 1.83 85000 62 | , Data 43 95 1.84 120000 63 | ] 64 | 65 | 66 | average : List Data 67 | average = 68 | [ Data 4 22.3 1.0 0 69 | , Data 25 79.7 1.8 46000 70 | , Data 43 85 1.82 70667 71 | ] 72 | -------------------------------------------------------------------------------- /elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "package", 3 | "name": "terezka/line-charts", 4 | "summary": "A library for plotting lines charts in SVG.", 5 | "license": "BSD-3-Clause", 6 | "version": "2.0.2", 7 | "exposed-modules": [ 8 | "LineChart", 9 | "LineChart.Area", 10 | "LineChart.Axis", 11 | "LineChart.Axis.Intersection", 12 | "LineChart.Axis.Line", 13 | "LineChart.Axis.Range", 14 | "LineChart.Axis.Tick", 15 | "LineChart.Axis.Ticks", 16 | "LineChart.Axis.Title", 17 | "LineChart.Axis.Values", 18 | "LineChart.Colors", 19 | "LineChart.Container", 20 | "LineChart.Coordinate", 21 | "LineChart.Dots", 22 | "LineChart.Events", 23 | "LineChart.Grid", 24 | "LineChart.Interpolation", 25 | "LineChart.Junk", 26 | "LineChart.Legends", 27 | "LineChart.Line" 28 | ], 29 | "elm-version": "0.19.0 <= v < 0.20.0", 30 | "dependencies": { 31 | "avh4/elm-color": "1.0.0 <= v < 2.0.0", 32 | "debois/elm-dom": "1.3.0 <= v < 2.0.0", 33 | "elm/core": "1.0.0 <= v < 2.0.0", 34 | "elm/html": "1.0.0 <= v < 2.0.0", 35 | "elm/json": "1.0.0 <= v < 2.0.0", 36 | "elm/svg": "1.0.0 <= v < 2.0.0", 37 | "elm/time": "1.0.0 <= v < 2.0.0", 38 | "justinmimbs/time-extra": "1.1.0 <= v < 2.0.0", 39 | "myrho/elm-round": "1.0.4 <= v < 2.0.0", 40 | "ryan-haskell/date-format": "1.0.0 <= v < 2.0.0" 41 | }, 42 | "test-dependencies": {} 43 | } 44 | -------------------------------------------------------------------------------- /src/Internal/Axis/Title.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Title exposing (Config, Properties, default, atAxisMax, atDataMax, atPosition, custom, config) 2 | 3 | import Svg exposing (Svg) 4 | import Internal.Coordinate as Coordinate 5 | import Internal.Svg as Svg 6 | 7 | 8 | 9 | {-| -} 10 | type Config msg = 11 | Config (Properties msg) 12 | 13 | 14 | {-| -} 15 | type alias Properties msg = 16 | { view : Svg msg 17 | , position : Coordinate.Range -> Coordinate.Range -> Float 18 | , offset : ( Float, Float ) 19 | } 20 | 21 | 22 | {-| -} 23 | default : String -> Config msg 24 | default = 25 | atAxisMax 0 0 26 | 27 | 28 | {-| -} 29 | atAxisMax : Float -> Float -> String -> Config msg 30 | atAxisMax = 31 | let position data range = range.max in 32 | atPosition position 33 | 34 | 35 | {-| -} 36 | atDataMax : Float -> Float -> String -> Config msg 37 | atDataMax = 38 | let position data range = Basics.min data.max range.max in 39 | atPosition position 40 | 41 | 42 | {-| -} 43 | atPosition : (Coordinate.Range -> Coordinate.Range -> Float) -> Float -> Float -> String -> Config msg 44 | atPosition position x y = 45 | custom position x y << Svg.label "inherit" 46 | 47 | 48 | {-| -} 49 | custom : (Coordinate.Range -> Coordinate.Range -> Float) -> Float -> Float -> Svg msg -> Config msg 50 | custom position x y title = 51 | Config 52 | { view = title 53 | , position = position 54 | , offset = ( x, y ) 55 | } 56 | 57 | 58 | 59 | -- INTERNAL 60 | 61 | 62 | {-| -} 63 | config : Config msg -> Properties msg 64 | config (Config title) = 65 | title 66 | -------------------------------------------------------------------------------- /docs/highlight/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006, Ivan Sagalaev 2 | All rights reserved. 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 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 highlight.js nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 16 | 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 THE REGENTS AND CONTRIBUTORS 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Tereza Sokol 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example7.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example7 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Dots as Dots 8 | 9 | 10 | main : Html.Html msg 11 | main = 12 | chart 13 | 14 | 15 | chart : Html.Html msg 16 | chart = 17 | LineChart.view .age .height 18 | [ LineChart.line Colors.pinkLight Dots.plus "Alice" alice 19 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 20 | , LineChart.line Colors.blueLight Dots.square "Chuck" chuck 21 | , dashedLine 22 | ] 23 | 24 | dashedLine : LineChart.Series Data 25 | dashedLine = 26 | let 27 | pattern = [ 4, 2 ] 28 | -- ^^^^^^^^ 29 | -- (scroll to the left to see where it's used!) 30 | -- Try passing different numbers! 31 | in 32 | LineChart.dash Colors.purpleLight Dots.none "Average" pattern average 33 | 34 | 35 | 36 | 37 | 38 | -- DATA 39 | 40 | 41 | type alias Data = 42 | { age : Float 43 | , weight : Float 44 | , height : Float 45 | , income : Float 46 | } 47 | 48 | 49 | alice : List Data 50 | alice = 51 | [ Data 4 24 0.94 0 52 | , Data 25 75 1.73 25000 53 | , Data 43 83 1.75 40000 54 | ] 55 | 56 | 57 | bobby : List Data 58 | bobby = 59 | [ Data 4 22 1.01 0 60 | , Data 25 75 1.87 28000 61 | , Data 43 77 1.87 52000 62 | ] 63 | 64 | 65 | chuck : List Data 66 | chuck = 67 | [ Data 4 21 0.98 0 68 | , Data 25 89 1.83 85000 69 | , Data 43 95 1.84 120000 70 | ] 71 | 72 | 73 | average : List Data 74 | average = 75 | [ Data 4 22.3 1.0 0 76 | , Data 25 79.7 1.8 46000 77 | , Data 43 85 1.82 70667 78 | ] 79 | -------------------------------------------------------------------------------- /src/LineChart/Interpolation.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Interpolation exposing (Config, default, linear, monotone, stepped) 2 | 3 | {-| 4 | 5 | Interpolation is the the kind of line which is drawn between your data points. 6 | It's meant to be a guide to where your data point would actually be if you had 7 | more data. It's not just for looks! 8 | 9 | @docs Config, default, linear, monotone, stepped 10 | 11 | -} 12 | 13 | import Internal.Interpolation as Interpolation 14 | 15 | 16 | {-| Use in the `LineChart.Config` passed to `LineChart.viewCustom`. 17 | 18 | chartConfig : LineChart.Config Data msg 19 | chartConfig = 20 | { ... 21 | , interpolation = Interpolation.default 22 | , ... 23 | } 24 | 25 | -} 26 | type alias Config = 27 | Interpolation.Config 28 | 29 | 30 | {-| The vanilla of interpolations: linear. 31 | -} 32 | default : Config 33 | default = 34 | linear 35 | 36 | 37 | {-| A linear interpolation. 38 | 39 | Legends 40 | 41 | -} 42 | linear : Config 43 | linear = 44 | Interpolation.Linear 45 | 46 | 47 | {-| A monotone-x interpolation. 48 | 49 | Legends 50 | 51 | -} 52 | monotone : Config 53 | monotone = 54 | Interpolation.Monotone 55 | 56 | 57 | {-| A stepped interpolation where the step comes after the dot. 58 | 59 | Legends 60 | 61 | -} 62 | stepped : Config 63 | stepped = 64 | Interpolation.Stepped 65 | -------------------------------------------------------------------------------- /src/Internal/Area.elm: -------------------------------------------------------------------------------- 1 | module Internal.Area 2 | exposing 3 | ( Config(..), default, none, percentage, normal, stacked 4 | , hasArea, opacity, opacitySingle, opacityContainer 5 | ) 6 | 7 | {-| -} 8 | 9 | 10 | 11 | {-| -} 12 | type Config 13 | = None 14 | | Normal Float 15 | | Stacked Float 16 | | Percentage Float 17 | 18 | 19 | {-| -} 20 | default : Config 21 | default = 22 | none 23 | 24 | 25 | {-| -} 26 | none : Config 27 | none = 28 | None 29 | 30 | 31 | {-| -} 32 | normal : Float -> Config 33 | normal = 34 | Normal 35 | 36 | 37 | {-| -} 38 | stacked : Float -> Config 39 | stacked = 40 | Stacked 41 | 42 | 43 | {-| -} 44 | percentage : Float -> Config 45 | percentage = 46 | Percentage 47 | 48 | 49 | 50 | -- INTERNAL 51 | 52 | 53 | {-| -} 54 | hasArea : Config -> Bool 55 | hasArea config = 56 | case config of 57 | None -> False 58 | Normal _ -> True 59 | Stacked _ -> True 60 | Percentage _ -> True 61 | 62 | 63 | {-| -} 64 | opacity : Config -> Float 65 | opacity config = 66 | case config of 67 | None -> 0 68 | Normal opacity_ -> opacity_ 69 | Stacked opacity_ -> opacity_ 70 | Percentage opacity_ -> opacity_ 71 | 72 | 73 | {-| -} 74 | opacitySingle : Config -> Float 75 | opacitySingle config = 76 | case config of 77 | None -> 0 78 | Normal opacity_ -> opacity_ 79 | Stacked opacity_ -> 1 80 | Percentage opacity_ -> 1 81 | 82 | 83 | {-| -} 84 | opacityContainer : Config -> Float 85 | opacityContainer config = 86 | case config of 87 | None -> 1 88 | Normal opacity_ -> 1 89 | Stacked opacity_ -> opacity_ 90 | Percentage opacity_ -> opacity_ 91 | -------------------------------------------------------------------------------- /src/Internal/Axis/Line.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Line exposing (Config, none, default, full, rangeFrame, Properties, custom, config) 2 | 3 | 4 | import Svg exposing (Attribute) 5 | import LineChart.Colors as Colors 6 | import Internal.Coordinate as Coordinate 7 | import Color 8 | 9 | 10 | 11 | {-| -} 12 | type Config msg = 13 | Config (Coordinate.Range -> Coordinate.Range -> Properties msg) 14 | 15 | 16 | {-| -} 17 | default : Config msg 18 | default = 19 | full Colors.gray 20 | 21 | 22 | {-| -} 23 | none : Config msg 24 | none = 25 | custom <| \_ {min, max} -> 26 | { color = Colors.transparent 27 | , width = 0 28 | , events = [] 29 | , start = min 30 | , end = max 31 | } 32 | 33 | 34 | {-| -} 35 | full : Color.Color -> Config msg 36 | full color = 37 | custom <| \data range -> 38 | { color = color 39 | , width = 1 40 | , events = [] 41 | , start = range.min 42 | , end = range.max 43 | } 44 | 45 | 46 | {-| -} 47 | rangeFrame : Color.Color -> Config msg 48 | rangeFrame color = 49 | custom <| \data range -> 50 | let smallest = Coordinate.smallestRange data range in 51 | { color = color 52 | , width = 1 53 | , events = [] 54 | , start = smallest.min 55 | , end = smallest.max 56 | } 57 | 58 | 59 | 60 | -- CUSTOM 61 | 62 | 63 | {-| -} 64 | type alias Properties msg = 65 | { color : Color.Color 66 | , width : Float 67 | , events : List (Attribute msg) 68 | , start : Float 69 | , end : Float 70 | } 71 | 72 | 73 | {-| -} 74 | custom : (Coordinate.Range -> Coordinate.Range -> Properties msg) -> Config msg 75 | custom = 76 | Config 77 | 78 | 79 | 80 | -- INTERNAL 81 | 82 | 83 | {-| -} 84 | config : Config msg -> Coordinate.Range -> Coordinate.Range -> Properties msg 85 | config (Config config_) = 86 | config_ 87 | -------------------------------------------------------------------------------- /src/LineChart/Area.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Area exposing (Config, default, normal, stacked) 2 | 3 | {-| 4 | 5 | @docs Config, default, normal, stacked 6 | 7 | -} 8 | 9 | import Internal.Area as Area 10 | 11 | 12 | 13 | {-| Use in the `LineChart.Config` passed to `LineChart.viewCustom`. 14 | 15 | chartConfig : LineChart.Config Data Msg 16 | chartConfig = 17 | { ... 18 | , area = Area.default 19 | , ... 20 | } 21 | 22 | -} 23 | type alias Config = 24 | Area.Config 25 | 26 | 27 | {-| No color below your lines. 28 | -} 29 | default : Config 30 | default = 31 | Area.none 32 | 33 | 34 | {-| Color the area below your lines. The color is always the color of 35 | your line, but you can pass the opacity. 36 | 37 | _See example [here](https://github.com/terezka/line-charts/blob/master/examples/Area.elm)._ 38 | 39 | -} 40 | normal : Float -> Config 41 | normal = 42 | Area.normal 43 | 44 | 45 | {-| Stacks your values and colors the area in the line color. The color is 46 | always the color of your line, but you can pass the opacity. 47 | 48 | _See example [here](https://github.com/terezka/line-charts/blob/master/examples/Area.elm)._ 49 | 50 | **Warning:** Right now, this only works if all your lines have the 51 | same set of x values and don't have missing data! 52 | If not, the area will not stack properly. 53 | It will be fixed sometime though! 54 | -} 55 | stacked : Float -> Config 56 | stacked = 57 | Area.stacked 58 | 59 | 60 | {-| Same as stacked, but the areas takes up the whole graph and your values 61 | are made into percentages. The color is always the color of your line, but 62 | you can pass the opacity. 63 | 64 | **Warning:** Right now, this only works if all your lines have the 65 | same set of x values! If not, the area will not add properly. 66 | -} 67 | percentage : Float -> Config 68 | percentage = 69 | Area.percentage 70 | -------------------------------------------------------------------------------- /src/Internal/Axis/Range.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Range exposing (Config, default, padded, window, custom, applyX, applyY) 2 | 3 | import LineChart.Coordinate as Coordinate 4 | 5 | 6 | 7 | {-| -} 8 | type Config 9 | = Padded Float Float 10 | | Window Float Float 11 | | Custom (Coordinate.Range -> Coordinate.Range) 12 | 13 | 14 | {-| -} 15 | default : Config 16 | default = 17 | padded 0 0 18 | 19 | 20 | {-| -} 21 | padded : Float -> Float -> Config 22 | padded = 23 | Padded 24 | 25 | 26 | {-| -} 27 | window : Float -> Float -> Config 28 | window = 29 | Window 30 | 31 | 32 | {-| -} 33 | custom : (Coordinate.Range -> Coordinate.Range) -> Config 34 | custom = 35 | Custom 36 | 37 | 38 | 39 | -- INTERNAL 40 | 41 | 42 | {-| -} 43 | applyX : Config -> Coordinate.System -> Coordinate.Range 44 | applyX range system = 45 | case range of 46 | Padded padMin padMax -> 47 | let 48 | { frame } = system 49 | { size } = frame 50 | system_ = { system | frame = { frame | size = { size | width = size.width - padMin - padMax |> Basics.max 1 } } } 51 | scale = Coordinate.scaleDataX system_ 52 | in 53 | Coordinate.Range (system.x.min - scale padMin) (system.x.max + scale padMax) 54 | 55 | Window min max -> Coordinate.Range min max 56 | Custom toRange -> toRange system.x 57 | 58 | 59 | {-| -} 60 | applyY : Config -> Coordinate.System -> Coordinate.Range 61 | applyY range system = 62 | case range of 63 | Padded padMin padMax -> 64 | let 65 | { frame } = system 66 | { size } = frame 67 | system_ = { system | frame = { frame | size = { size | height = size.height - padMin - padMax |> Basics.max 1 } } } 68 | scale = Coordinate.scaleDataY system_ 69 | in 70 | Coordinate.Range (system.y.min - scale padMin) (system.y.max + scale padMax) 71 | 72 | Window min max -> Coordinate.Range min max 73 | Custom toRange -> toRange system.y 74 | -------------------------------------------------------------------------------- /src/Internal/Axis/Ticks.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Ticks exposing 2 | ( Config 3 | , int, time, float 4 | , intCustom, timeCustom, floatCustom, custom 5 | -- INTERNAL 6 | , ticks 7 | ) 8 | 9 | 10 | 11 | import LineChart.Axis.Tick as Tick 12 | import Internal.Axis.Tick 13 | import Internal.Coordinate as Coordinate exposing (..) 14 | import Internal.Axis.Values as Values 15 | import Time 16 | 17 | 18 | -- AXIS 19 | 20 | 21 | {-| -} 22 | type Config msg 23 | = Config (Coordinate.Range -> Coordinate.Range -> List (Tick.Config msg)) 24 | 25 | 26 | 27 | -- API 28 | 29 | 30 | {-| -} 31 | int : Int -> Config msg 32 | int amount = 33 | intCustom amount Tick.int 34 | 35 | 36 | {-| -} 37 | float : Int -> Config msg 38 | float amount = 39 | floatCustom amount Tick.float 40 | 41 | 42 | {-| -} 43 | time : Time.Zone -> Int -> Config msg 44 | time zone amount = 45 | timeCustom zone amount Tick.time 46 | 47 | 48 | 49 | -- API / CUSTOM 50 | 51 | 52 | {-| -} 53 | intCustom : Int -> (Int -> Tick.Config msg) -> Config msg 54 | intCustom amount tick = 55 | custom <| \data range -> 56 | List.map tick <| Values.int (Values.around amount) (Coordinate.smallestRange data range) 57 | 58 | 59 | {-| -} 60 | floatCustom : Int -> (Float -> Tick.Config msg) -> Config msg 61 | floatCustom amount tick = 62 | custom <| \data range -> 63 | List.map tick <| Values.float (Values.around amount) (Coordinate.smallestRange data range) 64 | 65 | 66 | {-| -} 67 | timeCustom : Time.Zone -> Int -> (Tick.Time -> Tick.Config msg) -> Config msg 68 | timeCustom zone amount tick = 69 | custom <| \data range -> 70 | List.map tick <| Values.time zone amount (Coordinate.smallestRange data range) 71 | 72 | 73 | 74 | -- API / VERY CUSTOM 75 | 76 | 77 | {-| -} 78 | custom : (Coordinate.Range -> Coordinate.Range -> List (Tick.Config msg)) -> Config msg 79 | custom = 80 | Config 81 | 82 | 83 | 84 | -- INTERNAL 85 | 86 | 87 | ticks : Coordinate.Range -> Coordinate.Range -> Config msg -> List (Tick.Properties msg) 88 | ticks dataRange range (Config values) = 89 | List.map Internal.Axis.Tick.properties <| values dataRange range 90 | -------------------------------------------------------------------------------- /examples/Docs/Line/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Line.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.wider 3 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Container/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Container.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example9.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example9 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Container/Example4.elm: -------------------------------------------------------------------------------- 1 | module Docs.Container.Example4 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.spaced "line-chart-1" 60 110 60 70 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Legends/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Legends.Example2 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.grouped .max .min 10 -60 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Legends/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Legends.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.byEnding (Junk.label Colors.black) 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Container/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Container.Example2 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.responsive "line-chart-1" -- Try resizing your brower window! 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | 52 | -- DATA 53 | 54 | 55 | type alias Data = 56 | { age : Float 57 | , weight : Float 58 | , height : Float 59 | , income : Float 60 | } 61 | 62 | 63 | alice : List Data 64 | alice = 65 | [ Data 4 24 0.94 0 66 | , Data 25 75 1.73 25000 67 | , Data 43 83 1.75 40000 68 | ] 69 | 70 | 71 | bobby : List Data 72 | bobby = 73 | [ Data 4 22 1.01 0 74 | , Data 25 75 1.87 28000 75 | , Data 43 77 1.87 52000 76 | ] 77 | 78 | 79 | chuck : List Data 80 | chuck = 81 | [ Data 4 21 0.98 0 82 | , Data 25 89 1.83 85000 83 | , Data 43 95 1.84 120000 84 | ] 85 | 86 | 87 | average : List Data 88 | average = 89 | [ Data 4 22.3 1.0 0 90 | , Data 25 79.7 1.8 46000 91 | , Data 43 85 1.82 70667 92 | ] 93 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example2 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = Axis.default 700 "Age" .age 33 | , y = Axis.default 400 "Income" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = 44 | -- Dots.default 45 | Dots.custom (Dots.full 8) 46 | } 47 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 48 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 49 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 50 | ] 51 | 52 | 53 | 54 | -- DATA 55 | 56 | 57 | type alias Data = 58 | { age : Float 59 | , weight : Float 60 | , height : Float 61 | , income : Float 62 | } 63 | 64 | 65 | alice : List Data 66 | alice = 67 | [ Data 4 24 0.94 0 68 | , Data 25 75 1.73 25000 69 | , Data 43 83 1.75 40000 70 | ] 71 | 72 | 73 | bobby : List Data 74 | bobby = 75 | [ Data 4 22 1.01 0 76 | , Data 25 75 1.87 28000 77 | , Data 43 77 1.87 52000 78 | ] 79 | 80 | 81 | chuck : List Data 82 | chuck = 83 | [ Data 4 21 0.98 0 84 | , Data 25 89 1.83 85000 85 | , Data 43 95 1.84 120000 86 | ] 87 | 88 | 89 | average : List Data 90 | average = 91 | [ Data 4 22.3 1.0 0 92 | , Data 25 79.7 1.8 46000 93 | , Data 43 85 1.82 70667 94 | ] 95 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = xAxisConfig 33 | , y = Axis.default 400 "Income ($)" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | xAxisConfig : Axis.Config Data msg 52 | xAxisConfig = 53 | Axis.default 650 "Age (years)" .age 54 | 55 | 56 | 57 | -- DATA 58 | 59 | 60 | type alias Data = 61 | { age : Float 62 | , weight : Float 63 | , height : Float 64 | , income : Float 65 | } 66 | 67 | 68 | alice : List Data 69 | alice = 70 | [ Data 4 24 0.94 0 71 | , Data 25 75 1.73 25000 72 | , Data 43 83 1.75 40000 73 | ] 74 | 75 | 76 | bobby : List Data 77 | bobby = 78 | [ Data 4 22 1.01 0 79 | , Data 25 75 1.87 28000 80 | , Data 43 77 1.87 52000 81 | ] 82 | 83 | 84 | chuck : List Data 85 | chuck = 86 | [ Data 4 21 0.98 0 87 | , Data 25 89 1.83 85000 88 | , Data 43 95 1.84 120000 89 | ] 90 | 91 | 92 | average : List Data 93 | average = 94 | [ Data 4 22.3 1.0 0 95 | , Data 25 79.7 1.8 46000 96 | , Data 43 85 1.82 70667 97 | ] 98 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example2 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { x = xAxisConfig 33 | , y = Axis.default 400 "Income ($)" .income 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 46 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 47 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 48 | ] 49 | 50 | 51 | xAxisConfig : Axis.Config Data msg 52 | xAxisConfig = 53 | Axis.full 650 "Age (years)" .age 54 | 55 | 56 | 57 | -- DATA 58 | 59 | 60 | type alias Data = 61 | { age : Float 62 | , weight : Float 63 | , height : Float 64 | , income : Float 65 | } 66 | 67 | 68 | alice : List Data 69 | alice = 70 | [ Data 4 24 0.94 0 71 | , Data 25 75 1.73 25000 72 | , Data 43 83 1.75 40000 73 | ] 74 | 75 | 76 | bobby : List Data 77 | bobby = 78 | [ Data 4 22 1.01 0 79 | , Data 25 75 1.87 28000 80 | , Data 43 77 1.87 52000 81 | ] 82 | 83 | 84 | chuck : List Data 85 | chuck = 86 | [ Data 4 21 0.98 0 87 | , Data 25 89 1.83 85000 88 | , Data 43 95 1.84 120000 89 | ] 90 | 91 | 92 | average : List Data 93 | average = 94 | [ Data 4 22.3 1.0 0 95 | , Data 25 79.7 1.8 46000 96 | , Data 43 85 1.82 70667 97 | ] 98 | -------------------------------------------------------------------------------- /examples/Docs/LineChart/Example8.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example8 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom chartConfig 32 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 33 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 34 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 35 | ] 36 | 37 | 38 | chartConfig : LineChart.Config Data msg 39 | chartConfig = 40 | { x = Axis.default 700 "Age" .age 41 | , y = Axis.default 400 "Income" .income 42 | , container = Container.default "line-chart-1" 43 | , interpolation = Interpolation.default 44 | , intersection = Intersection.default 45 | , legends = Legends.default 46 | , events = Events.default 47 | , junk = Junk.default 48 | , grid = Grid.default 49 | , area = Area.stacked 0.5 -- Changed from the default! 50 | , line = Line.default 51 | , dots = Dots.default 52 | } 53 | 54 | 55 | 56 | -- DATA 57 | 58 | 59 | type alias Data = 60 | { age : Float 61 | , weight : Float 62 | , height : Float 63 | , income : Float 64 | } 65 | 66 | 67 | alice : List Data 68 | alice = 69 | [ Data 4 24 0.94 0 70 | , Data 25 75 1.73 25000 71 | , Data 43 83 1.75 40000 72 | ] 73 | 74 | 75 | bobby : List Data 76 | bobby = 77 | [ Data 4 22 1.01 0 78 | , Data 25 75 1.87 28000 79 | , Data 43 77 1.87 52000 80 | ] 81 | 82 | 83 | chuck : List Data 84 | chuck = 85 | [ Data 4 21 0.98 0 86 | , Data 25 89 1.83 85000 87 | , Data 43 95 1.84 120000 88 | ] 89 | 90 | 91 | average : List Data 92 | average = 93 | [ Data 4 22.3 1.0 0 94 | , Data 25 79.7 1.8 46000 95 | , Data 43 85 1.82 70667 96 | ] 97 | -------------------------------------------------------------------------------- /examples/Size.elm: -------------------------------------------------------------------------------- 1 | module Size exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Dots as Dots 11 | import LineChart.Container as Container 12 | import LineChart.Interpolation as Interpolation 13 | import LineChart.Axis.Intersection as Intersection 14 | import LineChart.Axis as Axis 15 | import LineChart.Legends as Legends 16 | import LineChart.Line as Line 17 | import LineChart.Events as Events 18 | import LineChart.Grid as Grid 19 | import LineChart.Legends as Legends 20 | import LineChart.Area as Area 21 | import Color 22 | import Color 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | Html.div 28 | [ class "container" ] 29 | [ chart ] 30 | 31 | 32 | chart : Html.Html msg 33 | chart = 34 | LineChart.viewCustom 35 | { y = Axis.default 450 "Height" .height -- Change number here to edit height 36 | , x = Axis.default 700 "Age" .age -- Change number here to edit width 37 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 38 | , interpolation = Interpolation.default 39 | , intersection = Intersection.default 40 | , legends = Legends.default 41 | , events = Events.default 42 | , junk = Junk.default 43 | , grid = Grid.default 44 | , area = Area.default 45 | , line = Line.default 46 | , dots = Dots.default 47 | } 48 | [ LineChart.line Color.red Dots.diamond "Alice" alice 49 | , LineChart.line Color.blue Dots.circle "Bobby" bobby 50 | , LineChart.line Color.green Dots.plus "Chuck" chuck 51 | ] 52 | 53 | 54 | 55 | -- DATA 56 | 57 | 58 | type alias Info = 59 | { age : Float 60 | , weight : Float 61 | , height : Float 62 | , income : Float 63 | } 64 | 65 | 66 | alice : List Info 67 | alice = 68 | [ Info 10 34 1.34 0 69 | , Info 16 42 1.62 3000 70 | , Info 25 75 1.73 25000 71 | , Info 43 83 1.75 40000 72 | ] 73 | 74 | 75 | bobby : List Info 76 | bobby = 77 | [ Info 10 38 1.32 0 78 | , Info 17 69 1.75 2000 79 | , Info 25 75 1.87 32000 80 | , Info 43 77 1.87 52000 81 | ] 82 | 83 | 84 | chuck : List Info 85 | chuck = 86 | [ Info 10 42 1.35 0 87 | , Info 15 72 1.72 1800 88 | , Info 25 89 1.83 85000 89 | , Info 43 95 1.84 120000 90 | ] 91 | -------------------------------------------------------------------------------- /examples/Explanation/Intersections.elm: -------------------------------------------------------------------------------- 1 | module Explanation.Intersections exposing (main) 2 | 3 | 4 | import Svg 5 | import Svg.Attributes 6 | import Html 7 | import Html.Attributes exposing (class) 8 | import LineChart 9 | import LineChart.Colors as Colors 10 | import LineChart.Coordinate as Coordinate 11 | import LineChart.Junk as Junk exposing (..) 12 | import LineChart.Dots as Dots 13 | import LineChart.Container as Container 14 | import LineChart.Interpolation as Interpolation 15 | import LineChart.Axis.Intersection as Intersection 16 | import LineChart.Axis as Axis 17 | import LineChart.Legends as Legends 18 | import LineChart.Line as Line 19 | import LineChart.Events as Events 20 | import LineChart.Grid as Grid 21 | import LineChart.Legends as Legends 22 | import LineChart.Area as Area 23 | import Color 24 | 25 | 26 | 27 | main : Html.Html msg 28 | main = 29 | Html.div 30 | [ class "container" ] 31 | [ chart ] 32 | 33 | 34 | chart : Html.Html msg 35 | chart = 36 | LineChart.viewCustom 37 | { y = Axis.picky 500 "y" .y [ -1, 0, 1, 2, 3 ] 38 | , x = Axis.picky 700 "x" .x [ -1, 0 ,1, 2, 3] 39 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 40 | , interpolation = Interpolation.default 41 | , intersection = Intersection.at 1 1 42 | , legends = Legends.default 43 | , events = Events.default 44 | , junk = customJunk 45 | , grid = Grid.default 46 | , area = Area.default 47 | , line = Line.default 48 | , dots = Dots.default 49 | } 50 | [ LineChart.line Colors.pink Dots.none "some data" data 51 | ] 52 | 53 | 54 | customJunk : Junk.Config data msg 55 | customJunk = 56 | Junk.custom <| \system -> 57 | { below = [] 58 | , above = 59 | [ note system 1.2 1.25 0 0 "↙ The intersection" 60 | ] 61 | , html = [] 62 | } 63 | 64 | 65 | note : Coordinate.System -> Float -> Float -> Float -> Float -> String -> Svg.Svg msg 66 | note system x y xo yo text = 67 | let _ = Debug.log "system" system in 68 | Svg.g 69 | [ Junk.transform [ Junk.move system x y, Junk.offset xo yo ] 70 | , Svg.Attributes.style "text-anchor: start;" 71 | ] 72 | [ Junk.label Color.black text ] 73 | 74 | 75 | 76 | -- DATA 77 | 78 | 79 | type alias Data = 80 | { x : Float, y : Float } 81 | 82 | 83 | data : List Data 84 | data = 85 | [ Data -1 -3 86 | , Data 6 3 87 | ] 88 | -------------------------------------------------------------------------------- /src/Internal/Grid.elm: -------------------------------------------------------------------------------- 1 | module Internal.Grid exposing (Config, default, dots, lines, view) 2 | 3 | 4 | {-| -} 5 | 6 | import Svg 7 | import Svg.Attributes as Attributes 8 | import Internal.Svg as Svg 9 | import LineChart.Colors as Colors 10 | import LineChart.Coordinate as Coordinate 11 | import Internal.Axis as Axis 12 | import Internal.Axis.Ticks as Ticks 13 | import Color 14 | 15 | 16 | 17 | {-| -} 18 | type Config 19 | = Dots Float Color.Color 20 | | Lines Float Color.Color 21 | 22 | 23 | {-| -} 24 | default : Config 25 | default = 26 | lines 1 Colors.grayLightest 27 | 28 | 29 | {-| -} 30 | dots : Float -> Color.Color -> Config 31 | dots = 32 | Dots 33 | 34 | 35 | {-| -} 36 | lines : Float -> Color.Color -> Config 37 | lines = 38 | Lines 39 | 40 | 41 | 42 | -- INTERNAL 43 | 44 | 45 | {-| -} 46 | view : Coordinate.System -> Axis.Config data msg -> Axis.Config data msg -> Config -> List (Svg.Svg msg) 47 | view system xAxis yAxis grid = 48 | let 49 | verticals = 50 | Ticks.ticks system.xData system.x (Axis.ticks xAxis) 51 | |> List.filterMap hasGrid 52 | 53 | horizontals = 54 | Ticks.ticks system.yData system.y (Axis.ticks yAxis) 55 | |> List.filterMap hasGrid 56 | 57 | hasGrid tick = 58 | if tick.grid then Just tick.position else Nothing 59 | in 60 | case grid of 61 | Dots radius color -> viewDots system verticals horizontals radius color 62 | Lines width color -> viewLines system verticals horizontals width color 63 | 64 | 65 | viewDots : Coordinate.System -> List Float -> List Float -> Float -> Color.Color -> List (Svg.Svg msg) 66 | viewDots system verticals horizontals radius color = 67 | let 68 | alldots = 69 | List.concatMap dots_ verticals 70 | 71 | dots_ g = 72 | List.map (dot g) horizontals 73 | 74 | dot x y = 75 | Coordinate.toSvg system (Coordinate.Point x y) 76 | in 77 | List.map (Svg.gridDot radius color) alldots 78 | 79 | 80 | viewLines : Coordinate.System -> List Float -> List Float -> Float -> Color.Color -> List (Svg.Svg msg) 81 | viewLines system verticals horizontals width color = 82 | let 83 | attributes = 84 | [ Attributes.strokeWidth (String.fromFloat width), Attributes.stroke (Color.toCssString color) ] 85 | in 86 | List.map (Svg.horizontalGrid system attributes) horizontals ++ 87 | List.map (Svg.verticalGrid system attributes) verticals 88 | -------------------------------------------------------------------------------- /examples/Explanation/ChartArea.elm: -------------------------------------------------------------------------------- 1 | module Explanation.ChartArea exposing (main) 2 | 3 | 4 | import Svg 5 | import Svg.Attributes 6 | import Html 7 | import Html.Attributes exposing (class) 8 | import LineChart 9 | import LineChart.Colors as Colors 10 | import LineChart.Coordinate as Coordinate 11 | import LineChart as LineChart 12 | import LineChart.Junk as Junk exposing (..) 13 | import LineChart.Dots as Dots 14 | import LineChart.Container as Container 15 | import LineChart.Interpolation as Interpolation 16 | import LineChart.Axis.Intersection as Intersection 17 | import LineChart.Axis as Axis 18 | import LineChart.Legends as Legends 19 | import LineChart.Line as Line 20 | import LineChart.Events as Events 21 | import LineChart.Grid as Grid 22 | import LineChart.Legends as Legends 23 | import LineChart.Area as Area 24 | import Color 25 | 26 | 27 | 28 | main : Html.Html msg 29 | main = 30 | Html.div 31 | [ class "container" ] 32 | [ chart ] 33 | 34 | 35 | chart : Html.Html msg 36 | chart = 37 | LineChart.viewCustom 38 | { y = Axis.picky 500 "y" .y [] 39 | , x = Axis.picky 700 "x" .x [] 40 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 41 | , interpolation = Interpolation.default 42 | , intersection = Intersection.default 43 | , legends = Legends.default 44 | , events = Events.default 45 | , junk = customJunk 46 | , grid = Grid.default 47 | , area = Area.default 48 | , line = Line.default 49 | , dots = Dots.default 50 | } 51 | [ LineChart.line Colors.pink Dots.none "some data" data 52 | ] 53 | 54 | 55 | customJunk : Junk.Config data msg 56 | customJunk = 57 | Junk.custom <| \system -> 58 | { below = [ rectangle system ] 59 | , above = 60 | [ Junk.labelAt system 1 1.5 0 0 "middle" Color.black "chart area" 61 | , Junk.labelAt system 6.25 1.5 0 0 "middle" Color.black "not chart area" 62 | ] 63 | , html = [] 64 | } 65 | 66 | 67 | rectangle : Coordinate.System -> Svg.Svg msg 68 | rectangle system = 69 | Junk.rectangle system 70 | [ Svg.Attributes.fill "#aaf8a94d" 71 | , Svg.Attributes.clipPath "" 72 | ] 73 | system.x.min 74 | system.x.max 75 | system.y.min 76 | system.y.max 77 | 78 | 79 | 80 | -- DATA 81 | 82 | 83 | type alias Data = 84 | { x : Float, y : Float } 85 | 86 | 87 | data : List Data 88 | data = 89 | [ Data -1 -5 90 | , Data 5 5 91 | ] 92 | -------------------------------------------------------------------------------- /examples/Area.elm: -------------------------------------------------------------------------------- 1 | module CustomLines exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Dots as Dots 11 | import LineChart.Colors as Colors 12 | import LineChart.Container as Container 13 | import LineChart.Interpolation as Interpolation 14 | import LineChart.Axis.Intersection as Intersection 15 | import LineChart.Axis as Axis 16 | import LineChart.Legends as Legends 17 | import LineChart.Line as Line 18 | import LineChart.Events as Events 19 | import LineChart.Grid as Grid 20 | import LineChart.Legends as Legends 21 | import LineChart.Area as Area 22 | import Color 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | Html.div 28 | [ class "container" ] 29 | [ chart ] 30 | 31 | 32 | chart : Html.Html msg 33 | chart = 34 | LineChart.viewCustom 35 | { y = Axis.default 450 "Weight" .weight 36 | , x = Axis.default 700 "Age" .age 37 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 38 | , interpolation = Interpolation.default 39 | , intersection = Intersection.default 40 | , legends = Legends.default 41 | , events = Events.default 42 | , junk = Junk.default 43 | , grid = Grid.default 44 | , area = 45 | -- Try out these different configs! 46 | -- Area.default 47 | -- Area.normal 0.5 48 | Area.stacked 0.5 49 | , line = Line.default 50 | , dots = Dots.default 51 | } 52 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 53 | , LineChart.line Colors.blue Dots.circle "Bobby" bobby 54 | , LineChart.line Colors.cyan Dots.diamond "Alice" alice 55 | ] 56 | 57 | 58 | 59 | -- DATA 60 | 61 | 62 | type alias Info = 63 | { age : Float 64 | , weight : Float 65 | , height : Float 66 | , income : Float 67 | } 68 | 69 | 70 | alice : List Info 71 | alice = 72 | [ Info 10 34 1.34 0 73 | , Info 16 42 1.62 3000 74 | , Info 25 75 1.73 25000 75 | , Info 43 83 1.75 40000 76 | ] 77 | 78 | 79 | bobby : List Info 80 | bobby = 81 | [ Info 10 38 1.32 0 82 | , Info 17 69 1.75 2000 83 | , Info 25 75 1.87 32000 84 | , Info 43 77 1.87 52000 85 | ] 86 | 87 | 88 | chuck : List Info 89 | chuck = 90 | [ Info 10 42 1.35 0 91 | , Info 15 72 1.72 1800 92 | , Info 25 89 1.83 85000 93 | , Info 43 95 1.84 120000 94 | ] 95 | -------------------------------------------------------------------------------- /examples/Interpolation.elm: -------------------------------------------------------------------------------- 1 | module Interpolation exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Dots as Dots 11 | import LineChart.Container as Container 12 | import LineChart.Interpolation as Interpolation 13 | import LineChart.Axis.Intersection as Intersection 14 | import LineChart.Axis as Axis 15 | import LineChart.Colors as Colors 16 | import LineChart.Legends as Legends 17 | import LineChart.Line as Line 18 | import LineChart.Events as Events 19 | import LineChart.Grid as Grid 20 | import LineChart.Legends as Legends 21 | import LineChart.Area as Area 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | Html.div 27 | [ class "container" ] 28 | [ chart ] 29 | 30 | 31 | chart : Html.Html msg 32 | chart = 33 | LineChart.viewCustom 34 | { y = Axis.default 450 "Weight" .weight 35 | , x = Axis.default 700 "Age" .age 36 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 37 | , interpolation = 38 | -- Try out these different configs! 39 | -- Interpolation.linear 40 | -- Interpolation.monotone 41 | Interpolation.stepped 42 | , intersection = Intersection.default 43 | , legends = Legends.default 44 | , events = Events.default 45 | , junk = Junk.default 46 | , grid = Grid.default 47 | , area = Area.default 48 | , line = Line.default 49 | , dots = Dots.default 50 | } 51 | [ LineChart.line Colors.gold Dots.triangle "Chuck" chuck 52 | , LineChart.line Colors.pink Dots.circle "Bobby" bobby 53 | , LineChart.line Colors.blue Dots.diamond "Alice" alice 54 | ] 55 | 56 | 57 | 58 | -- DATA 59 | 60 | 61 | type alias Info = 62 | { age : Float 63 | , weight : Float 64 | , height : Float 65 | , income : Float 66 | } 67 | 68 | 69 | alice : List Info 70 | alice = 71 | [ Info 10 34 1.34 0 72 | , Info 16 42 1.62 3000 73 | , Info 25 75 1.73 25000 74 | , Info 43 83 1.75 40000 75 | ] 76 | 77 | 78 | bobby : List Info 79 | bobby = 80 | [ Info 10 38 1.32 0 81 | , Info 17 69 1.75 2000 82 | , Info 25 75 1.87 32000 83 | , Info 43 77 1.87 52000 84 | ] 85 | 86 | 87 | chuck : List Info 88 | chuck = 89 | [ Info 10 42 1.35 0 90 | , Info 15 72 1.72 1800 91 | , Info 25 89 1.83 85000 92 | , Info 43 95 1.84 120000 93 | ] 94 | -------------------------------------------------------------------------------- /examples/Line.elm: -------------------------------------------------------------------------------- 1 | module Line exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Dots as Dots 11 | import LineChart.Container as Container 12 | import LineChart.Interpolation as Interpolation 13 | import LineChart.Axis.Intersection as Intersection 14 | import LineChart.Axis as Axis 15 | import LineChart.Legends as Legends 16 | import LineChart.Line as Line 17 | import LineChart.Events as Events 18 | import LineChart.Grid as Grid 19 | import LineChart.Legends as Legends 20 | import LineChart.Area as Area 21 | import Color 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | Html.div 27 | [ class "container" ] 28 | [ chart ] 29 | 30 | 31 | chart : Html.Html msg 32 | chart = 33 | LineChart.viewCustom 34 | { y = Axis.default 450 "Height" .height 35 | , x = Axis.default 700 "Age" .age 36 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 37 | , interpolation = Interpolation.default 38 | , intersection = Intersection.default 39 | , legends = Legends.default 40 | , events = Events.default 41 | , junk = Junk.default 42 | , grid = Grid.default 43 | , area = Area.default 44 | , line = 45 | -- Try out these different configs! 46 | -- Line.default 47 | Line.wider 2 48 | -- For making the line change based on whether it's hovered, see Events.elm! 49 | , dots = Dots.default 50 | } 51 | [ LineChart.line Color.red Dots.diamond "Alice" alice 52 | , LineChart.line Color.blue Dots.circle "Bobby" bobby 53 | , LineChart.line Color.green Dots.triangle "Chuck" chuck 54 | ] 55 | 56 | 57 | 58 | -- DATA 59 | 60 | 61 | type alias Info = 62 | { age : Float 63 | , weight : Float 64 | , height : Float 65 | , income : Float 66 | } 67 | 68 | 69 | alice : List Info 70 | alice = 71 | [ Info 10 34 1.34 0 72 | , Info 16 42 1.62 3000 73 | , Info 25 75 1.73 25000 74 | , Info 43 83 1.75 40000 75 | ] 76 | 77 | 78 | bobby : List Info 79 | bobby = 80 | [ Info 10 38 1.32 0 81 | , Info 17 69 1.75 2000 82 | , Info 25 75 1.87 32000 83 | , Info 43 77 1.87 52000 84 | ] 85 | 86 | 87 | chuck : List Info 88 | chuck = 89 | [ Info 10 42 1.35 0 90 | , Info 15 72 1.72 1800 91 | , Info 25 89 1.83 85000 92 | , Info 43 95 1.84 120000 93 | ] 94 | -------------------------------------------------------------------------------- /examples/Grid.elm: -------------------------------------------------------------------------------- 1 | module Grid exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Junk as Junk exposing (..) 8 | import LineChart.Dots as Dots 9 | import LineChart.Colors as Colors 10 | import LineChart.Container as Container 11 | import LineChart.Interpolation as Interpolation 12 | import LineChart.Axis.Intersection as Intersection 13 | import LineChart.Axis as Axis 14 | import LineChart.Legends as Legends 15 | import LineChart.Line as Line 16 | import LineChart.Events as Events 17 | import LineChart.Grid as Grid 18 | import LineChart.Legends as Legends 19 | import LineChart.Area as Area 20 | 21 | 22 | main : Html.Html msg 23 | main = 24 | Html.div 25 | [ class "container" ] 26 | [ chart ] 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { y = Axis.default 500 "Weight" .weight 33 | , x = Axis.default 650 "Age" .age 34 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.default 40 | , grid = 41 | -- Try out these different configs! 42 | Grid.dots 1 Colors.grayLight 43 | -- Grid.lines 2 Color.lightGray 44 | 45 | -- Note: Where the lines show up is determined by the ticks. 46 | -- To edit, look at the Axis.elm module. 47 | , area = Area.default 48 | , line = Line.default 49 | , dots = Dots.default 50 | } 51 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 52 | , LineChart.line Colors.blue Dots.circle "Bobby" bobby 53 | , LineChart.line Colors.gold Dots.diamond "Alice" alice 54 | ] 55 | 56 | 57 | 58 | -- DATA 59 | 60 | 61 | type alias Info = 62 | { age : Float 63 | , weight : Float 64 | , height : Float 65 | , income : Float 66 | } 67 | 68 | 69 | alice : List Info 70 | alice = 71 | [ Info 10 34 1.34 0 72 | , Info 16 42 1.62 3000 73 | , Info 25 75 1.73 25000 74 | , Info 43 83 1.75 40000 75 | ] 76 | 77 | 78 | bobby : List Info 79 | bobby = 80 | [ Info 10 38 1.32 0 81 | , Info 17 69 1.75 2000 82 | , Info 25 75 1.87 32000 83 | , Info 43 77 1.87 52000 84 | ] 85 | 86 | 87 | chuck : List Info 88 | chuck = 89 | [ Info 10 42 1.35 0 90 | , Info 15 72 1.72 1800 91 | , Info 25 89 1.83 85000 92 | , Info 43 95 1.84 120000 93 | ] 94 | -------------------------------------------------------------------------------- /examples/Intersection.elm: -------------------------------------------------------------------------------- 1 | module Intersection exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Dots as Dots 11 | import LineChart.Container as Container 12 | import LineChart.Interpolation as Interpolation 13 | import LineChart.Axis.Intersection as Intersection 14 | import LineChart.Axis as Axis 15 | import LineChart.Legends as Legends 16 | import LineChart.Line as Line 17 | import LineChart.Events as Events 18 | import LineChart.Grid as Grid 19 | import LineChart.Legends as Legends 20 | import LineChart.Area as Area 21 | import Color 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | Html.div 27 | [ class "container" ] 28 | [ chart ] 29 | 30 | 31 | chart : Html.Html msg 32 | chart = 33 | LineChart.viewCustom 34 | { y = Axis.default 450 "Weight" .weight 35 | , x = Axis.default 700 "Age" .age 36 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 37 | , interpolation = Interpolation.default 38 | , intersection = 39 | -- Try out these different configs! 40 | -- Intersection.default 41 | -- Intersection.at 25 60 42 | Intersection.custom .max .min 43 | 44 | -- Note: Want to swap the direction of the ticks? Checkout out Axis.elm! 45 | , legends = Legends.default 46 | , events = Events.default 47 | , junk = Junk.default 48 | , grid = Grid.default 49 | , area = Area.default 50 | , line = Line.default 51 | , dots = Dots.default 52 | } 53 | [ LineChart.line Color.green Dots.triangle "Chuck" chuck 54 | , LineChart.line Color.blue Dots.circle "Bobby" bobby 55 | , LineChart.line Color.red Dots.diamond "Alice" alice 56 | ] 57 | 58 | 59 | 60 | -- DATA 61 | 62 | 63 | type alias Info = 64 | { age : Float 65 | , weight : Float 66 | , height : Float 67 | , income : Float 68 | } 69 | 70 | 71 | alice : List Info 72 | alice = 73 | [ Info 10 34 1.34 0 74 | , Info 16 42 1.62 3000 75 | , Info 25 75 1.73 25000 76 | , Info 43 83 1.75 40000 77 | ] 78 | 79 | 80 | bobby : List Info 81 | bobby = 82 | [ Info 10 38 1.32 0 83 | , Info 17 69 1.75 2000 84 | , Info 25 75 1.87 32000 85 | , Info 43 77 1.87 52000 86 | ] 87 | 88 | 89 | chuck : List Info 90 | chuck = 91 | [ Info 10 42 1.35 0 92 | , Info 15 72 1.72 1800 93 | , Info 25 89 1.83 85000 94 | , Info 43 95 1.84 120000 95 | ] 96 | -------------------------------------------------------------------------------- /examples/Docs/Colors/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.LineChart.Example6 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Dots as Dots 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Coordinate as Coordinate 21 | import LineChart.Interpolation as Interpolation 22 | import LineChart.Axis.Intersection as Intersection 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = Axis.picky 700 "" .x [ 0, 1 ] 34 | , y = Axis.picky 400 "" .y [ 0, 16 ] 35 | , container = Container.default "line-chart-1" 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.stacked 0.5 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.red Dots.circle "red" data 47 | , LineChart.line Colors.redLight Dots.circle "redLight" data 48 | , LineChart.line Colors.pink Dots.circle "pink" data 49 | , LineChart.line Colors.pinkLight Dots.circle "pinkLight" data 50 | , LineChart.line Colors.gold Dots.circle "gold" data 51 | , LineChart.line Colors.goldLight Dots.circle "goldLight" data 52 | , LineChart.line Colors.green Dots.circle "green" data 53 | , LineChart.line Colors.greenLight Dots.circle "greenLight" data 54 | , LineChart.line Colors.teal Dots.circle "teal" data 55 | , LineChart.line Colors.tealLight Dots.circle "tealLight" data 56 | , LineChart.line Colors.cyan Dots.circle "cyan" data 57 | , LineChart.line Colors.cyanLight Dots.circle "cyanLight" data 58 | , LineChart.line Colors.blue Dots.circle "blue" data 59 | , LineChart.line Colors.blueLight Dots.circle "blueLight" data 60 | , LineChart.line Colors.purple Dots.circle "purple" data 61 | , LineChart.line Colors.purpleLight Dots.circle "purpleLight" data 62 | ] 63 | 64 | 65 | data : List Coordinate.Point 66 | data = 67 | [ Coordinate.Point 0 1 68 | , Coordinate.Point 1 1 69 | ] 70 | -------------------------------------------------------------------------------- /examples/Docs/Container/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Container.Example3 exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Interpolation as Interpolation 21 | import LineChart.Axis.Intersection as Intersection 22 | 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = Axis.default 700 "Age" .age 34 | , y = Axis.default 400 "Income" .income 35 | , container = containerConfig 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 47 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 48 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 49 | ] 50 | 51 | 52 | containerConfig : Container.Config msg 53 | containerConfig = 54 | Container.custom 55 | { attributesHtml = [ Html.Attributes.style [ ( "font-family", "monospace" ) ] ] 56 | , attributesSvg = [] 57 | , size = Container.static 58 | , margin = Container.Margin 30 100 60 80 59 | , id = "chart-id" 60 | } 61 | 62 | 63 | 64 | -- DATA 65 | 66 | 67 | type alias Data = 68 | { age : Float 69 | , weight : Float 70 | , height : Float 71 | , income : Float 72 | } 73 | 74 | 75 | alice : List Data 76 | alice = 77 | [ Data 4 24 0.94 0 78 | , Data 25 75 1.73 25000 79 | , Data 43 83 1.75 40000 80 | ] 81 | 82 | 83 | bobby : List Data 84 | bobby = 85 | [ Data 4 22 1.01 0 86 | , Data 25 75 1.87 28000 87 | , Data 43 77 1.87 52000 88 | ] 89 | 90 | 91 | chuck : List Data 92 | chuck = 93 | [ Data 4 21 0.98 0 94 | , Data 25 89 1.83 85000 95 | , Data 43 95 1.84 120000 96 | ] 97 | 98 | 99 | average : List Data 100 | average = 101 | [ Data 4 22.3 1.0 0 102 | , Data 25 79.7 1.8 46000 103 | , Data 43 85 1.82 70667 104 | ] 105 | -------------------------------------------------------------------------------- /src/Internal/Container.elm: -------------------------------------------------------------------------------- 1 | module Internal.Container exposing 2 | ( Config, Properties, Size, Margin 3 | , default, spaced, styled, responsive, custom 4 | , relative, static 5 | , properties, sizeStyles 6 | ) 7 | 8 | {-| -} 9 | 10 | import Svg 11 | import Html 12 | import Html.Attributes 13 | 14 | 15 | 16 | {-| -} 17 | type Config msg = 18 | Config (Properties msg) 19 | 20 | 21 | {-| -} 22 | type alias Properties msg = 23 | { attributesHtml : List (Html.Attribute msg) 24 | , attributesSvg : List (Svg.Attribute msg) 25 | , size : Size 26 | , margin : Margin 27 | , id : String 28 | } 29 | 30 | 31 | {-| -} 32 | type Size 33 | = Static 34 | | Relative 35 | 36 | 37 | {-| -} 38 | type alias Margin = 39 | { top : Float 40 | , right : Float 41 | , bottom : Float 42 | , left : Float 43 | } 44 | 45 | 46 | {-| -} 47 | default : String -> Config msg 48 | default id = 49 | styled id [] 50 | 51 | 52 | {-| -} 53 | spaced : String -> Float -> Float -> Float -> Float -> Config msg 54 | spaced id top right bottom left = 55 | custom 56 | { attributesHtml = [] 57 | , attributesSvg = [] 58 | , size = static 59 | , margin = Margin top right bottom left 60 | , id = id 61 | } 62 | 63 | 64 | {-| -} 65 | styled : String -> List ( String, String ) -> Config msg 66 | styled id styles = 67 | custom 68 | { attributesHtml = List.map (\(p, v) -> Html.Attributes.style p v) styles 69 | , attributesSvg = [] 70 | , size = static 71 | , margin = Margin 60 140 60 80 72 | , id = id 73 | } 74 | 75 | 76 | {-| -} 77 | responsive : String -> Config msg 78 | responsive id = 79 | custom 80 | { attributesHtml = [] 81 | , attributesSvg = [] 82 | , size = relative 83 | , margin = Margin 60 140 60 80 84 | , id = id 85 | } 86 | 87 | 88 | {-| -} 89 | custom : Properties msg -> Config msg 90 | custom = 91 | Config 92 | 93 | 94 | {-| -} 95 | relative : Size 96 | relative = 97 | Relative 98 | 99 | 100 | {-| -} 101 | static : Size 102 | static = 103 | Static 104 | 105 | 106 | 107 | -- INTERNAL 108 | 109 | 110 | {-| -} 111 | properties : (Properties msg -> a) -> Config msg -> a 112 | properties f (Config properties_) = 113 | f properties_ 114 | 115 | 116 | {-| -} 117 | sizeStyles : Config msg -> Float -> Float -> List (Html.Attribute msg) 118 | sizeStyles (Config properties_) width height = 119 | case properties_.size of 120 | Static -> 121 | [ Html.Attributes.style "height" (String.fromFloat height ++ "px") 122 | , Html.Attributes.style "width" (String.fromFloat width ++ "px") 123 | ] 124 | 125 | Relative -> 126 | [] 127 | -------------------------------------------------------------------------------- /examples/Docs/Intersection/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Intersection.Example1 exposing (main) 2 | 3 | 4 | import Html 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Coordinate as Coordinate 20 | import LineChart.Interpolation as Interpolation 21 | import LineChart.Axis.Intersection as Intersection 22 | 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = Axis.default 650 "Age (years)" .age 34 | , y = Axis.default 400 "Income ($)" .income 35 | , container = Container.default "line-chart-1" 36 | , interpolation = Interpolation.default 37 | , intersection = intersectionConfig 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 47 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 48 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 49 | ] 50 | 51 | 52 | intersectionConfig : Intersection.Config 53 | intersectionConfig = 54 | Intersection.default 55 | -- Intersection.atOrigin 56 | -- Intersection.at 0 3 57 | -- Intersection.custom .min middle 58 | 59 | 60 | middle : Coordinate.Range -> Float 61 | middle { min, max } = 62 | min + (max - min) / 2 63 | 64 | 65 | 66 | -- DATA 67 | 68 | 69 | type alias Data = 70 | { age : Float 71 | , weight : Float 72 | , height : Float 73 | , income : Float 74 | } 75 | 76 | 77 | alice : List Data 78 | alice = 79 | [ Data 4 24 0.94 0 80 | , Data 25 75 1.73 25000 81 | , Data 43 83 1.75 40000 82 | ] 83 | 84 | 85 | bobby : List Data 86 | bobby = 87 | [ Data 4 22 1.01 0 88 | , Data 25 75 1.87 28000 89 | , Data 43 77 1.87 52000 90 | ] 91 | 92 | 93 | chuck : List Data 94 | chuck = 95 | [ Data 4 21 0.98 0 96 | , Data 25 89 1.83 85000 97 | , Data 43 95 1.84 120000 98 | ] 99 | 100 | 101 | average : List Data 102 | average = 103 | [ Data 4 22.3 1.0 0 104 | , Data 25 79.7 1.8 46000 105 | , Data 43 85 1.82 70667 106 | ] 107 | -------------------------------------------------------------------------------- /examples/Container.elm: -------------------------------------------------------------------------------- 1 | module Container exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import Svg.Attributes as SvgA 7 | import LineChart 8 | import LineChart.Dots as Dots 9 | import LineChart as LineChart 10 | import LineChart.Junk as Junk exposing (..) 11 | import LineChart.Dots as Dots 12 | import LineChart.Container as Container 13 | import LineChart.Interpolation as Interpolation 14 | import LineChart.Axis.Intersection as Intersection 15 | import LineChart.Axis as Axis 16 | import LineChart.Legends as Legends 17 | import LineChart.Line as Line 18 | import LineChart.Events as Events 19 | import LineChart.Grid as Grid 20 | import LineChart.Legends as Legends 21 | import LineChart.Area as Area 22 | import Color 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | Html.div 28 | [ class "container" ] 29 | [ chart ] 30 | 31 | 32 | chart : Html.Html msg 33 | chart = 34 | LineChart.viewCustom 35 | { y = Axis.default 450 "Weight" .weight 36 | , x = Axis.default 700 "Age" .age 37 | , container = 38 | -- Try out these different configs! 39 | -- Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 40 | -- Container.responsive "line-chart-1" -- Try resizing the window! 41 | Container.custom 42 | { attributesHtml = [] 43 | , attributesSvg = [ SvgA.style "background: #f2fff1;" ] 44 | , size = Container.static 45 | , margin = Container.Margin 20 140 60 80 46 | , id = "line-chart-1" 47 | } 48 | , interpolation = Interpolation.default 49 | , intersection = Intersection.default 50 | , legends = Legends.default 51 | , events = Events.default 52 | , junk = Junk.default 53 | , grid = Grid.default 54 | , area = Area.default 55 | , line = Line.default 56 | , dots = Dots.default 57 | } 58 | [ LineChart.line Color.green Dots.triangle "Chuck" chuck 59 | , LineChart.line Color.blue Dots.circle "Bobby" bobby 60 | , LineChart.line Color.red Dots.diamond "Alice" alice 61 | ] 62 | 63 | 64 | 65 | -- DATA 66 | 67 | 68 | type alias Info = 69 | { age : Float 70 | , weight : Float 71 | , height : Float 72 | , income : Float 73 | } 74 | 75 | 76 | alice : List Info 77 | alice = 78 | [ Info 10 34 1.34 0 79 | , Info 16 42 1.62 3000 80 | , Info 25 75 1.73 25000 81 | , Info 43 83 1.75 40000 82 | ] 83 | 84 | 85 | bobby : List Info 86 | bobby = 87 | [ Info 10 38 1.32 0 88 | , Info 17 69 1.75 2000 89 | , Info 25 75 1.87 32000 90 | , Info 43 77 1.87 52000 91 | ] 92 | 93 | 94 | chuck : List Info 95 | chuck = 96 | [ Info 10 42 1.35 0 97 | , Info 15 72 1.72 1800 98 | , Info 25 89 1.83 85000 99 | , Info 43 95 1.84 120000 100 | ] 101 | -------------------------------------------------------------------------------- /examples/Docs/Junk/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Junk.Example3 exposing (main) 2 | 3 | import Html 4 | import Svg 5 | import LineChart 6 | import LineChart.Junk as Junk 7 | import LineChart.Area as Area 8 | import LineChart.Axis as Axis 9 | import LineChart.Junk as Junk 10 | import LineChart.Dots as Dots 11 | import LineChart.Grid as Grid 12 | import LineChart.Dots as Dots 13 | import LineChart.Line as Line 14 | import LineChart.Colors as Colors 15 | import LineChart.Events as Events 16 | import LineChart.Legends as Legends 17 | import LineChart.Container as Container 18 | import LineChart.Coordinate as Coordinate 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Html.Html msg 25 | main = 26 | chart 27 | 28 | 29 | chart : Html.Html msg 30 | chart = 31 | LineChart.viewCustom 32 | { y = Axis.default 450 "Weight" .weight 33 | , x = Axis.default 700 "Age" .age 34 | , container = Container.default "line-chart-1" 35 | , interpolation = Interpolation.default 36 | , intersection = Intersection.default 37 | , legends = Legends.default 38 | , events = Events.default 39 | , junk = Junk.custom junk 40 | , grid = Grid.default 41 | , area = Area.default 42 | , line = Line.default 43 | , dots = Dots.default 44 | } 45 | [ LineChart.line Colors.blue Dots.triangle "Chuck" chuck 46 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 47 | , LineChart.line Colors.pink Dots.diamond "Alice" alice 48 | ] 49 | 50 | 51 | junk : Coordinate.System -> Junk.Layers msg 52 | junk system = 53 | { below = [] 54 | , above = [ movedStuff system ] 55 | , html = [] 56 | } 57 | 58 | 59 | someDataPoint : Data 60 | someDataPoint = 61 | Data 25 73 1.73 25000 62 | 63 | 64 | movedStuff : Coordinate.System -> Svg.Svg msg 65 | movedStuff system = 66 | Svg.g 67 | [ Junk.transform 68 | [ Junk.move system someDataPoint.age someDataPoint.weight 69 | , Junk.offset 20 10 70 | -- Try changing the offset! 71 | ] 72 | ] 73 | [ Junk.label Colors.blue "stuff" ] 74 | 75 | 76 | 77 | -- DATA 78 | 79 | 80 | type alias Data = 81 | { age : Float 82 | , weight : Float 83 | , height : Float 84 | , income : Float 85 | } 86 | 87 | 88 | alice : List Data 89 | alice = 90 | [ Data 10 34 1.34 0 91 | , Data 16 42 1.62 3000 92 | , Data 25 73 1.73 25000 93 | , Data 43 83 1.75 40000 94 | ] 95 | 96 | 97 | bobby : List Data 98 | bobby = 99 | [ Data 10 38 1.32 0 100 | , Data 17 69 1.75 2000 101 | , Data 25 76 1.87 32000 102 | , Data 43 77 1.87 52000 103 | ] 104 | 105 | 106 | chuck : List Data 107 | chuck = 108 | [ Data 10 42 1.35 0 109 | , Data 15 72 1.72 1800 110 | , Data 25 89 1.83 85000 111 | , Data 43 95 1.84 120000 112 | ] 113 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example5.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example5 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Interpolation as Interpolation 21 | import LineChart.Axis.Intersection as Intersection 22 | 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = Axis.time 650 "Date" .date 34 | , y = yAxisConfig 35 | , container = Container.default "line-chart-1" 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 47 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 48 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 49 | ] 50 | 51 | 52 | yAxisConfig : Axis.Config Data msg 53 | yAxisConfig = 54 | Axis.none 400 .income 55 | 56 | 57 | 58 | -- DATA 59 | 60 | 61 | type alias Data = 62 | { age : Float 63 | , weight : Float 64 | , height : Float 65 | , income : Float 66 | , date : Time.Time 67 | } 68 | 69 | 70 | alice : List Data 71 | alice = 72 | [ Data 4 24 0.94 0 (dateInterval 0) 73 | , Data 25 75 1.73 25000 (dateInterval 1) 74 | , Data 46 83 1.75 40000 (dateInterval 2) 75 | ] 76 | 77 | 78 | bobby : List Data 79 | bobby = 80 | [ Data 4 22 1.01 0 (dateInterval 0) 81 | , Data 25 75 1.87 28000 (dateInterval 1) 82 | , Data 46 77 1.87 52000 (dateInterval 2) 83 | ] 84 | 85 | 86 | chuck : List Data 87 | chuck = 88 | [ Data 4 21 0.98 0 (dateInterval 0) 89 | , Data 25 89 1.83 85000 (dateInterval 1) 90 | , Data 46 95 1.84 120000 (dateInterval 2) 91 | ] 92 | 93 | 94 | average : List Data 95 | average = 96 | [ Data 4 22.3 1.0 0 (dateInterval 0) 97 | , Data 25 79.7 1.8 46000 (dateInterval 1) 98 | , Data 46 85 1.82 70667 (dateInterval 2) 99 | ] 100 | 101 | 102 | dateInterval : Int -> Time.Time 103 | dateInterval i = 104 | 4 * year + toFloat i * 21 * year 105 | 106 | 107 | day : Time.Time 108 | day = 109 | 24 * Time.hour 110 | 111 | 112 | year : Time.Time 113 | year = 114 | 356 * day 115 | -------------------------------------------------------------------------------- /examples/Dots.elm: -------------------------------------------------------------------------------- 1 | module Dots exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart.Junk as Junk exposing (..) 9 | import LineChart.Container as Container 10 | import LineChart.Colors as Colors 11 | import LineChart.Interpolation as Interpolation 12 | import LineChart.Axis.Intersection as Intersection 13 | import LineChart.Axis as Axis 14 | import LineChart.Legends as Legends 15 | import LineChart.Line as Line 16 | import LineChart.Events as Events 17 | import LineChart.Grid as Grid 18 | import LineChart.Legends as Legends 19 | import LineChart.Area as Area 20 | import Color 21 | 22 | 23 | main : Html.Html msg 24 | main = 25 | Html.div 26 | [ class "container" ] 27 | [ chart ] 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { y = Axis.default 450 "Weight" .weight 34 | , x = Axis.default 700 "Age" .age 35 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = 45 | -- Try out these different configs! 46 | -- Dots.default 47 | -- Dots.custom (Dots.full 10) 48 | -- Dots.custom (Dots.aura 7 7 0.2) 49 | -- Dots.custom (Dots.empty 10 1) 50 | customConfig 51 | -- For making the dots change based on whether it's hovered, see Events.elm! 52 | } 53 | [ LineChart.line Colors.gold Dots.diamond "Alice" alice 54 | , LineChart.line Colors.red Dots.circle "Bobby" bobby 55 | , LineChart.line Colors.teal Dots.triangle "Chuck" chuck 56 | ] 57 | 58 | 59 | customConfig : Dots.Config Info 60 | customConfig = 61 | let 62 | style size = Dots.full size 63 | getSize datum = (datum.height - 1) * 12 64 | in 65 | Dots.customAny 66 | { legend = \_ -> style 7 67 | , individual = \datum -> style (getSize datum) 68 | } 69 | 70 | 71 | 72 | -- DATA 73 | 74 | 75 | type alias Info = 76 | { age : Float 77 | , weight : Float 78 | , height : Float 79 | , income : Float 80 | } 81 | 82 | 83 | alice : List Info 84 | alice = 85 | [ Info 10 34 1.34 0 86 | , Info 16 42 1.62 3000 87 | , Info 25 75 1.73 25000 88 | , Info 43 83 1.75 40000 89 | ] 90 | 91 | 92 | bobby : List Info 93 | bobby = 94 | [ Info 10 38 1.32 0 95 | , Info 17 69 1.75 2000 96 | , Info 25 78 1.87 32000 97 | , Info 43 77 1.87 52000 98 | ] 99 | 100 | 101 | chuck : List Info 102 | chuck = 103 | [ Info 10 42 1.35 0 104 | , Info 15 72 1.62 1800 105 | , Info 25 89 1.68 85000 106 | , Info 43 95 1.68 120000 107 | ] 108 | -------------------------------------------------------------------------------- /src/LineChart/Axis/Intersection.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Axis.Intersection exposing (Config, default, atOrigin, at, custom) 2 | 3 | {-| 4 | 5 | ## Where is the intersection? 6 | 7 | The intersection is where your two axis lines meet. By default this is at 8 | the smallest coordinate possible (the downmost left corner), but it need 9 | not be as illustated below. 10 | 11 | Ranges explained 12 | 13 | @docs Config, default, atOrigin, at, custom 14 | 15 | -} 16 | 17 | 18 | import Internal.Axis.Intersection as Intersection 19 | import LineChart.Coordinate as Coordinate 20 | 21 | 22 | 23 | {-| Use in the `LineChart.Config` passed to `LineChart.viewCustom`. 24 | 25 | chartConfig : LineChart.Config Data msg 26 | chartConfig = 27 | { ... 28 | , intersection = Intersection.default 29 | , ... 30 | } 31 | 32 | -} 33 | type alias Config = 34 | Intersection.Config 35 | 36 | 37 | {-| Sets the intersection at the minimum on both the range and domain. 38 | 39 | intersectionConfig : Intersection.Config 40 | intersectionConfig = 41 | Intersection.default 42 | 43 | 44 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Intersection/Example1.elm)._ 45 | 46 | -} 47 | default : Config 48 | default = 49 | Intersection.default 50 | 51 | 52 | {-| Sets the intersection as close to the origin as your range and domain allows. 53 | 54 | intersectionConfig : Intersection.Config 55 | intersectionConfig = 56 | Intersection.atOrigin 57 | 58 | 59 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Intersection/Example1.elm)._ 60 | 61 | 62 | -} 63 | atOrigin : Config 64 | atOrigin = 65 | Intersection.atOrigin 66 | 67 | 68 | {-| Sets the intersection to your chosen x and y respectively. 69 | 70 | intersectionConfig : Intersection.Config 71 | intersectionConfig = 72 | Intersection.at 0 3 73 | 74 | 75 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Intersection/Example1.elm)._ 76 | 77 | -} 78 | at : Float -> Float -> Config 79 | at = 80 | Intersection.at 81 | 82 | 83 | {-| Sets the intersection to your chosen x and y, given the range and domain 84 | respectively. 85 | 86 | intersectionConfig : Intersection.Config 87 | intersectionConfig = 88 | Intersection.custom .min middle 89 | 90 | middle : Coordinate.Range -> Float 91 | middle { min, max } = 92 | min + (max - min) / 2 93 | 94 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Intersection/Example1.elm)._ 95 | 96 | -} 97 | custom : (Coordinate.Range -> Float) -> (Coordinate.Range -> Float) -> Config 98 | custom = 99 | Intersection.custom 100 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example4.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example4 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Interpolation as Interpolation 21 | import LineChart.Axis.Intersection as Intersection 22 | 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = xAxisConfig 34 | , y = Axis.default 400 "($)" .income 35 | , container = Container.default "line-chart-1" 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 47 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 48 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 49 | ] 50 | 51 | 52 | xAxisConfig : Axis.Config Data msg 53 | xAxisConfig = 54 | Axis.picky 650 "Age (years)" .age [ 4, 25, 46 ] 55 | 56 | 57 | 58 | -- DATA 59 | 60 | 61 | type alias Data = 62 | { age : Float 63 | , weight : Float 64 | , height : Float 65 | , income : Float 66 | , date : Time.Time 67 | } 68 | 69 | 70 | alice : List Data 71 | alice = 72 | [ Data 4 24 0.94 0 (dateInterval 0) 73 | , Data 25 75 1.73 25000 (dateInterval 1) 74 | , Data 46 83 1.75 40000 (dateInterval 2) 75 | ] 76 | 77 | 78 | bobby : List Data 79 | bobby = 80 | [ Data 4 22 1.01 0 (dateInterval 0) 81 | , Data 25 75 1.87 28000 (dateInterval 1) 82 | , Data 46 77 1.87 52000 (dateInterval 2) 83 | ] 84 | 85 | 86 | chuck : List Data 87 | chuck = 88 | [ Data 4 21 0.98 0 (dateInterval 0) 89 | , Data 25 89 1.83 85000 (dateInterval 1) 90 | , Data 46 95 1.84 120000 (dateInterval 2) 91 | ] 92 | 93 | 94 | average : List Data 95 | average = 96 | [ Data 4 22.3 1.0 0 (dateInterval 0) 97 | , Data 25 79.7 1.8 46000 (dateInterval 1) 98 | , Data 46 85 1.82 70667 (dateInterval 2) 99 | ] 100 | 101 | 102 | dateInterval : Int -> Time.Time 103 | dateInterval i = 104 | 4 * year + toFloat i * 21 * year 105 | 106 | 107 | day : Time.Time 108 | day = 109 | 24 * Time.hour 110 | 111 | 112 | year : Time.Time 113 | year = 114 | 356 * day 115 | -------------------------------------------------------------------------------- /examples/Docs/Junk/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Junk.Example1 exposing (main) 2 | 3 | import Html 4 | import LineChart 5 | import LineChart.Junk as Junk 6 | import LineChart.Area as Area 7 | import LineChart.Axis as Axis 8 | import LineChart.Junk as Junk 9 | import LineChart.Dots as Dots 10 | import LineChart.Grid as Grid 11 | import LineChart.Dots as Dots 12 | import LineChart.Line as Line 13 | import LineChart.Colors as Colors 14 | import LineChart.Events as Events 15 | import LineChart.Legends as Legends 16 | import LineChart.Container as Container 17 | import LineChart.Interpolation as Interpolation 18 | import LineChart.Axis.Intersection as Intersection 19 | 20 | 21 | 22 | main : Program Never Model Msg 23 | main = 24 | Browser.sandbox 25 | { init = init 26 | , update = update 27 | , view = view 28 | } 29 | 30 | 31 | 32 | -- MODEL 33 | 34 | 35 | type alias Model = 36 | { hovered : Maybe Data } 37 | 38 | 39 | init : Model 40 | init = 41 | { hovered = Nothing } 42 | 43 | 44 | 45 | -- UPDATE 46 | 47 | 48 | type Msg 49 | = Hover (Maybe Data) 50 | 51 | 52 | update : Msg -> Model -> Model 53 | update msg model = 54 | case msg of 55 | Hover hovered -> 56 | { model | hovered = hovered } 57 | 58 | 59 | 60 | -- VIEW 61 | 62 | 63 | view : Model -> Html.Html Msg 64 | view = 65 | chart 66 | 67 | 68 | chart : Model -> Html.Html Msg 69 | chart model = 70 | LineChart.viewCustom 71 | { y = Axis.default 450 "Weight" .weight 72 | , x = Axis.default 700 "Age" .age 73 | , container = Container.default "line-chart-1" 74 | , interpolation = Interpolation.default 75 | , intersection = Intersection.default 76 | , legends = Legends.default 77 | , events = Events.hoverOne Hover 78 | , junk = 79 | Junk.hoverOne model.hovered 80 | [ ( "Age", toString << .age ) 81 | , ( "Weight", toString << .weight ) 82 | ] 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverOne model.hovered 87 | } 88 | [ LineChart.line Colors.green Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.gold Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 75 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 75 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example5.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example3 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : List Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = [] } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (List Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverMany Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverMany model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 73 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 76 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example3 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverOne Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverOne model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 75 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 75 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Events/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Events.Example2 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : List Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = [] } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (List Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverMany Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverMany model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 73 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 76 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Line/Example2.elm: -------------------------------------------------------------------------------- 1 | module Docs.Line.Example2 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverOne Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.hoverOne model.hovering 86 | , dots = Dots.default 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 75 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 75 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Events/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Events.Example1 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverOne Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverOne model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 75 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 75 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /examples/Docs/Events/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Events.Example3 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Click (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Click hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.click Click 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverOne model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | 95 | -- DATA 96 | 97 | 98 | type alias Data = 99 | { age : Float 100 | , weight : Float 101 | , height : Float 102 | , income : Float 103 | } 104 | 105 | 106 | alice : List Data 107 | alice = 108 | [ Data 10 34 1.34 0 109 | , Data 16 42 1.62 3000 110 | , Data 25 75 1.73 25000 111 | , Data 43 83 1.75 40000 112 | ] 113 | 114 | 115 | bobby : List Data 116 | bobby = 117 | [ Data 10 38 1.32 0 118 | , Data 17 69 1.75 2000 119 | , Data 25 75 1.87 32000 120 | , Data 43 77 1.87 52000 121 | ] 122 | 123 | 124 | chuck : List Data 125 | chuck = 126 | [ Data 10 42 1.35 0 127 | , Data 15 72 1.72 1800 128 | , Data 25 89 1.83 85000 129 | , Data 43 95 1.84 120000 130 | ] 131 | -------------------------------------------------------------------------------- /src/Internal/Coordinate.elm: -------------------------------------------------------------------------------- 1 | module Internal.Coordinate exposing 2 | ( System, Frame, Size, Margin, Range 3 | , range, minimum, minimumOrZero, maximum 4 | , ground, reachX, reachY, lengthX, lengthY 5 | , smallestRange, largestRange 6 | ) 7 | 8 | 9 | {-| -} 10 | 11 | 12 | 13 | {-| -} 14 | type alias System = 15 | { frame : Frame 16 | , x : Range 17 | , y : Range 18 | , xData : Range 19 | , yData : Range 20 | , id : String 21 | } 22 | 23 | 24 | {-| -} 25 | type alias Frame = 26 | { margin : Margin 27 | , size : Size 28 | } 29 | 30 | 31 | {-| -} 32 | type alias Size = 33 | { width : Float 34 | , height : Float 35 | } 36 | 37 | 38 | {-| -} 39 | type alias Margin = 40 | { top : Float 41 | , right : Float 42 | , bottom : Float 43 | , left : Float 44 | } 45 | 46 | 47 | {-| -} 48 | type alias Range = 49 | { min : Float 50 | , max : Float 51 | } 52 | 53 | 54 | 55 | -- HELPERS 56 | 57 | 58 | {-| -} 59 | range : (a -> Float) -> List a -> Range 60 | range toValue data = 61 | let 62 | range_ = 63 | { min = minimum toValue data 64 | , max = maximum toValue data 65 | } 66 | in 67 | if range_.min == range_.max then 68 | { range_ | max = range_.max + 1 } 69 | else 70 | range_ 71 | 72 | 73 | {-| -} 74 | minimum : (a -> Float) -> List a -> Float 75 | minimum toValue = 76 | List.map toValue 77 | >> List.minimum 78 | >> Maybe.withDefault 0 79 | 80 | 81 | {-| -} 82 | minimumOrZero : (a -> Float) -> List a -> Float 83 | minimumOrZero toValue = 84 | minimum toValue >> Basics.min 0 85 | 86 | 87 | {-| -} 88 | maximum : (a -> Float) -> List a -> Float 89 | maximum toValue = 90 | List.map toValue 91 | >> List.maximum 92 | >> Maybe.withDefault 1 93 | 94 | 95 | {-| -} 96 | ground : Range -> Range 97 | ground range_ = 98 | { range_ | min = Basics.min range_.min 0 } 99 | 100 | 101 | {-| -} 102 | reachX : System -> Float 103 | reachX system = 104 | let 105 | diff = 106 | system.x.max - system.x.min 107 | in 108 | if diff > 0 then diff else 1 109 | 110 | 111 | {-| -} 112 | reachY : System -> Float 113 | reachY system = 114 | let 115 | diff = 116 | system.y.max - system.y.min 117 | in 118 | if diff > 0 then diff else 1 119 | 120 | 121 | {-| -} 122 | lengthX : System -> Float 123 | lengthX system = 124 | max 1 (system.frame.size.width - system.frame.margin.left - system.frame.margin.right) 125 | 126 | 127 | {-| -} 128 | lengthY : System -> Float 129 | lengthY system = 130 | max 1 (system.frame.size.height - system.frame.margin.bottom - system.frame.margin.top) 131 | 132 | 133 | {-| -} 134 | smallestRange : Range -> Range -> Range 135 | smallestRange data range_ = 136 | { min = Basics.max data.min range_.min 137 | , max = Basics.min data.max range_.max 138 | } 139 | 140 | 141 | {-| -} 142 | largestRange : Range -> Range -> Range 143 | largestRange data range_ = 144 | { min = Basics.min data.min range_.min 145 | , max = Basics.max data.max range_.max 146 | } 147 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example3 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Interpolation as Interpolation 21 | import LineChart.Axis.Intersection as Intersection 22 | 23 | 24 | 25 | main : Html.Html msg 26 | main = 27 | chart 28 | 29 | 30 | chart : Html.Html msg 31 | chart = 32 | LineChart.viewCustom 33 | { x = xAxisConfig 34 | , y = Axis.default 400 "Income ($)" .income 35 | , container = Container.default "line-chart-1" 36 | , interpolation = Interpolation.default 37 | , intersection = Intersection.default 38 | , legends = Legends.default 39 | , events = Events.default 40 | , junk = Junk.default 41 | , grid = Grid.default 42 | , area = Area.default 43 | , line = Line.default 44 | , dots = Dots.default 45 | } 46 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 47 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 48 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 49 | ] 50 | 51 | 52 | xAxisConfig : Axis.Config Data msg 53 | xAxisConfig = 54 | Axis.time 650 "Date" .date 55 | -- Change the `dateInterval` function to change the dates! 56 | 57 | 58 | dateInterval : Int -> Time.Time 59 | dateInterval i = 60 | -- 4 * year + toFloat i * 21 * year 61 | -- 20 * day + toFloat i * 8 * day 62 | 4 * Time.hour + toFloat i * 21 * Time.hour 63 | 64 | 65 | day : Time.Time 66 | day = 67 | 24 * Time.hour 68 | 69 | 70 | year : Time.Time 71 | year = 72 | 356 * day 73 | 74 | 75 | 76 | -- DATA 77 | 78 | 79 | type alias Data = 80 | { age : Float 81 | , weight : Float 82 | , height : Float 83 | , income : Float 84 | , date : Time.Time 85 | } 86 | 87 | 88 | alice : List Data 89 | alice = 90 | [ Data 4 24 0.94 0 (dateInterval 0) 91 | , Data 25 75 1.73 25000 (dateInterval 1) 92 | , Data 46 83 1.75 40000 (dateInterval 2) 93 | ] 94 | 95 | 96 | bobby : List Data 97 | bobby = 98 | [ Data 4 22 1.01 0 (dateInterval 0) 99 | , Data 25 75 1.87 28000 (dateInterval 1) 100 | , Data 46 77 1.87 52000 (dateInterval 2) 101 | ] 102 | 103 | 104 | chuck : List Data 105 | chuck = 106 | [ Data 4 21 0.98 0 (dateInterval 0) 107 | , Data 25 89 1.83 85000 (dateInterval 1) 108 | , Data 46 95 1.84 120000 (dateInterval 2) 109 | ] 110 | 111 | 112 | average : List Data 113 | average = 114 | [ Data 4 22.3 1.0 0 (dateInterval 0) 115 | , Data 25 79.7 1.8 46000 (dateInterval 1) 116 | , Data 46 85 1.82 70667 (dateInterval 2) 117 | ] 118 | -------------------------------------------------------------------------------- /examples/Docs/Legends/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Legends.Example3 exposing (main) 2 | 3 | 4 | import Html 5 | import Svg 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Junk as Junk 12 | import LineChart.Dots as Dots 13 | import LineChart.Grid as Grid 14 | import LineChart.Dots as Dots 15 | import LineChart.Line as Line 16 | import LineChart.Colors as Colors 17 | import LineChart.Events as Events 18 | import LineChart.Legends as Legends 19 | import LineChart.Container as Container 20 | import LineChart.Coordinate as Coordinate 21 | import LineChart.Interpolation as Interpolation 22 | import LineChart.Axis.Intersection as Intersection 23 | 24 | 25 | 26 | main : Html.Html msg 27 | main = 28 | chart 29 | 30 | 31 | chart : Html.Html msg 32 | chart = 33 | LineChart.viewCustom 34 | { x = Axis.default 700 "Age" .age 35 | , y = Axis.default 400 "Income" .income 36 | , container = Container.default "line-chart-1" 37 | , interpolation = Interpolation.default 38 | , intersection = Intersection.default 39 | , legends = Legends.groupedCustom 30 viewLegends 40 | , events = Events.default 41 | , junk = Junk.default 42 | , grid = Grid.default 43 | , area = Area.default 44 | , line = Line.default 45 | , dots = Dots.default 46 | } 47 | [ LineChart.line Colors.gold Dots.triangle "Chuck" chuck 48 | , LineChart.line Colors.cyan Dots.circle "Alice" alice 49 | , LineChart.line Colors.pink Dots.diamond "Bobby" bobby 50 | ] 51 | 52 | 53 | viewLegends : Coordinate.System -> List (Legends.Legend msg) -> Svg.Svg msg 54 | viewLegends system legends = 55 | Svg.g 56 | [ Junk.transform 57 | [ Junk.move system system.x.min system.y.min 58 | , Junk.offset 20 20 59 | ] 60 | ] 61 | (List.indexedMap viewLegend legends) 62 | 63 | 64 | viewLegend : Int -> Legends.Legend msg -> Svg.Svg msg 65 | viewLegend index { sample, label } = 66 | Svg.g 67 | [ Junk.transform [ Junk.offset (toFloat index * 100) 20 ] ] 68 | [ sample, viewLabel label ] 69 | 70 | 71 | viewLabel : String -> Svg.Svg msg 72 | viewLabel label = 73 | Svg.g 74 | [ Junk.transform [ Junk.offset 40 4 ] ] 75 | [ Junk.label Colors.black label ] 76 | 77 | 78 | 79 | -- DATA 80 | 81 | 82 | type alias Data = 83 | { age : Float 84 | , weight : Float 85 | , height : Float 86 | , income : Float 87 | } 88 | 89 | 90 | alice : List Data 91 | alice = 92 | [ Data 4 24 0.94 0 93 | , Data 25 75 1.73 25000 94 | , Data 43 83 1.75 40000 95 | ] 96 | 97 | 98 | bobby : List Data 99 | bobby = 100 | [ Data 4 22 1.01 0 101 | , Data 25 75 1.87 28000 102 | , Data 43 77 1.87 52000 103 | ] 104 | 105 | 106 | chuck : List Data 107 | chuck = 108 | [ Data 4 21 0.98 0 109 | , Data 25 89 1.83 85000 110 | , Data 43 95 1.84 120000 111 | ] 112 | 113 | 114 | average : List Data 115 | average = 116 | [ Data 4 22.3 1.0 0 117 | , Data 25 79.7 1.8 46000 118 | , Data 43 85 1.82 70667 119 | ] 120 | -------------------------------------------------------------------------------- /src/LineChart/Colors.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Colors exposing 2 | ( pink, blue, gold, red, green, cyan, teal, purple, rust, strongBlue 3 | , pinkLight, blueLight, goldLight, redLight, greenLight, cyanLight, tealLight, purpleLight 4 | , black, gray, grayLight, grayLightest, transparent 5 | ) 6 | 7 | {-| 8 | 9 | Colors! 10 | 11 | @docs pink, blue, gold, red, green, cyan, teal, purple, rust, strongBlue 12 | 13 | ## Light 14 | @docs pinkLight, blueLight, goldLight, redLight, greenLight, cyanLight, tealLight, purpleLight 15 | 16 | ## Gray scale 17 | @docs black, gray, grayLight, grayLightest 18 | 19 | ## Other 20 | @docs transparent 21 | 22 | -} 23 | 24 | import Color 25 | 26 | 27 | 28 | {-| -} 29 | pink : Color.Color 30 | pink = 31 | Color.rgb255 245 105 215 32 | 33 | 34 | {-| -} 35 | pinkLight : Color.Color 36 | pinkLight = 37 | Color.rgb255 244 143 177 38 | 39 | 40 | {-| -} 41 | gold : Color.Color 42 | gold = 43 | Color.rgb255 205 145 60 44 | 45 | 46 | {-| -} 47 | goldLight : Color.Color 48 | goldLight = 49 | Color.rgb255 255 204 128 50 | 51 | 52 | {-| -} 53 | blue : Color.Color 54 | blue = 55 | Color.rgb255 3 169 244 56 | 57 | 58 | {-| -} 59 | blueLight : Color.Color 60 | blueLight = 61 | Color.rgb255 128 222 234 62 | 63 | 64 | {-| -} 65 | green : Color.Color 66 | green = 67 | Color.rgb255 67 160 71 68 | 69 | 70 | {-| -} 71 | greenLight : Color.Color 72 | greenLight = 73 | Color.rgb255 197 225 165 74 | 75 | 76 | {-| -} 77 | red : Color.Color 78 | red = 79 | Color.rgb255 216 27 96 80 | 81 | 82 | {-| -} 83 | redLight : Color.Color 84 | redLight = 85 | Color.rgb255 239 154 154 86 | 87 | 88 | {-| -} 89 | rust : Color.Color 90 | rust = 91 | Color.rgb255 205 102 51 92 | 93 | 94 | {-| -} 95 | purple : Color.Color 96 | purple = 97 | Color.rgb255 156 39 176 98 | 99 | 100 | {-| -} 101 | purpleLight : Color.Color 102 | purpleLight = 103 | Color.rgb255 206 147 216 104 | 105 | 106 | {-| -} 107 | cyan : Color.Color 108 | cyan = 109 | Color.rgb255 0 229 255 110 | 111 | 112 | {-| -} 113 | cyanLight : Color.Color 114 | cyanLight = 115 | Color.rgb255 128 222 234 116 | 117 | 118 | {-| -} 119 | teal : Color.Color 120 | teal = 121 | Color.rgb255 29 233 182 122 | 123 | 124 | {-| -} 125 | tealLight : Color.Color 126 | tealLight = 127 | Color.rgb255 128 203 196 128 | 129 | 130 | {-| -} 131 | strongBlue : Color.Color 132 | strongBlue = 133 | Color.rgb255 89 51 204 134 | 135 | 136 | 137 | 138 | 139 | -- GRAY SCALE 140 | 141 | 142 | {-| -} 143 | black : Color.Color 144 | black = 145 | Color.rgb255 0 0 0 146 | 147 | 148 | {-| -} 149 | gray : Color.Color 150 | gray = 151 | Color.rgb255 163 163 163 152 | 153 | 154 | {-| -} 155 | grayLight : Color.Color 156 | grayLight = 157 | Color.rgb255 211 211 211 158 | 159 | 160 | {-| -} 161 | grayLightest : Color.Color 162 | grayLightest = 163 | Color.rgb255 243 243 243 164 | 165 | 166 | {-| -} 167 | transparent : Color.Color 168 | transparent = 169 | Color.rgba 0 0 0 0 170 | -------------------------------------------------------------------------------- /examples/Docs/Events/Example4.elm: -------------------------------------------------------------------------------- 1 | module Docs.Events.Example4 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = 82 | Events.custom 83 | [ Events.onMouseMove Hover Events.getNearest 84 | , Events.onMouseLeave (Hover Nothing) 85 | ] 86 | , junk = Junk.default 87 | , grid = Grid.default 88 | , area = Area.default 89 | , line = Line.default 90 | , dots = Dots.hoverOne model.hovering 91 | } 92 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 93 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 94 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 95 | ] 96 | 97 | 98 | 99 | -- DATA 100 | 101 | 102 | type alias Data = 103 | { age : Float 104 | , weight : Float 105 | , height : Float 106 | , income : Float 107 | } 108 | 109 | 110 | alice : List Data 111 | alice = 112 | [ Data 10 34 1.34 0 113 | , Data 16 42 1.62 3000 114 | , Data 25 75 1.73 25000 115 | , Data 43 83 1.75 40000 116 | ] 117 | 118 | 119 | bobby : List Data 120 | bobby = 121 | [ Data 10 38 1.32 0 122 | , Data 17 69 1.75 2000 123 | , Data 25 75 1.87 32000 124 | , Data 43 77 1.87 52000 125 | ] 126 | 127 | 128 | chuck : List Data 129 | chuck = 130 | [ Data 10 42 1.35 0 131 | , Data 15 72 1.72 1800 132 | , Data 25 89 1.83 85000 133 | , Data 43 95 1.84 120000 134 | ] 135 | -------------------------------------------------------------------------------- /src/Internal/Axis/Tick.elm: -------------------------------------------------------------------------------- 1 | module Internal.Axis.Tick exposing 2 | ( Config, Properties, Direction(..), isPositive 3 | , custom, int, float, long, gridless, labelless, opposite 4 | , properties 5 | ) 6 | 7 | {-| -} 8 | 9 | import Svg exposing (Svg, Attribute) 10 | import Internal.Svg as Svg 11 | import LineChart.Colors as Colors 12 | import Color 13 | 14 | 15 | 16 | {-| -} 17 | type Config msg = 18 | Config (Properties msg) 19 | 20 | 21 | {-| -} 22 | type alias Properties msg = 23 | { position : Float 24 | , color : Color.Color 25 | , width : Float 26 | , length : Float 27 | , grid : Bool 28 | , direction : Direction 29 | , label : Maybe (Svg msg) 30 | } 31 | 32 | 33 | 34 | -- DIRECTION 35 | 36 | 37 | {-| -} 38 | type Direction 39 | = Negative 40 | | Positive 41 | 42 | 43 | 44 | -- INTERNAL 45 | 46 | 47 | isPositive : Direction -> Bool 48 | isPositive direction = 49 | case direction of 50 | Positive -> True 51 | Negative -> False 52 | 53 | 54 | 55 | -- TICKS 56 | 57 | 58 | {-| -} 59 | int : Int -> Config msg 60 | int n = 61 | custom 62 | { position = toFloat n 63 | , color = Colors.gray 64 | , width = 1 65 | , length = 5 66 | , grid = True 67 | , direction = Negative 68 | , label = Just <| Svg.label "inherit" (String.fromInt n) 69 | } 70 | 71 | 72 | {-| -} 73 | float : Float -> Config msg 74 | float n = 75 | custom 76 | { position = n 77 | , color = Colors.gray 78 | , width = 1 79 | , length = 5 80 | , grid = True 81 | , direction = Negative 82 | , label = Just <| Svg.label "inherit" (String.fromFloat n) 83 | } 84 | 85 | 86 | {-| -} 87 | gridless : Float -> Config msg 88 | gridless n = 89 | custom 90 | { position = n 91 | , color = Colors.gray 92 | , width = 1 93 | , length = 5 94 | , grid = False 95 | , direction = Negative 96 | , label = Just <| Svg.label "inherit" (String.fromFloat n) 97 | } 98 | 99 | 100 | {-| -} 101 | labelless : Float -> Config msg 102 | labelless n = 103 | custom 104 | { position = n 105 | , color = Colors.gray 106 | , width = 1 107 | , length = 5 108 | , grid = True 109 | , direction = Negative 110 | , label = Nothing 111 | } 112 | 113 | 114 | {-| -} 115 | long : Float -> Config msg 116 | long n = 117 | custom 118 | { position = n 119 | , color = Colors.gray 120 | , width = 1 121 | , length = 20 122 | , grid = True 123 | , direction = Negative 124 | , label = Just <| Svg.label "inherit" (String.fromFloat n) 125 | } 126 | 127 | 128 | {-| -} 129 | opposite : Float -> Config msg 130 | opposite n = 131 | custom 132 | { position = n 133 | , color = Colors.gray 134 | , width = 1 135 | , length = 5 136 | , grid = True 137 | , direction = Positive 138 | , label = Just <| Svg.label "inherit" (String.fromFloat n) 139 | } 140 | 141 | 142 | {-| -} 143 | custom : Properties msg -> Config msg 144 | custom = 145 | Config 146 | 147 | 148 | 149 | -- INTERNAL 150 | 151 | 152 | {-| -} 153 | properties : Config msg -> Properties msg 154 | properties (Config properties_) = 155 | properties_ 156 | -------------------------------------------------------------------------------- /examples/Events3.elm: -------------------------------------------------------------------------------- 1 | module Events3 exposing (main) 2 | 3 | import Html exposing (Html, div, h1, node, p, text) 4 | import Html.Attributes exposing (class) 5 | import Svg exposing (Attribute, Svg, g, text_, tspan) 6 | import LineChart as LineChart 7 | import LineChart.Junk as Junk exposing (..) 8 | import LineChart.Dots as Dots 9 | import LineChart.Container as Container 10 | import LineChart.Interpolation as Interpolation 11 | import LineChart.Axis.Intersection as Intersection 12 | import LineChart.Axis as Axis 13 | import LineChart.Legends as Legends 14 | import LineChart.Line as Line 15 | import LineChart.Events as Events 16 | import LineChart.Grid as Grid 17 | import LineChart.Legends as Legends 18 | import LineChart.Area as Area 19 | import Color 20 | import Browser 21 | 22 | 23 | 24 | main : Program () Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : List Info } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = [] } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (List Info) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = 82 | Events.custom 83 | [ Events.onMouseMove Hover Events.getNearestX 84 | , Events.onMouseLeave (Hover []) 85 | ] 86 | , junk = Junk.default 87 | , grid = Grid.default 88 | , area = Area.default 89 | , line = Line.default 90 | , dots = Dots.hoverMany model.hovering 91 | } 92 | [ LineChart.line Color.orange Dots.triangle "Chuck" chuck 93 | , LineChart.line Color.yellow Dots.circle "Bobby" bobby 94 | , LineChart.line Color.purple Dots.diamond "Alice" alice 95 | ] 96 | 97 | 98 | 99 | -- DATA 100 | 101 | 102 | type alias Info = 103 | { age : Float 104 | , weight : Float 105 | , height : Float 106 | , income : Float 107 | } 108 | 109 | 110 | alice : List Info 111 | alice = 112 | [ Info 10 34 1.34 0 113 | , Info 16 42 1.62 3000 114 | , Info 25 75 1.73 25000 115 | , Info 43 83 1.75 40000 116 | ] 117 | 118 | 119 | bobby : List Info 120 | bobby = 121 | [ Info 10 38 1.32 0 122 | , Info 17 69 1.75 2000 123 | , Info 25 75 1.87 32000 124 | , Info 43 77 1.87 52000 125 | ] 126 | 127 | 128 | chuck : List Info 129 | chuck = 130 | [ Info 10 42 1.35 0 131 | , Info 15 72 1.72 1800 132 | , Info 25 89 1.83 85000 133 | , Info 43 95 1.84 120000 134 | ] 135 | -------------------------------------------------------------------------------- /examples/Events2.elm: -------------------------------------------------------------------------------- 1 | module Events2 exposing (main) 2 | 3 | import Html exposing (Html, div, h1, node, p, text) 4 | import Html.Attributes exposing (class) 5 | import Svg exposing (Attribute, Svg, g, text_, tspan) 6 | import LineChart as LineChart 7 | import LineChart.Junk as Junk exposing (..) 8 | import LineChart.Dots as Dots 9 | import LineChart.Container as Container 10 | import LineChart.Interpolation as Interpolation 11 | import LineChart.Axis.Intersection as Intersection 12 | import LineChart.Axis as Axis 13 | import LineChart.Legends as Legends 14 | import LineChart.Line as Line 15 | import LineChart.Events as Events 16 | import LineChart.Grid as Grid 17 | import LineChart.Legends as Legends 18 | import LineChart.Area as Area 19 | import Color 20 | import Browser 21 | 22 | 23 | 24 | main : Program () Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Info } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Info) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Svg Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = 82 | Events.custom 83 | [ Events.onMouseMove Hover Events.getNearest 84 | , Events.onMouseLeave (Hover Nothing) 85 | ] 86 | , junk = Junk.default 87 | , grid = Grid.default 88 | , area = Area.default 89 | , line = Line.hoverOne model.hovering 90 | , dots = Dots.hoverOne model.hovering 91 | } 92 | [ LineChart.line Color.orange Dots.triangle "Chuck" chuck 93 | , LineChart.line Color.yellow Dots.circle "Bobby" bobby 94 | , LineChart.line Color.purple Dots.diamond "Alice" alice 95 | ] 96 | 97 | 98 | 99 | -- DATA 100 | 101 | 102 | type alias Info = 103 | { age : Float 104 | , weight : Float 105 | , height : Float 106 | , income : Float 107 | } 108 | 109 | 110 | alice : List Info 111 | alice = 112 | [ Info 10 34 1.34 0 113 | , Info 16 42 1.62 3000 114 | , Info 25 75 1.73 25000 115 | , Info 43 83 1.75 40000 116 | ] 117 | 118 | 119 | bobby : List Info 120 | bobby = 121 | [ Info 10 38 1.32 0 122 | , Info 17 69 1.75 2000 123 | , Info 25 75 1.87 32000 124 | , Info 43 77 1.87 52000 125 | ] 126 | 127 | 128 | chuck : List Info 129 | chuck = 130 | [ Info 10 42 1.35 0 131 | , Info 15 72 1.72 1800 132 | , Info 25 89 1.83 85000 133 | , Info 43 95 1.84 120000 134 | ] 135 | -------------------------------------------------------------------------------- /examples/Tooltip1.elm: -------------------------------------------------------------------------------- 1 | module Tooltip1 exposing (main) 2 | 3 | import Html exposing (Html, div, h1, node, p, text) 4 | import Html.Attributes exposing (class) 5 | import Svg exposing (Attribute, Svg, g, text_, tspan) 6 | import LineChart as LineChart 7 | import LineChart.Junk as Junk exposing (..) 8 | import LineChart.Dots as Dots 9 | import LineChart.Container as Container 10 | import LineChart.Junk as Junk 11 | import LineChart.Interpolation as Interpolation 12 | import LineChart.Axis.Intersection as Intersection 13 | import LineChart.Axis as Axis 14 | import LineChart.Legends as Legends 15 | import LineChart.Line as Line 16 | import LineChart.Events as Events 17 | import LineChart.Grid as Grid 18 | import LineChart.Legends as Legends 19 | import LineChart.Area as Area 20 | import Color 21 | import Browser 22 | 23 | 24 | 25 | main : Program () Model Msg 26 | main = 27 | Browser.sandbox 28 | { init = init 29 | , update = update 30 | , view = view 31 | } 32 | 33 | 34 | 35 | -- MODEL 36 | 37 | 38 | type alias Model = 39 | { hovered : Maybe Info } 40 | 41 | 42 | init : Model 43 | init = 44 | { hovered = Nothing } 45 | 46 | 47 | 48 | -- UPDATE 49 | 50 | 51 | type Msg 52 | = Hover (Maybe Info) 53 | 54 | 55 | update : Msg -> Model -> Model 56 | update msg model = 57 | case msg of 58 | Hover hovered -> 59 | { model | hovered = hovered } 60 | 61 | 62 | 63 | -- VIEW 64 | 65 | 66 | view : Model -> Svg Msg 67 | view model = 68 | Html.div 69 | [ class "container" ] 70 | [ chart model ] 71 | 72 | 73 | chart : Model -> Html.Html Msg 74 | chart model = 75 | LineChart.viewCustom 76 | { y = Axis.default 450 "Weight" .weight 77 | , x = Axis.default 700 "Age" .age 78 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 79 | , interpolation = Interpolation.default 80 | , intersection = Intersection.default 81 | , legends = Legends.default 82 | , events = Events.hoverOne Hover 83 | , junk = 84 | Junk.hoverOne model.hovered 85 | [ ( "Age", String.fromFloat << .age ) 86 | , ( "Weight", String.fromFloat << .weight ) 87 | ] 88 | , grid = Grid.default 89 | , area = Area.default 90 | , line = Line.default 91 | , dots = Dots.hoverOne model.hovered 92 | } 93 | [ LineChart.line Color.orange Dots.triangle "Chuck" chuck 94 | , LineChart.line Color.yellow Dots.circle "Bobby" bobby 95 | , LineChart.line Color.purple Dots.diamond "Alice" alice 96 | ] 97 | 98 | 99 | 100 | -- DATA 101 | 102 | 103 | type alias Info = 104 | { age : Float 105 | , weight : Float 106 | , height : Float 107 | , income : Float 108 | } 109 | 110 | 111 | alice : List Info 112 | alice = 113 | [ Info 10 34 1.34 0 114 | , Info 16 42 1.62 3000 115 | , Info 25 75 1.73 25000 116 | , Info 43 83 1.75 40000 117 | ] 118 | 119 | 120 | bobby : List Info 121 | bobby = 122 | [ Info 10 38 1.32 0 123 | , Info 17 69 1.75 2000 124 | , Info 25 75 1.87 32000 125 | , Info 43 77 1.87 52000 126 | ] 127 | 128 | 129 | chuck : List Info 130 | chuck = 131 | [ Info 10 42 1.35 0 132 | , Info 15 72 1.72 1800 133 | , Info 25 89 1.83 85000 134 | , Info 43 95 1.84 120000 135 | ] 136 | -------------------------------------------------------------------------------- /examples/Docs/Axis/Example6.elm: -------------------------------------------------------------------------------- 1 | module Docs.Axis.Example6 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Axis.Title as Title 12 | import LineChart.Axis.Range as Range 13 | import LineChart.Axis.Line as AxisLine 14 | import LineChart.Axis.Ticks as Ticks 15 | import LineChart.Junk as Junk 16 | import LineChart.Dots as Dots 17 | import LineChart.Grid as Grid 18 | import LineChart.Dots as Dots 19 | import LineChart.Line as Line 20 | import LineChart.Colors as Colors 21 | import LineChart.Events as Events 22 | import LineChart.Legends as Legends 23 | import LineChart.Container as Container 24 | import LineChart.Interpolation as Interpolation 25 | import LineChart.Axis.Intersection as Intersection 26 | 27 | 28 | 29 | main : Html.Html msg 30 | main = 31 | chart 32 | 33 | 34 | chart : Html.Html msg 35 | chart = 36 | LineChart.viewCustom 37 | { x = xAxisConfig 38 | , y = Axis.default 400 "($)" .income 39 | , container = Container.default "line-chart-1" 40 | , interpolation = Interpolation.default 41 | , intersection = Intersection.default 42 | , legends = Legends.default 43 | , events = Events.default 44 | , junk = Junk.default 45 | , grid = Grid.default 46 | , area = Area.default 47 | , line = Line.default 48 | , dots = Dots.default 49 | } 50 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 51 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 52 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 53 | ] 54 | 55 | 56 | xAxisConfig : Axis.Config Data msg 57 | xAxisConfig = 58 | Axis.custom 59 | { title = Title.default "Year" 60 | , variable = Just << .date 61 | , pixels = 700 62 | , range = Range.padded 20 20 63 | , axisLine = AxisLine.full Colors.black 64 | , ticks = Ticks.time 5 65 | } 66 | 67 | 68 | 69 | -- DATA 70 | 71 | 72 | type alias Data = 73 | { age : Float 74 | , weight : Float 75 | , height : Float 76 | , income : Float 77 | , date : Time.Time 78 | } 79 | 80 | 81 | alice : List Data 82 | alice = 83 | [ Data 4 24 0.94 0 (dateInterval 0) 84 | , Data 25 75 1.73 25000 (dateInterval 1) 85 | , Data 46 83 1.75 40000 (dateInterval 2) 86 | ] 87 | 88 | 89 | bobby : List Data 90 | bobby = 91 | [ Data 4 22 1.01 0 (dateInterval 0) 92 | , Data 25 75 1.87 28000 (dateInterval 1) 93 | , Data 46 77 1.87 52000 (dateInterval 2) 94 | ] 95 | 96 | 97 | chuck : List Data 98 | chuck = 99 | [ Data 4 21 0.98 0 (dateInterval 0) 100 | , Data 25 89 1.83 85000 (dateInterval 1) 101 | , Data 46 95 1.84 120000 (dateInterval 2) 102 | ] 103 | 104 | 105 | average : List Data 106 | average = 107 | [ Data 4 22.3 1.0 0 (dateInterval 0) 108 | , Data 25 79.7 1.8 46000 (dateInterval 1) 109 | , Data 46 85 1.82 70667 (dateInterval 2) 110 | ] 111 | 112 | 113 | dateInterval : Int -> Time.Time 114 | dateInterval i = 115 | 4 * year + toFloat i * 21 * year 116 | 117 | 118 | day : Time.Time 119 | day = 120 | 24 * Time.hour 121 | 122 | 123 | year : Time.Time 124 | year = 125 | 356 * day 126 | -------------------------------------------------------------------------------- /docs/assets/main.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | margin: 0; 4 | font-family: monospace; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | } 10 | 11 | a { 12 | color: #848484; 13 | text-decoration: none; 14 | cursor: pointer; 15 | } 16 | 17 | a:hover { 18 | color: rgb(245, 105, 215); 19 | } 20 | 21 | .hidden { 22 | display: none; 23 | } 24 | 25 | button { 26 | border: none; 27 | background: white; 28 | font-family: monospace; 29 | } 30 | 31 | button:hover { 32 | color: rgb(245, 105, 215); 33 | } 34 | 35 | 36 | /* */ 37 | 38 | 39 | .view { 40 | margin: 200px 20px 200px 300px 41 | } 42 | 43 | .view__title__container { 44 | position: fixed; 45 | top: 40px; 46 | left: 40px; 47 | } 48 | 49 | .view__title { 50 | font-weight: lighter; 51 | } 52 | 53 | .view__tag-line { 54 | max-width: 250px; 55 | } 56 | 57 | .view__body { 58 | max-width: 1270px; 59 | } 60 | 61 | .view__example__container { 62 | margin-bottom: 20px; 63 | } 64 | 65 | .view__example__container--full { 66 | width: 100%; 67 | } 68 | 69 | .view__example__container--half { 70 | width: 50%; 71 | } 72 | 73 | .view__example__toggle-source { 74 | opacity: 0; 75 | pointer-events: none; 76 | padding-left: 5px 77 | padding-bottom: 5px 78 | } 79 | 80 | .view__example__container:hover .view__example__toggle-source { 81 | opacity: 1; 82 | pointer-events: auto; 83 | cursor: pointer; 84 | } 85 | 86 | .view__source__container { 87 | max-width: 100vw; 88 | width: 800px; 89 | height: 100vh; 90 | background: white; 91 | position: fixed; 92 | top: 0; 93 | right: 0; 94 | padding: 30px 40px; 95 | transition: 0.5s ease-in-out; 96 | pointer-events: auto; 97 | border-left: 1px solid rgb(163, 163, 163); 98 | } 99 | 100 | .view__source__container--open { 101 | transform: translatex(0); 102 | } 103 | 104 | .view__source__container--closed { 105 | transform: translatex(100%); 106 | } 107 | 108 | .view__source__inner { 109 | margin-top: 30px; 110 | height: 85vh; 111 | } 112 | 113 | 114 | /* */ 115 | 116 | 117 | .view__selection__placeholder { 118 | width: 42.5%; 119 | height: 0%; 120 | margin-left: 5.5%; 121 | margin-top: 3%; 122 | margin-right: 2%; 123 | padding-bottom: 28.2222%; 124 | display: inline-block; 125 | vertical-align: top; 126 | position: relative; 127 | } 128 | 129 | .view__selection__placeholder__inner { 130 | width: 100%; 131 | height: 100%; 132 | background: #a6a6a61a; 133 | text-align: center; 134 | position: absolute; 135 | top: 50; 136 | } 137 | 138 | .view__selection__placeholder__inner__text { 139 | text-align: center; 140 | position: absolute; 141 | top: 50%; 142 | width: 100%; 143 | padding: 0 10%; 144 | transform: translateY(-50%); 145 | } 146 | 147 | 148 | /* */ 149 | 150 | @media (max-width: 1500px) { 151 | body { 152 | font-size: 12px; 153 | } 154 | 155 | .view { 156 | margin: 240px 20px 200px 20px 157 | } 158 | 159 | .view__title__container { 160 | position: absolute; 161 | } 162 | 163 | .view__example__container { 164 | width: 100%; 165 | } 166 | } 167 | 168 | @media (max-width: 800px) { 169 | 170 | .view__example__container:nth-child(2) { 171 | display: none; 172 | } 173 | 174 | .view__example__container div { 175 | pointer-events: none; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /examples/Tooltip3.elm: -------------------------------------------------------------------------------- 1 | module Tooltip3 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes 5 | import LineChart as LineChart 6 | import LineChart.Junk as Junk exposing (..) 7 | import LineChart.Dots as Dots 8 | import LineChart.Colors as Colors 9 | import LineChart.Container as Container 10 | import LineChart.Junk as Junk 11 | import LineChart.Interpolation as Interpolation 12 | import LineChart.Axis.Intersection as Intersection 13 | import LineChart.Axis as Axis 14 | import LineChart.Legends as Legends 15 | import LineChart.Line as Line 16 | import LineChart.Events as Events 17 | import LineChart.Grid as Grid 18 | import LineChart.Legends as Legends 19 | import LineChart.Area as Area 20 | import Browser 21 | 22 | 23 | main : Program () Model Msg 24 | main = 25 | Browser.sandbox 26 | { init = init 27 | , update = update 28 | , view = view 29 | } 30 | 31 | 32 | 33 | -- MODEL 34 | 35 | 36 | type alias Model = 37 | { hovered : List Info } 38 | 39 | 40 | init : Model 41 | init = 42 | { hovered = [] } 43 | 44 | 45 | 46 | -- UPDATE 47 | 48 | 49 | type Msg 50 | = Hover (List Info) 51 | 52 | 53 | update : Msg -> Model -> Model 54 | update msg model = 55 | case msg of 56 | Hover hovered -> 57 | { model | hovered = hovered } 58 | 59 | 60 | 61 | -- VIEW 62 | 63 | 64 | view : Model -> Html.Html Msg 65 | view model = 66 | Html.div 67 | [ Html.Attributes.style "font-family" "monospace" ] 68 | [ chart model ] 69 | 70 | 71 | chart : Model -> Html.Html Msg 72 | chart model = 73 | LineChart.viewCustom 74 | { y = Axis.default 450 "Weight" .weight 75 | , x = Axis.default 700 "Age" .age 76 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 77 | , interpolation = Interpolation.default 78 | , intersection = Intersection.default 79 | , legends = Legends.default 80 | , events = Events.hoverMany Hover 81 | , junk = 82 | Junk.hoverMany model.hovered formatX formatY 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = Dots.hoverMany model.hovered 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | formatX : Info -> String 95 | formatX info = 96 | "Age: " ++ String.fromFloat info.age 97 | 98 | 99 | formatY : Info -> String 100 | formatY info = 101 | String.fromFloat info.weight ++ " kg" 102 | 103 | 104 | 105 | -- DATA 106 | 107 | 108 | type alias Info = 109 | { age : Float 110 | , weight : Float 111 | , height : Float 112 | , income : Float 113 | } 114 | 115 | 116 | alice : List Info 117 | alice = 118 | [ Info 10 34 1.34 0 119 | , Info 16 42 1.62 3000 120 | , Info 25 75 1.73 25000 121 | , Info 43 83 1.75 40000 122 | ] 123 | 124 | 125 | bobby : List Info 126 | bobby = 127 | [ Info 10 38 1.32 0 128 | , Info 17 69 1.75 2000 129 | , Info 25 75 1.87 32000 130 | , Info 43 77 1.87 52000 131 | ] 132 | 133 | 134 | chuck : List Info 135 | chuck = 136 | [ Info 10 42 1.35 0 137 | , Info 15 72 1.72 1800 138 | , Info 25 89 1.83 85000 139 | , Info 43 95 1.84 120000 140 | ] 141 | -------------------------------------------------------------------------------- /examples/BrokenData.elm: -------------------------------------------------------------------------------- 1 | module BrokenData exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Dots as Dots 8 | import LineChart as LineChart 9 | import LineChart.Junk as Junk exposing (..) 10 | import LineChart.Colors as Colors 11 | import LineChart.Dots as Dots 12 | import LineChart.Container as Container 13 | import LineChart.Interpolation as Interpolation 14 | import LineChart.Axis.Intersection as Intersection 15 | import LineChart.Axis.Title as Title 16 | import LineChart.Axis.Ticks as Ticks 17 | import LineChart.Axis.Range as Range 18 | import LineChart.Axis.Line as AxisLine 19 | import LineChart.Axis as Axis 20 | import LineChart.Legends as Legends 21 | import LineChart.Line as Line 22 | import LineChart.Events as Events 23 | import LineChart.Grid as Grid 24 | import LineChart.Legends as Legends 25 | import LineChart.Area as Area 26 | 27 | 28 | main : Html.Html msg 29 | main = 30 | Html.div 31 | [ class "container" ] 32 | [ chart ] 33 | 34 | 35 | chart : Html.Html msg 36 | chart = 37 | LineChart.viewCustom 38 | { y = 39 | Axis.custom 40 | { title = Title.default "Weight" 41 | , variable = .income -- or .weight -- as opposed to `Just << .height` 42 | , pixels = 450 43 | , range = Range.default 44 | , axisLine = AxisLine.default 45 | , ticks = Ticks.default 46 | } 47 | , x = Axis.default 700 "Age" .age 48 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 49 | , interpolation = Interpolation.linear 50 | , intersection = Intersection.default 51 | , legends = Legends.default 52 | , events = Events.default 53 | , junk = Junk.default 54 | , grid = Grid.default 55 | , area = Area.default 56 | , line = Line.default 57 | , dots = Dots.default 58 | } 59 | [ LineChart.line Colors.gold Dots.diamond "Alice" alice 60 | , LineChart.line Colors.pink Dots.circle "Bobby" bobby 61 | , LineChart.line Colors.blue Dots.plus "Chuck" chuck 62 | ] 63 | 64 | 65 | 66 | -- DATA 67 | 68 | 69 | type alias Info = 70 | { age : Float 71 | , weight : Maybe Float 72 | , height : Float 73 | , income : Maybe Float -- This is now a Maybe! 74 | } 75 | 76 | 77 | alice : List Info 78 | alice = 79 | [ Info 10 (Just 34) 1.34 (Just 0) 80 | , Info 16 (Just 42) 1.62 (Just 3000) 81 | , Info 22 (Just 75) 1.73 (Just 25000) 82 | , Info 25 (Just 75) 1.73 (Just 25000) 83 | , Info 43 (Just 83) 1.75 (Just 40000) 84 | , Info 53 (Just 83) 1.75 (Just 80000) 85 | ] 86 | 87 | 88 | bobby : List Info 89 | bobby = 90 | [ Info 10 (Just 38) 1.32 (Just 0) 91 | , Info 16 (Just 69) 1.75 (Just 2000) 92 | , Info 22 (Nothing) 1.87 (Just 31000) 93 | , Info 25 (Nothing) 1.87 (Just 32000) 94 | , Info 43 (Just 77) 1.87 (Just 52000) 95 | , Info 53 (Just 77) 1.87 (Just 82000) 96 | ] 97 | 98 | 99 | chuck : List Info 100 | chuck = 101 | [ Info 10 (Just 42) 1.35 (Just 0) 102 | , Info 16 (Just 72) 1.72 (Just 1800) 103 | , Info 22 (Just 82) 1.72 (Just 90800) 104 | , Info 25 (Just 82) 1.72 (Nothing) 105 | , Info 43 (Just 95) 1.84 (Just 120000) 106 | , Info 53 (Just 95) 1.84 (Just 130000) 107 | ] 108 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example4.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example4 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverOne Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = customDotsConfig 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | customDotsConfig : Dots.Config Data 95 | customDotsConfig = 96 | let 97 | styleLegend _ = 98 | Dots.full 7 99 | 100 | styleIndividual datum = 101 | Dots.full <| (datum.height - 1) * 12 102 | in 103 | Dots.customAny 104 | { legend = styleLegend 105 | , individual = styleIndividual 106 | } 107 | 108 | 109 | 110 | -- DATA 111 | 112 | 113 | type alias Data = 114 | { age : Float 115 | , weight : Float 116 | , height : Float 117 | , income : Float 118 | } 119 | 120 | 121 | alice : List Data 122 | alice = 123 | [ Data 10 34 1.34 0 124 | , Data 16 42 1.62 3000 125 | , Data 25 73 1.73 25000 126 | , Data 43 83 1.75 40000 127 | ] 128 | 129 | 130 | bobby : List Data 131 | bobby = 132 | [ Data 10 38 1.32 0 133 | , Data 17 69 1.75 2000 134 | , Data 25 78 1.87 32000 135 | , Data 43 77 1.87 52000 136 | ] 137 | 138 | 139 | chuck : List Data 140 | chuck = 141 | [ Data 10 42 1.35 0 142 | , Data 15 72 1.72 1800 143 | , Data 25 89 1.83 85000 144 | , Data 43 95 1.84 120000 145 | ] 146 | -------------------------------------------------------------------------------- /src/LineChart/Axis/Line.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Axis.Line exposing 2 | ( Config, default, full, rangeFrame, none 3 | , Properties, custom 4 | ) 5 | 6 | {-| 7 | 8 | _If you're confused as to what "axis range" and "data range" means, 9 | check out `Axis.Range` for an explanation!_ 10 | 11 | @docs Config, default, full, rangeFrame, none, custom, Properties 12 | 13 | -} 14 | 15 | import Svg exposing (Attribute) 16 | import LineChart.Coordinate as Coordinate 17 | import Internal.Axis.Line as Line 18 | import Color 19 | 20 | 21 | 22 | {-| This configuration is part of the 23 | configuration in `Axis.custom`. 24 | 25 | axisConfig : Axis.Config Data msg 26 | axisConfig = 27 | Axis.custom 28 | { .. 29 | , range = AxisLine.default 30 | , ... 31 | } 32 | 33 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 34 | 35 | -} 36 | type alias Config msg = 37 | Line.Config msg 38 | 39 | 40 | {-| Draws the full length of your axis range. 41 | 42 | axisLineConfig : AxisLine.Config msg 43 | axisLineConfig = 44 | AxisLine.default 45 | 46 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 47 | 48 | -} 49 | default : Config msg 50 | default = 51 | Line.default 52 | 53 | 54 | {-| Same as the default, except you get to pick the color. 55 | 56 | axisLineConfig : AxisLine.Config msg 57 | axisLineConfig = 58 | AxisLine.full Color.red 59 | 60 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 61 | 62 | -} 63 | full : Color.Color -> Config msg 64 | full = 65 | Line.full 66 | 67 | 68 | {-| Draws the full length of your data range in your given color. 69 | 70 | axisLineConfig : AxisLine.Config msg 71 | axisLineConfig = 72 | AxisLine.rangeFrame Color.red 73 | 74 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 75 | 76 | -} 77 | rangeFrame : Color.Color -> Config msg 78 | rangeFrame = 79 | Line.rangeFrame 80 | 81 | 82 | {-| Removes the axis line entirely. 83 | 84 | axisLineConfig : AxisLine.Config msg 85 | axisLineConfig = 86 | AxisLine.none 87 | 88 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 89 | 90 | -} 91 | none : Config msg 92 | none = 93 | Line.none 94 | 95 | 96 | 97 | -- CUSTOM 98 | 99 | 100 | {-| -} 101 | type alias Properties msg = 102 | { color : Color.Color 103 | , width : Float 104 | , events : List (Attribute msg) 105 | , start : Float 106 | , end : Float 107 | } 108 | 109 | 110 | {-| Given your data range and axis range respectively, define your own 111 | axis line configuration. 112 | 113 | axisLineConfig : AxisLine.Config msg 114 | axisLineConfig = 115 | AxisLine.custom <| \dataRange axisRange -> 116 | { color = Colors.gray 117 | , width = 2 118 | , events = [] 119 | , start = dataRange.min 120 | , end = 5 121 | } 122 | 123 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/AxisLine/Example1.elm)._ 124 | 125 | 126 | -} 127 | custom : (Coordinate.Range -> Coordinate.Range -> Properties msg) -> Config msg 128 | custom = 129 | Line.custom 130 | -------------------------------------------------------------------------------- /examples/LotsOfData.elm: -------------------------------------------------------------------------------- 1 | module LotsOfData exposing (main) 2 | 3 | import Html exposing (Html, div, h1, node, p, text) 4 | import Html.Attributes exposing (class) 5 | import Svg exposing (Attribute, Svg, g, text_, tspan) 6 | import LineChart as LineChart 7 | import LineChart.Junk as Junk exposing (..) 8 | import LineChart.Dots as Dots 9 | import LineChart.Container as Container 10 | import LineChart.Coordinate as Coordinate 11 | import LineChart.Junk as Junk 12 | import LineChart.Colors as Colors 13 | import LineChart.Interpolation as Interpolation 14 | import LineChart.Axis.Intersection as Intersection 15 | import LineChart.Axis as Axis 16 | import LineChart.Legends as Legends 17 | import LineChart.Line as Line 18 | import LineChart.Events as Events 19 | import LineChart.Grid as Grid 20 | import LineChart.Legends as Legends 21 | import LineChart.Area as Area 22 | import Random 23 | import Browser 24 | 25 | 26 | 27 | main : Program () Model Msg 28 | main = 29 | Browser.element 30 | { init = \_ -> init 31 | , update = update 32 | , view = view 33 | , subscriptions = always Sub.none 34 | } 35 | 36 | 37 | 38 | -- MODEL 39 | 40 | 41 | type alias Model = 42 | { data : List Coordinate.Point } 43 | 44 | 45 | init : ( Model, Cmd Msg ) 46 | init = 47 | ( { data = [] }, getNumbers ) 48 | 49 | 50 | 51 | -- UPDATE 52 | 53 | 54 | type Msg 55 | = ReceiveNumbers (List Float) 56 | 57 | 58 | update : Msg -> Model -> ( Model, Cmd Msg ) 59 | update msg model = 60 | case msg of 61 | ReceiveNumbers numbers -> 62 | ( { model | data = List.indexedMap toData numbers } 63 | , Cmd.none 64 | ) 65 | 66 | 67 | toData : Int -> Float -> Coordinate.Point 68 | toData index = 69 | Coordinate.Point (toFloat index) 70 | 71 | 72 | getNumbers : Cmd Msg 73 | getNumbers = 74 | Random.list 1501 (Random.float 0 20) 75 | |> Random.generate ReceiveNumbers 76 | 77 | 78 | 79 | -- VIEW 80 | 81 | 82 | view : Model -> Svg Msg 83 | view model = 84 | Html.div 85 | [ class "container" ] 86 | [ chart model ] 87 | 88 | 89 | chart : Model -> Html.Html Msg 90 | chart model = 91 | LineChart.viewCustom 92 | { y = Axis.default 450 "y" .y 93 | , x = Axis.default 1700 "x" .x 94 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 95 | , interpolation = Interpolation.default 96 | , intersection = Intersection.custom .min .min 97 | , legends = Legends.default 98 | , events = Events.default 99 | , junk = Junk.default 100 | , grid = Grid.default 101 | , area = Area.default 102 | , line = Line.default 103 | , dots = Dots.default 104 | } 105 | [ LineChart.line Colors.pink Dots.none "data" model.data ] 106 | 107 | 108 | 109 | -- DATA 110 | 111 | 112 | type alias Info = 113 | { age : Float 114 | , weight : Float 115 | , height : Float 116 | , income : Float 117 | } 118 | 119 | 120 | alice : List Info 121 | alice = 122 | [ Info 10 34 1.34 0 123 | , Info 16 42 1.62 3000 124 | , Info 25 75 1.73 25000 125 | , Info 43 83 1.75 40000 126 | ] 127 | 128 | 129 | bobby : List Info 130 | bobby = 131 | [ Info 10 38 1.32 0 132 | , Info 17 69 1.75 2000 133 | , Info 25 75 1.87 32000 134 | , Info 43 77 1.87 52000 135 | ] 136 | 137 | 138 | chuck : List Info 139 | chuck = 140 | [ Info 10 42 1.35 0 141 | , Info 15 72 1.72 1800 142 | , Info 25 89 1.83 85000 143 | , Info 43 95 1.84 120000 144 | ] 145 | -------------------------------------------------------------------------------- /examples/Docs/Dots/Example6.elm: -------------------------------------------------------------------------------- 1 | module Docs.Dots.Example3 exposing (main) 2 | 3 | import Html 4 | import Html.Attributes exposing (class) 5 | import LineChart 6 | import LineChart.Colors as Colors 7 | import LineChart.Junk as Junk 8 | import LineChart.Area as Area 9 | import LineChart.Axis as Axis 10 | import LineChart.Junk as Junk 11 | import LineChart.Dots as Dots 12 | import LineChart.Grid as Grid 13 | import LineChart.Dots as Dots 14 | import LineChart.Line as Line 15 | import LineChart.Colors as Colors 16 | import LineChart.Events as Events 17 | import LineChart.Legends as Legends 18 | import LineChart.Container as Container 19 | import LineChart.Interpolation as Interpolation 20 | import LineChart.Axis.Intersection as Intersection 21 | 22 | 23 | 24 | main : Program Never Model Msg 25 | main = 26 | Browser.sandbox 27 | { init = init 28 | , update = update 29 | , view = view 30 | } 31 | 32 | 33 | 34 | -- MODEL 35 | 36 | 37 | type alias Model = 38 | { hovering : Maybe Data } 39 | 40 | 41 | init : Model 42 | init = 43 | { hovering = Nothing } 44 | 45 | 46 | 47 | -- UPDATE 48 | 49 | 50 | type Msg 51 | = Hover (Maybe Data) 52 | 53 | 54 | update : Msg -> Model -> Model 55 | update msg model = 56 | case msg of 57 | Hover hovering -> 58 | { model | hovering = hovering } 59 | 60 | 61 | 62 | -- VIEW 63 | 64 | 65 | view : Model -> Html.Html Msg 66 | view model = 67 | Html.div 68 | [ class "container" ] 69 | [ chart model ] 70 | 71 | 72 | chart : Model -> Html.Html Msg 73 | chart model = 74 | LineChart.viewCustom 75 | { y = Axis.default 450 "Weight" .weight 76 | , x = Axis.default 700 "Age" .age 77 | , container = Container.default "line-chart-1" 78 | , interpolation = Interpolation.default 79 | , intersection = Intersection.default 80 | , legends = Legends.default 81 | , events = Events.hoverOne Hover 82 | , junk = Junk.default 83 | , grid = Grid.default 84 | , area = Area.default 85 | , line = Line.default 86 | , dots = customDotsConfig model.hovering 87 | } 88 | [ LineChart.line Colors.pink Dots.triangle "Chuck" chuck 89 | , LineChart.line Colors.cyan Dots.circle "Bobby" bobby 90 | , LineChart.line Colors.purple Dots.diamond "Alice" alice 91 | ] 92 | 93 | 94 | customDotsConfig : Maybe Data -> Dots.Config Data 95 | customDotsConfig maybeHovered = 96 | let 97 | styleLegend _ = 98 | Dots.disconnected 10 2 99 | 100 | styleIndividual datum = 101 | if Just datum == maybeHovered 102 | then Dots.empty 8 2 103 | else Dots.disconnected 10 2 104 | in 105 | Dots.customAny 106 | { legend = styleLegend 107 | , individual = styleIndividual 108 | } 109 | 110 | 111 | 112 | -- DATA 113 | 114 | 115 | type alias Data = 116 | { age : Float 117 | , weight : Float 118 | , height : Float 119 | , income : Float 120 | } 121 | 122 | 123 | alice : List Data 124 | alice = 125 | [ Data 10 34 1.34 0 126 | , Data 16 42 1.62 3000 127 | , Data 25 73 1.73 25000 128 | , Data 43 83 1.75 40000 129 | ] 130 | 131 | 132 | bobby : List Data 133 | bobby = 134 | [ Data 10 38 1.32 0 135 | , Data 17 69 1.75 2000 136 | , Data 25 76 1.87 32000 137 | , Data 43 77 1.87 52000 138 | ] 139 | 140 | 141 | chuck : List Data 142 | chuck = 143 | [ Data 10 42 1.35 0 144 | , Data 15 72 1.72 1800 145 | , Data 25 89 1.83 85000 146 | , Data 43 95 1.84 120000 147 | ] 148 | -------------------------------------------------------------------------------- /examples/Explanation/SvgAndDataSpace.elm: -------------------------------------------------------------------------------- 1 | module Explanation.Ranges exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Coordinate as Coordinate 9 | import LineChart as LineChart 10 | import LineChart.Junk as Junk exposing (..) 11 | import LineChart.Dots as Dots 12 | import LineChart.Container as Container 13 | import LineChart.Interpolation as Interpolation 14 | import LineChart.Axis.Intersection as Intersection 15 | import LineChart.Axis as Axis 16 | import LineChart.Legends as Legends 17 | import LineChart.Line as Line 18 | import LineChart.Events as Events 19 | import LineChart.Grid as Grid 20 | import LineChart.Legends as Legends 21 | import LineChart.Area as Area 22 | import Color 23 | 24 | 25 | 26 | main : Html.Html msg 27 | main = 28 | Html.div 29 | [ class "container" ] 30 | [ chart ] 31 | 32 | 33 | chart : Html.Html msg 34 | chart = 35 | LineChart.viewCustom 36 | { y = Axis.picky 500 "y" .y [ 0, 3 ] 37 | , x = Axis.picky 700 "x" .x [ 0, 3 ] 38 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 39 | , interpolation = Interpolation.default 40 | , intersection = Intersection.default 41 | , legends = Legends.default 42 | , events = Events.default 43 | , junk = Junk.custom customJunk 44 | , grid = Grid.default 45 | , area = Area.default 46 | , line = Line.default 47 | , dots = Dots.default 48 | } 49 | [ LineChart.line Colors.pink Dots.none "some data" data 50 | ] 51 | 52 | 53 | customJunk : Coordinate.System -> Junk.Layers msg 54 | customJunk system = 55 | let 56 | dataLabel point = 57 | Junk.labelAt system point.x point.y 12 5 "start" 58 | 59 | svgLabel point = 60 | Junk.labelAt system point.x point.y 12 25 "start" 61 | 62 | circle point = 63 | Junk.circle system 3 Colors.cyan point.x point.y 64 | 65 | dataSpace point = 66 | "Data-space: " ++ pointToString point 67 | 68 | svgSpace point = 69 | "SVG-space: " ++ pointToString point 70 | 71 | pointData1 = Coordinate.Point 0 3 72 | pointSvg1 = Coordinate.toSvg system pointData1 73 | 74 | pointData2 = Coordinate.Point 0 0 75 | pointSvg2 = Coordinate.toSvg system pointData2 76 | 77 | pointData3 = Coordinate.Point 3 0 78 | pointSvg3 = Coordinate.toSvg system pointData3 79 | in 80 | { below = [] 81 | , above = 82 | [ dataLabel pointData1 Color.black (dataSpace pointData1) 83 | , svgLabel pointData1 Color.black (svgSpace pointSvg1) 84 | , circle pointData1 85 | -- 86 | , dataLabel pointData2 Color.black (dataSpace pointData2) 87 | , svgLabel pointData2 Color.black (svgSpace pointSvg2) 88 | , circle pointData2 89 | -- 90 | , dataLabel pointData3 Color.black (dataSpace pointData3) 91 | , svgLabel pointData3 Color.black (svgSpace pointSvg3) 92 | , circle pointData3 93 | ] 94 | , html = [] 95 | } 96 | 97 | 98 | pointToString : Coordinate.Point -> String 99 | pointToString { x, y } = 100 | let round10 n = toFloat (round (n * 10)) / 10 in 101 | "( " ++ toString (round10 x) ++ ", " ++ toString (round10 y) ++ " )" 102 | 103 | 104 | 105 | -- DATA 106 | 107 | 108 | type alias Data = 109 | { x : Float, y : Float } 110 | 111 | 112 | data : List Data 113 | data = 114 | [ Data -1 -5 115 | , Data 5 5 116 | ] 117 | -------------------------------------------------------------------------------- /src/LineChart/Axis/Title.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Axis.Title exposing (Config, default, atAxisMax, atDataMax, atPosition, custom) 2 | 3 | {-| 4 | 5 | @docs Config, default, atAxisMax, atDataMax, atPosition, custom 6 | 7 | -} 8 | 9 | import Svg exposing (Svg) 10 | import Internal.Axis.Title as Title 11 | import LineChart.Coordinate as Coordinate 12 | 13 | 14 | 15 | {-| Part of the configuration in `Axis.custom`. 16 | 17 | axisConfig : Axis.Config Data msg 18 | axisConfig = 19 | Axis.custom 20 | { title = Title.default 21 | , ... 22 | } 23 | 24 | -} 25 | type alias Config msg = 26 | Title.Config msg 27 | 28 | 29 | {-| Place the title at the maxima of your axis range. 30 | -} 31 | default : String -> Config msg 32 | default = 33 | Title.default 34 | 35 | 36 | {-| Place the title at the maxima of your data range. Arguments: 37 | 38 | 1. The x offset in SVG-space. 39 | 2. The y offset in SVG-space. 40 | 3. The title. 41 | 42 | 43 | titleConfig : Title.Config msg 44 | titleConfig = 45 | Title.atDataMax 0 10 "Age" 46 | 47 | 48 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Title/Example1.elm)._ 49 | 50 | -} 51 | atDataMax : Float -> Float -> String -> Config msg 52 | atDataMax = 53 | Title.atDataMax 54 | 55 | 56 | {-| Place the title at the maxima of your axis range. Arguments: 57 | 58 | 1. The x offset in SVG-space. 59 | 2. The y offset in SVG-space. 60 | 3. The title. 61 | 62 | 63 | titleConfig : Title.Config msg 64 | titleConfig = 65 | Title.atAxisMax 0 10 "Age" 66 | 67 | 68 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Title/Example1.elm)._ 69 | 70 | -} 71 | atAxisMax : Float -> Float -> String -> Config msg 72 | atAxisMax = 73 | Title.atAxisMax 74 | 75 | 76 | {-| Place your title in any spot along your axis. Arguments: 77 | 78 | 1. Given the data range and axis range, provide a position. 79 | 2. The x offset in SVG-space. 80 | 3. The y offset in SVG-space. 81 | 4. The title. 82 | 83 | 84 | titleConfig : Title.Config msg 85 | titleConfig = 86 | let position dataRange axisRange = 80 in 87 | Title.atPosition position -15 30 "Weight" 88 | 89 | 90 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Title/Example1.elm)._ 91 | 92 | -} 93 | atPosition : (Coordinate.Range -> Coordinate.Range -> Float) -> Float -> Float -> String -> Config msg 94 | atPosition = 95 | Title.atPosition 96 | 97 | 98 | {-| Almost the same as `atPosition` except instead of a string title, you pass a 99 | SVG title. Arguments: 100 | 101 | 1. Given the data range and axis range, provide a position. 102 | 2. The x offset in SVG-space. 103 | 3. The y offset in SVG-space. 104 | 4. The title view. 105 | 106 | 107 | titleConfig : Title.Config msg 108 | titleConfig = 109 | let position dataRange axisRange = middle axisRange in 110 | Title.custom position -10 35 <| 111 | Svg.g 112 | [ Svg.Attributes.style "text-anchor: middle;" ] 113 | [ Junk.label Colors.pink "Weight" ] 114 | 115 | middle : Coordinate.Range -> Float 116 | middle { min, max } = 117 | min + (max - min) / 2 118 | 119 | 120 | _See full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Title/Example1.elm)._ 121 | 122 | -} 123 | custom : (Coordinate.Range -> Coordinate.Range -> Float) -> Float -> Float -> (Svg msg) -> Config msg 124 | custom = 125 | Title.custom 126 | -------------------------------------------------------------------------------- /examples/Docs/Values/Example3.elm: -------------------------------------------------------------------------------- 1 | module Docs.Values.Example1 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Axis.Title as Title 12 | import LineChart.Axis.Range as Range 13 | import LineChart.Axis.Line as AxisLine 14 | import LineChart.Axis.Ticks as Ticks 15 | import LineChart.Axis.Tick as Tick 16 | import LineChart.Axis.Values as Values 17 | import LineChart.Junk as Junk 18 | import LineChart.Dots as Dots 19 | import LineChart.Grid as Grid 20 | import LineChart.Dots as Dots 21 | import LineChart.Line as Line 22 | import LineChart.Colors as Colors 23 | import LineChart.Events as Events 24 | import LineChart.Legends as Legends 25 | import LineChart.Container as Container 26 | import LineChart.Interpolation as Interpolation 27 | import LineChart.Axis.Intersection as Intersection 28 | 29 | 30 | 31 | main : Html.Html msg 32 | main = 33 | chart 34 | 35 | 36 | chart : Html.Html msg 37 | chart = 38 | LineChart.viewCustom 39 | { x = xAxisConfig 40 | , y = Axis.default 400 "($)" .income 41 | , container = Container.default "line-chart-1" 42 | , interpolation = Interpolation.default 43 | , intersection = Intersection.default 44 | , legends = Legends.default 45 | , events = Events.default 46 | , junk = Junk.default 47 | , grid = Grid.default 48 | , area = Area.default 49 | , line = Line.default 50 | , dots = Dots.default 51 | } 52 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 53 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 54 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 55 | ] 56 | 57 | 58 | xAxisConfig : Axis.Config Data msg 59 | xAxisConfig = 60 | Axis.custom 61 | { title = Title.default "Weight" 62 | , variable = Just << .weight 63 | , pixels = 700 64 | , range = Range.default 65 | , axisLine = AxisLine.rangeFrame Colors.gray 66 | , ticks = ticksConfig 67 | } 68 | 69 | 70 | ticksConfig : Ticks.Config msg 71 | ticksConfig = 72 | Ticks.custom <| \dataRange axisRange -> 73 | List.map Tick.float (Values.custom 45 10 dataRange) ++ 74 | List.map Tick.long (Values.custom 30 20 dataRange) 75 | 76 | 77 | 78 | -- DATA 79 | 80 | 81 | type alias Data = 82 | { age : Float 83 | , weight : Float 84 | , height : Float 85 | , income : Float 86 | , date : Time.Time 87 | } 88 | 89 | 90 | alice : List Data 91 | alice = 92 | [ Data 4 24 0.94 0 (dateInterval 0) 93 | , Data 25 75 1.73 25000 (dateInterval 1) 94 | , Data 46 83 1.75 40000 (dateInterval 2) 95 | ] 96 | 97 | 98 | bobby : List Data 99 | bobby = 100 | [ Data 4 22 1.01 0 (dateInterval 0) 101 | , Data 25 75 1.87 28000 (dateInterval 1) 102 | , Data 46 77 1.87 52000 (dateInterval 2) 103 | ] 104 | 105 | 106 | chuck : List Data 107 | chuck = 108 | [ Data 4 21 0.98 0 (dateInterval 0) 109 | , Data 25 89 1.83 85000 (dateInterval 1) 110 | , Data 46 95 1.84 120000 (dateInterval 2) 111 | ] 112 | 113 | 114 | average : List Data 115 | average = 116 | [ Data 4 22.3 1.0 0 (dateInterval 0) 117 | , Data 25 79.7 1.8 46000 (dateInterval 1) 118 | , Data 46 85 1.82 70667 (dateInterval 2) 119 | ] 120 | 121 | 122 | dateInterval : Int -> Time.Time 123 | dateInterval i = 124 | 4 * year + toFloat i * 21 * year 125 | 126 | 127 | day : Time.Time 128 | day = 129 | 24 * Time.hour 130 | 131 | 132 | year : Time.Time 133 | year = 134 | 356 * day 135 | -------------------------------------------------------------------------------- /examples/Legends.elm: -------------------------------------------------------------------------------- 1 | module Legends exposing (main) 2 | 3 | 4 | import Html 5 | import Html.Attributes exposing (class) 6 | import Svg 7 | import Svg.Attributes as SvgA 8 | import LineChart 9 | import LineChart.Dots as Dots 10 | import LineChart as LineChart 11 | import LineChart.Junk as Junk exposing (..) 12 | import LineChart.Dots as Dots 13 | import LineChart.Container as Container 14 | import LineChart.Coordinate as Coordinate 15 | import LineChart.Interpolation as Interpolation 16 | import LineChart.Axis.Intersection as Intersection 17 | import LineChart.Axis as Axis 18 | import LineChart.Colors as Colors 19 | import LineChart.Legends as Legends 20 | import LineChart.Line as Line 21 | import LineChart.Events as Events 22 | import LineChart.Grid as Grid 23 | import LineChart.Legends as Legends 24 | import LineChart.Area as Area 25 | import Color 26 | 27 | 28 | main : Html.Html msg 29 | main = 30 | Html.div 31 | [ class "container" ] 32 | [ chart ] 33 | 34 | 35 | chart : Html.Html msg 36 | chart = 37 | LineChart.viewCustom 38 | { y = Axis.default 450 "Weight" .weight 39 | , x = Axis.default 700 "Age" .age 40 | , container = Container.styled "line-chart-1" [ ( "font-family", "monospace" ) ] 41 | , interpolation = Interpolation.default 42 | , intersection = Intersection.default 43 | , legends = 44 | -- Try out these different configs! 45 | Legends.default 46 | -- Legends.byEnding (Junk.label Color.black) 47 | -- Legends.byBeginning (Junk.label Color.black) 48 | -- Legends.grouped .max .min 0 -60 -- Arguments: x-coordinate y-coordinate x-offset y-offset 49 | -- Legends.groupedCustom 30 viewLegends 50 | -- Legends.groupedCustom 20 viewLegends 51 | , events = Events.default 52 | , junk = Junk.default 53 | , grid = Grid.default 54 | , area = Area.default 55 | , line = Line.default 56 | , dots = Dots.default 57 | } 58 | [ LineChart.line Colors.gold Dots.triangle "Chuck" chuck 59 | , LineChart.line Colors.pink Dots.circle "Bobby" bobby 60 | , LineChart.line Colors.blue Dots.diamond "Alice" alice 61 | ] 62 | 63 | 64 | viewLegends : Coordinate.System -> List (Legends.Legend msg) -> Svg.Svg msg 65 | viewLegends system legends = 66 | Svg.g 67 | [ SvgA.class "chart__legends" 68 | , Junk.transform 69 | [ Junk.move system system.x.min system.y.min 70 | , Junk.offset 20 20 71 | ] 72 | ] 73 | (List.indexedMap viewLegend legends) 74 | 75 | 76 | viewLegend : Int -> Legends.Legend msg -> Svg.Svg msg 77 | viewLegend index { sample, label } = 78 | Svg.g 79 | [ SvgA.class "chart__legend" 80 | , Junk.transform [ Junk.offset (toFloat index * 100) 20 ] 81 | ] 82 | [ sample 83 | , Svg.g 84 | [ Junk.transform [ Junk.offset 40 4 ] ] 85 | [ Junk.label Color.black label ] 86 | ] 87 | 88 | 89 | 90 | 91 | 92 | -- DATA 93 | 94 | 95 | type alias Info = 96 | { age : Float 97 | , weight : Float 98 | , height : Float 99 | , income : Float 100 | } 101 | 102 | 103 | alice : List Info 104 | alice = 105 | [ Info 10 34 1.34 0 106 | , Info 16 42 1.62 3000 107 | , Info 25 75 1.73 25000 108 | , Info 43 83 1.75 40000 109 | ] 110 | 111 | 112 | bobby : List Info 113 | bobby = 114 | [ Info 10 38 1.32 0 115 | , Info 17 69 1.75 2000 116 | , Info 25 75 1.87 32000 117 | , Info 43 77 1.87 52000 118 | ] 119 | 120 | 121 | chuck : List Info 122 | chuck = 123 | [ Info 10 42 1.35 0 124 | , Info 15 72 1.72 1800 125 | , Info 25 89 1.83 85000 126 | , Info 43 95 1.84 120000 127 | ] 128 | -------------------------------------------------------------------------------- /examples/Docs/Range/Example1.elm: -------------------------------------------------------------------------------- 1 | module Docs.Range.Example1 exposing (main) 2 | 3 | 4 | import Time 5 | import Html 6 | import LineChart 7 | import LineChart.Colors as Colors 8 | import LineChart.Junk as Junk 9 | import LineChart.Area as Area 10 | import LineChart.Axis as Axis 11 | import LineChart.Axis.Title as Title 12 | import LineChart.Axis.Range as Range 13 | import LineChart.Axis.Line as AxisLine 14 | import LineChart.Axis.Ticks as Ticks 15 | import LineChart.Junk as Junk 16 | import LineChart.Dots as Dots 17 | import LineChart.Grid as Grid 18 | import LineChart.Dots as Dots 19 | import LineChart.Line as Line 20 | import LineChart.Colors as Colors 21 | import LineChart.Events as Events 22 | import LineChart.Legends as Legends 23 | import LineChart.Container as Container 24 | import LineChart.Coordinate as Coordinate 25 | import LineChart.Interpolation as Interpolation 26 | import LineChart.Axis.Intersection as Intersection 27 | 28 | 29 | 30 | main : Html.Html msg 31 | main = 32 | chart 33 | 34 | 35 | chart : Html.Html msg 36 | chart = 37 | LineChart.viewCustom 38 | { x = xAxisConfig 39 | , y = Axis.default 400 "($)" .income 40 | , container = Container.default "line-chart-1" 41 | , interpolation = Interpolation.default 42 | , intersection = Intersection.default 43 | , legends = Legends.default 44 | , events = Events.default 45 | , junk = Junk.default 46 | , grid = Grid.default 47 | , area = Area.default 48 | , line = Line.default 49 | , dots = Dots.default 50 | } 51 | [ LineChart.line Colors.blueLight Dots.square "Chuck" chuck 52 | , LineChart.line Colors.pinkLight Dots.plus "Alice" alice 53 | , LineChart.line Colors.goldLight Dots.diamond "Bobby" bobby 54 | ] 55 | 56 | 57 | xAxisConfig : Axis.Config Data msg 58 | xAxisConfig = 59 | Axis.custom 60 | { title = Title.default "Weight" 61 | , variable = Just << .weight 62 | , pixels = 700 63 | , range = rangeConfig 64 | , axisLine = AxisLine.rangeFrame Colors.gray 65 | , ticks = Ticks.float 5 66 | } 67 | 68 | 69 | rangeConfig : Range.Config 70 | rangeConfig = 71 | -- Range.default 72 | Range.window 70 97 73 | -- Range.padded 40 40 74 | -- Range.custom specialRange 75 | 76 | 77 | specialRange : Coordinate.Range -> Coordinate.Range 78 | specialRange { min, max } = 79 | { min = min - 5, max = max + 10 } 80 | 81 | 82 | 83 | -- DATA 84 | 85 | 86 | type alias Data = 87 | { age : Float 88 | , weight : Float 89 | , height : Float 90 | , income : Float 91 | , date : Time.Time 92 | } 93 | 94 | 95 | alice : List Data 96 | alice = 97 | [ Data 4 24 0.94 0 (dateInterval 0) 98 | , Data 25 75 1.73 25000 (dateInterval 1) 99 | , Data 46 83 1.75 40000 (dateInterval 2) 100 | ] 101 | 102 | 103 | bobby : List Data 104 | bobby = 105 | [ Data 4 22 1.01 0 (dateInterval 0) 106 | , Data 25 75 1.87 28000 (dateInterval 1) 107 | , Data 46 77 1.87 52000 (dateInterval 2) 108 | ] 109 | 110 | 111 | chuck : List Data 112 | chuck = 113 | [ Data 4 21 0.98 0 (dateInterval 0) 114 | , Data 25 89 1.83 85000 (dateInterval 1) 115 | , Data 46 95 1.84 120000 (dateInterval 2) 116 | ] 117 | 118 | 119 | average : List Data 120 | average = 121 | [ Data 4 22.3 1.0 0 (dateInterval 0) 122 | , Data 25 79.7 1.8 46000 (dateInterval 1) 123 | , Data 46 85 1.82 70667 (dateInterval 2) 124 | ] 125 | 126 | 127 | dateInterval : Int -> Time.Time 128 | dateInterval i = 129 | 4 * year + toFloat i * 21 * year 130 | 131 | 132 | day : Time.Time 133 | day = 134 | 24 * Time.hour 135 | 136 | 137 | year : Time.Time 138 | year = 139 | 356 * day 140 | -------------------------------------------------------------------------------- /src/LineChart/Line.elm: -------------------------------------------------------------------------------- 1 | module LineChart.Line exposing 2 | ( Config, default 3 | , wider, hoverOne 4 | , custom 5 | , Style, style 6 | ) 7 | 8 | {-| 9 | 10 | @docs Config, default, wider, hoverOne, custom 11 | 12 | ## Styles 13 | @docs Style, style 14 | 15 | -} 16 | 17 | import Internal.Line as Line 18 | import Color 19 | 20 | 21 | 22 | {-| Use in the `LineChart.Config` passed to `LineChart.viewCustom`. 23 | 24 | chartConfig : LineChart.Config Data msg 25 | chartConfig = 26 | { ... 27 | , line = Line.default 28 | , ... 29 | } 30 | 31 | -} 32 | type alias Config data = 33 | Line.Config data 34 | 35 | 36 | {-| Makes 1px wide lines. 37 | -} 38 | default : Config data 39 | default = 40 | Line.default 41 | 42 | 43 | {-| Pass the desired width of your lines. 44 | 45 | chartConfig : LineChart.Config Data msg 46 | chartConfig = 47 | { ... 48 | , line = Line.wider 3 49 | , ... 50 | } 51 | 52 | 53 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Line/Example1.elm)._ 54 | 55 | -} 56 | wider : Float -> Config data 57 | wider = 58 | Line.wider 59 | 60 | 61 | {-| Makes the line, to which the data in the first argument belongs, wider! 62 | 63 | chartConfig : Maybe Data -> LineChart.Config Data Msg 64 | chartConfig hovered = 65 | { ... 66 | , line = Line.hoverOne hovered 67 | , ... 68 | } 69 | 70 | 71 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Line/Example2.elm)._ 72 | 73 | -} 74 | hoverOne : Maybe data -> Config data 75 | hoverOne hovered = 76 | custom <| \data -> 77 | if List.any (Just >> (==) hovered) data then 78 | style 3 identity 79 | else 80 | style 1 identity 81 | 82 | 83 | {-| Edit as style of a line based on its data. 84 | 85 | lineConfig : Maybe Data -> Line.Config Data 86 | lineConfig maybeHovered = 87 | Line.custom (toLineStyle maybeHovered) 88 | 89 | 90 | toLineStyle : Maybe Data -> List Data -> Line.Style 91 | toLineStyle maybeHovered lineData = 92 | case maybeHovered of 93 | Nothing -> -- No line is hovered 94 | Line.style 1 identity 95 | 96 | Just hovered -> -- Some line is hovered 97 | if List.any ((==) hovered) lineData then 98 | -- It is this one, so make it pop! 99 | Line.style 2 (Manipulate.darken 0.1) 100 | else 101 | -- It is not this one, so hide it a bit 102 | Line.style 1 (Manipulate.lighten 0.35) 103 | 104 | 105 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Line/Example3.elm)._ 106 | 107 | -} 108 | custom : (List data -> Style) -> Config data 109 | custom = 110 | Line.custom 111 | 112 | 113 | 114 | -- STYLE 115 | 116 | 117 | {-| -} 118 | type alias Style = 119 | Line.Style 120 | 121 | 122 | {-| Pass the width of the line and a function transforming the line's color. 123 | 124 | vanilla : Line.Style 125 | vanilla = 126 | Line.style 1 identity 127 | 128 | emphasize : Line.Style 129 | emphasize = 130 | Line.style 2 (Manipulate.darken 0.15) 131 | 132 | hide : Line.Style 133 | hide = 134 | Line.style 1 (Manipulate.lighten 0.15) 135 | 136 | blacken : Line.Style 137 | blacken = 138 | Line.style 2 (\_ -> Colors.black) 139 | 140 | 141 | _See the full example [here](https://github.com/terezka/line-charts/blob/master/examples/Docs/Line/Example4.elm)._ 142 | 143 | -} 144 | style : Float -> (Color.Color -> Color.Color) -> Style 145 | style = 146 | Line.style 147 | -------------------------------------------------------------------------------- /tests/Coordinate.elm: -------------------------------------------------------------------------------- 1 | module Coordinate exposing (..) 2 | 3 | import Expect exposing (Expectation) 4 | import Fuzz exposing (Fuzzer, list, int, float, string) 5 | import Test exposing (..) 6 | import Internal.Coordinate exposing (Margin) 7 | import LineChart.Coordinate exposing (..) 8 | 9 | 10 | -- MATERIAL 11 | 12 | 13 | frame : Frame 14 | frame = 15 | { margin = Margin 0 0 0 0 16 | , size = Size 100 100 17 | } 18 | 19 | 20 | system : System 21 | system = 22 | { frame = frame 23 | , x = Range 0 10 24 | , y = Range 0 10 25 | , xData = Range 0 10 26 | , yData = Range 0 10 27 | , id = "test dummy" 28 | } 29 | 30 | 31 | 32 | -- TESTS 33 | 34 | 35 | coordinates : Test 36 | coordinates = 37 | describe "Defaults" 38 | [ test "Length should default to 1" <| 39 | \() -> 40 | Expect.equal 0.9 (toSvgY (updateFrame system { frame | size = Size 0 0 }) 1) 41 | , fuzz float "x-coordinate produced should always be a number" <| 42 | \number -> 43 | toSvgX system number 44 | |> isNaN 45 | |> Expect.false "Coordinate should always be a number!" 46 | , fuzz float "y-coordinate produced should always be a number" <| 47 | \number -> 48 | toSvgY system number 49 | |> isNaN 50 | |> Expect.false "Coordinate should always be a number!" 51 | ] 52 | 53 | 54 | horizontal : Test 55 | horizontal = 56 | describe "Horizontal translation" 57 | [ test "toSvg" <| 58 | \() -> 59 | Expect.equal 10 (toSvgX system 1) 60 | , test "toSvg with lower margin" <| 61 | \() -> 62 | Expect.equal 28 (toSvgX (updateFrame system { frame | margin = Margin 0 0 0 20 }) 1) 63 | , test "toSvg with upper margin" <| 64 | \() -> 65 | Expect.equal 8 (toSvgX (updateFrame system { frame | margin = Margin 0 20 0 0 }) 1) 66 | , test "toCartesian" <| 67 | \() -> 68 | Expect.equal 1 (toDataX system 10) 69 | , test "toCartesian with lower margin" <| 70 | \() -> 71 | Expect.equal 1 (toDataX (updateFrame system { frame | margin = Margin 0 0 0 20 }) 28) 72 | , test "toCartesian with upper margin" <| 73 | \() -> 74 | Expect.equal 1 (toDataX (updateFrame system { frame | margin = Margin 0 20 0 0 }) 8) 75 | ] 76 | 77 | 78 | vertical : Test 79 | vertical = 80 | describe "Vertical translation" 81 | [ test "toSvg" <| 82 | \() -> 83 | Expect.equal 90 (toSvgY system 1) 84 | , test "toSvg with lower margin" <| 85 | \() -> 86 | Expect.equal 72 (toSvgY (updateFrame system { frame | margin = Margin 0 0 20 0 }) 1) 87 | , test "toSvg with upper margin" <| 88 | \() -> 89 | Expect.equal 92 (toSvgY (updateFrame system { frame | margin = Margin 20 0 0 0 }) 1) 90 | , test "toCartesian" <| 91 | \() -> 92 | Expect.equal 1 (toDataY system 90) 93 | , test "toCartesian with lower margin" <| 94 | \() -> 95 | Expect.equal 1 (toDataY (updateFrame system { frame | margin = Margin 0 0 20 0 }) 72) 96 | , test "toCartesian with upper margin" <| 97 | \() -> 98 | Expect.equal 1 (toDataY (updateFrame system { frame | margin = Margin 20 0 0 0 }) 92) 99 | ] 100 | 101 | 102 | updateFrame : System -> Frame -> System 103 | updateFrame system frame = 104 | { system | frame = frame } 105 | --------------------------------------------------------------------------------