@@ -368,6 +368,44 @@ const template = (template_string, template_variables = {}) => {
368368 return new Function ( "return `" + template_string + "`;" ) . call ( template_variables ) ;
369369} ;
370370
371+ /**
372+ * Get the visible ratio of an element compared to container.
373+ * If no container is given, the viewport is used.
374+ *
375+ * Note: currently only vertical ratio is supported.
376+ *
377+ * @param {Node } el - The element to get the visible ratio from.
378+ * @param {Node } [container] - The container to compare the element to.
379+ * @returns {number } - The visible ratio of the element.
380+ * 0 means the element is not visible.
381+ * 1 means the element is fully visible.
382+ */
383+ const get_visible_ratio = ( el , container ) => {
384+ if ( ! el ) {
385+ return 0 ;
386+ }
387+
388+ const rect = el . getBoundingClientRect ( ) ;
389+ const container_rect =
390+ container !== window
391+ ? container . getBoundingClientRect ( )
392+ : {
393+ top : 0 ,
394+ bottom : window . innerHeight ,
395+ } ;
396+
397+ let visible_ratio = 0 ;
398+ if ( rect . top < container_rect . bottom && rect . bottom > container_rect . top ) {
399+ const rect_height = rect . bottom - rect . top ;
400+ const visible_height =
401+ Math . min ( rect . bottom , container_rect . bottom ) -
402+ Math . max ( rect . top , container_rect . top ) ;
403+ visible_ratio = visible_height / rect_height ;
404+ }
405+
406+ return visible_ratio ;
407+ } ;
408+
371409const dom = {
372410 toNodeArray : toNodeArray ,
373411 querySelectorAllAndMe : querySelectorAllAndMe ,
@@ -389,6 +427,7 @@ const dom = {
389427 set_data : set_data ,
390428 delete_data : delete_data ,
391429 template : template ,
430+ get_visible_ratio : get_visible_ratio ,
392431 add_event_listener : events . add_event_listener , // BBB export. TODO: Remove in an upcoming version.
393432 remove_event_listener : events . remove_event_listener , // BBB export. TODO: Remove in an upcoming version.
394433} ;
0 commit comments