Giter Site home page Giter Site logo

contex's Introduction

ContEx

ContEx is a simple server side charting package for elixir. See these demos on the live site: https://contex-charts.org/

Example Charts

... and it works nicely in Phoenix LiveView

Animated Barchart

CI badge

Core concepts

Dataset

ContEx uses a simple Dataset structure - a list of lists or a list of tuples together with a list of column names.

For example:

 data = [{1, 1}, {2, 2}]
 ds = Dataset.new(data, ["x", "y"])

Charts

Data can be represented within different chart types. Currently supported charts are BarChart, PointPlot, LinePlot, GanttChart and Sparkline. Generally speaking, you can create a chart structure by calling new(<DataSet>) on the relevant module and Contex will take a reasonable guess at what you want. For example:

point_plot = PointPlot.new(ds)

Will make a new point plot with the first column used for the x-axis, the second for the y-axis, and the scales set to look ok.

Each module has different option. For example, BarChart allows you to set the :padding between the bar groups, specify whether you want :type to be :grouped or :stacked. The options are described in each module's documentation and are set in new/2.

DataSet columns are mapped to the attributes each different chart type expects. For example, a PointPlot expects an x column and at least one y column. These are set up by passing a :mapping option in the options when creating a new chart. For example,

   chart = PointPlot.new(
       dataset,
       mapping: %{x_col: :column_a, y_cols: [:column_b, column_c]}
     )

It isn't necessary to supply a mapping unless the DataSet is a list of maps. If no mapping is provided, columns will be allocated automatically. For a PointPlot, the first column will be used for x, and the second for y.

Each chart type implements the PlotContent protocol which requires it to scale to a defined height and width, emit SVG and optionally emit SVG for a legend. Generally, you won't directly access this protocol however, because...

Plots

... Charts live within a Plot. Plots manage things like titles, margins, axis titles, legend placement etc.

So to generate SVG ready for your web-page you would do something like:

plot = Plot.new(600, 400, point_plot)
 |> Plot.plot_options(%{legend_setting: :legend_right})
 |> Plot.titles("My first plot", "With a fancy subtitle")

Plot.to_svg(plot)
#^ This generates something like {:safe, "<svg> fancy SVG chart rendering stuff representing your plot</svg>"}

There is a short-cut API which creates the PlotContent and plot in a single pass by providing the chart type module to Plot.new/5.

For example:

plot = Plot.new(dataset, Contex.PointPlot, 600, 400, mapping: %{x_col: :column_a, y_cols: [:column_b, :column_c]})

Plot.to_svg(plot)

Scales

Scales are all about mapping attributes to plotting geometry. They handle transformation of data to screen coordinates (and other plotting attributes). They also handle calculation of tick intervals and the like where appropriate. Scales currently implemented are:

  • ContinuousLinearScale : A linear continuous scale
  • ContinuousLogScale : A log version of continuous scale
  • OrdinalScale : For categories / discrete attributes. Used for plotting the category axis in a BarChart.
  • CategoryColourScale : Maps unique attributes into colours
  • TimeScale : A continuous timescale for DateTime and NaiveDateTime data types

Others under consideration:

  • ContinuousColourScale : Generate colour gradients

Legends

Legends are generated for scales. Currently legend generation is only supported for a CategoryColourScale

WARNING

There are quite a few things to tidy up to make this ready for the real world, and the API is likely to be unstable for a little while yet...

  • Reasonable docs - the best resource currently is the accompanying demo project
  • Default styling
  • Upgrade Elixir required version to 1.10 and fix up some of the data comparison operators to use the new sort capabilities. Holding off on this for a while so we don't force an unwanted Elixir upgrade.
  • Multiple series in point plot
  • Line plot
  • Some test coverage - it has been built interactively using a liveview page for testing / refinement. Thanks to @srowley for getting some test coverage in place.
  • More test coverage... An approach for comparing "blessed" output SVG would make sense, including handling minor difference in spacing or element attribute order.
  • Options handling - needs to be better structured and use keyword lists rather than maps
    • Options for BarChart, PointPlot and GanttChart
    • Plot options
  • Colour handling
  • Plot overlays (e.g. line chart on bar chart)
  • SVG generation is poorly structured - lots of string interpolation.
  • Benchmarks - particularly for the situation where large datasets are getting updated frequently and served via LiveViews.
  • Pie Charts

Installation

The package can be installed by adding contex to your list of dependencies in mix.exs:

def deps do
  [
    {:contex, "~> 0.5.0"}
  ]
end

Prior Art, Related Material & Alternatives

Various details relating to scales, axes and SVG layout have been learnt from the excellent D3 library by Mike Bostock.

The theory of translating data into graphics is also very well handled by ggplot2 and various papers by Hadley Wickham, such as A Layered Grammar of Graphics

Pure Elixir Alternatives

  • GGity - modelled on ggplot2
  • PlotEx - has good line & time-series support and more optimised for certain situations.
  • Sasa Juric Homebrew - graph.html.leex has examples of injecting data into SVGs for very specific use cases.

contex's People

Contributors

axelson avatar datrader avatar general-cbic avatar imsoulfly avatar kianmeng avatar l3nz avatar littlestudent avatar mindok avatar mrjoelkemp avatar rodrigues avatar ruimfernandes avatar srowley avatar tobstarr avatar zdenal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contex's Issues

Tests failing with elixir 1.14.3

It looks like tests fail on Elixir 1.14 because they changed the way dates are represented (?)

asdf local elixir 1.13.4-otp-25

mix test


Finished in 0.1 seconds (0.00s async, 0.1s sync)
6 doctests, 173 tests, 0 failures

But

asdf local elixir 1.14.3-otp-25

mix test

Finished in 0.1 seconds (0.00s async, 0.1s sync)
6 doctests, 173 tests, 5 failures

This happens because (the error is the same in all failing tests):

image

❓ [QUESTION] What is the best way to handle long text in legend?

I have a long text for my legend and it shows up being cut. I was trying to play around with the :legend_setting like legend_setting: :legend_bottom but couldn't make it work except :legend_right ...

image

I am wondering if there are any other options or alternatives to solve long text in legend.

Thank you so much in advance. ❤️

Best regards,
Jing Hui P.

Timescale and Milliseconds

Just curious if there was specific reason why milliseconds aren't supported as part of @default_tick_intervals?

Thanks for being so helpful over the last few days @mindok

Sparklines rendering outside their parent element.

Hi.

I'm trying to build simple dashboard using liveview which displays the output from various sensors connected to my system. I'm having trouble with the sparkline paths being outside the visible area of the svg element:

Screen Shot 2020-03-07 at 21 21 37

In the above screenshot I have allowed the following CSS properties to the svg element so that I can see what's happening:

svg {
  border: 1px blue solid;
  overflow: visible;
}

I believe that this is being caused by the code attempting to rescale the chart based on the data. In the power sensor data this makes sense (because these values are all positive integers). But for the orientation data the values are a quaternion (so they're all between -1 and 1). I've scaled the data manually so that they're between 0 and 2, however that hasn't fixed the problem. When I pick up my device and move it around the paths actually move vertically up and down the screen.

If you have any suggestions I'd love to hear them.

Missing Plot options for PointPlot and LinePlot

I've noticed while using Contex that is wasn't possible to use the plot_options to hide one or both axis on PointPlot's/LinePlot's. I tried to add it following how it's implemented on BarChat with success, including updating the tests to handle the change (the branch is there fix-hidden-axis.

Have i missed something and there's a reason for the missing options ?

Details not appearing on mouse-hover with PieChart

I'm making a PieChart like so

dataset = Contex.Dataset.new(data, ["Name", "Avg Runtime"])

opts = [
  mapping: %{category_col: "Name", value_col: "Avg Runtime"},
  legend_setting: :legend_right,
  data_labels: true,
  title: "System Runtimes"
]

Contex.Plot.new(dataset, Contex.PieChart, 600, 400, opts)

But I'm not getting the Avg Runtime details displaying when the user hovers the mouse over the pie slice. I must be missing an option, but I don't see in the docs a list of the options and their effects. What do I need for on-hover functionality?

If this is a bug or missing feature, let me know - I'm happy to contribute :)

Implement Line chart

Hi,
thanks for this interesting nice library.
I am interested in line charts that I have rendered with D3.js so far. I wonder how difficult it is to program the Line Plot?

Is it on the agenda at the moment?

Best regards,
Werner.

Legend not appearing

Thanks for your work on this library. It looks like it could be very useful.

I tried creating a few charts and everything seems to be working as expected except for legends. I am calling this on every chart:

Contex.Plot.plot_options(%{legend_setting: :legend_bottom})

but no legends appear.

I found this in the docs: https://github.com/mindok/contex#legends

Legends are generated for scales. Currently legend generation is only supported for a CategoryColourScale

But one chart is a bar chart modeled on the sample code here: https://contex-charts.org/barcharts

Any idea what might be going on? It might be nice to raise or at least show a warning when a setting is being ignored, rather than silently failing to respect it.

SparkLine grid?

Hi,
Is it possible to draw the grid behind the Sparkline plot?
i don't understand how to do it :/

Cédric

Make ContinuousLinearScale display_decimals a parameter

It's be awesome to be able to set the number of decimals.

right now I'm using an ugly hack:

      custom_value_scale: Contex.ContinuousLinearScale.new()
        |> Contex.ContinuousLinearScale.domain(0, max_display)
        |> Contex.ContinuousLinearScale.interval_count(10)
        |> Map.merge(%{display_decimals: 0}) # ugly hack

Is there a way to define custom x-axis values for the TimeSeries scale?

So if I understand correctly the best way to use custom scales for time series data, for example to change the default formatting of "%h %s" for a 1 second tick, I need to create a TimeSeries struct and pass in those values to the LinePlot? Same thing for the number of intervals right?

Format code with elixir formatter

Would a PR that formats the code with the elixir formatter be accepted/welcome? It would be make it much easier for those of us whose editor automatically formats the code to submit PR's. Otherwise I have to manually pull out just the changes required from a large diff like: master...axelson:spread-labels

Values not showing on axis on point plot

Hey, great library!

I am having a problem, which is probably of my own making. The values are not showing on the axis for my point plot.

image

Here is the code for my little example:

 def basic_plot(test_data) do
    plot_content =
      PointPlot.new(test_data)
      |> PointPlot.set_y_col_names(["Humidity", "Temperature"])

    Plot.new(900, 500, plot_content)
    |> Plot.plot_options(%{legend_setting: :legend_right})
    |> Plot.to_svg()
  end

  defp make_test_data(socket) do
    data =
      Wetter.HumidityReading.generate_sample_data()
      |> Enum.map(fn %{timestamp: timestamp, temperature: temp, humidity: humidity} ->
        [timestamp, humidity, temp]
      end)
      |> Dataset.new(["Time", "Humidity", "Temperature"])

    assign(socket, test_data: data)
  end

Click event on a pie wedge

would this just be a matter of adding the code that is in the bar already for the click to the pie chart or is there more to it than that?
[I mean for me to do :-) ]
Thanks!

Examples as ExDocs

As the point of this library is to generate SVG, and Elixir supports code evals, it should be very easy to generate ExDocs for a "samples" module that embeds:

  • the source code needed to generate such examples
  • the resulting SVG graph

This is better IMHO compared to having images, because if you make a change in the library, it is immediately reflected on all the graphs generated. Also, examples are where they are supposed to be, in the documentation! And, thanks to issue #74 we have a number of examples to get started on.

This could also be useful for generating automated formal tests, e.g that the SVG generated is always formally valid (this could be done I think with Floki).

I have used this approach to check different cases the LogLinearScale and found it quite useful. So it would not be much work sending a PR for it, if interested.

Include SVG styling for SVG Files

It would be handy to generate a SVG with the XML styling that could be served as a img.

I put this in a Phoenix controller:

@svg ["<?xml version=\"1.0\" encoding=\"utf-8\"?><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"]
  
  def plot(conn, params) do
    data = [
        {0.0, 0.0, "Hippo"},
        {0.5, 0.3, "Turtle"},
        {0.4, 0.3, "Turtle"},
        {0.2, 0.3, "Rabbit"}
        ]
    dataset = Contex.Dataset.new(data, ["x", "y", "category"])
    plot_content = Contex.BarChart.new(dataset)
    plot = Contex.Plot.new(600, 400, plot_content)
    {:safe, output} = Contex.Plot.to_svg(plot)

    conn = put_resp_content_type(conn, "image/svg+xml")
    send_resp(conn, 200, @svg ++ output ++ ["</svg>"])

I just surrounded the SVG from to_plot with this: @svg ++ output ++ ["</svg>"]
It works but isn't graceful.

I should be able to include SVGs in img tags instead of including them in templates.

Would something like this be a reasonable addition?:

def to_svg_file(plot) do
  {:safe, svg} = to_svg(plot)
  svgfile = @svgxml ++ svg ++ ["</svg>"]
  svgfile
end

This could also be useful for generating static svgs.

TimeSeries BarChart?

It looks like there is not a way to use the TimeSeries scale with a bar chart?

I like to use time series bar charts for things a lot. Would love to be able to do this Contex. I can try to implement if you're up for it?

0.3.0 release

Will there be a 0.3.0 release soon? It looks like there's a bunch of good improvements that are currently pending.

v0.2.0 fails to compile (elixir v1.10.3, erlang/otp 22)

v0.2.0 of the library fails to compile for me running elixir v1.10.3 and erlang/otp 22.

Stacktrace below:

==> contex
Compiling 17 files (.ex)

== Compilation error in file lib/chart/dataset.ex ==
** (CompileError) lib/chart/dataset.ex:61: type t/0 undefined (no such type in Contex.Dataset)
    (elixir 1.10.3) lib/kernel/typespec.ex:898: Kernel.Typespec.compile_error/2
    (elixir 1.10.3) lib/kernel/typespec.ex:937: Kernel.Typespec.fn_args/6
    (elixir 1.10.3) lib/kernel/typespec.ex:377: Kernel.Typespec.translate_spec/8
    (stdlib 3.12.1) lists.erl:1354: :lists.mapfoldl/3
    (elixir 1.10.3) lib/kernel/typespec.ex:229: Kernel.Typespec.translate_typespecs_for_module/2
    (elixir 1.10.3) src/elixir_erl_compiler.erl:12: anonymous fn/3 in :elixir_erl_compiler.spawn/2
could not compile dependency :contex, "mix compile" failed. You can recompile this dependency with "mix deps.compile contex", update it with "mix deps.update contex" or clean it with "mix deps.clean contex"

When using v0.1.0, the library is able to compile successfully.

Update readme to install latest version (0.3.0)

The current installation instructions have:

defp deps do
    [
        {:contex, "~> 0.1.0"}
    ]
end

Which means that lazy, slapdash people might simply cut'n'paste version 0.1.0 into their code and THEN SPEND HALF-A-DAY TRYING TO UNDERSTAND WHY IT WANTS BarPlot NOT BarChart !!!!! ;-)

suggest they are updated to:

defp deps do
    [
        {:contex, "~> 0.3.0"}
    ]
end

Suggestion: support hyperlinks

It can be useful to have hyperlinks in charts. For example, in a system which runs jobs, you could graph the duration of the jobs and have each point be a link to that job's details. (I have a couple of use cases like that in mind.)

Apparently hyperlinks in inline SVG can be done like this.

Maybe the best way to support that would be to pass a link function, which could look at the dataset and use one of the values (like id:) to build a link.

No git tags

There's no git tags in this repository so it is difficult to go from the hexdocs directly to the matching version of the code. It would be great if tags were added to the repository.

Support for empty data sets?

Right now an error is raised if an empty list is passed to a data set:

** (exit) an exception was raised:
   ** (FunctionClauseError) no function clause matching in MapSet.new_from_list/2
     (elixir 1.13.4) lib/map_set.ex:119: MapSet.new_from_list(nil, [nil: []])
...

While there is arguably not much use of displaying an empty chart, it means that somewhat awkward conditional logic is required for cases where there is no data to show in the chart. Personally I'd like to see a way to display a custom "empty state" message where the chart otherwise would be with the same dimensions.

install version 0.4.0 don't match the version on Mix

I am trying to install the contex with the version 0.4.0:

{:contex, "~> 0.4.0"}

And mix complains for this:

 mix deps.get
** (Mix) No matching version for contex ~> 0.4.0 (from: mix.exs) in registry

The latest version is: 0.3.0
❯ mix hex.info contex
Contex - a server-side charting library for Elixir.

Config: {:contex, "~> 0.3.0"}
Releases: 0.3.0, 0.2.0, 0.1.0

Licenses: MIT
Links:
  GitHub: https://github.com/mindok/contex
  Website: https://contex-charts.org/

But the initial README.md tells to install the version 0.4.0.

Ability to see Sparkline datapoint

Right now it's dead simple to make a Sparkline chart, as it's just a list of values.

data = [1, 2, 3, 4, 5, 6]

and this renders out a chart nicely, but then the chart would look something like:

image

This doesn't really give off any context.

What I'd propose, I'm not sure if very feasible, but maybe something like:

data = [{"monday", 123, {"tuesday", 42}]

A list of tuples, with the first element of the tuple being used as the value for when you hover over the point on the chart.

Allow specifying rotation of labels

Currently for a bar chart the rotation of the labels cannot be preset and instead only kicks in after a hard-coded number of elements (IIRC), for longer label text this results in unreadable text.

contex-screenshot

A few examples for new users

Thanks for creating a fantastic library for Elixir!

I'm currently using Contex for:

  • The sparklines on our website to show members upvotes and comments on our posts
  • Our backend moderation stats page

I recently needed to develop a few "one off" charts for a static marketing page, and decided to try Contex for that too. However I struggled a little bit to find straight up example code for some of the charts. As a new user of the library, it took me a little longer than usual to get started as I was trying to hunt down some simple copy-paste examples that could work out of the box.

Anyway, I eventually made a couple of charts and thought I'd share the code in case you wanted to add more examples to help other users. Alternatively, I could put this in a gist. Sorry if I've put this in the wrong place!

Cheers,
Ian


Screen Shot 2023-01-17 at 12 26 41 am

data = [
  ["Blog (400)", 400],
  ["Instagram (399)", 399],
  ["Twitter (348)", 348],
  ["YouTube (200)", 200],
  ["Tiktok (72)", 72]
]

dataset = Contex.Dataset.new(data, ["Channel", "Count"])

opts = [
  mapping: %{category_col: "Channel", value_col: "Count"},
  colour_palette: ["16a34a", "c13584", "499be4", "FF0000", "00f2ea"],
  legend_setting: :legend_right,
  data_labels: true,
  title: "Social Media Accounts"
]

Contex.Plot.new(dataset, Contex.PieChart, 600, 400, opts)
|> Contex.Plot.to_svg()

Screen Shot 2023-01-17 at 12 26 47 am

data = [
  ["Tiktok", 7.7],
  ["Twitter", 8.7],
  ["YouTube", 10.2],
  ["Blog/Website", 17],
  ["Instagram", 17.5]
]

series_cols = ["Series 1"]
test_data = Contex.Dataset.new(data, ["Category" | series_cols])

options = [
  mapping: %{category_col: "Category", value_cols: ["Series 1"]},
  type: :stacked,
  data_labels: true,
  orientation: :vertical,
  colour_palette: ["4c4bdc"],
  series_columns: series_cols
]

Contex.Plot.new(test_data, Contex.BarChart, 500, 400, options)
  |> Contex.Plot.titles("Combined Reach (M)", "")
  |> Contex.Plot.axis_labels("", "")
  |> Contex.Plot.plot_options(%{})
  |> Contex.Plot.to_svg()

Screen Shot 2023-01-17 at 12 27 00 am

data = [
  ["Writing", 248],
  ["Adventure", 166],
  ["Food", 145],
  ["Travel Guide", 109],
  ["Photography", 94],
  ["Lifestyle", 78],
  ["Family", 75],
  ["Video", 71],
  ["Sustainability", 55],
  ["Luxury", 55],
  ["Womens Travel", 48],
  ["Vanlife", 46],
  ["Journalist", 39],
  ["Solo Travel", 29],
  ["Podcast", 25],
  ["Accommodation", 24],
  ["Outdoors", 24],
  ["Nomad", 20],
  ["Fashion", 20],
  ["Hiking", 18],
  ["Flying", 17],
  ["Cruise", 16],
  ["Points", 13],
  ["Wellness", 12],
  ["Slow Travel", 11],
] |> Enum.reverse()

series_cols = ["Series 1"]
test_data = Contex.Dataset.new(data, ["Category" | series_cols])

options = [
  mapping: %{category_col: "Category", value_cols: ["Series 1"]},
  type: :stacked,
  data_labels: true,
  orientation: :horizontal,
  colour_palette: ["1e293b"],
  series_columns: series_cols
]

Contex.Plot.new(test_data, Contex.BarChart, 500, 400, options)
  |> Contex.Plot.titles("", "")
  |> Contex.Plot.axis_labels("", "")
  |> Contex.Plot.plot_options(%{})
  |> Contex.Plot.to_svg()

Render as png

Hi, I have an elixir app and must display charts in Slack. But Slack does not support SVG. I know I can use inkscape as a command line tool, but it is a bit overkill. Do you know any other tool that I could use.

Also, your charts are dynamic, so I guess there is JS inside the graphs, they are not just images. Would it work, still ?

Thank you

Change formatting for y-axis in PointPlot

Hello,
I have a need to plot NIC traffic data over time. I have a prototype that's working, but I would like the Y axis to be read something like "MB/sec" instead of a raw numeric value. I'm probably just too thick-headed to see how to do this. Any suggestions?
Screenshot from 2020-06-29 17-25-18

Pluggable backend

I'm thinking about how to add charts to a scenic-based project and I was thinking that Contex would be a good way to go about it. Do you think a pluggable backend would make sense for contex?

Labels/ticks never appear

I am using code which is basically copy/pasted from the example at contex-charts.org

defp plot_chart(record_list) do
    options = [
      mapping: %{category_col: "date", value_cols: ["load"]},
      type: :stacked,
      data_labels: false,
      orientation: :vertical,
      colour_palette: ["ff9838", "fdae53", "fbc26f", "fad48e", "fbe5af", "fff5d1"]
    ]

    record_list
    |> Contex.Dataset.new(["date", "load"])
    |> Contex.Plot.new(Contex.BarChart, 600, 400, options)
    |> Contex.Plot.axis_labels("", "")
    |> Contex.Plot.plot_options(%{})
    |> Contex.Plot.titles("My first plot", "With a fancy subtitle")
  end

And everything shows up fine, except there are no labels on the axis. I played around with the options, but couldn't find any documentation about this. The documentation even says it should "just work" with minimal tinkering.

Here is the result I am getting:
Screen Shot 2021-06-23 at 12 49 57 PM

Also the color palette is totally different, which is strange because I am pulling those values straight from the example on contex-charts.org

EDIT: data_labels: false also doesn't appear to be taking effect, as you can see in the pic.

Long legend text truncated

Hello,

I'm using Contex version 0.4.0. I try to generate a point plot with a right legend in a Phoenix LiveView application. The legend appears on the right side, but long texts will be truncated. Is it possible to make them appear in full length?

thanks

contex

Publish new Hex version

Hello!

I have a package that I'm trying to publish, but it requires some functions that are only available in your development version of ContEx. Unfortunately, Hex is telling me I'm unable to publish a package which depends on a git hash, and is requiring that I use a Hex-published version.

Is there any chance that a new version is coming any time soon?

Thank you!

BarChart: Allow more control over Value Axis

Hi,

In my BarChart the vertical axis has a range 0-20, BarChart generates ticks of 0, 2.5, 5, 7.5 ...
My data is integral (numbers of items)
How can I make the ticks integer values within the range e.g. 0,2,4,8 ... ?

Excited by Contex but struggling a bit to make it do what I want. Can I ask questions here or is there a better forum?

Thanks

Tom

Trailing space after sparkline

Hi, the svg for sparklines is a bit wider than the paths - this becomes apparent for example when adding a border:
image

This seems to be due to Contex.Sparkline.draw calculating the viewbox width as sparkline.length + 1. Without looking too deeply, changing that to length - 1 seems to fix the issue.

PS: While writing this I noticed the same fix in 56f7ec7 Maybe that could be cherry-picked?

Thanks for this very cool lib!

Add markers to LinePlot

Add an option to LinePlot for markers.

type: circle, square, diamond, triangle (default to cycle through these in order for each series)
size: (with SVG it’s all relative, but figure out a sensible default)
filled: true or false, default true
colour will be the colour of the line

Note that the plot content protocol will need to be extended to provide "defs" for a given dataset that can be embedded at the top of the SVG ahead of the main plot content.

Options passed in like this:

#show markers with defaults
markers: true 

#show markers explicitly, setting marker properties for each series
markers: [
  [type: :circle, size: 3, filled: false], 
  [type: :square, filled: false],
] 

What about missing/nil values?

At the moment missing or nil values are not allowed, if I tested this correctly.
Is this quite difficult to implement or does this requirement throw everything out of whack?

We use Point Plot and btw. will test the new Line Chart's, thank you for the implementation!

Examples for the use of missing values are ApexCharts oder billboard.js Charts:
ApexCharts missing values

Labels have no color

image

As can see from the image above, the X and Y labels are clearly there (I also checked the DevTool and they are there indeed), but then they have on color. If I manually change the stroke of the <g> tag to stroke="#000" then it does show up as black.

image

If I manually change the stroke to this

image

Then the graph shows with color:

image

Tooltip on a line chart

Hi,

Thanks for the great work.
Is there a way to display a tooltip on a line chart to display the value in the graph?

Thx

Version without timex

I hesitate before filing this issue because it might be a little overbearing. But would it be possible to remove timex as a dependency? Because I use contex in an application that runs as an escript I have to workaround lau/tzdata#24 and timex isn't really being used heavily in Contex. If it it too much work/not worth changing then feel free to close this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.