pianoSVG = notes => {
const keyWidth = 30;
const keyHeight = keyWidth * 2;
const keyHeightExpand = keyHeight * 1.05;
const keyPad = 2;
const computeColor = index =>
d3.interpolateLab(
d3.lab(83.813, -10.891, -11.484),
d3.lab(86.385, 17.854, 7.357)
)((index - smallest_index) / notes.length);
const svg = d3
.create('svg')
.attr('width', (keyWidth + keyPad) * notes.length + margin * 2)
.attr('height', keyHeightExpand + margin * 2);
const smallest_index = _.min(notes.map(({ index }) => index));
svg
.selectAll('rect')
.data(notes)
.join('rect')
.attr("width", keyWidth)
.attr("height", keyHeight)
.attr(
"x",
({ frequency, index }) =>
(index - smallest_index) * (keyWidth + keyPad) + margin
)
.attr("y", ({ frequency, index }) => margin)
.style("fill", ({ frequency, index }) => computeColor(index))
.style("rx", 2)
.on('mouseover', async function(event) {
d3.select(this)
.transition()
.attr('height', keyHeightExpand)
.attr('stroke', '#333')
.attr('stroke-width', 2);
})
.on('mouseout', async function(event, { frequency, index }) {
d3.select(this)
.transition()
.attr('height', keyHeight)
.attr('stroke', null)
.style("fill", computeColor(index));
})
.on('mousedown', async function(event, { frequency, index }) {
press(index);
});
const press = (index, length) => {
let selection = svg
.selectAll('rect')
.filter((d, i) => i == index - smallest_index);
const oldColor = computeColor(index);
const newColor = d3.color(oldColor).darker(1);
selection.style("fill", newColor).attr('height', keyHeightExpand);
selection
.transition()
.style("fill", oldColor)
.attr('height', keyHeight);
synth.triggerAttackRelease(notes[index - smallest_index].frequency, length);
};
return Object.assign(svg, {
press,
notes: notes,
length: notes.length
});
return svg;
}