Giter Site home page Giter Site logo

andreaskroepelin / polylux Goto Github PK

View Code? Open in Web Editor NEW
963.0 8.0 47.0 15.47 MB

A package for creating slides in Typst

Home Page: https://polylux.dev/book

License: MIT License

Shell 0.41% Julia 50.96% Rust 7.76% Typst 40.88%
presentation presentation-slides slides talk typst typst-package typst-template

polylux's Introduction

Polylux

This is a package for creating presentation slides in Typst. Read the book to learn all about it and click here to see what's new!

If you like it, consider giving a star on GitHub!

Book badge GitHub GitHub release (latest by date) GitHub Repo stars Demo badge Themes badge

Quickstart

For the bare-bones, do-it-yourself experience, all you need is:

// Get Polylux from the official package repository
#import "@preview/polylux:0.3.1": *

// Make the paper dimensions fit for a presentation and the text larger
#set page(paper: "presentation-16-9")
#set text(size: 25pt)

// Use #polylux-slide to create a slide and style it using your favourite Typst functions
#polylux-slide[
  #align(horizon + center)[
    = Very minimalist slides

    A lazy author

    July 23, 2023
  ]
]

#polylux-slide[
  == First slide

  Some static text on this slide.
]

#polylux-slide[
  == This slide changes!

  You can always see this.
  // Make use of features like #uncover, #only, and others to create dynamic content
  #uncover(2)[But this appears later!]
]

This code produces these PDF pages: minimal example

From there, you can either start creatively adapting the looks to your likings or you can use one of the provided themes. The simplest one of them is called simple (what a coincidence!). It is still very unintrusive but gives you some sensible defaults:

#import "@preview/polylux:0.3.1": *

#import themes.simple: *

#set text(font: "Inria Sans")

#show: simple-theme.with(
  footer: [Simple slides],
)

#title-slide[
  = Keep it simple!
  #v(2em)

  Alpha #footnote[Uni Augsburg] #h(1em)
  Bravo #footnote[Uni Bayreuth] #h(1em)
  Charlie #footnote[Uni Chemnitz] #h(1em)

  July 23
]

#slide[
  == First slide

  #lorem(20)
]

#focus-slide[
  _Focus!_

  This is very important.
]

#centered-slide[
  = Let's start a new section!
]

#slide[
  == Dynamic slide
  Did you know that...

  #pause
  ...you can see the current section at the top of the slide?
]

This time, we obtain these PDF pages: simple example

As you can see, a theme can introduce its own types of slides (here: title-slide, slide, focus-slide, centered-slide) to let you quickly switch between different layouts. The book has more infos on how to use (and create your own) themes.

For dynamic content, Polylux also provides a convenient API for complex overlays.

If you use pdfpc to display your slides, you can rely on Polylux' support for it and create speaker notes, hide slides, configure the timer and more!

Visit the book for more details or take a look at the demo PDF where you can see the features of this template in action.

⚠ This package is under active development and there are no backwards compatibility guarantees!

Acknowledgements

Thank you to...

  • @drupol for the university theme
  • @Enivex for the metropolis theme
  • @MarkBlyth for contributing to the clean theme
  • @ntjess for contributing to the height fitting feature
  • @JuliusFreudenberger for maintaining the polylux2pdfpc AUR package
  • @fncnt for coming up with the name "Polylux"
  • the Typst authors and contributors for this refreshing piece of software

polylux's People

Contributors

andreaskroepelin avatar drodt avatar drupol avatar enivex avatar fantasquex avatar kianmeng avatar krestenlaust avatar kronosthelate avatar markblyth avatar ntjess avatar pgbiel avatar sitandr 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

polylux's Issues

Discussion regarding potentially interesting Typst feature: state freezing/restoring

This is not really an issue per-se, but a feature request for Typst, that you might be very interested in. As such, you're probably in the best position to suggest a possible implementation that would suit your needs.

c.f. typst/typst#1841


Issue

In order to generate subslides, polylux needs to be able to duplicate a slide in similar-but-not-equal versions. They differ in which #only or #uncover are shown, but all the rest (page number, title numbers, etc.) should be strictly identical.

Except that this is not exactly what happens. If you decide to enable numbering on headings, each "instance" of the heading will have a different number on its subslide, which is certainly not what you (or at least I) want. Here's an example. Similarly, footnote numbers are duplicated. And so would be any counter or state-managed value.

Suggestion

I invite you to go to the issue linked above, as I've explained a few possible implementations, but the essential idea would be to have a new primitive element function that can be used to create copies of a content with a frozen state.

Make transparent covering actually transparent

Currently, when you cover someting transparently, it is actually just displayed normally but the text color is set to a light grey. This obviously doesn't work for any content that sets its own text colors (including syntax highlighted code), images, visualisations etc.

How can we force arbitrary content to appear transparent? Does the implementation of this feature in beamer help in any way?

Counting subslides

Hi, I'm trying to write a template and I want to add a "count bullet points" while the sub slides are rolling out. I have something like:

  let displayed-header(slide-info) = {
    let filledcircle(..nums) = {
      range(0, nums.pos().first()).map(_ => sym.circle.filled).join()
    }
    if "title" in slide-info {
      text(size: 1.2em, fill: clear, slide-info.title ) + h(1fr) + text(size: .5em, fill: clear,  subslide.display(filledcircle) )
    } else {
      text(size: 1.2em, fill: clear, section.display() ) + h(1fr) + text(size: .5em, fill: clear,  subslide.display(filledcircle) )
    }
  }

It works fine, but I haven't figured out how to add the remaining sym.circle.stroked (from the current subslide value+1 to the maximum subslide value). Is there a way to do this?

Allow themes to `set()` options globally

Currently themes are restricted to changing things within a page. Sometimes it might however be useful to change things globally, for example when setting a font or changing the page size (the later of which currently isn't possible at all as far as I can tell).

This could be done by adding an init or setup function to themes, which can produce arbitrary content before the first slide is rendered.
It's not possible to add this to the top-level of the theme function, as it has to return the dictionary of theme-variants and therefor can't return content.

pdfpc doesnt work with notes

Testing with example "gauss.typ", I compiled it with typst v0.7.0:
typst compile gauss.typ --root ..

which worked (the "--root .." is necessary because of the reference to ../polylux.typ)

Then I build the gauss.pdfpc file with the new tool, which gave the exact file as delivered with git.

But unfortunatly no notes are shown (started with one screen with slide and note in parallel).

I tried pdfpc Version v4.5.1pre from ubuntu 22.04 und self compiled variant v4.7.0pre, both with the same result.

It seems, that the first slide shown on the left and the second slide in small right of this. In the next step the second slide in big and the third in small and so on.

TfH,
Oliver

Have non space occupying hidden content

It should be possible to hide content such that it doesn't occupy any space. I especially imagine a variant of #one-by-one that allows to substitute contents by each other.

Obtain subslide number

Hi, awesome work!

It would be helpful if there was a way to retrieve the current subslide number, for instance for highlighting cells in a table:

#table(
  fill: (row, col) => {
    if (subslide() == 2) return red
  },
  [a],[b]
)

I could not find a way to achieve this with #only and co. Did I overlook something?

Simplify mulitslide API when custom `#show` rules are possible

Once #show rules work for all functions, I think we can make the multislide API much more conveniant.

#multislide(3)[
    #only(2)[Only visible on subslide 2]
]

This would require

#let multislide(amount, body) = {
    for i in range(1, amount+1) {
        show only: it => hide(it.body)
        show only.where(subslide: i): it => it.body

        body
    }
}

It might be less nice for more complex visibility rules (like beginning) but that should work as well.

Alternatives: repeat-last

Hi there,

I'd like to suggest something like a boolean repeat-last option for alternatives. This takes only effect if other stuff on the slide generates more subslides than options given to alternative. Then, the last alternative is "held" instead of showing nothing.

This would be useful for slides with several visual components.

Setting the page counter should also set the pdf metadata

If I generate a typst document with page 1 twice it sets only the number in the footer:
play.pdf

But with latex I can have the same number on multiple pages in the metadata as well, e.g. in this file:
https://github.com/pdfpc/pdfpc/releases/latest/download/pdfpc-demo.pdf (scroll to page 5, visible in firefox)

This is for example used by pdfpc to handle overlays in slides, but it is also generally useful to have the number in your pdf viewer match with the number shown in the pdf.

`background-img`, metropolis

Nice to see this!

A few questions/issues on background images:

Absolute file paths?

I'm new to typst, so not sure if I'm just misunderstanding, but it appears I can only use relative paths for images? Is that necessary?

typst compile slides.typ
error: file not found (searched at /home/bruce/Code/typst-examples/~/Pictures/student-map-example.png)
   ┌─ /slides.typ:41:35

41 │ #focus-slide(background-img: image("~/Pictures/student-map-example.png"))[
   │                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

background-img and metropolis?

Using metropolis, if I copy the image to the directory, it then compiles, but I don't see any image. Is background-img just not supported in metropolis? If that's the case, could you add it?

only in focus-slide?

Also, is it only available on focus-slide? I'd like to be able to use it more broadly.

nice to have

Finally, in the "nice to have" category:

I use background images a lot. Ideally it would be possible to modify their rendering; for example, to darken them, or add transparency, so that the text on top of them can be adjusted to be better legible.

Support for pdfpc overlays (override page numbers)

I use both this template, and since more recently, https://pdfpc.github.io/ for a keynote-style app with speaker notes support

One feature of pdfpc that I haven't used yet are Overlays: pdfpc tries to identify slides that are transitions between themselves (e.g.: a typical bullet list where every new slide reveals a new item). It tries to infer this by looking at the page number, and then the speaker view handles this accordingly (e.g.: showing the speaker notes for that bullet list on all those slides)

Would it be possible to somehow override the current page number counter in a way that plays nicely with this? e.g.: tell a given slide that it should not increment the number

Section helpers not usable for "private" themes

First of all, thank you for contributing this amazing package :)

Trying to create a custom theme that is not going to be contributed to polylux itself, I am facing the problem that I cannot access the helper functions for defining sections and retrieving the current one (i.e., #helpers.register-section() and #helpers.current-section). Would it be possible to also export these via polylux.typ?

Have themes

It would be nice if user could choose from different themes that change colors and decoration etc.

Presentation information in the footer moves

For many pages the information given in the footer like the title jumps left and right by some pixels.
I have not looked at the code but the reason is probably that the position is based on the width of the other information in the footer like the page number. We can see this especially between page 9 (one digit) and 10 (two digits) in the demo file, the title jumps by some pixels.
The expected result would be that all information is at a fixed position.

Note that also for pages that have the same number of digits the text moves a bit, even the kerning seems to change sometimes (tested with different viewers).

This one seems to work: #21

Composability, nesting and avoiding exlicit subslide numbering

Currently, functions for handling presence of content at subslides (such as alternatives, one-by-one, etc.) are bounded to subslide indexes from 1, which is a serious problem for composability. For instance, consider this code:

    #alternatives[First option][
        Common text for second option
        #one-by-one[2][3][4]
    ]

one would expect this to firstly show First option and then uncover the variants of the second one one-by-one. But alternatives constrain the scope of the second option to just the second slide. Moreover, both 3 and 4 are already uncovered by that time because one-by-one counts relative to 1, not to the index at which the parent would decide.

Ideally, the language should be expressive enough to mitigate the necessity of explicit numbering for arbitrarily complex «content flow control» logic.

Another use-case would be

#alternatives[
    One alternative
][
    Another alternative
    #alternatives[Sub-alternative 1][Sub-alternative 2]
]

which should probably render as… expected.

So, I wonder if it would be possible to implement something like this. Probably, at every recursion level of polylux invocation the whole content tree should traversed and the relative indexes of «transient» objects (the ones created by one of those helper functions) should be shifted.
Also, given a top-level instance (could it be polylux-slide?), we could traverse the tree to root (collecting offsets and nodes) and then from root (propagating the offsets down to leafs).

Obviously, that sounds like a breaking change, so functions with different names could be used (or a semver-compatible version increase could be made). Anyway, the mainstream code with just one of those primitives per slide wouldn't be affected.

As an intermediate solution, some interoperation of the primitives can be handled by users if the blocks would return an index at which it ended its counting. For example, one could write (with imaginary syntax):

#let (content, next_index) = #fancy-alternatives[…][…]…
#content
#one-by-one(start: next_index)[…][…][…]

but the latter approach is clearly pretty limited.

Speaker notes

First of all, amazing project (or a package?) which I used for my PhD proposal presentation.

I wanted to start a discussion around speaker notes and how to implement it and which features it should contain (happy to help out).
It seems natural that speaker-notes would be a named argument to slide and that there would be a global switch: #show: slides.with( /* ... */, notes: true ) which would print them out, likely underneath the slide (this would mean changing the aspect ratio etc).

Currently I have the notes on separate slides with custom theme variant which are turned off based on a state:

#let notes(body) = {
  locate(loc => {
    if notes-mode.at(loc) {
        slide(theme-variant: "notes", body)
    } 
  })
}

Improve PDFPC support

I just saw that you now support pdfpc, which is really nice. I thought if the intermediate step of processing the query output could be avoided. Would it be possible to save the metadata of each slide into a state at first; and create some hook to emit the #metadata at the end of each slide in exactly the format that pdfpc requires?

I'm experimenting with a different approach for another 3rd party integration right now.

Document boxing of hiddden content

The book should contain some description of why and how we #box the content that is about to be hidden. Maybe in a "Development" section? Depends on how important that is to users of the template.

@PgBiel would you like to have a go at this?

authors: none isn't allowed

See title. Because of this

authors: if type(authors) == "array" {
            authors
        } else if type(authors) in ("string", "content") {
            (authors, )
        } else {
            panic("authors must be an array, string, or content.")
        },

it's impossible to not provide an author.

There can be legitimate reasons why someone might not want to put an author on their presentation.

Add background support for custom themes

The ability to customize the background of slides via user-built themes would be a fantastic feature.

I come up with a really simple solution to let theme creators decide that for their own themes:

  1. In slides(), read special variants from the theme:
let the-theme = theme(data)
set page(
    paper: "presentation-" + aspect-ratio,
    margin: 0pt,
    background: the-theme.at("theme:background", default: none) // here
)
  1. In user's theme factory function, return with this special key:
let background = place(
    top + left,
    dx: 80% - 11cm / 2,
    dy: 25%,
    image(
        "my-university-or-company-logo.png", width: 11cm
    )
)

// ...

(
    "title slide": title-slide,
    "default": default,
    "wake up": wake-up,
    "theme:background": background
)

And that's done. I patched slides.typ to show how this option works in my own slides :

Broken memoization with "simple" theme

I found that incremental compilation doesn't work when using "simple" theme (recompilation works approximately the same time as compilation). I found I could fix it if I remove line show outline.entry: it => it.body.

My presentation is pretty simple, even no outline, just lots of code highlighting. It is easy to reproduce on smaller slides, but the difference is not that noticable. Currently I have no idea why is it happening, but I guess it is related to state management. Maybe it is worth to temporaly remove that line to prevent the problem.

Full slide images with metropolis theme, break out of margins.

Maybe I just don't know how to do this in Typst, but I'm using the metropolis theme for preparing lecture slides and every so often I want to have a image take up the full slide (or full height if it's part of a column). The default margins for slides are pretty aggressive (and good for text!) but they make images look too small.

Is there a way for an image to breakout of the margins and take up a full dimension of the slide?

Consider using page header+footer for slides

Having some text that cannot be manually split over multiple pages like, e.g., a bibliography (not yet working with typst-slides but hopefully soon TM typst/typst#785).

I experimented a bit, and this seems to work:

#style(styles => {
    let header = block(
        width: 100%,
        inset: (x:.5em, y:.7em),
        stroke: (bottom: 1mm + red),
        grid(columns: (1fr, 1fr),
            image("logo.svg", width: 2cm),
            align(right)[Header]
        )
        
    )
    let footer = block(
        width: 100%,
        inset: (x:.5em, y:.7em),
        stroke: (top: 1mm + red),
        align(right)[Footer]
    )
    page(width: 5cm, height: 5cm, margin: (x: 3%, 
      top: measure(header, styles).height + .5em, 
      bottom: measure(footer, styles).height + .5em), 
      header: header, header-ascent: .5em, 
      footer:footer, footer-descent: .5em, 
      lorem(50))
})

grafik

Currently, stuff like that breaks the layouting:
grafik

Table outline is not hide when using uncover

#slide(title: [k-distinctness], theme-variant: "north")[
  #set text(size: 18pt)
  
  == Problem Description

  - Given an input $x in [q]^n$, for some $q in "poly"(n)$, decide if there exist distinct $a_1, ..., a_k in [n]$ such that $x_(a_1) = thick dots.c thick = x_a_k$.
  - When $k=2$, it is the collision problem we discuss in class.
  
  
  #uncover(2)[
    == Current Results

    #table(
      columns: (auto, auto),
      inset: 15pt,
      [=== Query Complexity], [=== Time Complexity],
      [$O(n^(k\/(k+1)))$ [2003]], [$tilde(O)(n^(k\/(k+1)))$ [2003]],
      [$O(n^(3/4-1/4(2^k-1)))$], [$tilde(O)(n^(5\/7)) (k=3)$; $tilde(O)(n^((k-1)\/k)) (k>3)$ [2013 #super("*")]],
      [$O(n^(3/4-1/4(2^k-1)))$], [$tilde(O)(n^(3/4-1/4(2^k-1)))$ [2023]]
    )
  ]
]

image

Accessing theme helpers while developing an external theme (`logic.*`)

Thanks for the package, this is what finally got me to try learning typst! :)

I started building my theme from scratch, starting with

#import "@preview/polylux:0.2.0": *

However, when trying to implement a slide counter, the book refers me to:

#logic.logical-slide.display()

The online editor then lets me know that logic is an unknown variable, and as far as I can see I don't have any way of accessing these helpers without directly importing logic.typ locally, is that correct?

Since I'm trying to replicate my institute's slide template, I'm currently not working under the assumption of adding this theme to polylux anytime toon, so I'm wondering how feasible it is to develop a "proper" theme using just the polylux package import.

Then again, since I literally started learning typst yesterday I fully assume that I may just be holding it wrong 😅

Adding typst-slides to the offical packages repository

Typst just added support for packages through a Github repository, so it's probably a good idea to add this template as an official package.

There's just a problem though. The submission guidelines state that the package state that the package name can't contain neither "typst", nor generic descriptive words (like "slides"). So it needs a new name.

Simple way to disable all dynamic-ness

It would be nice to be able to export all of my slides with all of the dynamic content rendered as if it was static; I like to post my slides after I give my presentations, and it's inconvenient for people looking at them later.

Examples should use [] instead of "" for title etc.

If you wish to use markup in a title, say an en-dash between names, or italic, you need to swap "" for []. Someone new to typst might not know this, so I think it would be good idea to use this in the documentation. That is, for instance

#show: slides.with(
    authors: [Names of author(s)],
    short-authors: [Shorter author for slide footer],
    title: [Title of the presentation],
    subtitle: [Subtitle of the presentation],
    short-title: [Shorter title for slide footer],
    date: [March 2023],
)

(I ran into this while making a presentation today.)

Book is no longer online?

Are the demo github.io links supposed to still be valid? Visiting the url referenced in the example slides now results in a 404.

line-by-line support for non tight lists

a non tight list like:

#line-by-line[
-  a

- b

- c
]

doesn't seam to work corrrectly, this seems to fix it, but feels a bit hacky:

    let idx = start
    let parbreak = none
    for item in items {
        if repr(item.func()) == "parbreak" {
            parbreak = item
        } else if repr(item.func()) != "space" {
            uncover((beginning: idx), mode: mode, {parbreak; item})
            idx += 1
        } else {
            item
        }
    }

Too many PDF bookmarks

As shown here the resulting pdf has too many and also empty pdf bookmarks, which can be seen when compiled with a newer version of typst.

Show the actual page number

Is there a standard way to show the actual page numbers (ignoring slides generated by uncovering functions)?

By reading the source code I found I can achieve it with

#set page(
  paper: "presentation-16-9",
  fill: orange.lighten(95%),
  footer: [
    #set text(size: 0.5em)
    #h(1fr)
    #counter("logical-slide").display("1")
  ]
)

(this works because counters are globally accessible via their names)

But I think it is better to have a standard way. My solution feels like an abstraction leakage.

Layout primitives

Hi, love the work!

Do you have/have plans for/any thoughts on layout primitives (theme-agnostic layouts)? See the attached pdf where I imitate google slides.

main.pdf

Page break lacking on first slide

In the current main branch, a page break isn't properly added on the first slide because of this logic:

polylux/logic.typ

Lines 268 to 272 in f98e7c4

locate( loc => {
if counter(page).at(loc).first() > 1 {
pagebreak(weak: true)
}
})

MWE:

#import "polylux.typ": *

#set page(paper: "presentation-16-9", height: auto)
#set text(size: 25pt)

#let slide = polylux-slide

#slide[
  = Very minimalist slides

  #lorem(5)
]

#slide[
  == First slide
  #lorem(10)
]

Produces:

out

Can this be fixed by simply replacing that block of code as in the following patch?

#let polylux-slide(body) = {
-  locate( loc => {
-    if counter(page).at(loc).first() > 1 {
-      pagebreak(weak: true)
-    }
-  })
+  pagebreak(weak: true)
   logical-slide.step()
   subslide.update(1)
   repetitions.update(1)

Improve usage of uncover, only, etc., in math mode

Maybe I missed something, but usage of uncover, etc., in math mode seems kind of tricky, I tried the following:

# times is not directly available, need to go for #sym.times
$  x = 4 #uncover(2)[#sym.times (y + 5)] $

# needs to escape * and the * symbol is not the one from math mode (not vertically centered)
$ x = 4 #uncover(2)[\* (y + 5)] $

# does not work, compile error
$ uncover(2 *, y + 5) $

Ideally, one should be able to write math as if inside an equation when using uncover, etc.

idea: documentation writing

Hey just got an idea!

How about maintaining the documentation of this plugin directly in a Typst document?

WDYT ?

Bibliography

Is there an elegant way to add Bibliography in each page? Thank you very much

simple document make the compiler crash

The following code panics with thread 'main' panicked at 'assertion failed: min <= max', /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/cmp.rs:867:9
Am I the only one?

It's probably a typst bug.

//".libs/plot.typ"

#import "../libs/slides.typ" : *

#show: slides.with(
    authors: "Mme Cercy",
    short-authors: "Mme Cercy",
    title: [Chapitre 6 -- activité 1: Correction],
    short-title: "correction activité 1",
    date: "Avril 2023"
)
#slide(title: "Question 4")[]

Theme logo path resolution

Is there any way to resolve the path to the logo relative to the file instead of the packages themes folder?

I need to do:

theme: bristol-theme(
  logo: "../../../logo.png",
  // logo: "logo.png" would resolve at packages/typst-slides/themes/logo.png
)

Handout mode doesn't handle `#pause`

The new #pause is great, but unaffected by #enable-handout-mode(true)

An option I am wondering about would be to take only the last version of each slide instead of tweaking the separate functions. I don't know if it would be simpler implementation-wise, but I think that's what would suit my use-case best regarding alternatives.

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.