I've spent an hour or two trying to uncover the problem with my math but cant seem to find it. I create a visual that has a certain height based off of how long the note was pressed. It will fall down and I want to play the audio once it hits the key. The key is 25% of the key_wrapper. (measurements in attached image)
I make the duration 3 seconds for the key to travel from 0 top to key_wrapper top (so that top of div is 0 from bottom), then I get this rate of speed and multiply it to the visual height as the animation starts from -visual_height. This should keep the 3 second timing from -visual_height to 0 top. Then I play the sound at 75% of 3 seconds as it should be 3 seconds to go from top 0 to top key_wrapper height, which means if we consider the bottom of the visual is at 0 top at the start, it should be at the top of the key (25% wrapper height) at 75% of the 3 second rate defined in the duration.
// visual creation
return ({...prev_state,
[pb_counter.current]: (
<div key={`${pb_counter.current}`} ref={ref => playback_visual_refs.current[pb_counter.current] = ref} className='pb-visualizer-instance'
style={{height: `${(timestamps[1] - timestamps[0]) * 0.3}px`}}></div>
)
})
useEffect(() => {
if (playback_visuals[pb_counter.current] && curr_pb_anim.current[1]) {
const computed_style = window.getComputedStyle(playback_visual_refs.current[pb_counter.current])
const height = parseFloat(computed_style.getPropertyValue('height'))
const duration = 3000 + ((3000 / key_wrapper.current.clientHeight) * height)
// Timer just sets a timeout
const f_timeout_id = new Timer(() => {
audio.current.play()
// ((3000 / key_wrapper.current.clientHeight) * 7.5) for 7.5 pixel line on top of keys
}, (3000 * .75) + ((3000 / key_wrapper.current.clientHeight) * 7.5))
curr_pb_anim.current[0].push(attribute_animation(playback_visual_refs.current[pb_counter.current], 'top',
`-${height}px`,
`${(key_wrapper.current.clientHeight)}px`, duration))
curr_pb_anim.current[1] = false
}
}, [playback_visuals])
// animation function
export const attribute_animation = (object, attribute, start, end, duration, easing) => {
return object.animate(
[{[attribute]: start}, { [attribute]: end}],
{duration: duration, fill: 'forwards', easing: easing}
)
}
