Public
Edited
Oct 8, 2024
Fork of Interaction
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
render({
mark: { type: 'circle' },
data: { url: cars },
params: [
{ name: 'highlight', select: { type: 'point' } }
],
encoding: {
x: { field: 'Horsepower', type: 'Q' },
y: { field: 'Miles_per_Gallon', type: 'Q' },
color: {
condition: { param: 'highlight', field: 'Cylinders', type: 'O' },
value: 'grey'
},
opacity: {
condition: { param: 'highlight', value: 0.8 },
value: 0.1
}
}
})
Insert cell
Insert cell
function plot(selection, title) {
const name = selection.name;
return {
mark: { type: 'circle' },
data: { url: cars },
params: [ selection ],
encoding: {
x: { field: 'Horsepower', type: 'Q' },
y: { field: 'Miles_per_Gallon', type: 'Q' },
color: {
condition: { param: name, field: 'Cylinders', type: 'O' },
value: 'grey'
},
opacity: {
condition: { param: name, value: 0.8 },
value: 0.1
}
},
title,
width: 300,
height: 225
};
}
Insert cell
Insert cell
render({
hconcat: [
plot({ name: 'click', select: { type: 'point' } }, 'Point (Click)'),
plot({ name: 'drag', select: { type: 'interval' } }, 'Interval (Drag)')
]
})
Insert cell
Insert cell
render({
hconcat: [
plot({ name: 'click', select: { type: 'point', on: 'mouseover' } }, 'Point (Mouseover)'),
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
genres = uniqueValid(movies, d => d.Major_Genre)
Insert cell
Insert cell
mpaa = ['G', 'PG', 'PG-13', 'R', 'NC-17', 'Not Rated']
Insert cell
Insert cell
render({
mark: { type: 'circle' },
data: { values: movies },
params: [
{
name: 'Select', // name the selection 'Select'
select: { type: 'point', fields: ['Major_Genre'] }, // limit selection to the Major_Genre field
value: { Major_Genre: genres[0] }, // use first genre entry as initial value
bind: {
input: 'select', options: genres, // bind to a menu of unique genre values
name: 'Major Genre' // set the menu label text
}
}
],
encoding: {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: { field: 'IMDB_Rating', type: 'Q' },
tooltip: { field: 'Title', type: 'N' },
opacity: {
condition: { param: 'Select', value: 0.75 },
value: 0.05
}
}
})
Insert cell
Insert cell
Insert cell
render({
mark: { type: 'circle' },
data: { values: movies },
params: [
{
name: 'Select',
// point-value selection over [Major_Genre, MPAA_Rating] pairs
select: { type: 'point', fields: ['Major_Genre', 'MPAA_Rating'] },
// use specific hard-wired values as the initial selected values
value: { Major_Genre: 'Drama', MPAA_Rating: 'R' },
bind: {
Major_Genre: { input: 'select', options: genres, name: 'Major Genre' },
MPAA_Rating: { input: 'radio', options: mpaa, name: 'MPAA Rating' }
}
}
],
// scatter plot, modify opacity based on selection
encoding: {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: { field: 'IMDB_Rating', type: 'Q' },
tooltip: { field: 'Title', type: 'N' },
opacity: {
condition: { param: 'Select', value: 0.75 },
value: 0.05
}
}
})
Insert cell
Insert cell
Insert cell
render({
vconcat: [
{
// dynamic query histogram
mark: { type: 'bar', width: 4 },
data: { values: movies },
params: [
// interval selection, limited to x-axis (year) values
{ name: 'brush', select: { type: 'interval', encodings: ['x'] } }
],
encoding: {
x: { timeUnit: 'year', field: 'Release_Date', title: 'Films by Release Year' },
y: { aggregate: 'count', title: null }
},
width: 600,
height: 50
},
{
mark: { type: 'circle' },
data: { values: movies },
encoding: {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: { field: 'IMDB_Rating', type: 'Q' },
tooltip: { field: 'Title', type: 'N' },
opacity: {
condition: { param: 'brush', value: 0.75 },
value: 0.05
}
},
width: 600,
height: 400
}
],
spacing: 5
})
Insert cell
Insert cell
Insert cell
Insert cell
render({
mark: { type: 'circle' },
data: { values: movies },
params: [
// bind interval selection to scale domains
{ name: 'sel', select: { type: 'interval' }, bind: 'scales' }
],
encoding: {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: {
field: 'IMDB_Rating', type: 'Q',
axis: { minExtent: 30 } // add min extent to stabilize axis title placement
},
tooltip: [
{ field: 'Title', type: 'N' },
{ field: 'Release_Date', type: 'T' },
{ field: 'IMDB_Rating', type: 'Q' },
{ field: 'Rotten_Tomatoes_Rating', type: 'Q' }
]
},
width: 600,
height: 450
})
Insert cell
Insert cell
render({
mark: { type: 'circle' },
data: { values: movies },
params: [
// limit interval selection to x-axis scale only
{ name: 'sel', select: { type: 'interval', encodings: ['x'] }, bind: 'scales' }
],
encoding: {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: {
field: 'IMDB_Rating', type: 'Q',
axis: { minExtent: 30 } // add min extent to stabilize axis title placement
},
tooltip: [
{ field: 'Title', type: 'N' },
{ field: 'Release_Date', type: 'T' },
{ field: 'IMDB_Rating', type: 'Q' },
{ field: 'Rotten_Tomatoes_Rating', type: 'Q' }
]
},
width: 600,
height: 450
})
Insert cell
Insert cell
Insert cell
Insert cell
render({
data: { url: sp500 },
vconcat: [
{
mark: { type: 'area' },
encoding: {
x: {
field: 'date', type: 'T', title: null,
scale: { domain: { param: 'brush' } }
},
y: { field: 'price', type: 'Q' }
},
width: 700
},
{
mark: { type: 'area' },
params: [
{ name: 'brush', select: { type: 'interval', encodings: ['x'] } }
],
encoding: {
x: { field: 'date', type: 'T', title: null },
y: { field: 'price', type: 'Q' }
},
width: 700,
height: 60
}
]
})
Insert cell
Insert cell
Insert cell
Insert cell
{
// scatter plot encodings shared by all marks
const xy = {
x: { field: 'Rotten_Tomatoes_Rating', type: 'Q' },
y: { field: 'IMDB_Rating', type: 'Q' }
};

const hover = {
name: 'hover',
select: {
type: 'point',
on: 'mouseover', // select on mouseover
nearest: true, // select nearest point to mouse cursor
toggle: false // do not toggle on shift-hover
}
};
const click = { name: 'click', select: { type: 'point' } };
// logical 'or' to select points in either selection
// empty selections should match nothing
const filter = {
filter: {
or: [
{ param: 'click', empty: false },
{ param: 'hover', empty: false }
]
}
};
return render({
// layer scatter plot points, halo annotations, and title labels
layer: [
{
mark: { type: 'circle' },
params: [ hover, click ],
encoding: xy
},
{
mark: { type: 'point', size: 100, stroke: 'firebrick', strokeWidth: 1 },
transform: [filter],
encoding: xy
},
{
mark: { type: 'text', dx: 4, dy: -8, align: 'right', stroke: 'white', strokeWidth: 2 },
transform: [filter],
encoding: { ...xy, text: { field: 'Title', type: 'N' } }
},
{
mark: { type: 'text', dx: 4, dy: -8, align: 'right' },
transform: [filter],
encoding: { ...xy, text: { field: 'Title', type: 'N' } }
}
],
data: { values: movies },
width: 600,
height: 450
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const brush = {
name: 'brush',
// resolve all selections to a single global instance
select: { type: 'interval', resolve: 'global' }
};

const legend = {
name: 'legend',
select: { type: 'point', fields: ['Cylinders'] },
bind: 'legend' // bind to interactions with the color legend
};

const brushAndLegend = { and: [ { param: 'brush' }, { param: 'legend' } ] };

return render({
repeat: {
column: ['Acceleration', 'Horsepower', 'Miles_per_Gallon'],
row: ['Miles_per_Gallon', 'Horsepower', 'Acceleration']
},
spec: {
mark: { type: 'circle' },
data: { url: cars },
params: [ brush, legend ],
encoding: {
x: { field: { repeat: 'column' }, type: 'Q' },
y: { field: { repeat: 'row' }, type: 'Q' },
color: {
condition: { test: brushAndLegend, field: 'Cylinders', type: 'O' },
value: 'grey'
},
opacity: {
condition: { test: brushAndLegend, value: 0.8 },
value: 0.1
}
},
width: 140,
height: 140
}
});
}
Insert cell
Insert cell
Insert cell
{
const brush = {
name: 'brush',
select: { type: 'interval', encodings: ['x'], resolve: 'intersect' }
};

// x/y encodings shared across layers
const xy = {
x: {
field: { repeat: 'row' }, type: 'Q',
bin: { maxbins: 100, minstep: 1 }, // up to 100 bins, but no smaller than 1 unit
axis: {format: 'd', titleAnchor: 'start'} // integer format, left-aligned title
},
y: {
aggregate: 'count',
title: null // no y-axis title
}
};

return render({
data: { url: flights },
transform: [
{ calculate: 'datum.delay < 180 ? datum.delay : 180', as: 'delay' }, // clamp delays > 3 hours
{ calculate: 'hours(datum.date) + minutes(datum.date) / 60', as: 'time' } // fractional hours
],
repeat: { row: [ 'delay', 'distance', 'time' ] },
spec: {
layer: [
{
mark: { type: 'bar' },
params: [ brush ],
encoding: { ...xy, color: { value: 'lightgrey' } }
},
{
mark: { type: 'bar' },
transform: [
{ filter: { param: 'brush' } }
],
encoding: xy
}
],
width: 900,
height: 100
},
config: { view: { stroke: null } } // no chart outlines
})
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more