Published
Edited
Aug 19, 2022
1 star
Insert cell
# 加上动画的图表
Insert cell
import {data} from "@d3/learn-d3-animation"
Insert cell
Insert cell
htl.html`<svg viewBox="0 0 ${width} ${height}">
${d3.select(htl.svg`<g>`).call(xAxis).node()}
${d3.select(htl.svg`<g>`).call(yAxis).node()}
<g>
<path fill="none" stroke="steelblue" stroke-width="1.5" d="${line(data)}" stroke-miterlimit="1" stroke-dasharray="${strokeDasharray(t)}" />
</g>
</svg>`
Insert cell
ramp(d3.interpolateRgb("steelblue", "orange"))
Insert cell
ramp(d3.interpolateRgb.gamma(2)("steelblue", "orange"))
Insert cell
{
const path = htl.svg`<path d="${line(data)}" fill="none" stroke="steelblue" stroke-width="1.5" stroke-miterlimit="1">`;

const chart = htl.html`<svg viewBox="0 0 ${width} ${height}">
${d3.select(htl.svg`<g>`).call(xAxis).node()}
${d3.select(htl.svg`<g>`).call(yAxis).node()}
<g>
${path}
</g>
</svg>`
for(let i = 0; i < 301; i ++) {
path.setAttribute("stroke-dasharray", strokeDasharray(i / 301))
yield chart
}
}
Insert cell
Insert cell
chart = {
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', [0, 0, width, height])
.attr('style', `max-width: 100%; height: auto; height:intrinsic;`)

const zx = x.copy()
const zy = y.copy()

const line = d3.line().x(d => zx(d.date)).y(d => zy(d.close))

const gy = svg.append('g')
.call(yAxis, zy)

const gx = svg.append('g')
.call(xAxis, zx)

const path = svg.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1.5)
.attr('stroke-miterlimit', 1)
.attr('d', line(data))

return Object.assign(svg.node(), {
update(domain) {
const t = d3.transition().duration(1000)
const fdata = data.filter(d => {
const date = new Date(d.date)
return date >= new Date(domain[0]) && date <= new Date(domain[1])
})
// 避免溢出坐标轴显示范围
const getData = (d) => fdata.includes(d) ? d : new Date(d.date) < new Date(fdata[0].date) ? fdata[0] : fdata[fdata.length - 1];
const line = d3.line().x(d => zx(getData(d).date)).y(d => zy(getData(d).close))
zx.domain(domain)
zy.domain([0, d3.max(fdata, d => d.close)])
gx.transition(t).call(xAxis, zx)
gy.transition(t).call(yAxis, zy)
path.transition(t).attr('d', line(data))
}
})
}
Insert cell
chart.update(ranger)
Insert cell
linelength = htl.svg`<path d="${line(data)}" />`.getTotalLength()
Insert cell
strokeDasharray = d3.interpolate(`0, ${linelength}`, `${linelength}, ${linelength}`)
Insert cell
line = d3.line().x(d => x(d.date)).y(d => y(d.close))
Insert cell
x = d3.scaleUtc().domain(d3.extent(data, d => d.date)).range([margin.left, width -margin.right])
Insert cell
y = d3.scaleLinear().domain([0, d3.max(data, d => d.upper)]).range([height - margin.bottom, margin.top])
Insert cell
xAxis = (g, scale = x) => g.attr('transform', `translate(0, ${ height - margin.bottom })`)
.call(d3.axisBottom(scale).ticks(width / 80).tickSizeOuter(0))
Insert cell
yAxis = (g, scale = y) => g.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(scale).ticks(height / 40))
.call(g => g.select('.domain').remove())
Insert cell
height = 240
Insert cell
margin = ({top: 20, right: 30, bottom: 30, left: 40})
Insert cell
import {Scrubber} from "@mbostock/scrubber"
Insert cell
import {ramp} from "@mbostock/color-ramp"
Insert cell
tween = path => path.transition().duration(1000).ease(d3.easeLinear).attrTween('stroke-dasharray', function () {
const length = this.getTotalLength()
return d3.interpolate(`0,${length}`, `${length},${length}`)
})
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