npm install vue-vega --save
<script src="https://unpkg.com/vue-vega"></script>
Let's pick a trivial use case of creation dashboard with single bar chart
src/components/Dashboard.vue
<template>
<div class='dashboard'>
<vega-lite :data="values" mark="bar" :encoding="encoding"/>
</div>
</template>
import Vue from 'vue'
import VueVega from 'vue-vega'
Vue.use(VueVega)
export default{
data () {
return {
values: [
{a: 'A', b: 28}, {a: 'B', b: 55}, {a: 'C', b: 43},
{a: 'D', b: 91}, {a: 'E', b: 81}, {a: 'F', b: 53},
{a: 'G', b: 19}, {a: 'H', b: 87}, {a: 'I', b: 52}
],
encoding: {
x: {field: 'a', type: 'ordinal'},
y: {field: 'b', type: 'quantitative'}
}
}
}
}
Another way to use the same bar chart is to create component directly from prepared spec
src/components/Dashboard.vue
<template>
<div class='dashboard'>
<BarChart/>
<div/>
</template>
import {mapVegaLiteSpec} from 'vue-vega'
import BarChartSpec from 'spec/vega-lite/bar.vl.json'
export default {
components: {
BarChart: mapVegaLiteSpec(BarChartSpec)
}
}
As you may noticed, it's very natural to convert spec in component options with the help of a webpack. We are working on one for you vue-vega-webpack
One of the main features of vega it's an ability to reuse in in different environemtns.
In that case you even no need to create spec yourself but take it from some collection
import VueVega from 'vue-vega'
import BarChartSpec from 'spec/vega-lite/bar.vl.json'
export default {
components: {
BarChart: VueVega.mapVegaLiteSpec(BarChartSpec)
}
}
BarChart
<BarChart></BarChart>
In some scenarious you even no need to fetch data manually, for example data is already stored in JSON, CSV file, provide url and vega spec would load data under the hood
import VueVega from 'vue-vega'
import BarChartSpec from 'spec/vega-lite/bar_aggregate_empty.json'
export default {
components: {
BarChart: VueVega.mapVegaLiteSpec(BarChartSpec)
}
}
BarChart(
:data="{url: 'data/population.json'}"
)
<BarChart :data="{url: 'data/population.json'}"></BarChart>
Pass all spec as property
export default {
data () {
return {
spec: {
'$schema': 'https://vega.github.io/schema/vega-lite/v2.json',
'data': {'url': 'data/cars.json'},
'mark': 'bar',
'encoding': {
'x': {
'bin': {'maxbins': 15},
'field': 'Horsepower',
'type': 'quantitative'
},
'y': {
'aggregate': 'count',
'type': 'quantitative'
}
}
}
}
}
}
div
vega-lite(
:spec='spec'
)
<div>
<vega-lite :spec="spec"></vega-lite>
</div>
Change data and it would propagate changes up tp vega view
export default{
data () {
return {
values: [
{val: 1}, {val: 5}, {val: 3},
{val: 4}, {val: 5}, {val: 6},
{val: 7}, {val: 8}, {val: 9}
],
encoding: {
x: {bin: true, field: 'val', type: 'quantitative'},
y: {aggregate: 'count', type: 'quantitative'}
}
}
},
methods: {
refreshNumbers () {
this.values = this.values.map(() => {
return {val: Math.random() * 10}
})
}
}
}
div
vega-lite(
mark="bar",
:data="values",
:encoding="encoding"
)
button.button.button--medium(@click="refreshNumbers") Refresh
<div>
<vega-lite mark="bar" :data="values" :encoding="encoding"></vega-lite>
<button class="button button--medium" @click="refreshNumbers">Refresh</button>
</div>
Change mark of visualization, yep you can build some dynamic graph builder
import Multiselect from 'vue-multiselect'
export default {
components: {
Multiselect
},
data () {
return {
data: [
{a: 'A', b: 28}, {a: 'B', b: 55}, {a: 'C', b: 43},
{a: 'D', b: 91}, {a: 'E', b: 81}, {a: 'F', b: 53},
{a: 'G', b: 19}, {a: 'H', b: 87}, {a: 'I', b: 52}
],
encoding: {
x: {field: 'a', type: 'ordinal'},
y: {field: 'b', type: 'quantitative'}
},
mark: 'bar',
availableMarks: ['bar', 'point', 'circle', 'line']
}
}
}
div
multiselect(
v-model="mark",
:options="availableMarks",
:searchable="false",
:close-on-select="true",
:show-labels="false",
placeholder="Pick a mark"
)
vega-lite(
:data="data",
:mark="mark",
:encoding="encoding"
)
<div>
<multiselect v-model="mark" :options="availableMarks" :searchable="false" :close-on-select="true" :show-labels="false" placeholder="Pick a mark"></multiselect>
<vega-lite :data="data" :mark="mark" :encoding="encoding"></vega-lite>
</div>
Update encoding by adding and removing encoding channels
import Vue from 'vue'
import Multiselect from 'vue-multiselect'
import cars from './data/cars.json'
export default {
components: {
Multiselect
},
data () {
return {
data: cars,
mark: 'point',
encoding: {
x: {field: 'Horsepower', type: 'quantitative'},
y: {field: 'Miles_per_Gallon', type: 'quantitative'}
},
options: [
{
name: 'Origin - Color',
channel: {
color: {field: 'Origin', type: 'nominal'}
}
},
{
name: 'Origin - Shape',
channel: {
shape: {field: 'Origin', type: 'nominal'}
}
},
{
name: 'Displacement - Opacity',
channel: {
opacity: {field: 'Displacement', type: 'quantitative'}
}
}
]
}
},
methods: {
addEncodingChannel (newOption) {
const channel = newOption.channel
const channelName = Object.keys(channel).pop()
const channelVal = Object.values(channel).pop()
Vue.set(this.encoding, channelName, channelVal)
},
removeEncodingChannel (option) {
const channel = option.channel
const channelName = Object.keys(channel).pop()
Vue.delete(this.encoding, channelName)
}
}
}
div
multiselect(
:options='options',
:multiple='true',
:close-on-select='true',
:clear-on-select='false',
:hide-selected='true',
:preserve-search='false',
placeholder='Add Channel'
label='name',
track-by='name',
@select='addEncodingChannel',
@remove='removeEncodingChannel'
)
vega-lite(
:data='data',
:mark='mark',
:encoding='encoding'
)
<div>
<multiselect :options="options" :multiple="true" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="false" placeholder="Add Channel" label="name" track-by="name" @select="addEncodingChannel" @remove="removeEncodingChannel"></multiselect>
<vega-lite :data="data" :mark="mark" :encoding="encoding"></vega-lite>
</div>
Able to render layering with resolve
import VueVega from 'vue-vega'
import BarDualAxis from 'spec/vega-lite/layer_bar_dual_axis.vl.json'
export default {
components: {
BarDualAxis: VueVega.mapVegaLiteSpec(BarDualAxis)
}
}
BarDualAxis
<BarDualAxis></BarDualAxis>
Able to render layering with resolve
import VueVega from 'vue-vega'
import CarTrellis from 'spec/vega-lite/trellis_bar_histogram.vl.json'
export default {
components: {
CarTrellis: VueVega.mapVegaLiteSpec(CarTrellis)
}
}
CarTrellis
<CarTrellis></CarTrellis>
Allow to subscribe to all native-like events and get information about selected datum.
import VueVega from 'vue-vega'
import Interactive from 'spec/vega-lite/interactive.vl.json'
export default {
components: {
Interactive: VueVega.mapVegaLiteSpec(Interactive)
},
data () {
return {
origin: 'N/A',
cylinders: 0,
records: 0
}
},
methods: {
displaySelection (event, item) {
if (item && item.datum) {
let datum = item.datum
this.origin = datum.Origin
this.cylinders = datum.Cylinders
this.records = datum['count_*']
}
}
}
}
div
Interactive(@click="displaySelection")
div
span Origin : {{origin}}
div
span Cylinders : {{cylinders}}
div
span Records : {{records}}
<div>
<Interactive @click="displaySelection"></Interactive>
<div><span>Origin : {{origin}}</span></div>
<div><span>Cylinders : {{cylinders}}</span></div>
<div><span>Records : {{records}}</span></div>
</div>
Allow to subscribe to low-level vega spec signals, not sure on what to doe with them. If you need just a data prever 'native-like' events over signals
import VueVega from 'vue-vega'
import Interactive from 'spec/vega-lite/interactive.vl.json'
export default {
components: {
Interactive: VueVega.mapVegaLiteSpec(Interactive)
},
data () {
return {
field: '',
value: ''
}
},
methods: {
onPointer (tuple) {
if (tuple && tuple.fields) {
this.field = tuple.fields[1]
this.value = tuple.values[1]
}
}
}
}
div
Interactive(@signal:pointer_tuple="onPointer")
div
span {{field}} : {{value}}
<div>
<Interactive @signal:pointer_tuple="onPointer"></Interactive>
<div><span>{{field}} : {{value}}</span></div>
</div>
There are next functions and objects present in vue-vega:
Register VegaLiteComponent under 'vega-lite' name, so you can use `vega-lite` tag in your Vue templates
Name | Arguments | Description |
---|---|---|
install | Vue | Register VegaLiteComponent under 'vega-lite' name |
Map vega lite specification object to vue component object definition
Name | Arguments | Description |
---|---|---|
mapVegaLiteSpec | VegaLiteSpec | Returns Vue component object definition |
VegaLiteComponent - vue component wrapper around vega-lite. For more details refer to Vega Lit Docs
Name | Type | Default | Description |
---|---|---|---|
Props | |||
$schema | String | URL to JSON schema for a Vega-Lite specification. | |
description | String | An optional description of this visualization for commenting purpose. | |
transform | Array | The top-level transform object is an array of objects describing transformations | |
data | Array || Object | { values: [] } | Tabular data, similar to a spreadsheet or a database table. It passable to pass url but without format and names, default format json In vue-vega we provide a shortcut, so you user can pass `[]` instead of `{ values: [] }` |
mark | String||Object | Required. A string describing the mark type (one of "bar", "circle", "square", "tick", "line", "area", "point", "rule", and "text") or a mark definition object. | |
encoding | Object | An integral part of the data visualization process is encoding data with visual properties of graphical marks. | |
autoResize | Boolean | Resize is a boolean indicating if autosize layout should be re-calculated on every update. | |
background | String | CSS color property to use as the background of visualization. | |
padding | Number || Object | The default visualization padding, in pixels | |
config | Object | Vega-Lite configuration object. | |
width | Number | The width of a visualization. | |
height | Number | The height of a visualization. |
Events for VegaLiteComponent
Name | Attributes | Listen to | Description |
---|---|---|---|
Signal | (tuple) | @signal:name | Subscribe to signal defined in vega spec, name is a name of signal, you can find all signals at this.vegaSpec.signals |
Click | (DomEvent, item) | @click or @mouseover or etc. | Delegate DOM events, you can use 'click', 'mouseover' etc.item.datum contains fields which usually you interested in |