@preschen/gen-vis 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,241 @@
1
+ # gen-vis
2
+
3
+ A declarative d3 visualisation library: a chart is described by a JSON
4
+ definition (the *def*) and a CSV or JSON data file. Line, point, bar, stacked
5
+ bar and area charts with legends, hover, facets and form elements are
6
+ supported.
7
+
8
+ ## Usage
9
+
10
+ ### Standalone script
11
+
12
+ `npm run lib` builds `dist-lib/gen-vis-<version>.js`. It includes Vue, d3 and
13
+ the styles, and provides two global functions:
14
+
15
+ ```html
16
+ <div class="genVis" data-def-file="/data/bev/def.json"></div>
17
+
18
+ <script src="gen-vis-0.5.0.js"></script>
19
+ <script>mountGenVisByClass('genVis')</script>
20
+ ```
21
+
22
+ `mountGenVisByClass(className)` mounts all elements with the class which are
23
+ not mounted yet, `mountGenVisElement(element)` mounts a single element. The
24
+ props are taken from the `data-` attributes, see below.
25
+
26
+ ### Vue component
27
+
28
+ ```js
29
+ import GenVis from '@preschen/gen-vis';
30
+
31
+ app.use(GenVis);
32
+ ```
33
+
34
+ ```html
35
+ <GenVis def-file="/data/bev/def.json"/>
36
+ <GenVis :def="def" :data="rows"/>
37
+ ```
38
+
39
+ `import { GenVis } from '@preschen/gen-vis'` registers the component
40
+ locally instead. `vue` is a peer dependency, the package uses the Vue of the
41
+ application. `mountGenVisElement` and `mountGenVisByClass` are exported as
42
+ well.
43
+
44
+ ### Props
45
+
46
+ | Prop | Attribute | Description |
47
+ |------------|-----------------|-------------|
48
+ | `defFile` | `data-def-file` | url of the definition |
49
+ | `def` | `data-def` | the definition, an object or a JSON string |
50
+ | `data` | `data-data` | the data as rows or a CSV/JSON string, if not given it is loaded from the `data` url of the definition |
51
+ | `debug` | `data-debug` | shows the prepared definition |
52
+
53
+ Every visualisation has its own state, several of them can be used on a page.
54
+ If the props change, the visualisation is loaded again. Errors are shown in
55
+ place of the visualisation.
56
+
57
+ ## Definition
58
+
59
+ ```json
60
+ {
61
+ "parent": "../shared/def.json",
62
+ "data": "data.csv",
63
+ "options": { ... },
64
+ "globals": { ... },
65
+ "mapping": { ... },
66
+ "plot": [ ... ],
67
+ "facets": { ... },
68
+ "formElements": [ ... ]
69
+ }
70
+ ```
71
+
72
+ Relative urls are resolved against the definition referencing them, e.g.
73
+ `data.csv` is next to the definition file. A definition is deep merged into
74
+ its `parent` (and its parent into its own parent), arrays are replaced, not
75
+ merged. The merged definition is checked for common mistakes, e.g. unknown
76
+ plot types, the findings are logged as warnings in the console.
77
+
78
+ The package contains a JSON Schema of the definitions, `schema.json`. With
79
+ `"$schema"` in a definition, editors like VS Code complete and check it:
80
+
81
+ ```json
82
+ {
83
+ "$schema": "https://unpkg.com/@preschen/gen-vis/schema.json",
84
+ ...
85
+ }
86
+ ```
87
+
88
+ or with a local path, e.g. `"./node_modules/@preschen/gen-vis/schema.json"`.
89
+ The schema also allows parts of definitions, e.g. definitions with a `parent`.
90
+
91
+ ### `options`
92
+
93
+ `title`, `subtitle`, `footer` (HTML), `width` (the width of the container if
94
+ not given), `height` and `margins` (`{"top", "right", "bottom", "left"}` in
95
+ pixels). `height` can be a prop based on `totalWidth`, see [props](#props-1).
96
+
97
+ `locale` sets the number and date formats of the axes and the hover, also of
98
+ axes without `format`: `de` (the default) or `en`, or an object with a `base`
99
+ locale and the parts which are changed, see d3's
100
+ [formatLocale](https://d3js.org/d3-format#formatLocale) and
101
+ [timeFormatLocale](https://d3js.org/d3-time-format#timeFormatLocale):
102
+
103
+ ```json
104
+ "locale": { "base": "de", "number": { "currency": ["", " EUR"] } }
105
+ ```
106
+
107
+ `timeTicks` of the object are the tick formats of time axes without `format`,
108
+ by the interval of the date (`millisecond`, `second`, `minute`, `hour`, `day`,
109
+ `week`, `month`, `year`).
110
+
111
+ `fontFamily` sets the font, by default the css variable
112
+ `--gen-vis-font-family` or Century Gothic, so the font of all visualisations of
113
+ a page can be set with css:
114
+
115
+ ```css
116
+ .vis { --gen-vis-font-family: Arial, sans-serif; }
117
+ ```
118
+
119
+ ### `mapping`
120
+
121
+ Maps columns of the data to named dimensions, the plots and all other parts of
122
+ the definition refer to these names.
123
+
124
+ ```json
125
+ "y": {
126
+ "column": "value",
127
+ "type": "numeric",
128
+ "stacked": false,
129
+ "scale": { "type": "linear", "orientation": "vertical", "domain": [0, null] },
130
+ "axis": { "position": "left", "ticks": 8, "format": ".1f", "grid": true, "title": { "name": "€/l", "offset": 50 } },
131
+ "hover": { "format": ".2f" }
132
+ }
133
+ ```
134
+
135
+ - `type`: `numeric`, `date` or `categorical`. Numeric and date values which
136
+ are missing or invalid are `null`: they are gaps in lines and areas, points
137
+ and bars are not drawn, and they are not shown in the hover. Dates are
138
+ parsed with `Date.parse` or are timestamps.
139
+ - `scale`: `type` is a d3 scale (`linear`, `time`, `log`, `point`, `band`,
140
+ ...), continuous scales need a `numeric` or `date` type, `point` and `band`
141
+ a `categorical` one. `orientation` (`horizontal` or `vertical`) places the
142
+ scale on the plot. `domain` fixes the domain, `null` entries are taken from
143
+ the data. `domainRel` (relative to the domain) and `domainAbs` (absolute)
144
+ extend it. `padding` for categorical scales.
145
+ - `axis`: `position` (`top`, `bottom`, `left`, `right`), `ticks`, `values`
146
+ (fixed ticks), `format` (d3 number or time format), `rotate` (the angle of
147
+ the labels in degrees, positive counterclockwise, negative clockwise), `grid`
148
+ (lines at the ticks), `title` (`{"name", "offset"}`) and `padding`.
149
+ - `hover`: the hover shows the values of the vertical axis at the position of
150
+ the mouse. On touch devices it is shown by a tap and stays until a tap
151
+ outside of the plot, horizontal swipes move it, vertical ones scroll the
152
+ page. `format` of the horizontal and vertical axis, it defaults to the
153
+ axis format. For categorical mappings `props` are the columns of the entries,
154
+ `name` by default.
155
+ - `props`: the categories and their props, e.g. colors. `common` props are
156
+ used for all `manual` entries, `name` and `visible` are set by default. Only
157
+ visible categories are shown.
158
+ - `legend`: a toggle for every category, `symbol` draws svg `elements` (with
159
+ props) of the given `size` before the name.
160
+ - `stacked`: stacks the values of a vertical axis, see `stackedBar`.
161
+
162
+ ### `plot`
163
+
164
+ A plot or a list of plots, drawn in order:
165
+
166
+ ```json
167
+ {
168
+ "type": "svg:path",
169
+ "categories": ["nuts"],
170
+ "props": {
171
+ "stroke": "@color",
172
+ "fill": "none",
173
+ "d": { "x": "@x:scaled", "y": "@y:scaled" },
174
+ "highlight-stroke-width": "@highlight-stroke-width"
175
+ }
176
+ }
177
+ ```
178
+
179
+ - `type`: `svg:path` (a line per group, `d` with `x` and `y`), `base:area`
180
+ (an area per group, `d` with `x`, `y0` and `y1`), `svg:circle`, `svg:rect`,
181
+ `svg:line`, `svg:text` (an element per row), `bar` (props `cx` and
182
+ `height`, `width` defaults to the step of a categorical scale) and
183
+ `stackedBar` (props `x`, `y` and `width`).
184
+ - `categories`: the rows are grouped by these mappings, the props of their
185
+ categories are available in the plot props.
186
+ - `props`: svg attributes (and `text`). Props starting with `highlight-` are
187
+ used for the elements of the category under the mouse or the legend entry.
188
+
189
+ ### Props
190
+
191
+ Most values of a definition can be props:
192
+
193
+ - fixed values, e.g. `3` or `"none"`
194
+ - references `"@name"`: in a plot a column of the row (e.g. `@x`), the scaled
195
+ value (`@x:scaled`, `@x:scaled:0` for the position of 0, `@y:st:e:scaled`
196
+ for the end of a stacked value), a prop of the categories (e.g. `@color`) or
197
+ the size of the plot (`@width`, `@innerWidth`, `@height`, `@innerHeight`)
198
+ - `{"prop": "relative", "ref": "innerWidth", "ratio": 0.01}`: a ratio of a
199
+ reference
200
+ - `{"prop": "steps", "ref": "totalWidth", "steps": [{"cut": 0, "value": 220}, {"cut": 550, "value": 250}]}`:
201
+ the value of the last step with a cut below the reference
202
+
203
+ Objects without `prop` are nested props, e.g. `d` of a path.
204
+
205
+ ### `facets`
206
+
207
+ A plot for every category of `dim` (the name of a mapping with `props`), in
208
+ `cols` columns. The mappings listed in `scales` share their scale across all facets.
209
+ `cols` can be a prop based on `totalWidth`, `scales` a reference to `globals`.
210
+
211
+ ### `formElements` and `globals`
212
+
213
+ Form elements change `globals`, e.g. the shared scales of the facets. An entry
214
+ with a `mapping` also patches the mappings while it is selected, e.g. to switch
215
+ the column of an axis:
216
+
217
+ ```json
218
+ "globals": { "column": "value" },
219
+ "formElements": [{
220
+ "id": "column", "name": "Wert", "ref": "column", "type": "switch",
221
+ "values": [
222
+ { "id": "value", "name": "Wert", "value": "value" },
223
+ { "id": "share", "name": "Anteil", "value": "share", "mapping": { "y": { "column": "share" } } }
224
+ ]
225
+ }]
226
+ ```
227
+
228
+ ## Development
229
+
230
+ ```sh
231
+ npm install
232
+ npm run dev # dev server, the definition shown by dev.html is set in src/globals.js
233
+ npm test # unit tests, rendering and schema check of all definitions in data/
234
+ npm run build # es module for bundlers in dist/
235
+ npm run watch # rebuilds dist/ on changes, e.g. for `npm link`
236
+ npm run lib # standalone script in dist-lib/
237
+ npm run deploy # builds and uploads the standalone script
238
+ ```
239
+
240
+ `lib.html` shows the embedding with the dev server. The examples in `data/`
241
+ are rendered by the tests, so they have to stay valid.