Skip to main content
creating-data-visualizations
Published by @askskills
Transform raw data into compelling, shareable charts and visualizations using D3.js, Chart.js, or description-ready specs
Third-Party Content
This skill is created by a third-party developer, not Asterism. While security-scanned, we cannot guarantee safety. By using any skill, you accept our Terms of Service and assume all risk.
Installation
aster install creating-data-visualizationsUniversal installation
By installing, you accept the Terms of Service. Skills are third-party content; Asterism is not liable for their use.
README
# Creating Data Visualizations
Transform data into compelling visual stories that inform, persuade, and go viral.
## What This Skill Does
This skill helps you create effective data visualizations by:
- Choosing the right chart type for your data
- Generating production-ready code (D3.js, Chart.js, or pure SVG)
- Adding annotations and storytelling elements
- Optimizing for different platforms (web, social, presentations)
## Chart Selection Guide
### When to Use Each Chart Type
| Data Type | Best Chart | Avoid |
|-----------|-----------|-------|
| **Comparison** (categories) | Bar chart | Pie chart (>5 items) |
| **Trend over time** | Line chart | Pie chart |
| **Part of whole** | Pie/Donut (≤5 items), Treemap | Line chart |
| **Distribution** | Histogram, Box plot | Pie chart |
| **Correlation** | Scatter plot | Bar chart |
| **Ranking** | Horizontal bar | Pie chart |
| **Geographic** | Choropleth map | Bar chart |
| **Flow/Process** | Sankey, Funnel | Scatter plot |
| **Hierarchy** | Treemap, Sunburst | Line chart |
## Chart.js Templates
### Line Chart (Time Series)
```javascript
const config = {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Revenue ($)',
data: [12000, 19000, 15000, 25000, 22000, 30000],
borderColor: '#3B82F6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
fill: true,
tension: 0.4,
pointRadius: 4,
pointHoverRadius: 6
}]
},
options: {
responsive: true,
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Monthly Revenue Growth',
font: { size: 18, weight: 'bold' }
},
annotation: {
annotations: {
milestone: {
type: 'line',
xMin: 'Apr',
xMax: 'Apr',
borderColor: '#10B981',
borderWidth: 2,
label: {
display: true,
content: 'Product Launch',
position: 'start'
}
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: (value) => '$' + value.toLocaleString()
}
}
}
}
};
```
### Bar Chart (Comparison)
```javascript
const config = {
type: 'bar',
data: {
labels: ['Product A', 'Product B', 'Product C', 'Product D', 'Product E'],
datasets: [{
label: 'Sales',
data: [65, 59, 80, 81, 56],
backgroundColor: [
'#3B82F6', '#3B82F6', '#10B981', '#3B82F6', '#3B82F6'
],
borderRadius: 8,
barThickness: 40
}]
},
options: {
indexAxis: 'y', // Horizontal bars
responsive: true,
plugins: {
legend: { display: false },
title: {
display: true,
text: 'Product Performance Comparison'
}
},
scales: {
x: {
grid: { display: false }
}
}
}
};
```
### Donut Chart (Part of Whole)
```javascript
const config = {
type: 'doughnut',
data: {
labels: ['Direct', 'Organic', 'Referral', 'Social', 'Email'],
datasets: [{
data: [35, 25, 20, 12, 8],
backgroundColor: [
'#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6'
],
borderWidth: 0,
cutout: '70%'
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'right'
},
title: {
display: true,
text: 'Traffic Sources'
}
}
}
};
```
## D3.js Templates
### Responsive Line Chart
```javascript
function createLineChart(data, selector) {
const margin = { top: 40, right: 30, bottom: 50, left: 60 };
const width = 800 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3.select(selector)
.append('svg')
.attr('viewBox', `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// Scales
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value) * 1.1])
.range([height, 0]);
// Area
const area = d3.area()
.x(d => x(d.date))
.y0(height)
.y1(d => y(d.value))
.curve(d3.curveMonotoneX);
svg.append('path')
.datum(data)
.attr('fill', 'rgba(59, 130, 246, 0.1)')
.attr('d', area);
// Line
const line = d3.line()
.x(d => x(d.date))
.y(d => y(d.value))
.curve(d3.curveMonotoneX);
svg.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', '#3B82F6')
.attr('stroke-width', 2)
.attr('d', line);
// Axes
svg.append('g')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom(x).ticks(6))
.selectAll('text')
.style('font-size', '12px');
svg.append('g')
.call(d3.axisLeft(y).ticks(5).tickFormat(d => '$' + d.toLocaleString()))
.selectAll('text')
.style('font-size', '12px');
// Interactive tooltip
const tooltip = d3.select(selector)
.append('div')
.attr('class', 'tooltip')
.style('opacity', 0)
.style('position', 'absolute')
.style('background', 'white')
.style('padding', '8px 12px')
.style('border-radius', '4px')
.style('box-shadow', '0 2px 8px rgba(0,0,0,0.15)');
// Dots with hover
svg.selectAll('.dot')
.data(data)
.enter()
.append('circle')
.attr('class', 'dot')
.attr('cx', d => x(d.date))
.attr('cy', d => y(d.value))
.attr('r', 4)
.attr('fill', '#3B82F6')
.on('mouseover', function(event, d) {
tooltip.transition().duration(200).style('opacity', 1);
tooltip.html(`<strong>${d3.timeFormat('%b %Y')(d.date)}</strong><br/>$${d.value.toLocaleString()}`)
.style('left', (event.pageX + 10) + 'px')
.style('top', (event.pageY - 10) + 'px');
})
.on('mouseout', function() {
tooltip.transition().duration(500).style('opacity', 0);
});
}
```
### Animated Bar Chart Race
```javascript
function createBarChartRace(data, selector) {
const duration = 500;
const n = 10; // Number of bars to show
const margin = { top: 16, right: 6, bottom: 6, left: 0 };
const barSize = 48;
const height = margin.top + barSize * n + margin.bottom;
const width = 800;
const x = d3.scaleLinear([0, 1], [margin.left, width - margin.right]);
const y = d3.scaleBand()
.domain(d3.range(n + 1))
.rangeRound([margin.top, margin.top + barSize * (n + 1 + 0.1)])
.padding(0.1);
const color = d3.scaleOrdinal(d3.schemeTableau10);
const svg = d3.select(selector)
.append('svg')
.attr('viewBox', [0, 0, width, height]);
// Animation loop
async function animate() {
for (const keyframe of keyframes) {
const transition = svg.transition()
.duration(duration)
.ease(d3.easeLinear);
x.domain([0, keyframe[1][0].value]);
updateBars(transition, keyframe);
updateLabels(transition, keyframe);
updateAxis(transition);
await transition.end();
}
}
animate();
}
```
## Visualization Best Practices
### Color Accessibility
```javascript
// Colorblind-safe palette
const accessiblePalette = [
'#0072B2', // Blue
'#E69F00', // Orange
'#009E73', // Green
'#CC79A7', // Pink
'#F0E442', // Yellow
'#56B4E9', // Light Blue
'#D55E00', // Red-Orange
];
// Always include non-color indicators
// ✓ Different shapes for data points
// ✓ Patterns in addition to colors
// ✓ Labels directly on data
// ✓ Sufficient contrast (4.5:1 minimum)
```
### Annotation Tips
```javascript
// Key insight callout
const annotation = {
type: 'label',
xValue: 'March',
yValue: 45000,
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderRadius: 4,
content: ['↑ 45% increase', 'after campaign launch'],
font: { size: 12 },
padding: 8
};
// Trend line
const trendLine = {
type: 'line',
borderColor: 'rgba(0, 0, 0, 0.3)',
borderWidth: 2,
borderDash: [6, 6],
label: {
display: true,
content: 'Trend: +12% monthly'
}
};
```
### Data Labels for Social Media
```javascript
// Large, bold numbers for thumbnails
const socialMediaStyle = {
plugins: {
datalabels: {
color: '#fff',
font: {
size: 24,
weight: 'bold'
},
formatter: (value) => value + '%',
anchor: 'center',
align: 'center'
}
}
};
```
## Platform-Specific Optimizations
### For Twitter/X
- **Dimensions**: 1200 x 675px (1.91:1)
- **Key data point prominent** in top-left
- **Minimal text** - let visual do the work
- **Strong contrast** for small displays
### For LinkedIn
- **Dimensions**: 1200 x 627px
- **Professional color palette**
- **Include source citation**
- **Clear title and subtitle**
### For Presentations
- **Dimensions**: 1920 x 1080px (16:9)
- **Minimal elements** - one point per slide
- **Large fonts** (24px minimum)
- **Animate data reveal** for storytelling
### For Websites/Dashboards
- **Responsive** - use viewBox for SVGs
- **Interactive** - tooltips, hover states
- **Loading states** - skeleton or spinner
- **Export options** - PNG, SVG, CSV
## Storytelling Framework
### The Data Story Arc
1. **Hook**: Start with the most surprising insight
2. **Context**: What's the baseline/expectation?
3. **Tension**: Show the gap or problem
4. **Resolution**: Reveal the insight
5. **Call to Action**: What should viewer do?
### Example Narrative
```
HOOK: "Revenue grew 150% in 6 months"
↓
CONTEXT: "Industry average is 15% annually"
↓
TENSION: "We were flat for 2 years"
↓
RESOLUTION: "Product redesign in March changed everything"
↓
CTA: "Here's what we learned..."
```
## Output Format
When creating visualizations, provide:
1. **Chart Code** - Production-ready implementation
2. **Design Specs** - Colors, fonts, dimensions
3. **Data Insights** - Key takeaways (2-3 bullets)
4. **Annotation Suggestions** - What to highlight
5. **Platform Optimization** - Size/format for target
6. **Accessibility Notes** - Color contrast, alt text
Sign in to leave a comment